使用 Ocelot 匹配路由的方法匹配路由

Intro

之前我们在 Ocelot 网关的基础上自定义了一个认证授权的 Ocelot 中间件,根据请求的路径和 Method 进行匹配,找到对应的权限配置,并判断是否可以拥有访问资源的角色,如果没有则返回 401/403,如果有权限则转发到下游服务。

原来的匹配方式是首先根据请求路径和方法完全匹配,如果匹配不到则尝试使用正则匹配。

我们这次要做的就是将原来的正则匹配替换成 Ocelot 內部的路由匹配方式,这样我们在配置的时候就不再需要配置两套了,一边写 Ocelot 路由的配置,一边写权限的配置,这样能减少不少工作量

深入 Ocelot 路由匹配

我们想使用 Ocelot 的路由匹配,首先应该了解 Ocelot 的执行过程,然后找到对应的路由匹配的地方,看路由匹配使用到了哪一个服务,用这个服务在我们自己的业务逻辑里匹配即可。

先来看一下 Ocelot 的服务注册,Ocelot 的服务注册

可以看到主要的服务注册代码应该在 OcelotBuilder 中,查看 OcelotBuilder https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/DependencyInjection/OcelotBuilder.cs

可以看到,Ocelot 的服务注册都在这里, Ocelot 内部好多都是基于接口的,所以需要找对应的实现的话可以看它的服务注册是注册的哪一个服务即可。

简单分析一下,Ocelot 的路由匹配过程一定在寻找下游地址的时候,根据上游的请求信息(直接请求网关的请求)匹配,所以我们首先找到 DownstreamRouteFinderMiddleware https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/DownstreamRouteFinder/Middleware/DownstreamRouteFinderMiddleware.cs

由上面的代码,我们可以看到,下游路由地址是通过 IDownstreamRouteFinder 来找下游路由的,转到对应的实现代码:https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/DownstreamRouteFinder/Finder/DownstreamRouteFinder.cs

这里我们可以看到是通过 IUrlPathToUrlTemplateMatcher 来进行路由匹配的,所以我们需要用到这个服务,然后看这个 Match 方法的参数,前两个参数比较明确,第一个参数是上游请求的地址,第二个参数是请求的 queryString,第三个参数则是 Ocelot 内部构建出来的路由模板信息 UpstreamPathTemplate,然后我们就需要知道怎么构建一个 UpstreamPathTemplate 对象,继续探索

直接看 UpstreamPathTemplate,表示一脸懵逼,不知道怎么构建, 全局搜素了一下,发现有一个 IUpstreamTemplatePatternCreator 里面定义了一个 Create 的方法

这个方法看上去简单了好多,查看 IReRoute 的定义 https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/Configuration/File/IReRoute.cs

我们只需要根据路径模板构建一个 IReRoute 对象即可,Ocelot 中有一个实现了 IReRoute 的类 FileReRoute,但是感觉有些复杂,就没有用,自定义了一个类型实现了 IReRoute

自此,我们就已经找到了要使用 Ocelot 路由匹配所需要的服务了:

  • IUrlPathToUrlTemplateMatcher

  • IUpstreamTemplatePatternCreator

使用 Ocelot 路由匹配

上面提到了我们没有使用 FileReRoute 对象,所以我们就需要自定义一个 IReRoute 对象:

private class FakeReRoute : IReRoute
{public string UpstreamPathTemplate { get; set; }public bool ReRouteIsCaseSensitive { get; set; }public int Priority { get; set; }
}

使用 Ocelot 路由匹配示例:

public class UrlBasedAuthenticationMiddleware : Ocelot.Middleware.OcelotMiddleware
{private readonly GatewayOptions _gatewayOptions;private readonly IMemoryCache _memoryCache;private readonly OcelotRequestDelegate _next;private readonly IUrlPathToUrlTemplateMatcher _urlTemplateMatcher;private readonly IUpstreamTemplatePatternCreator _templatePatternCreator;public UrlBasedAuthenticationMiddleware(OcelotRequestDelegate next, IOptions<GatewayOptions> options, IMemoryCache memoryCache, IOcelotLoggerFactory loggerFactory,IUrlPathToUrlTemplateMatcher urlTemplateMatcher,IUpstreamTemplatePatternCreator templatePatternCreator): base(loggerFactory.CreateLogger<UrlBasedAuthenticationMiddleware>()){_next = next;_gatewayOptions = options.Value;_memoryCache = memoryCache;_urlTemplateMatcher = urlTemplateMatcher;_templatePatternCreator = templatePatternCreator;}public async Task Invoke(DownstreamContext context){var permissions = await _memoryCache.GetOrCreateAsync(_gatewayOptions.ApiPermissionsCacheKey, async entry =>{using (var conn = new SqlConnection(_gatewayOptions.PermissionsConnectionString)){entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);return (await conn.QueryAsync<ApiPermission>(@"")).Select(_ => _.GetViewModel()).ToArray();}});var request = context.HttpContext.Request;var permission = permissions.FirstOrDefault(p =>request.Path.Value.Equals(p.PathPattern, StringComparison.OrdinalIgnoreCase) &&p.Method == request.Method.ToUpper());if (null == permission){permission = permissions.FirstOrDefault(p =>p.Method == request.Method.ToUpper() &&_urlTemplateMatcher.Match(request.Path.Value, request.QueryString.Value,_templatePatternCreator.Create(new FakeReRoute(){UpstreamPathTemplate = p.PathPattern})).Data.Match);}// ...await _next.Invoke(context);}private class FakeReRoute : IReRoute{public string UpstreamPathTemplate { get; set; }public bool ReRouteIsCaseSensitive { get; set; }public int Priority { get; set; }}
}

