Ocelot是啥就不介绍了哈,网关大家都知道,如果大家看过源码会发现其核心就是由一个个的管道中间件组成的,当然这也是Net Core的亮点之一。一个请求到来,会按照中间件的注册顺序进行处理,今天的问题出在Ocelot管道中间件这里,现在有个需求是想要在网关层面对数据进行加密解密,前端会对数据进行加密,通过网关的时候进行解密传递下游,下游返回数据网关进行加密返回给前端。

所以这里就想在走Ocelot管道前后注册两个中间件对请求和结果数据进行处理。然后就按想的去做,但悲催的是,Ocelot处理完后就直接返回数据给调用方了,根本没有走它后面的管道中间件,查资料才知道Ocelot之后不会再调用下一个管道中间件了,这就蛋疼了,怎么办??

突然想到Ocelot应该会提供扩展来让使用者自定义管道中间件吧,回答当然是可以的,本篇我们就来自定义一个管道中间件放在Ocelot中。

首先需要写一个自己的中间件,需要继承OcelotMiddleware:

  1. public class TestResponseMiddleware: OcelotMiddleware
  2. {
  3. private readonly OcelotRequestDelegate _next;
  4. public TestResponseMiddleware(OcelotRequestDelegate next,IOcelotLoggerFactory loggerFactory)
  5. : base(loggerFactory.CreateLogger<TestResponseMiddleware>())
  6. {
  7. _next = next;
  8. }
  9.  
  10. public async Task Invoke(DownstreamContext context)
  11. {
  12. if (!context.IsError && context.HttpContext.Request.Method.ToUpper() != "OPTIONS")
  13. {
  14. //对返回结果进行加密
  15. //Logger.LogInformation("");
  16. if (context.HttpContext.Response != null && context.DownstreamResponse.Content.Headers.ContentLength > )
  17. {
  18. var result= await context.DownstreamResponse.Content.ReadAsStringAsync();
  19. using (var md5 = MD5.Create())
  20. {
  21. var md5Result = md5.ComputeHash(Encoding.ASCII.GetBytes(result));
  22. var strResult = BitConverter.ToString(md5Result);
  23. strResult = strResult.Replace("-", "");
  24. context.HttpContext.Response.Body.Write(Encoding.UTF8.GetBytes(strResult));
  25. }
  26. }
  27. }
  28. else
  29. {
  30. await _next.Invoke(context);
  31. }
  32. }
  33. }

这个逻辑就是拿到请求结果之后对数据进行MD5加密,然后再返回。

然后我们新建一个注册类,创建专门用来注册管道中间件的方法:

  1. public static class TestServiceExtension
  2. {
  3. public static IOcelotPipelineBuilder UseTestResponseMiddleware(this IOcelotPipelineBuilder builder)
  4. {
  5. return builder.UseMiddleware<TestResponseMiddleware>();
  6. }
  7. }

然后就是重点了!!我们需要去翻Ocelot的源码,找到其中注册管道中间件的地方,然后把那个类文件复制过来,放到自己的项目中引用,你可以理解为修改了源码来用。我们首先要看的是OcelotMiddlewareExtensions.cs文件,这里是Ocelot管道中间件的调用入口,不信你看UseOcelot扩展方法:

  1. public static class OcelotMiddlewareExtensions
  2. {
  3. public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder)
  4. {
  5. await builder.UseOcelot(new OcelotPipelineConfiguration());
  6. return builder;
  7. }

