本文介绍如何为开发代理创建自定义插件。 通过为开发代理创建插件,可以扩展其功能并添加自定义功能以满足你的需求。
先决条件
在开始创建自定义插件之前,请确保满足以下先决条件:
- .NET Core SDK
- 可在开发代理 GitHub 发布页上找到的最新版本的开发代理抽象 DLL
创建新插件
按照后续步骤创建新项目:
使用
dotnet new classlib
命令创建新的类库项目。dotnet new classlib -n MyCustomPlugin
在 Visual Studio Code 中打开新创建的项目。
code MyCustomPlugin
将开发代理抽象 DLL (
dev-proxy-abstractions.dll
) 添加到项目文件夹。添加作为
dev-proxy-abstractions.dll
对项目DevProxyCustomPlugin.csproj
文件的引用。<ItemGroup> <Reference Include="dev-proxy-abstractions"> <HintPath>.\dev-proxy-abstractions.dll</HintPath> <Private>false</Private> <ExcludeAssets>runtime</ExcludeAssets> </Reference> </ItemGroup>
添加项目所需的 NuGet 包。
dotnet add package Microsoft.Extensions.Configuration dotnet add package Microsoft.Extensions.Configuration.Binder dotnet add package Microsoft.Extensions.Logging.Abstractions dotnet add package Unobtanium.Web.Proxy
通过在文件中添加标记
ExcludeAssets
PackageReference
DevProxyCustomPlugin.csproj
,从生成输出中排除依赖项 DLL。<ExcludeAssets>runtime</ExcludeAssets>
创建实现
BaseProxyPlugin
接口的新类。using Microsoft.DevProxy.Abstractions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace MyCustomPlugin; public class CatchApiCalls(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> UrlsToWatch, IConfigurationSection? configSection = null) : BaseProxyPlugin(pluginEvents, context, logger, UrlsToWatch, configSection) { public override string Name => nameof(CatchApiCalls); public override async Task RegisterAsync() { await base.RegisterAsync(); PluginEvents.BeforeRequest += BeforeRequestAsync; } private Task BeforeRequestAsync(object sender, ProxyRequestArgs e) { if (UrlsToWatch is null || !e.HasRequestUrlMatch(UrlsToWatch)) { // No match for the URL, so we don't need to do anything Logger.LogRequest("URL not matched", MessageType.Skipped, new LoggingContext(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; } return Task.CompletedTask; } }
生成项目。
dotnet build
使用自定义插件
若要使用自定义插件,需要将其添加到开发代理配置文件:
在文件中添加新插件配置
devproxyrc.json
。{ "plugins": [{ "name": "CatchApiCalls", "enabled": true, "pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll", }] }
运行开发代理。
devproxy
示例插件检查所需授权标头的所有匹配 URL。 如果标头不存在,则会显示警告消息。
将自定义配置添加到插件(可选)
可以通过添加自定义配置来扩展插件的逻辑:
_configuration
添加新对象并在方法中Register
绑定它。using Microsoft.DevProxy.Abstractions; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace MyCustomPlugin; public class CatchApiCallsConfiguration { public string? RequiredHeader { get; set; } } public class CatchApiCalls(IPluginEvents pluginEvents, IProxyContext context, ILogger logger, ISet<UrlToWatch> UrlsToWatch, IConfigurationSection? configSection = null) : BaseProxyPlugin(pluginEvents, context, logger, UrlsToWatch, configSection) { public override string Name => nameof(CatchApiCalls); // Define you custom configuration private readonly CatchApiCallsConfiguration _configuration = new(); public override async Task RegisterAsync() { await base.RegisterAsync(); // Bind your plugin configuration configSection?.Bind(_configuration); // Register your event handlers PluginEvents.BeforeRequest += BeforeRequestAsync; } private Task BeforeRequestAsync(object sender, ProxyRequestArgs e) { if (UrlsToWatch is null || !e.HasRequestUrlMatch(UrlsToWatch)) { // No match for the URL, so we don't need to do anything Logger.LogRequest("URL not matched", MessageType.Skipped, new LoggingContext(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; } return Task.CompletedTask; } }
生成项目。
dotnet build
devproxyrc.json
更新文件以包含新配置。{ "plugins": [{ "name": "CatchApiCalls", "enabled": true, "pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll", "configSection": "catchApiCalls" }], "catchApiCalls": { "requiredHeader": "Authorization" // Example configuration } }
运行开发代理。
devproxy