概览
目标: 生成自定义开发代理插件
时间: 30 分钟
插件: 自定义插件
Prerequisites:设置开发代理,.NET 10 SDK
本文介绍如何为开发代理创建自定义插件。 通过为开发代理创建插件,可以扩展其功能并添加自定义功能以满足你的需求。
HTTP 插件与 stdio 插件
开发代理(Dev Proxy)支持两种类型的插件,这取决于您想截获的流量类型:
HTTP 插件 截获应用与 API 之间的 HTTP(S) 请求和响应。 它们继承自
BasePlugin,并重写诸如BeforeRequestAsync和BeforeResponseAsync之类的方法。 如果要模拟 API 错误、添加模拟响应、验证请求标头或其他检查和修改 HTTP 流量,请使用 HTTP 插件。Stdio 插件会拦截父进程与子进程之间通过标准输入/输出(stdin、stdout、stderr)传递的消息。 它们实现了
IStdioPlugin接口(BasePlugin也实现了该接口),并重写了诸如BeforeStdinAsync、AfterStdoutAsync和AfterStderrAsync之类的方法。 请在与通过 stdio 进行通信的工具(例如模型上下文协议(MCP)服务器)合作时,使用 stdio 插件。
单个插件类可以通过重写这两个集中的方法来处理 HTTP 和 stdio 流量。
先决条件
在开始创建自定义插件之前,请确保满足以下先决条件:
创建新插件
按照后续步骤创建新项目:
使用
dotnet new classlib命令创建新的类库项目。dotnet new classlib -n MyCustomPlugin在Visual Studio Code中打开新建的项目。
code MyCustomPlugin将 Dev Proxy Abstractions NuGet 包添加到你的项目中。
dotnet add package DevProxy.Abstractions通过在
ExcludeAssets文件中为每个PackageReference添加一个MyCustomPlugin.csproj标记,将依赖动态链接库(DLL)从生成输出中排除。<ExcludeAssets>runtime</ExcludeAssets>创建继承自
BaseProxy该类的新类。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; } }构建项目。
dotnet build
使用自定义插件
若要使用自定义插件,需要将其添加到开发代理配置文件:
在
devproxyrc.json文件中添加新的插件配置。文件: devproxyrc.json
{ "plugins": [{ "name": "CatchApiCallsPlugin", "enabled": true, "pluginPath": "./bin/Debug/net10.0/MyCustomPlugin.dll", }] }运行开发代理。
devproxy
示例插件检查所有匹配 URL 是否包含所需的 Authorization 标头。 如果标头不存在,则会显示警告消息。
将自定义配置添加到插件(可选)
可以通过添加自定义配置来扩展插件的逻辑:
继承自
BasePlugin<TConfiguration>类。 开发代理在运行时通过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; } }构建项目。
dotnet build更新您的
devproxyrc.json文件,以包含新的配置。文件: 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" } }运行开发代理。
devproxy