使用YARP从MapForwarder切换到MapReverseProxy的重定向异常问题
核心原因
AllowAutoRedirect=false时域名跳转问题
YARP的MapReverseProxy默认不会修改后端响应的Location头。当遗留ASP.NET MVC应用返回重定向到foo.com/account/login的响应时,YARP直接转发这个响应给浏览器,导致浏览器跳转到foo域名,而非期望的bar域名。而MapForwarder作为轻量转发组件,默认内置了重定向Host的替换逻辑,所以之前能正常工作。AllowAutoRedirect=true时路径丢失问题
开启自动跳转后,YARP会内部跟随foo.com的重定向请求,直接把foo.com/account/login的内容返回给浏览器,但不会通知浏览器更新地址栏路径——因为这是代理侧的内部跳转,浏览器感知不到,所以地址栏仍停留在bar.com,而非bar.com/account/login。
解决方案
要实现和MapForwarder一致的效果,需要给YARP配置重定向响应转换规则,让它自动把响应中Location头的foo域名替换为bar域名,同时保留路径和查询参数。
方式1:通过配置文件实现
在appsettings.json的ReverseProxy配置中添加ResponseHeaderLocation转换:
{ "ReverseProxy": { "Routes": { "legacyAppRoute": { "ClusterId": "legacyFooCluster", "Match": { "Path": "{**catch-all}" }, "Transforms": [ // 保留原始请求的Host头传递给后端 { "RequestHeaderOriginalHost": "true" }, // 替换响应Location头的Host为bar.com { "ResponseHeaderLocation": { "Host": "bar.com" } } ] } }, "Clusters": { "legacyFooCluster": { "Destinations": { "fooApp": { "Address": "https://foo.com/" } } } } } }
方式2:通过代码自定义转换
如果需要更灵活的逻辑(比如动态替换域名),可以添加自定义转换提供者:
var builder = WebApplication.CreateBuilder(args); // 添加YARP并加载配置 builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")) .AddTransforms<RedirectHostTransformProvider>(); var app = builder.Build(); app.MapReverseProxy(); app.Run(); // 自定义重定向Host转换提供者 public class RedirectHostTransformProvider : ITransformProvider { public void Apply(TransformBuilderContext context) { context.AddResponseTransform(async transformContext => { // 处理所有3xx重定向响应 if (transformContext.HttpContext.Response.StatusCode is >= 300 and < 400) { var locationHeader = transformContext.HttpContext.Response.Headers.Location.ToString(); if (!string.IsNullOrWhiteSpace(locationHeader)) { // 替换foo.com为bar.com,保留路径和参数 var updatedLocation = locationHeader.Replace("https://foo.com", "https://bar.com"); transformContext.HttpContext.Response.Headers.Location = updatedLocation; } } }); } }
最终配置建议
- 设置
handler.AllowAutoRedirect=false(关闭代理侧的自动跳转) - 启用上述重定向转换规则
这样浏览器会收到指向bar.com/account/login的重定向响应,地址栏更新为该路径,同时YARP将这个请求转发到foo.com/account/login,完全复刻之前MapForwarder的行为。
内容的提问来源于stack exchange,提问作者Yehor Androsov

