能否基于请求体中的值使用Ocelot实现路由?
可以用Ocelot根据请求体值实现路由
Ocelot支持通过自定义路由中间件或扩展路由查找逻辑,实现基于请求体中Token值的动态路由,具体实现方式如下:
1. 自定义路由中间件
编写自定义中间件解析请求体、提取Token,动态指定下游服务地址:
public class RequestBodyRoutingMiddleware { private readonly RequestDelegate _next; public RequestBodyRoutingMiddleware(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { // 开启请求体缓冲,避免后续无法重复读取 context.Request.EnableBuffering(); using var reader = new StreamReader(context.Request.Body, leaveOpen: true); var body = await reader.ReadToEndAsync(); context.Request.Body.Position = 0; // 解析请求体中的Token值 var requestData = JsonSerializer.Deserialize<dynamic>(body); var token = requestData?.Token?.ToString(); // 根据Token设置下游地址 if (token == "1") { context.Items["DownstreamTarget"] = "http://google.com"; } else if (token == "2") { context.Items["DownstreamTarget"] = "http://microsoft.com"; } await _next(context); } } // 扩展方法注册中间件 public static class MiddlewareExtensions { public static IApplicationBuilder UseRequestBodyRouting(this IApplicationBuilder app) { return app.UseMiddleware<RequestBodyRoutingMiddleware>(); } }
注册中间件后,可在Ocelot的后续流程中读取context.Items中的地址,修改路由目标。
2. 扩展Ocelot路由查找逻辑
实现IRouteFinder接口,替换默认路由查找逻辑,加入请求体解析和Token判断:
public class CustomRouteFinder : IRouteFinder { private readonly IRouteFinder _originalFinder; public CustomRouteFinder(IRouteFinder originalFinder) { _originalFinder = originalFinder; } public async Task<RouteFinderResult> Find(HttpContext httpContext) { // 先执行默认路由查找 var result = await _originalFinder.Find(httpContext); if (result.IsError) return result; // 解析请求体Token httpContext.Request.EnableBuffering(); using var reader = new StreamReader(httpContext.Request.Body, leaveOpen: true); var body = await reader.ReadToEndAsync(); httpContext.Request.Body.Position = 0; var requestData = JsonSerializer.Deserialize<dynamic>(body); var token = requestData?.Token?.ToString(); // 根据Token修改下游服务地址 if (token == "1") { result.Route.DownstreamHostAndPorts = new List<DownstreamHostAndPort> { new DownstreamHostAndPort { Host = "google.com", Port = 80 } }; } else if (token == "2") { result.Route.DownstreamHostAndPorts = new List<DownstreamHostAndPort> { new DownstreamHostAndPort { Host = "microsoft.com", Port = 80 } }; } return result; } }
在DI容器中替换默认实现:
services.AddOcelot() .AddSingleton<IRouteFinder, CustomRouteFinder>();
注意事项
- 处理请求体时必须开启缓冲,确保后续中间件能正常读取请求内容
- 需添加异常处理,应对非JSON格式请求体的解析失败场景
- 中间件要注册在Ocelot路由流程之前,才能生效
内容的提问来源于stack exchange,提问作者Szymson
相关产品推荐
相关产品推荐