我们要看的是这里面的另外一个方法,Ocelot管道的CreateOcelotPipeline:

  1. private static IApplicationBuilder CreateOcelotPipeline(IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
  2. {
  3. var pipelineBuilder = new OcelotPipelineBuilder(builder.ApplicationServices);
  4.  
  5. pipelineBuilder.BuildOcelotPipeline(pipelineConfiguration);
  6.  
  7. var firstDelegate = pipelineBuilder.Build();
  8.  
  9. /*
  10. inject first delegate into first piece of asp.net middleware..maybe not like this
  11. then because we are updating the http context in ocelot it comes out correct for
  12. rest of asp.net..
  13. */
  14.  
  15. builder.Properties["analysis.NextMiddlewareName"] = "TransitionToOcelotMiddleware";
  16.  
  17. builder.Use(async (context, task) =>
  18. {
  19. var downstreamContext = new DownstreamContext(context);
  20. await firstDelegate.Invoke(downstreamContext);
  21. });
  22.  
  23. return builder;
  24. }

可以看到里面 pipelineBuilder.BuildOcelotPipeline(pipelineConfiguration)这句代码,这是Ocelot管道中间件的创建方法,我们要修改的就是这两个地方,这个方法在OcelotPipelineExtensions.cs类文件里,点进去看一下:

  1. public static class OcelotPipelineExtensions
  2. {
  3. public static OcelotRequestDelegate BuildCustomeOcelotPipeline(this IOcelotPipelineBuilder builder,
  4. OcelotPipelineConfiguration pipelineConfiguration)
  5. {
  6. // This is registered to catch any global exceptions that are not handled
  7. // It also sets the Request Id if anything is set globally
  8. builder.UseExceptionHandlerMiddleware();
  9.  
  10. // If the request is for websockets upgrade we fork into a different pipeline
  11. builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
  12. app =>
  13. {
  14. app.UseDownstreamRouteFinderMiddleware();
  15. app.UseDownstreamRequestInitialiser();
  16. app.UseLoadBalancingMiddleware();
  17. app.UseDownstreamUrlCreatorMiddleware();
  18. app.UseWebSocketsProxyMiddleware();
  19. });
  20.  
  21. // Allow the user to respond with absolutely anything they want.
  22. builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware);
  23.  
  24. // This is registered first so it can catch any errors and issue an appropriate response
  25. builder.UseResponderMiddleware();
  26.  
  27. // Then we get the downstream route information
  28. builder.UseDownstreamRouteFinderMiddleware();
  29.  
  30. // This security module, IP whitelist blacklist, extended security mechanism
  31. builder.UseSecurityMiddleware();
  32.  
  33. //Expand other branch pipes
  34. if (pipelineConfiguration.MapWhenOcelotPipeline != null)
  35. {
  36. foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
  37. {
  38. builder.MapWhen(pipeline);
  39. }
  40. }
  41.  
  42. // Now we have the ds route we can transform headers and stuff?
  43. builder.UseHttpHeadersTransformationMiddleware();
  44.  
  45. // Initialises downstream request
  46. builder.UseDownstreamRequestInitialiser();
  47.  
  48. // We check whether the request is ratelimit, and if there is no continue processing
  49. builder.UseRateLimiting();
  50.  
  51. // This adds or updates the request id (initally we try and set this based on global config in the error handling middleware)
  52. // If anything was set at global level and we have a different setting at re route level the global stuff will be overwritten
  53. // This means you can get a scenario where you have a different request id from the first piece of middleware to the request id middleware.
  54. builder.UseRequestIdMiddleware();
  55.  
  56. // Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
  57. builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware);
  58.  
  59. // Now we know where the client is going to go we can authenticate them.
  60. // We allow the ocelot middleware to be overriden by whatever the
  61. // user wants
  62. if (pipelineConfiguration.AuthenticationMiddleware == null)
  63. {
  64. builder.UseAuthenticationMiddleware();
  65. }
  66. else
  67. {
  68. builder.Use(pipelineConfiguration.AuthenticationMiddleware);
  69. }
  70.  
  71. // The next thing we do is look at any claims transforms in case this is important for authorisation
  72. builder.UseClaimsToClaimsMiddleware();
  73.  
  74. // Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
  75. builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);
  76.  
  77. // Now we have authenticated and done any claims transformation we
  78. // can authorise the request
  79. // We allow the ocelot middleware to be overriden by whatever the
  80. // user wants
  81. if (pipelineConfiguration.AuthorisationMiddleware == null)
  82. {
  83. builder.UseAuthorisationMiddleware();
  84. }
  85. else
  86. {
  87. builder.Use(pipelineConfiguration.AuthorisationMiddleware);
  88. }
  89.  
  90. // Now we can run the claims to headers transformation middleware
  91. builder.UseClaimsToHeadersMiddleware();
  92.  
  93. // Allow the user to implement their own query string manipulation logic
  94. builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);
  95.  
  96. // Now we can run any claims to query string transformation middleware
  97. builder.UseClaimsToQueryStringMiddleware();
  98.  
  99. // Get the load balancer for this request
  100. builder.UseLoadBalancingMiddleware();
  101.  
  102. // This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
  103. builder.UseDownstreamUrlCreatorMiddleware();
  104.  
  105. // Not sure if this is the best place for this but we use the downstream url
  106. // as the basis for our cache key.
  107. builder.UseOutputCacheMiddleware();
  108.  
  109. //We fire off the request and set the response on the scoped data repo
  110. builder.UseHttpRequesterMiddleware();
  111.  
  112. //添加自定义测试中间件
  113. builder.UseTestResponseMiddleware();
  114.  
  115. return builder.Build();
  116. }
  117.  
  118. private static void UseIfNotNull(this IOcelotPipelineBuilder builder,
  119. Func<DownstreamContext, Func<Task>, Task> middleware)
  120. {
  121. if (middleware != null)
  122. {
  123. builder.Use(middleware);
  124. }
  125. }
  126. }

