.NET Core如何将不同子域名请求转发到不同本地端口?
在.NET Core中实现子域名转发到不同本地端口的方案
不管是自定义中间件还是YARP都能实现这个需求,YARP其实支持基于主机头的路由规则,可能是你没找对配置方式。下面给两种可行的实现方案:
一、自定义中间件实现
如果想自己控制转发逻辑,可以写个简单的中间件:
- 先创建中间件类,解析请求的子域名,匹配对应的目标端口:
public class SubdomainProxyMiddleware { private readonly RequestDelegate _next; private readonly HttpClient _httpClient; public SubdomainProxyMiddleware(RequestDelegate next, HttpClient httpClient) { _next = next; _httpClient = httpClient; } public async Task InvokeAsync(HttpContext context) { var host = context.Request.Host.Host; string targetBaseUrl = host switch { "app1.localhost" => "http://localhost:5001", "app2.localhost" => "http://localhost:5002", // 可添加更多子域名映射 _ => null }; if (targetBaseUrl != null) { // 拼接目标URL,保留原请求的路径和查询参数 var targetUrl = new Uri(new Uri(targetBaseUrl), context.Request.Path + context.Request.QueryString); // 构建转发请求 var requestMessage = new HttpRequestMessage(new HttpMethod(context.Request.Method), targetUrl); // 复制原请求的所有头信息 foreach (var header in context.Request.Headers) { if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null) { requestMessage.Content.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()); } } // 发送请求并获取响应 var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted); // 将响应状态码和头信息回写给客户端 context.Response.StatusCode = (int)responseMessage.StatusCode; foreach (var header in responseMessage.Headers) { context.Response.Headers.TryAdd(header.Key, header.Value.ToArray()); } foreach (var header in responseMessage.Content.Headers) { context.Response.Headers.TryAdd(header.Key, header.Value.ToArray()); } // 复制响应内容到客户端 await responseMessage.Content.CopyToAsync(context.Response.Body); return; } // 未匹配到子域名,继续执行后续中间件逻辑 await _next(context); } }
- 在
Program.cs中注册中间件和HttpClient:
var builder = WebApplication.CreateBuilder(args); // 注册HttpClient供中间件使用 builder.Services.AddHttpClient<SubdomainProxyMiddleware>(); var app = builder.Build(); // 启用自定义代理中间件 app.UseMiddleware<SubdomainProxyMiddleware>(); app.Run();
二、用YARP实现(更推荐生产环境)
YARP完全支持基于主机头的路由,只需简单配置即可:
- 先安装YARP包:
dotnet add package Yarp.ReverseProxy
- 在
appsettings.json中配置路由和集群,指定不同子域名对应不同本地端口:
{ "ReverseProxy": { "Routes": { "app1_route": { "ClusterId": "app1_cluster", "Match": { "Hosts": [ "app1.localhost" ] } }, "app2_route": { "ClusterId": "app2_cluster", "Match": { "Hosts": [ "app2.localhost" ] } } }, "Clusters": { "app1_cluster": { "Destinations": { "app1": { "Address": "http://localhost:5001/" } } }, "app2_cluster": { "Destinations": { "app2": { "Address": "http://localhost:5002/" } } } } } }
- 在
Program.cs中启用YARP:
var builder = WebApplication.CreateBuilder(args); // 添加YARP服务并加载配置 builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); var app = builder.Build(); // 映射反向代理路由 app.MapReverseProxy(); app.Run();
本地测试必做配置
不管用哪种方案,本地测试时都需要修改hosts文件(Windows路径:C:\Windows\System32\drivers\etc\hosts;Linux/macOS路径:/etc/hosts),添加如下映射:
127.0.0.1 app1.localhost app2.localhost
这样本地才能正常解析这些子域名。
内容的提问来源于stack exchange,提问作者gartenkralle
相关产品推荐
相关产品推荐

