This repository is a .NET library that combines Microsoft YARP (Yet Another Reverse Proxy) with runtime configuration APIs and automatic self-signed ephemeral certificate generation. It's designed to simplify development and testing of reverse proxy scenarios. The examples/ directory is set up to use Aspire. Aspire is an orchestrator for the entire application and will take care of configuring dependencies, building, and running the application. The resources that make up the application are defined in examples/Aspire.AppHost/Program.cs including application code and external dependencies.
The src/ReverseProxy directory implements the core functionality of the library. The src/ReverseProxy.Aspire directory is an extension that integrates src/ReverseProxy into an Aspire solution for managing YARP route/cluster configuration.
- .NET 10.0
- .NET 8.0
- Aspire
- C#
- Multi-platform support (Windows, Linux, macOS, containers)
- Make only high confidence suggestions when reviewing code changes.
- Always use the version of C# that matches the latest .NET LTS.
- Always use the latest released (stable) version of Aspire.
- Never change global.json unless explicitly asked to.
- Never change package.json or package-lock.json files unless explicitly asked to.
- Never change NuGet.config files unless explicitly asked to.
- Apply code-formatting style defined in
.editorconfigand.editorconfigfiles in nested directories. - Prefer file-scoped namespace declarations and single-line using directives.
- Insert a newline before the opening curly brace of any code block (e.g., after
if,for,while,foreach,using,try, etc.). - Ensure that the final return statement of a method is on its own line.
- Use pattern matching and switch expressions wherever possible.
- Use
nameofinstead of string literals when referring to member names. - Place private class declarations at the bottom of the file.
- Declare variables non-nullable, and check for
nullat entry points. - Always use
is nulloris not nullinstead of== nullor!= null. - Trust the C# null annotations and don't add null checks when the type system says a value cannot be null.
- Markdown files should not have multiple consecutive blank lines.
- Code blocks should be formatted with triple backticks (```) and include the language identifier for syntax highlighting.
- JSON code blocks should be indented properly.
The following specialized skills are available in .github/skills/:
- aspire: Aspire skill covering the Aspire CLI, AppHost orchestration, service discovery, integrations, MCP server, VS Code extension, Dev Containers, templates, dashboard, and deployment
-
ReverseProxy Core (
src/ReverseProxy)- ReverseProxyApp: Manages routes/clusters using YARP's configuration system
- Certificate Management: Automatic generation of self-signed ephemeral certificates with caching and trust added by a local CA
- Runtime API: Web API endpoints for managing routes/clusters at runtime
-
ReverseProxy.Aspire (
src/ReverseProxy.Aspire)- Integrates with the Aspire orchestration platform for route/cluster configuration for services without requiring the Runtime API
WithReverseProxyReference(): Extension for configuring Aspire resourcesServiceDiscoveryStartupFilter: Auto-discovers and configures annotated Aspire resources as YARP routes/clusters
-
Examples (
examples/)- AppHost: Aspire app host demonstrating the reverse proxy in action
- ReverseProxy: Example reverse proxy service using the library
- Website: Example backend service discoverable by the proxy
- InMemoryConfigProvider: Holds runtime-added routes/clusters
- IProxyConfigProvider: Base abstraction; implementations are merged in ReverseProxyApp
- Multiple providers can coexist; routes/clusters are combined across all
Services use primary constructor injection with sealed internal classes:
internal sealed class ReverseProxyApp(
IConfigValidator configValidator,
InMemoryConfigProvider inMemoryConfigProvider,
IEnumerable<IProxyConfigProvider> proxyConfigProviders)Use the extension methods in src/ReverseProxy/ReverseProxyExtensions.cs to configure services:
ConfigureReverseProxy(): Registers core servicesUseSelfSignedCertificate(): Enables automatic certificate generation on Kestrel
- Lazy Generation: Certificates are created on-demand via ServerCertificateSelector
- Caching: IMemoryCache prevents redundant certificate generation
- Wildcard Support: Handles both
*.example.comand specific domain names - Self-Signed CA: Generated once and installed into the trusted root store on the platform; certificates derive trust from it
- xUnit with SutFactory for mocking
- SutFactory (HenrikJensen.SutFactory): Custom builder pattern for automatic arrangement of the dependency graph while creating the System Under Test instance
- Reduces boilerplate; use
SutBuilder→InputBuilder→Instance<T>()or if no spy instances are inspected, the preferred patternSystemUnderTest.For<T>(arrange => { })where 'arrange' is an InputBuilder.
- Reduces boilerplate; use
- Arrange-Act-Assert: Standard pattern with setup helpers (see
SetHappyPath(InputBuilder arrange)in tests)
test/ReverseProxy.UnitTest/ReverseProxy/ReverseProxyApiTests.cs: Tests the API endpointstest/ReverseProxy.UnitTest/ReverseProxy/ReverseProxyAppTests.cs: Tests configuration managementtest/ReverseProxy.UnitTest/Certificate/CertificateAppTests.cs: Tests certificate generationtest/ReverseProxy.UnitTest/Certificate/CertificateConfigTests.cs: Tests configuration managementtest/ReverseProxy.Aspire.UnitTest/ServiceDiscoveryTests.cs: Tests the Aspire service discovery
To test the library run the following command from the solution root:
dotnet test
Projects target both net8.0 and net10.0. Compatibility with Windows, macOS and Linux must be ensured when adding and changing code.
Use dotnet test to verify.
- EnforceCodeStyleInBuild: Code style violations fail the build
- Configuration:
stylecop.jsonrequiresxmlHeader: truefor packable projects
Central package versioning via Directory.Packages.props:
- Add new dependencies by adding
<PackageVersion>entries there - Projects reference by
<PackageReference Include="Name" />(version auto-inherited)
Common namespaces are globally imported via Directory.Build.props and project .csproj files
- Uses
Yarp.ReverseProxyNuGet package - Core types:
RouteConfig,ClusterConfig,DestinationConfig - Validation via
IConfigValidator
- DI service registration via
IServiceCollection. - Startup filters for configuring reverse proxy routes/clusters using injected service discovery environment variables.
- Resource builders follow Aspire conventions
- IProxyConfigProvider: Implement to add custom configuration sources
- ICertificateConfig: Customize certificate generation options (algorithm, subject name)
- IFileStore: Abstract file storage for certificates
These instructions are comprehensive and tested. Only search for additional information if:
- The instructions appear outdated or incorrect
- You encounter specific errors not covered here
- You need details about new features not yet documented