我们可以看到其实就是一个个的扩展方法的调用,也是我们所说的中间件,我在最后把刚才写的中间件加了上去,就是标红的那里,现在所有进入Ocelot的请求就都会走我们的中间件处理了,使用的时候需要将修改的OcelotPipelineExtensions.cs类文件放在自己项目里哦。

大功告成!

Ocelot自定义管道中间件的更多相关文章

  1. ASP.NET Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middleware)的方式注册在管道中.显而易见这样的设计非常松耦合 ...

  2. Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...

  3. ocelot 自定义认证和授权

    ocelot 自定义认证和授权 Intro 最近又重新启动了网关项目,服务越来越多,每个服务都有一个地址,这无论是对于前端还是后端开发调试都是比较麻烦的,前端需要定义很多 baseUrl,而后端需要没 ...

  4. 第五节:管道中间件入门(Use、Run、Map)

    一. 简介 1.中间件是一种装配到应用管道以处理请求和响应的组件,每个组件可以选择是否把请求传递到管道中的下一个组件.可在管道中的下一个组件的前后执行工作.请求管道中的每一个组件负责调用管道中的下一个 ...

  5. react+redux教程(七)自定义redux中间件

    今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 ...

  6. [转]Angular2 使用管道Pipe以及自定义管道格式数据

    本文转自:https://www.pocketdigi.com/20170209/1563.html 管道(Pipe)可以根据开发者的意愿将数据格式化,还可以多个管道串联. 纯管道(Pure Pipe ...

  7. DotNetCore学习-3.管道中间件

    中间件是用于组成应用程序管道来处理请求和响应的组件.管道内的每个组件都可以选择是否将请求交给下一个组件,并在管道中调用下一个组件之前和之后执行一些操作. 请求委托被用来建立请求管道,并处理每一个HTT ...

  8. 自定义Django中间件(登录验证中间件实例)

    前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰 ...

  9. angular自定义管道

    原文地址 https://www.jianshu.com/p/5140a91959ca 对自定义管道的认识 管道的定义中体现了几个关键点: 1.管道是一个带有“管道元数据(pipe metadata) ...

随机推荐

  1. SPSS数据分析方法不知道如何选择

      一提到数学,高等数学,线性代数,概率论与数理统计,数值分析,空间解析几何这些数学课程,头疼呀.作为文科生,遇见这些课程时,通常都是各种寻求帮助,班上有位宅男数学很厉害,各种被女生‘围观’,这数学为 ...

  2. Python实现 下载IJCAI会议所有论文

    import requests import threading def get_file_content(num): savepath = '%04d.pdf' % (num) suburl = ' ...

  3. CodeForces 939E Maximize

    Maximize 题意:整个程序有2种操作,操作1将一个元素放入集合S中,且保证最新插入的元素不小于上一次的元素, 操作2 找到集合S中的某个子集合, 使得 集合中最大的元素减去平均数的值最大. 题解 ...

  4. CodeForces 601B Lipshitz Sequence

    Lipshitz Sequence 题解: 可以通过观察得到,对于任意一个区间来说, 只有相邻的2个点的差值才会是区间的最大值. 具体观察方法,可以用数学分析, 我是通过画图得到的. 那么基于上面的观 ...

  5. ZOJ-1610 Count the Colors ( 线段树 )

    题目链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1610 Description Painting some co ...

  6. codeforces 862 C. Mahmoud and Ehab and the xor(构造)

    题目链接:http://codeforces.com/contest/862/problem/C 题解:一道简单的构造题,一般构造题差不多都考自己脑补,脑洞一开就过了 由于数据x只有1e5,但是要求是 ...

  7. Numbers That Count POJ - 1016

    "Kronecker's Knumbers" is a little company that manufactures plastic digits for use in sig ...

  8. 最短路问题---Dijkstra算法学习

    Dijkstra又称单源最短路算法,就从一个节点到其他各点的最短路,解决的是有向图的最短路问题 此算法的特点是:从起始点为中心点向外层层扩展,直到扩展到中终点为止. 该算法的条件是所给图的所有边的权值 ...

  9. HTML5 01. 布局、语义化标签、智能化表单、表单元素/标签/属性/事件、多媒体、类操作、自定义属性

    1.知识点 lang = “en”   所用语言是英文 文档结构更简洁 IE8一下不支持h5c3 书写更宽松 div没有语义 标签语义化:在合适的地方使用合适的标签 对seo优化友谊 网页经典布局 页 ...

  10. Day004_Linux基础命令之特殊符号与正则表达式通配符

    特殊符号: . 点 cd . 表示当前目录 ' '' 单引号,所见即所得 原封不动输出 " ""双引号,里面的特殊符号会被解析运行 `` ====$( ) 先运行() 里 ...