YARP中多路由指向同一目标地址的实现及路径前缀移除方案
在YARP中实现多路由复用转发逻辑及优雅移除路径前缀
一、复用转发逻辑处理多路由
你可以通过两种方式避免重复代码,实现多个路由指向同一转发逻辑:
方式1:封装转发逻辑为独立委托
先把重复的转发逻辑抽成单独的RequestDelegate实例,再给多个路由绑定该实例:
// 封装通用转发逻辑 var googleMapsForward = new RequestDelegate(async httpContext => { var error = await forwarder.SendAsync(httpContext, "https://maps.googleapis.com/maps/api/", httpClient, requestConfig, transformer); if (error != ForwarderError.None) { var errorFeature = httpContext.GetForwarderErrorFeature(); var exception = errorFeature.Exception; // 可在此添加异常处理逻辑 } }); // 给多个路由绑定同一个转发逻辑 endpoints.Map("/place/{**catch-all}", googleMapsForward); endpoints.Map("/geocode/{**catch-all}", googleMapsForward);
方式2:用正则路由模板匹配多路径
如果路径规则统一,直接使用路由模板的正则约束,一次注册即可匹配多个目标路径:
// 同时匹配/place/xxx和/geocode/xxx格式的所有请求 endpoints.Map("/{segment:regex(place|geocode)}/{**catch-all}", async httpContext => { var error = await forwarder.SendAsync(httpContext, "https://maps.googleapis.com/maps/api/", httpClient, requestConfig, transformer); if (error != ForwarderError.None) { var errorFeature = httpContext.GetForwarderErrorFeature(); var exception = errorFeature.Exception; // 异常处理逻辑 } });
二、优雅移除路径前缀(如/proxyme/)
当请求带有前置前缀(例如/proxyme/place/xxx),无需手动字符串切割,可通过以下两种优雅方式处理:
方式1:自定义Transformer实现前缀剥离
在自定义的HttpTransformer中,利用ASP.NET Core内置的PathString.StartsWithSegments方法处理:
public class CustomPrefixTransformer : HttpTransformer { public override async ValueTask TransformRequestAsync(HttpContext httpContext, HttpRequestMessage proxyRequest, string destinationPrefix) { // 先执行默认转换逻辑 await base.TransformRequestAsync(httpContext, proxyRequest, destinationPrefix); // 定义需要移除的前缀 var targetPrefix = "/proxyme"; if (httpContext.Request.Path.StartsWithSegments(targetPrefix, out var remainingPath)) { // 更新当前请求路径 httpContext.Request.Path = remainingPath; // 更新代理请求的目标Uri proxyRequest.RequestUri = new Uri(destinationPrefix + remainingPath); } } }
方式2:利用YARP内置转换配置
注册转发时,直接通过AddTransforms配置前缀移除规则:
var requestConfig = new ForwarderRequestConfig(); // 添加路径转换规则:自动移除/proxyme前缀 requestConfig.AddTransforms(transforms => { transforms.AddPathRemovePrefix("/proxyme"); }); // 绑定带前缀的路由并使用该配置 endpoints.Map("/proxyme/{segment:regex(place|geocode)}/{**catch-all}", async httpContext => { var error = await forwarder.SendAsync(httpContext, "https://maps.googleapis.com/maps/api/", httpClient, requestConfig, transformer); // 异常处理逻辑 });
内容的提问来源于stack exchange,提问作者BeniaminoBaggins
相关产品推荐
相关产品推荐

