With YARP(Yet-Another-Reverse-Proxy) you can transform your ASP.NET Core application into a reverse proxy.
It offers features like routing, discovery, load balancing, retries,... However in the application I'm building that is a lot more then what I need. I only need the ability to take a specific request and forward it to a specific destination. In that case you can use Direct Forwarding through the IHttpForwarder.
IHttpForwarder supports:
- Dynamic destination selection, you specify the destination for each request
- Http client customization, you provide the HttpMessageInvoker
- Request and response customization (except bodies)
- Streaming protocols like gRPC and WebSockets
- Error handling
It does not include:
- Routing
- Load balancing
- Affinity
- Retries
Direct forwarding in .NET 6 and beyond
You can find an example of Direct Forwarding in the documentation. However this documentation is written for .NET 5 still using the Startup.cs
class.
Let me share an example on how to achieve the same thing in .NET 6:
using System.Diagnostics; | |
using System.Net; | |
using Yarp.ReverseProxy.Forwarder; | |
var builder = WebApplication.CreateBuilder(args); | |
var targetUrl = builder.Configuration.GetValue<string>("targetUrl"); | |
builder.Services.AddHttpForwarder(); | |
var app = builder.Build(); | |
app.UseRouting(); | |
//Always use HttpMessageInvoker rather than HttpClient, HttpClient buffers responses by default. | |
//Buffering breaks streaming scenarios and increases memory usage and latency. | |
var httpClient = new HttpMessageInvoker(new SocketsHttpHandler() | |
{ | |
UseProxy = false, | |
AllowAutoRedirect = false, | |
AutomaticDecompression = DecompressionMethods.None, | |
UseCookies = false, | |
ActivityHeadersPropagator = new ReverseProxyPropagator(DistributedContextPropagator.Current) | |
}); | |
var requestConfig = new ForwarderRequestConfig { ActivityTimeout = TimeSpan.FromSeconds(100) }; | |
app.Map("/{**catch-all}", async (HttpContext httpContext, IHttpForwarder forwarder) => { | |
var error = await forwarder.SendAsync(httpContext, targetUrl, httpClient, requestConfig); | |
// Check if the operation was successful | |
if (error != ForwarderError.None) | |
{ | |
var errorFeature = httpContext.GetForwarderErrorFeature(); | |
var exception = errorFeature.Exception; | |
//TODO: Log exception | |
} | |
}); | |
app.Run(); |
You can find the complete example here: https://github.com/wullemsb/YarpDirectForwarding