Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<Project>
<PropertyGroup>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.SourceLink.GitHub">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" />
Expand Down
1 change: 1 addition & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Authors>Henrik Jensen</Authors>
<Copyright>Copyright 2026 Henrik Jensen</Copyright>
<PackageProjectUrl>https://github.com/henrikhimself/DotNet-ReverseProxy</PackageProjectUrl>
<RepositoryUrl>https://github.com/henrikhimself/DotNet-ReverseProxy.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
Expand Down
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.9.0" />
<PackageVersion Include="Microsoft.Extensions.ServiceDiscovery" Version="10.1.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.102" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.13.0" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.13.0" />
Expand Down
1 change: 1 addition & 0 deletions examples/Aspire.AppHost/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"launchBrowser": true,
"applicationUrl": "https://localhost:17294",
"environmentVariables": {
"ASPNETCORE_PREVENTHOSTINGSTARTUP": "true",
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21134",
Expand Down
5 changes: 5 additions & 0 deletions examples/Aspire.ReverseProxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
// Use the configured reverse proxy.
app.UseReverseProxy();

// Use the optional reverse proxy API to manage the reverse proxy configuration at runtime.
// Beware that adding new routes/clusters will clear discovered Aspire resources from the configuration.
// See ReverseProxyApi.http for example usage of the API.
app.UseReverseProxyApi("reverse-proxy-api");
Comment thread
henrikhimself marked this conversation as resolved.

// No further routes are registered. This means that you will get a 404 error status on all requests
// that do not match a proxied Aspire resource.
await app.RunAsync();
61 changes: 61 additions & 0 deletions examples/Aspire.ReverseProxy/ReverseProxyApi.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Reverse Proxy API Examples (port can be changed in AppHost)
# The "/reverse-proxy-api" is the base path for the reverse proxy API, which is configured when adding
# the reverse proxy API to the application builder.
@Test_HostAddress = https://localhost:8443

# Get clusters
# View the current clusters configured in the reverse proxy.
GET {{Test_HostAddress}}/reverse-proxy-api/cluster

###
# Add cluster
# Add a cluster that points to the catfact.ninja API. This cluster will be used in the route configuration
# to forward requests to the catfact API.
POST {{Test_HostAddress}}/reverse-proxy-api/cluster
Content-Type: application/json

{
"Clusters": [
{
"ClusterId": "catfact-from-api",
"Destinations": {
"destination1": {
"Address": "https://catfact.ninja/fact"
}
}
}
],
"AllowOverwrite": true
}

###
# Get routes
# View the current routes configured in the reverse proxy. After adding the route, you should see
# the new route in the response.
GET {{Test_HostAddress}}/reverse-proxy-api/route

###
# Add route
# Add a route that matches requests to /catfact and forwards them to the catfact cluster. The route also
# includes a transform to remove the /catfact prefix before forwarding the request to the destination.
Comment thread
henrikhimself marked this conversation as resolved.
POST {{Test_HostAddress}}/reverse-proxy-api/route
Content-Type: application/json

{
"Routes": [
{
"RouteId": "catfact-from-api",
"ClusterId": "catfact-from-api",
"Order": 100,
"Match": {
"Path": "catfact-from-api/{**catch-all}"
Comment thread
henrikhimself marked this conversation as resolved.
},
"Transforms": [
{
"PathRemovePrefix": "/catfact-from-api"
}
]
}
],
"AllowOverwrite": true
}
24 changes: 24 additions & 0 deletions examples/Aspire.ReverseProxy/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,29 @@
"AllowedHosts": "*",
"SelfSignedCertificate": {
"CaFilePath": "{REVERSEPROXY_HOME}"
},
"ReverseProxy": {
"Routes": {
"catfact-route-from-appsettings": {
"ClusterId": "catfact-cluster-from-appsettings",
"Match": {
"Path": "catfact-from-appsettings/{**catch-all}"
Comment thread
henrikhimself marked this conversation as resolved.
},
"Transforms": [
{
"PathRemovePrefix": "/catfact-from-appsettings"
}
]
}
},
"Clusters": {
"catfact-cluster-from-appsettings": {
"Destinations": {
"destination1": {
"Address": "https://catfact.ninja/fact"
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion examples/Aspire.Website/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</head>
<body>
<h1>Website</h1>
<p><b>You should see this page when navigating to "https://example-website.local/".</b></p>
<p><b>You should see this page when navigating to "<a href="https://example-website.local:8443/">https://example-website.local:8443/</a>"</b> (port can be changed in AppHost).</p>
<p>This website does not use SSL. Instead, a secure HTTPS connection is provided by the reverse proxy.</p>
<p>In case "example-website.local" cannot be found then you need to map it in your local hosts file.</p>
</body>
Expand Down
2 changes: 1 addition & 1 deletion src/ReverseProxy.Aspire/ReverseProxy.Aspire.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageTags>testing;reverse-proxy;aspire</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.0.0-beta6</Version>
<Version>1.0.0-beta7</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
11 changes: 6 additions & 5 deletions src/ReverseProxy/Certificate/CertificateFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,12 @@ public X509Certificate2 CreateCertificate(AsymmetricAlgorithm key, X509Certifica
validTo,
serialNumber);

// EphemeralKeySet is not supported on macOS (requires keychain which writes to disk)
// but is supported on Windows, Linux, iOS/tvOS/MacCatalyst, and Android
var keyStorageFlags = OperatingSystem.IsMacOS()
? X509KeyStorageFlags.Exportable
: X509KeyStorageFlags.Exportable | X509KeyStorageFlags.EphemeralKeySet;
// EphemeralKeySet is only usable on Linux where SslStream is backed by OpenSSL.
// On Windows, Schannel requires the private key to be persisted in a CNG key
// container. On macOS, EphemeralKeySet is not supported (requires keychain).
var keyStorageFlags = OperatingSystem.IsLinux()
? X509KeyStorageFlags.Exportable | X509KeyStorageFlags.EphemeralKeySet
: X509KeyStorageFlags.Exportable;

#pragma warning disable SYSLIB0057 // Type or member is obsolete
var pfx = new X509Certificate2(pfxBytes, (string?)null, keyStorageFlags);
Expand Down
2 changes: 1 addition & 1 deletion src/ReverseProxy/ReverseProxy.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageTags>testing;reverse-proxy;certificates</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.0.0-beta6</Version>
<Version>1.0.0-beta7</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading