使用YARP简单转发功能时,如何自动添加X-Forwarded请求头?
YARP简单转发场景下自动添加X-Forwarded请求头的最佳方案
我正在使用YARP的IHttpForwarder将请求反向代理到上游服务,仅需替换传入请求的主机名和部分路径后转发。但由于没有使用完整的反向代理中间件(比如UseReverseProxy()),无法直接使用内置的X-Forwarded请求头自动添加功能。当前示例代码如下:
ForwarderRequestConfig requestOptions = new(){ ActivityTimeout = TimeSpan.FromSeconds(100) }; app.UseRouting(); app.Map( "/test/{**catch-all}", async (HttpContext httpContext, IHttpForwarder forwarder) => { var error = await forwarder.SendAsync( httpContext, "http://localhost:5001", httpClient, requestOptions, static (context, proxyRequest) => { var queryContext = new QueryTransformContext(context.Request); var transformedPath = context.Request.Path; if (transformedPath.StartsWithSegments("/test", remaining: out var remaining)) { transformedPath = remaining; } proxyRequest.RequestUri = RequestUtilities.MakeDestinationAddress( "http://localhost:5001", transformedPath, queryContext.QueryString); proxyRequest.Headers.Host = null; return default; }); if (error != ForwarderError.None) { var errorFeature = httpContext.Features.Get<IForwarderErrorFeature>(); var exception = errorFeature.Exception; // TODO } });
我希望能通过类似request.AddXForwarded();的扩展方法,让YARP自动添加正确的X-Forwarded系列请求头并完成必要验证,而不是手动编写头信息。请问使用YARP实现此需求的最佳方案是什么?
解决方案
YARP内置了专门处理X-Forwarded头的工具类ForwardedHeadersUtilities,可以直接在请求转换委托中调用其方法来实现自动添加与验证,无需手动拼接头信息。
1. 引入必要命名空间
确保代码顶部添加:
using Yarp.ReverseProxy.Forwarder;
2. 修改请求转换逻辑
在请求转换的委托中,调用ForwardedHeadersUtilities.AddXForwardedHeaders方法,该方法会自动处理X-Forwarded-For、X-Forwarded-Proto、X-Forwarded-Host等标准头,同时完成重复头处理、IP验证等逻辑。
修改后的完整代码示例:
using Yarp.ReverseProxy.Forwarder; var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpForwarder(); builder.Services.AddHttpClient(); var app = builder.Build(); ForwarderRequestConfig requestOptions = new() { ActivityTimeout = TimeSpan.FromSeconds(100) }; app.UseRouting(); app.Map( "/test/{**catch-all}", async (HttpContext httpContext, IHttpForwarder forwarder, IHttpClientFactory httpClientFactory) => { var httpClient = httpClientFactory.CreateClient(); var error = await forwarder.SendAsync( httpContext, "http://localhost:5001", httpClient, requestOptions, static (context, proxyRequest) => { var queryContext = new QueryTransformContext(context.Request); var transformedPath = context.Request.Path; if (transformedPath.StartsWithSegments("/test", remaining: out var remaining)) { transformedPath = remaining; } proxyRequest.RequestUri = RequestUtilities.MakeDestinationAddress( "http://localhost:5001", transformedPath, queryContext.QueryString); proxyRequest.Headers.Host = null; // 调用YARP内置方法自动添加X-Forwarded系列请求头 ForwardedHeadersUtilities.AddXForwardedHeaders(context, proxyRequest); return default; }); if (error != ForwarderError.None) { var errorFeature = httpContext.Features.Get<IForwarderErrorFeature>(); var exception = errorFeature?.Exception; // 示例错误处理 httpContext.Response.StatusCode = StatusCodes.Status502BadGateway; await httpContext.Response.WriteAsync($"Proxy error: {exception?.Message ?? "Unknown error"}"); } }); app.Run();
3. 自定义配置(可选)
如果需要调整头的生成规则(比如修改头名称、限制允许的代理IP),可以使用重载方法传入ForwardedHeadersOptions参数:
var forwardedOptions = new ForwardedHeadersOptions { ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All, // 添加信任的代理IP,避免伪造的X-Forwarded头 KnownProxies = { IPAddress.Parse("192.168.1.100") } }; ForwardedHeadersUtilities.AddXForwardedHeaders(context, proxyRequest, forwardedOptions);
内容的提问来源于stack exchange,提问作者Rob L
相关产品推荐
相关产品推荐

