title | description | author | ms.author | ms.date |
---|---|---|---|---|
Create a custom plugin |
How to create a custom plugin for Dev Proxy |
estruyf |
wmastyka |
02/05/2025 |
In this article, you learn how to create a custom plugin for the Dev Proxy. By creating plugins for Dev Proxy, you can extend its functionality and add custom features to fit your needs.
Before you start creating a custom plugin, make sure you have the following prerequisites:
- .NET Core SDK
- The latest version of the Dev Proxy Abstractions DLL, which you can find on the Dev Proxy GitHub releases page
Follow the next steps to create a new project:
-
Create a new class library project using the
dotnet new classlib
command.dotnet new classlib -n MyCustomPlugin
-
Open the newly created project in Visual Studio Code.
code MyCustomPlugin
-
Add the Dev Proxy Abstractions DLL (
dev-proxy-abstractions.dll
) to the project folder. -
Add the
dev-proxy-abstractions.dll
as a reference to your projectDevProxyCustomPlugin.csproj
file.<ItemGroup> <Reference Include="dev-proxy-abstractions"> <HintPath>.\dev-proxy-abstractions.dll</HintPath> <Private>false</Private> <ExcludeAssets>runtime</ExcludeAssets> </Reference> </ItemGroup>
-
Add the NuGet packages required for your project.
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
-
Exclude the dependency DLLs from the build output by adding a
ExcludeAssets
tag perPackageReference
in theDevProxyCustomPlugin.csproj
file.<ExcludeAssets>runtime</ExcludeAssets>
-
Create a new class that implements the
BaseProxyPlugin
interface.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; } }
-
Build your project.
dotnet build
To use your custom plugin, you need to add it to the Dev Proxy configuration file:
-
Add the new plugin configuration in the
devproxyrc.json
file.{ "plugins": [{ "name": "CatchApiCalls", "enabled": true, "pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll", }] }
-
Run the Dev Proxy.
devproxy
The example plugin checks all matching URLs for the required Authorization header. If the header isn't present, it shows a warning message.
You can extend your plugin's logic by adding custom configuration:
-
Add a new
_configuration
object and bind it in theRegister
method.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; } }
-
Build your project.
dotnet build
-
Update your
devproxyrc.json
file to include the new configuration.{ "plugins": [{ "name": "CatchApiCalls", "enabled": true, "pluginPath": "./bin/Debug/net8.0/MyCustomPlugin.dll", "configSection": "catchApiCalls" }], "catchApiCalls": { "requiredHeader": "Authorization" // Example configuration } }
-
Run the Dev Proxy.
devproxy