Erstellen eines benutzerdefinierten Plug-Ins

Auf einen Blick
Ziel: Erstellen eines benutzerdefinierten Dev Proxy-Plug-Ins
Zeit: 30 Minuten
Plugins: Benutzerdefiniertes Plug-In
Prerequisites:Set up Dev Proxy, .NET 10 SDK

In diesem Artikel erfahren Sie, wie Sie ein benutzerdefiniertes Plug-In für den Dev-Proxy erstellen. Durch das Erstellen von Plug-Ins für Dev Proxy können Sie seine Funktionalität erweitern und benutzerdefinierte Features hinzufügen, um Ihren Anforderungen gerecht zu werden.

HTTP-Plug-Ins im Vergleich zu Stdio-Plug-Ins

Dev Proxy unterstützt zwei Arten von Plug-Ins je nach Datenverkehr, den Sie abfangen möchten:

  • HTTP-Plugins fangen HTTP(S)-Anfragen und -Antworten zwischen Ihrer App und den APIs ab. Sie erben von BasePlugin und überschreiben Methoden wie BeforeRequestAsync und BeforeResponseAsync. Verwenden Sie HTTP-Plug-Ins, wenn Sie API-Fehler simulieren, simulierte Antworten hinzufügen, Anforderungsheader überprüfen oder anderweitig HTTP-Datenverkehr überprüfen und ändern möchten.

  • Stdio-Plugins fangen Nachrichten ab, die über die Standardein-/ausgabe (stdin, stdout, stderr) zwischen einem Elternprozess und einem Kindprozess gesendet werden. Sie implementieren die IStdioPlugin Schnittstelle (die BasePlugin auch implementiert wird) und überschreiben Methoden wie BeforeStdinAsync, AfterStdoutAsyncund AfterStderrAsync. Verwenden Sie Stdio-Plug-Ins beim Arbeiten mit Tools, die über Stdio kommunizieren, z. B. McP-Server (Model Context Protocol).

Eine einzelne Plug-In-Klasse kann sowohl HTTP- als auch Stdiodatenverkehr verarbeiten, indem Methoden aus beiden Sätzen überschrieben werden.

Voraussetzungen

Bevor Sie mit dem Erstellen eines benutzerdefinierten Plug-Ins beginnen, stellen Sie sicher, dass Sie über die folgenden Voraussetzungen verfügen:

Erstellen eines neuen Plug-Ins

Führen Sie die nächsten Schritte aus, um ein neues Projekt zu erstellen:

  1. Erstellen Sie mithilfe des dotnet new classlib Befehls ein neues Klassenbibliotheksprojekt.

    dotnet new classlib -n MyCustomPlugin
    
  2. Öffnen Sie das neu erstellte Projekt in Visual Studio Code.

    code MyCustomPlugin
    
  3. Fügen Sie dem Projekt das NuGet-Paket "Dev Proxy Abstractions" hinzu.

    dotnet add package DevProxy.Abstractions
    
  4. Schließen Sie die abhängigen Dynamic-Link-Bibliotheken (DLLs) aus der Buildausgabe aus, indem Sie in der Datei MyCustomPlugin.csproj pro PackageReference ein ExcludeAssets-Tag hinzufügen.

    <ExcludeAssets>runtime</ExcludeAssets>
    
  5. Erstellen Sie eine neue Klasse, die von der BaseProxy Klasse erbt.

    using DevProxy.Abstractions.Plugins;
    using DevProxy.Abstractions.Proxy;
    using Microsoft.Extensions.Logging;
    
    namespace MyCustomPlugin;
    
    public sealed class CatchApiCallsPlugin(
        ILogger<CatchApiCallsPlugin> logger,
        ISet<UrlToWatch> urlsToWatch) : BasePlugin(logger, urlsToWatch)
    {
        public override string Name => nameof(CatchApiCallsPlugin);
    
        public override Task BeforeRequestAsync(ProxyRequestArgs e, CancellationToken cancellationToken)
        {
            Logger.LogTrace("{Method} called", nameof(BeforeRequestAsync));
    
            ArgumentNullException.ThrowIfNull(e);
    
            if (!e.HasRequestUrlMatch(UrlsToWatch))
            {
                Logger.LogRequest("URL not matched", MessageType.Skipped, new(e.Session));
                return Task.CompletedTask;
            }
    
            var headers = e.Session.HttpClient.Request.Headers;
            var header = headers.Where(h => h.Name == "Authorization").FirstOrDefault();
            if (header is null)
            {
                Logger.LogRequest($"Does not contain the Authorization header", MessageType.Warning, new LoggingContext(e.Session));
                return Task.CompletedTask;
            }
    
            Logger.LogTrace("Left {Name}", nameof(BeforeRequestAsync));
            return Task.CompletedTask;
        }
    }
    
  6. Erstellen Sie das Projekt.

    dotnet build
    

