Creación de un complemento personalizado

De un vistazo
Objetivo: Crear un complemento de proxy Dev personalizado
Tiempo: 30 minutos
Complementos: Complemento personalizado
Requisitos previos:Configurar Dev Proxy, .NET 10 SDK

En este artículo, aprenderá a crear un complemento personalizado para el proxy de desarrollo. Al crear complementos para el proxy de desarrollo, puede ampliar su funcionalidad y agregar características personalizadas para satisfacer sus necesidades.

Complementos HTTP frente a complementos stdio

Dev Proxy admite dos tipos de complementos en función del tráfico que quiera interceptar:

  • Los complementos HTTP interceptan las solicitudes y respuestas HTTP(S) entre la aplicación y las API. Heredan de BasePlugin y invalidan métodos como BeforeRequestAsync y BeforeResponseAsync. Use complementos HTTP cuando quiera simular errores de API, agregar respuestas simuladas, validar encabezados de solicitud o inspeccionar y modificar el tráfico HTTP.

  • Los complementos stdio interceptan los mensajes enviados a través de la entrada y salida estándar (stdin, stdout, stderr) entre un proceso primario y un proceso secundario. Implementan la IStdioPlugin interfaz (que BasePlugin también implementa) e invalidan métodos como BeforeStdinAsync, AfterStdoutAsyncy AfterStderrAsync. Use complementos stdio al trabajar con herramientas que se comunican a través de stdio, como servidores de Protocolo de contexto de modelo (MCP).

Una sola clase de complemento puede controlar el tráfico HTTP y stdio invalidando métodos de ambos conjuntos.

Requisitos previos

Antes de empezar a crear un complemento personalizado, asegúrese de que tiene los siguientes requisitos previos:

Creación de un complemento

Siga los pasos siguientes para crear un proyecto:

  1. Cree un nuevo proyecto de biblioteca de clases mediante el dotnet new classlib comando .

    dotnet new classlib -n MyCustomPlugin
    
  2. Abra el proyecto recién creado en Visual Studio Code.

    code MyCustomPlugin
    
  3. Agregue el paquete NuGet Abstracciones de Dev Proxy a su proyecto.

    dotnet add package DevProxy.Abstractions
    
  4. Excluya las bibliotecas de vínculos dinámicos (DLL) de dependencia de la salida de compilación agregando la etiqueta ExcludeAssets por cada PackageReference en el archivo MyCustomPlugin.csproj.

    <ExcludeAssets>runtime</ExcludeAssets>
    
  5. Cree una nueva clase que herede de la BaseProxy clase .

    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. Construya su proyecto.

    dotnet build
    

Uso del complemento personalizado

Para usar el complemento personalizado, debe agregarlo al archivo de configuración del proxy de desarrollo:

  1. Agregue la nueva configuración del complemento en el devproxyrc.json archivo.

    Archivo: devproxyrc.json

    {
      "plugins": [{
        "name": "CatchApiCallsPlugin",
        "enabled": true,
        "pluginPath": "./bin/Debug/net10.0/MyCustomPlugin.dll",
      }]
    }
    
  2. Ejecute el proxy de desarrollo.

    devproxy
    

El complemento de ejemplo comprueba todas las direcciones URL coincidentes para el encabezado necesario Authorization . Si el encabezado no está presente, se muestra un mensaje de advertencia.

Adición de una configuración personalizada al complemento (opcional)

Puede ampliar la lógica del complemento agregando una configuración personalizada:

  1. Hereda de la clase BasePlugin<TConfiguration>. El proxy de desarrollo expone la configuración del complemento interpretada a través de la propiedad Configuration en tiempo de ejecución.

    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. Construya su proyecto.

    dotnet build
    
  3. Actualice el devproxyrc.json archivo para incluir la nueva configuración.

    Archivo: devproxyrc.json

    {
      "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.1.0/rc.schema.json",
      "plugins": [{
        "name": "CatchApiCallsPlugin",
        "enabled": true,
        "pluginPath": "./bin/Debug/net10.0/MyCustomPlugin.dll",
        "configSection": "catchApiCalls"
      }],
      "catchApiCalls": {
        "requiredHeader": "Authorization"
      }
    }
    
  4. Ejecute el proxy de desarrollo.

    devproxy
    

Consulte también