More

这样,apiPermission 的 Path 配置基本可以使用和 Ocelot 配置一样的路由,可以更方便的配置,避免 996 咯

Reference

  • https://github.com/ThreeMammals/Ocelot

  • https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/DependencyInjection/OcelotBuilder.cs#L95

  • https://github.com/ThreeMammals/Ocelot/blob/13.5.2/src/Ocelot/DownstreamRouteFinder/UrlMatcher/IUrlPathToUrlTemplateMatcher.cs

使用 Ocelot 匹配路由的方法匹配路由相关推荐

  1. vue-router详尽:编程式导航、路由重定向、动态路由匹配、路由别名、嵌套路由、命名视图

    vue-router编程式导航 在vue项目中经常用到this.$router.push() 和 this.$router.replace() 方法进行路由跳转就是编程式导航... 通俗理解编程式导航 ...

  2. python中RabbitMQ的使用(路由键模糊匹配)

    路由键模糊匹配 使用正则表达式进行匹配.其中"#"表示所有.全部的意思:"*"只匹配到一个词. 匹配规则: 路由键:routings = [ 'happy.wo ...

  3. linux服务器怎么添加路由,linux系统中添加路由的方法

    linux系统中添加路由的方法 发布时间:2020-06-17 11:38:59 来源:亿速云 阅读:95 作者:Leah 这篇文章将为大家详细讲解有关linux系统中添加路由的方法,小编觉得挺实用的 ...

  4. IP路由基础、路由器静态路由配置方法、自治系统、缺省路由的配置方法、路由选路规则、缺省路由、备份路由、等价路由、三种查询路由表命令

    目录 路由器特点: 网络IP地址规划 网络间的特性: 基本路由思想: ​编辑 静态路由部分: 查询设备整个路由表: 查看特定的路由协议时使用: 查询目的地址2.2.2.2的路由条目: IP路由表代码写 ...

  5. linux下添加路由的方法

    Linux中增加软路由的两种方法 第一种: route add -net 172.16.6.0 netmask 255.255.255.0 gw 172.16.2.254 dev eth0 /* 增加 ...

  6. 关于Java重载方法匹配优先级

    2019独角兽企业重金招聘Python工程师标准>>> 写出以下程序的输出: public class Overload {// Object 参数public static voi ...

  7. xpath的数据和节点类型以及XPath中节点匹配的基本方法

    XPath数据类型  XPath可分为四种数据类型:  节点集(node-set)  节点集是通过路径匹配返回的符合条件的一组节点的集合.其它类型的数据不能转换为节点集.  布尔值(boolean)  ...

  8. 搜索引擎solr系列---多字段匹配的实现方法

    https://blog.csdn.net/wohaqiyi/article/details/78402262 solr可以实现多字段匹配查询的结果,即传入一个条件,可以按照你预选设置好的匹配范围去匹 ...

  9. Spring-AOP 静态正则表达式方法匹配切面

    文章目录 概述 实例 正则表达式语法 正则表达式工具 RegexBuddy 概述 在Spring-AOP 静态普通方法名匹配切面案例中 StaticMethodMatcherPointcutAdvis ...

最新文章

  1. java和内存交互,java内存模型-内存间交互操作
  2. wpf每隔一小时_包河区徐河排涝站24小时不间断运作 11座区管泵站全面应战保安澜...
  3. java飞行器服务端_使用jvisualvm和飞行记录器分析Java程序cpu占用率过高
  4. nginx 502错误 upstream sent too big header while reading response header from upstream
  5. WIFI配置专项测试
  6. 简单的 密文认证方式
  7. OS- -I/O之I/O软件原理及层次结构
  8. IE下及标准浏览器下的图片旋转(二)—— Canvas(2)
  9. Centos7选定默认启动的内核版本
  10. 用户'sa'登录失败(错误18456)解决方案图解
  11. Modbus调试软件--ModbusPoll、ModbusSlave使用详解
  12. tornado总结4-html模板使用2
  13. open读取文件操作
  14. 三级数据库知识点总结
  15. 使用Canvas合成多张图片和文字为一张图片
  16. 如何使用计算机求和公式,excel求和公式怎么用
  17. 是时候搞清楚煎饼大妈的真实收入了!来看看专业的研究流程
  18. 用Python写个「倒计时」软件
  19. 2021大三学习机器学习课程手杖之机器学习基本概念的理解
  20. 告白气球,这个情人节你值得拥有!

热门文章

  1. 周报_2013第03周(2013/01/13-2013/01/19)
  2. msdn中C#中常用词汇概念(转帖)
  3. php图片地址参数错误,图片上传时一直显示请求地址错误怎么办
  4. audacity_如何在Audacity中快速编辑多个文件
  5. 在Linux上运行Windows软件的4种以上方法
  6. [There will be more story......]
  7. 关于一个js栈溢出的异常
  8. Asymptote 学习记录(2):例子阅读
  9. [BOOST] BOOST::Format
  10. poj-2029 Get Many Persimmon Trees