Verwenden Ihres benutzerdefinierten Plug-Ins

Um Ihr benutzerdefiniertes Plug-In zu verwenden, müssen Sie es der Dev Proxy-Konfigurationsdatei hinzufügen:

  1. Fügen Sie die neue Plug-In-Konfiguration in der devproxyrc.json Datei hinzu.

    Datei: devproxyrc.json

    {
      "plugins": [{
        "name": "CatchApiCallsPlugin",
        "enabled": true,
        "pluginPath": "./bin/Debug/net10.0/MyCustomPlugin.dll",
      }]
    }
    
  2. Führen Sie den Dev-Proxy aus.

    devproxy
    

Das Beispiel-Plug-In überprüft alle übereinstimmenden URLs auf den erforderlichen Authorization Header. Wenn die Kopfzeile nicht vorhanden ist, wird eine Warnmeldung angezeigt.

Hinzufügen einer benutzerdefinierten Konfiguration zu Ihrem Plug-In (optional)

Sie können die Logik Ihres Plug-Ins erweitern, indem Sie eine benutzerdefinierte Konfiguration hinzufügen:

  1. Erbe von der BasePlugin<TConfiguration> Klasse. Dev Proxy stellt zur Laufzeit die analysierte Plug-in-Konfiguration über die Configuration-Eigenschaft bereit.

    using DevProxy.Abstractions.Plugins;
    using DevProxy.Abstractions.Proxy;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace MyCustomPlugin;
    
    public sealed class CatchApiCallsConfiguration
    {
        public string? RequiredHeader { get; set; }
    }
    
    public sealed class CatchApiCallsPlugin(
        HttpClient httpClient,
        ILogger<CatchApiCallsPlugin> logger,
        ISet<UrlToWatch> urlsToWatch,
        IProxyConfiguration proxyConfiguration,
        IConfigurationSection pluginConfigurationSection) :
        BasePlugin<CatchApiCallsConfiguration>(
            httpClient,
            logger,
            urlsToWatch,
            proxyConfiguration,
            pluginConfigurationSection)
    {
        public override string Name => nameof(CatchApiCallsPlugin);
    
        public override Task BeforeRequestAsync(ProxyRequestArgs e, CancellationToken cancellationToken)
        {
            Logger.LogTrace("{Method} called", nameof(BeforeRequestAsync));
    
            ArgumentNullException.ThrowIfNull(e);
    
            if (!e.HasRequestUrlMatch(UrlsToWatch))
            {
                Logger.LogRequest("URL not matched", MessageType.Skipped, new(e.Session));
                return Task.CompletedTask;
            }
    
            // Start using your custom configuration
            var requiredHeader = Configuration.RequiredHeader ?? string.Empty;
            if (string.IsNullOrEmpty(requiredHeader))
            {
                // Required header is not set, so we don't need to do anything
                Logger.LogRequest("Required header not set", MessageType.Skipped, new LoggingContext(e.Session));
                return Task.CompletedTask;
            }
    
            var headers = e.Session.HttpClient.Request.Headers;
            var header = headers.Where(h => h.Name == requiredHeader).FirstOrDefault();
            if (header is null)
            {
                Logger.LogRequest($"Does not contain the {requiredHeader} header", MessageType.Warning, new LoggingContext(e.Session));
                return Task.CompletedTask;
            }
    
            Logger.LogTrace("Left {Name}", nameof(BeforeRequestAsync));
            return Task.CompletedTask;
        }
    }
    
  2. Erstellen Sie das Projekt.

    dotnet build
    
  3. Aktualisieren Sie Ihre devproxyrc.json Datei so, dass sie die neue Konfiguration enthält.

    Datei: devproxyrc.json

    {
      "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.0.0/rc.schema.json",
      "plugins": [{
        "name": "CatchApiCallsPlugin",
        "enabled": true,
        "pluginPath": "./bin/Debug/net10.0/MyCustomPlugin.dll",
        "configSection": "catchApiCalls"
      }],
      "catchApiCalls": {
        "requiredHeader": "Authorization"
      }
    }
    
  4. Führen Sie den Dev-Proxy aus.

    devproxy
    

Siehe auch