YARP integration
Esta página aún no está disponible en tu idioma.
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
Section titled “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:
aspire add yarpLa CLI de Aspire es interactiva; asegúrate de seleccionar el resultado adecuado cuando se te pida:
Select an integration to add:
> yarp (Aspire.Hosting.Yarp)> Other results listed as selectable options...#:package Aspire.Hosting.Yarp@*<PackageReference Include="Aspire.Hosting.Yarp" Version="*" />Add YARP resource
Section titled “Add YARP resource”In your AppHost, add a YARP resource and configure routes 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 => { yarp.AddRoute(catalogService); yarp.AddRoute("/api/{**catch-all}", basketService); });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const catalogService = await builder.addProject( 'catalogservice', '../CatalogService/CatalogService.csproj');const basketService = await builder.addProject( 'basketservice', '../BasketService/BasketService.csproj');
const gateway = await builder.addYarp('gateway');await gateway.withConfiguration(async (yarp) => { await yarp.addCatchAllRoute(catalogService); await yarp.addRoute('/api/{**catch-all}', basketService);});
await builder.build().run();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.
Programmatic configuration
Section titled “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"); });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const catalogService = await builder.addProject( 'catalogservice', '../CatalogService/CatalogService.csproj');const basketService = await builder.addProject( 'basketservice', '../BasketService/BasketService.csproj');
const gateway = await builder.addYarp('gateway');await gateway.withConfiguration(async (yarp) => { // Add catch-all route for frontend service await yarp.addCatchAllRoute(catalogService);
// Add specific path route with transforms ( await yarp.addRoute('/api/{**catch-all}', basketService) ).withTransformPathRemovePrefix('/api');
// Configure route matching (await yarp.addRoute('/catalog/api/{**catch-all}', catalogService)) .withMatch({ path: '/catalog/api/{**catch-all}', methods: ['GET', 'POST'], }) .withTransformPathRemovePrefix('/catalog');});
await builder.build().run();Route configuration
Section titled “Route configuration”Routes define how incoming requests are matched and forwarded to backend services.
| Scenario | C# | TypeScript |
|---|---|---|
| Catch-all route for a resource | AddRoute(resource) | addCatchAllRoute(resource) |
| Route for a resource | AddRoute(path, resource) | addRoute(path, resource) |
| Route for an external service | AddRoute(path, externalService) | addRoute(path, externalService) |
| Route for an endpoint | AddRoute(path, cluster) | addRoute(path, cluster) |
| Route for a URL destination | AddRoute(path, destination) | addRoute(path, destination) |
TypeScript AppHosts use unified route helpers. Pass any supported target to addRoute(path, target) or addCatchAllRoute(target): a YARP cluster, endpoint, service-discovery resource, external service, or URL string.
await gateway.withConfiguration(async (yarp) => { const httpEndpoint = await catalogService.getEndpoint('http'); const externalApi = await builder.addExternalService( 'external-api', 'https://api.example.com' ); const endpointCluster = await yarp.addClusterFromEndpoint(httpEndpoint);
await yarp.addRoute('/from-cluster/{**catch-all}', endpointCluster); await yarp.addRoute('/from-endpoint/{**catch-all}', httpEndpoint); await yarp.addRoute('/from-resource/{**catch-all}', catalogService); await yarp.addRoute('/from-external/{**catch-all}', externalApi); await yarp.addRoute('/from-url/{**catch-all}', 'https://api.example.net'); await yarp.addCatchAllRoute(catalogService);});Transforms
Section titled “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");(await 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; TypeScript useswithTransformPathRemovePrefix,withTransformPathPrefix, andwithTransformPathSet. - Header transforms:
WithTransformRequestHeader,WithTransformResponseHeader; TypeScript useswithTransformRequestHeaderandwithTransformResponseHeader. - Query transforms:
WithTransformQueryParameter,WithTransformQueryRemoveParameter; TypeScript useswithTransformQueryValue,withTransformQueryRouteValue, andwithTransformQueryRemoveKey. - Custom transforms:
WithTransformorwithTransformfor custom transformation logic.
Customize host port
Section titled “Customize host port”To configure the host port that the YARP resource is exposed on, use the host port API:
var builder = DistributedApplication.CreateBuilder(args);
var gateway = builder.AddYarp("gateway") .WithHostPort(8080) .WithConfiguration(yarp => { // Configure routes... });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const gateway = await builder.addYarp('gateway').withHostPort({ port: 8080 });
await gateway.withConfiguration(async (yarp) => { // Configure routes...});
await builder.build().run();Service discovery integration
Section titled “Service discovery integration”The YARP integration automatically works with 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); });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const catalogService = await builder.addProject( 'catalogservice', '../CatalogService/CatalogService.csproj');
const gateway = await builder.addYarp('gateway');await gateway.withConfiguration(async (yarp) => { // Service discovery automatically resolves catalogservice endpoints await yarp.addRoute('/catalog/{**catch-all}', catalogService);});
await builder.build().run();For external services, use AddExternalService or addExternalService:
var builder = DistributedApplication.CreateBuilder(args);
var externalApi = builder.AddExternalService("external-api") .WithHttpsEndpoint("https://api.example.com");
var gateway = builder.AddYarp("gateway") .WithConfiguration(yarp => { yarp.AddRoute("/external/{**catch-all}", externalApi); });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const externalApi = await builder.addExternalService( 'external-api', 'https://api.example.com');
const gateway = await builder.addYarp('gateway');await gateway.withConfiguration(async (yarp) => { await yarp.addRoute('/external/{**catch-all}', externalApi);});
await builder.build().run();Static file serving
Section titled “Static file serving”YARP can serve static files alongside proxied routes. Use the static files API to enable static file serving:
var builder = DistributedApplication.CreateBuilder(args);
var staticServer = builder.AddYarp("static") .WithStaticFiles("../static");
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const staticServer = await builder.addYarp('static').withStaticFiles();
await builder.build().run();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");
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const frontend = await builder .addYarp('frontend') .withDockerfile('../npmapp') .withStaticFiles();
await builder.build().run();Combining static files with routing
Section titled “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 });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
const apiService = await builder.addProject( 'api', '../ApiService/ApiService.csproj');
const gateway = await builder.addYarp('gateway').withStaticFiles();
await gateway.withConfiguration(async (yarp) => { // API routes take precedence over static files await yarp.addRoute('/api/{**catch-all}', apiService); // Static files are served for all other routes});
await builder.build().run();HTTPS endpoints
Section titled “HTTPS endpoints”When both the YARP gateway and backend services use HTTPS, configure HTTPS endpoints using WithHttpsEndpoint or 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 HTTPSvar razorPages = builder.AddProject<Projects.RazorPagesApp>("razorpages") .WithHttpsEndpoint();
// YARP gateway proxying to the HTTPS backendvar gateway = builder.AddYarp("gateway") .WithHttpsEndpoint() .WithHttpsDeveloperCertificate() .WithConfiguration(yarp => { yarp.AddRoute("/{**catch-all}", razorPages); });
builder.Build().Run();import { createBuilder } from './.modules/aspire.js';
const builder = await createBuilder();
// Backend service with HTTPSconst razorPages = await builder .addProject('razorpages', '../RazorPagesApp/RazorPagesApp.csproj') .withHttpsEndpoint();
// YARP gateway proxying to the HTTPS backendconst gateway = await builder .addYarp('gateway') .withHttpsEndpoint() .withHttpsDeveloperCertificate();
await gateway.withConfiguration(async (yarp) => { await yarp.addRoute('/{**catch-all}', razorPages);});
await builder.build().run();