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. Añade el paquete NuGet Dev Proxy Abstractions a tu proyecto.

    dotnet add package DevProxy.Abstractions
    
  4. Excluye las bibliotecas de enlace dinámico (DLL) de las dependencias del resultado de la compilación añadiendo una etiqueta ExcludeAssets por cada PackageReference en el archivo MyCustomPlugin.csproj.

    <ExcludeAssets>runtime</ExcludeAssets>
    
  5. Cree una nueva clase que herede de la BasePlugin 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. Heredar de la clase BasePlugin<TConfiguration>. Dev Proxy expone en tiempo de ejecución la configuración del complemento analizada a través de la propiedad Configuration.

    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.3.1/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