You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET反向代理下Url.Link()返回错误主机/端口的解决求助

解决方案

1. 自定义消息处理器修改请求Uri

ASP.NET Web API的Url.Link()依赖HttpRequestMessage的RequestUri生成URL,而非HttpContext的请求信息。需要编写自定义消息处理器,读取反向代理传递的X-Forwarded-Host头来修正请求Uri:

public class ForwardedHeadersHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.Headers.TryGetValues("X-Forwarded-Host", out var forwardedHosts))
        {
            var forwardedHost = forwardedHosts.FirstOrDefault();
            if (!string.IsNullOrEmpty(forwardedHost))
            {
                var uriBuilder = new UriBuilder(request.RequestUri);
                // 拆分主机和端口(处理Ingress可能传递的带端口/不带端口情况)
                var hostParts = forwardedHost.Split(':');
                uriBuilder.Host = hostParts[0];
                
                if (hostParts.Length > 1)
                {
                    uriBuilder.Port = int.Parse(hostParts[1]);
                }
                else
                {
                    // 根据协议自动设置默认端口
                    uriBuilder.Port = uriBuilder.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) ? 443 : 80;
                }
                
                request.RequestUri = uriBuilder.Uri;
            }
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

在WebApiConfig.cs中注册该处理器:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // 注册转发头处理器
        config.MessageHandlers.Add(new ForwardedHeadersHandler());
        
        // 其他Web API配置
        config.MapHttpAttributeRoutes();
        // ...
    }
}

2. 确保反向代理正确传递转发头

Nginx配置补充

除了X-Forwarded-Host,还需传递协议头保证URL使用正确的http/https:

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;

YARP配置补充

在YARP的配置文件中明确设置转发头:

"ReverseProxy": {
  "Routes": {
    "oldApiRoute": {
      "ClusterId": "oldApiCluster",
      "Match": {
        "Path": "/oldapi/{**catch-all}"
      }
    }
  },
  "Clusters": {
    "oldApiCluster": {
      "Destinations": {
        "oldApi": {
          "Address": "http://localhost:12345"
        }
      },
      "HttpRequest": {
        "Headers": {
          "X-Forwarded-Host": "{Request.Host}",
          "X-Forwarded-Proto": "{Request.Scheme}"
        }
      }
    }
  }
}

3. 手动修正URL生成(备选方案)

如果自定义处理器仍有问题,可手动指定主机生成URL:

var routeValues = new { controller = "YourController", action = "TargetAction" };
var baseUri = new UriBuilder(Request.RequestUri)
{
    Host = "your-production-domain.com",
    Port = 443,
    Scheme = "https"
}.Uri;
var fullUrl = new Uri(baseUri, Url.Link("DefaultApi", routeValues)).ToString();

4. 检查CORS配置

确保旧应用的CORS策略允许客户端实际域名,而非仅带端口的本地地址:

config.EnableCors(new EnableCorsAttribute("https://your-client-domain.com", "*", "*"));
之前方案无效的原因
  • 修改HttpContext.Current.Request.ServerVariables["HTTP_HOST"]仅影响System.Web的HttpRequest对象,但Web API的Url.Link()依赖独立的HttpRequestMessage.RequestUri,因此不会生效。
  • 仅设置X-Forwarded-Host但未在Web API中处理该头,框架默认不会自动替换请求Uri,必须通过自定义处理器主动解析修改。

内容的提问来源于stack exchange,提问作者Melted Away

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:10:06