YARP integration
YARP (Yet Another Reverse Proxy) is a toolkit for building fast and customizable reverse proxies using .NET. The Aspire YARP integration enables you to add reverse proxy capabilities to your distributed applications.
Hosting integration
The YARP hosting integration models a YARP resource as the YarpResource type. To access this type and APIs, add the 📦 Aspire.Hosting.Yarp NuGet package in your AppHost project:
dotnet add package Aspire.Hosting.YarpAdd YARP resource
In your AppHost project, call AddYarp on the builder instance to add a YARP resource:
var builder = DistributedApplication.CreateBuilder(args);
var catalogService = builder.AddProject<Projects.CatalogService>("catalogservice");
var basketService = builder.AddProject<Projects.BasketService>("basketservice");
var gateway = builder.AddYarp("gateway")
.WithConfiguration(yarp =>
{
// Configure routes programmatically
yarp.AddRoute(catalogService);
yarp.AddRoute("/api/{**catch-all}", basketService);
});
When Aspire adds a YARP resource to the AppHost, it creates a new containerized YARP instance using the mcr.microsoft.com/dotnet/nightly/yarp container image.
Caution
Starting with Aspire 9.4, the WithConfigFile method has been removed. YARP
configuration is now done exclusively through code-based configuration using
the WithConfiguration method. This provides better IntelliSense support,
type safety, and works seamlessly with deployment scenarios.
Programmatic configuration
The YARP integration provides a fluent API for configuring routes, clusters, and transforms programmatically:
var builder = DistributedApplication.CreateBuilder(args);
var catalogService = builder.AddProject<Projects.CatalogService>("catalogservice");
var basketService = builder.AddProject<Projects.BasketService>("basketservice");
var gateway = builder.AddYarp("gateway")
.WithConfiguration(yarp =>
{
// Add catch-all route for frontend service
yarp.AddRoute(catalogService);
// Add specific path route with transforms
yarp.AddRoute("/api/{**catch-all}", basketService)
.WithTransformPathRemovePrefix("/api");
// Configure route matching
yarp.AddRoute("/catalog/api/{**catch-all}", catalogService)
.WithMatchMethods("GET", "POST")
.WithTransformPathRemovePrefix("/catalog");
});
Route configuration
Routes define how incoming requests are matched and forwarded to backend services:
AddRoute(resource)- Creates a catch-all route for the specified resourceAddRoute(path, resource)- Creates a route with a specific path patternAddRoute(path, externalService)- Creates a route targeting an external service
Transforms
Transforms modify requests and responses as they pass through the proxy:
yarp.AddRoute("/api/{**catch-all}", basketService)
.WithTransformPathRemovePrefix("/api")
.WithTransformPathPrefix("/v1")
.WithTransformRequestHeader("X-Forwarded-Host", "gateway.example.com")
.WithTransformResponseHeader("X-Powered-By", "YARP");
Common transform methods include:
- Path transforms:
WithTransformPathRemovePrefix,WithTransformPathPrefix,WithTransformPathSet - Header transforms:
WithTransformRequestHeader,WithTransformResponseHeader - Query transforms:
WithTransformQueryParameter,WithTransformQueryRemoveParameter - Custom transforms:
WithTransformfor custom transformation logic
Customize host port
To configure the host port that the YARP resource is exposed on, use the WithHostPort method:
var builder = DistributedApplication.CreateBuilder(args);
var gateway = builder.AddYarp("gateway")
.WithHostPort(8080)
.WithConfiguration(yarp =>
{
// Configure routes...
});
Service discovery integration
The YARP integration automatically works with .NET service discovery when targeting resources:
var builder = DistributedApplication.CreateBuilder(args);
var catalogService = builder.AddProject<Projects.CatalogService>("catalogservice");
var gateway = builder.AddYarp("gateway")
.WithConfiguration(yarp =>
{
// Service discovery automatically resolves catalogservice endpoints
yarp.AddRoute("/catalog/{**catch-all}", catalogService);
});
For external services, use AddExternalService:
var externalApi = builder.AddExternalService("external-api")
.WithHttpsEndpoint("https://api.example.com");
var gateway = builder.AddYarp("gateway")
.WithConfiguration(yarp =>
{
yarp.AddRoute("/external/{**catch-all}", externalApi);
});
Static file serving
YARP can serve static files alongside proxied routes. Use the WithStaticFiles method to copy files from a local directory:
var builder = DistributedApplication.CreateBuilder(args);
var staticServer = builder.AddYarp("static")
.WithStaticFiles("../static");
For building frontend applications, you can use a Docker multi-stage build:
var builder = DistributedApplication.CreateBuilder(args);
var frontend = builder.AddYarp("frontend")
.WithStaticFiles()
.WithDockerfile("../npmapp");
Combining static files with routing
You can combine static file serving with dynamic routing:
var builder = DistributedApplication.CreateBuilder(args);
var apiService = builder.AddProject<Projects.ApiService>("api");
var gateway = builder.AddYarp("gateway")
.WithStaticFiles("../webapp/dist")
.WithConfiguration(yarp =>
{
// API routes take precedence over static files
yarp.AddRoute("/api/{**catch-all}", apiService);
// Static files are served for all other routes
});
HTTPS endpoints
When both the YARP gateway and backend services use HTTPS, configure HTTPS endpoints using WithHttpsEndpoint and the developer certificate. YARP can proxy HTTPS-to-HTTPS when the backend service exposes an HTTPS endpoint:
var builder = DistributedApplication.CreateBuilder(args);
// Backend service with HTTPS
var razorPages = builder.AddProject<Projects.RazorPagesApp>("razorpages")
.WithHttpsEndpoint();
// YARP gateway proxying to the HTTPS backend
var gateway = builder.AddYarp("gateway")
.WithHttpsEndpoint()
.WithHttpsDeveloperCertificate()
.WithConfiguration(yarp =>
{
yarp.AddRoute("/{**catch-all}", razorPages);
});
// After adding all resources, run the app...
Note
When using HTTPS with YARP, ensure that the developer certificate is trusted on your machine. Run dotnet dev-certs https --trust if you see certificate validation errors.