Watch Aspire live streamsDocumentaciónPrueba Aspire
Watch Aspire live streamsDocumentaciónProbar

YARP integration

Esta página aún no está disponible en tu idioma.

YARP logo

This article is the reference for the Aspire YARP Hosting integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.mts — that you use to model a YARP (Yet Another Reverse Proxy) resource in your AppHost project.

The YARP hosting integration models a YARP resource as the YarpResource type. To access this type and APIs, install the 📦 Aspire.Hosting.Yarp NuGet package in your AppHost project:

Terminal
aspire add yarp

This updates your aspire.config.json with the YARP hosting integration package:

aspire.config.json
{
"packages": {
"Aspire.Hosting.Yarp": "*"
}
}

In your AppHost, add a YARP resource and configure routes programmatically:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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.

Tags reflect the latest defaults on the microsoft/aspire main branch, and may be newer than the version pinned by the package you install.

The YARP integration provides a fluent API for configuring routes, clusters, and transforms programmatically:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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();

Routes define how incoming requests are matched and forwarded to backend services.

ScenarioC#TypeScript
Catch-all route for a resourceAddRoute(resource)addCatchAllRoute(resource)
Route for a resourceAddRoute(path, resource)addRoute(path, resource)
Route for an external serviceAddRoute(path, externalService)addRoute(path, externalService)
Route for an endpointAddRoute(path, cluster)addRoute(path, cluster)
Route for a URL destinationAddRoute(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.

apphost.mts
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 modify requests and responses as they pass through the proxy:

apphost.mts
(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 uses withTransformPathRemovePrefix, withTransformPathPrefix, and withTransformPathSet.
  • Header transforms: WithTransformRequestHeader, WithTransformResponseHeader; TypeScript uses withTransformRequestHeader and withTransformResponseHeader.
  • Query transforms: WithTransformQueryParameter, WithTransformQueryRemoveParameter; TypeScript uses withTransformQueryValue, withTransformQueryRouteValue, and withTransformQueryRemoveKey.
  • Custom transforms: WithTransform or withTransform for custom transformation logic.

To configure the host port that the YARP resource is exposed on, use the host port API:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const gateway = await builder.addYarp('gateway').withHostPort({ port: 8080 });
await gateway.withConfiguration(async (yarp) => {
// Configure routes...
});
await builder.build().run();

The YARP integration automatically works with service discovery when targeting resources:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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();

YARP can serve static files alongside proxied routes. Use the static files API to enable static file serving:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const frontend = await builder
.addYarp('frontend')
.withDockerfile('../npmapp')
.withStaticFiles();
await builder.build().run();

You can combine static file serving with dynamic routing:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
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();

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:

apphost.mts
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// Backend service with HTTPS
const razorPages = await builder
.addProject('razorpages', '../RazorPagesApp/RazorPagesApp.csproj')
.withHttpsEndpoint();
// YARP gateway proxying to the HTTPS backend
const gateway = await builder
.addYarp('gateway')
.withHttpsEndpoint()
.withHttpsDeveloperCertificate();
await gateway.withConfiguration(async (yarp) => {
await yarp.addRoute('/{**catch-all}', razorPages);
});
await builder.build().run();