Ocelot自定义管道中间件
Ocelot是啥就不介绍了哈,网关大家都知道,如果大家看过源码会发现其核心就是由一个个的管道中间件组成的,当然这也是Net Core的亮点之一。一个请求到来,会按照中间件的注册顺序进行处理,今天的问题出在Ocelot管道中间件这里,现在有个需求是想要在网关层面对数据进行加密解密,前端会对数据进行加密,通过网关的时候进行解密传递下游,下游返回数据网关进行加密返回给前端。
所以这里就想在走Ocelot管道前后注册两个中间件对请求和结果数据进行处理。然后就按想的去做,但悲催的是,Ocelot处理完后就直接返回数据给调用方了,根本没有走它后面的管道中间件,查资料才知道Ocelot之后不会再调用下一个管道中间件了,这就蛋疼了,怎么办??
突然想到Ocelot应该会提供扩展来让使用者自定义管道中间件吧,回答当然是可以的,本篇我们就来自定义一个管道中间件放在Ocelot中。
首先需要写一个自己的中间件,需要继承OcelotMiddleware:
public class TestResponseMiddleware: OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
public TestResponseMiddleware(OcelotRequestDelegate next,IOcelotLoggerFactory loggerFactory)
: base(loggerFactory.CreateLogger<TestResponseMiddleware>())
{
_next = next;
} public async Task Invoke(DownstreamContext context)
{
if (!context.IsError && context.HttpContext.Request.Method.ToUpper() != "OPTIONS")
{
//对返回结果进行加密
//Logger.LogInformation("");
if (context.HttpContext.Response != null && context.DownstreamResponse.Content.Headers.ContentLength > )
{
var result= await context.DownstreamResponse.Content.ReadAsStringAsync();
using (var md5 = MD5.Create())
{
var md5Result = md5.ComputeHash(Encoding.ASCII.GetBytes(result));
var strResult = BitConverter.ToString(md5Result);
strResult = strResult.Replace("-", "");
context.HttpContext.Response.Body.Write(Encoding.UTF8.GetBytes(strResult));
}
}
}
else
{
await _next.Invoke(context);
}
}
}
这个逻辑就是拿到请求结果之后对数据进行MD5加密,然后再返回。
然后我们新建一个注册类,创建专门用来注册管道中间件的方法:
public static class TestServiceExtension
{
public static IOcelotPipelineBuilder UseTestResponseMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<TestResponseMiddleware>();
}
}
然后就是重点了!!我们需要去翻Ocelot的源码,找到其中注册管道中间件的地方,然后把那个类文件复制过来,放到自己的项目中引用,你可以理解为修改了源码来用。我们首先要看的是OcelotMiddlewareExtensions.cs文件,这里是Ocelot管道中间件的调用入口,不信你看UseOcelot扩展方法:
public static class OcelotMiddlewareExtensions
{
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder)
{
await builder.UseOcelot(new OcelotPipelineConfiguration());
return builder;
}
我们要看的是这里面的另外一个方法,Ocelot管道的CreateOcelotPipeline:
private static IApplicationBuilder CreateOcelotPipeline(IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
{
var pipelineBuilder = new OcelotPipelineBuilder(builder.ApplicationServices); pipelineBuilder.BuildOcelotPipeline(pipelineConfiguration); var firstDelegate = pipelineBuilder.Build(); /*
inject first delegate into first piece of asp.net middleware..maybe not like this
then because we are updating the http context in ocelot it comes out correct for
rest of asp.net..
*/ builder.Properties["analysis.NextMiddlewareName"] = "TransitionToOcelotMiddleware"; builder.Use(async (context, task) =>
{
var downstreamContext = new DownstreamContext(context);
await firstDelegate.Invoke(downstreamContext);
}); return builder;
}
可以看到里面 pipelineBuilder.BuildOcelotPipeline(pipelineConfiguration)这句代码,这是Ocelot管道中间件的创建方法,我们要修改的就是这两个地方,这个方法在OcelotPipelineExtensions.cs类文件里,点进去看一下:
public static class OcelotPipelineExtensions
{
public static OcelotRequestDelegate BuildCustomeOcelotPipeline(this IOcelotPipelineBuilder builder,
OcelotPipelineConfiguration pipelineConfiguration)
{
// This is registered to catch any global exceptions that are not handled
// It also sets the Request Id if anything is set globally
builder.UseExceptionHandlerMiddleware(); // If the request is for websockets upgrade we fork into a different pipeline
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
app =>
{
app.UseDownstreamRouteFinderMiddleware();
app.UseDownstreamRequestInitialiser();
app.UseLoadBalancingMiddleware();
app.UseDownstreamUrlCreatorMiddleware();
app.UseWebSocketsProxyMiddleware();
}); // Allow the user to respond with absolutely anything they want.
builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware); // This is registered first so it can catch any errors and issue an appropriate response
builder.UseResponderMiddleware(); // Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware(); // This security module, IP whitelist blacklist, extended security mechanism
builder.UseSecurityMiddleware(); //Expand other branch pipes
if (pipelineConfiguration.MapWhenOcelotPipeline != null)
{
foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
{
builder.MapWhen(pipeline);
}
} // Now we have the ds route we can transform headers and stuff?
builder.UseHttpHeadersTransformationMiddleware(); // Initialises downstream request
builder.UseDownstreamRequestInitialiser(); // We check whether the request is ratelimit, and if there is no continue processing
builder.UseRateLimiting(); // This adds or updates the request id (initally we try and set this based on global config in the error handling middleware)
// If anything was set at global level and we have a different setting at re route level the global stuff will be overwritten
// 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.
builder.UseRequestIdMiddleware(); // Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware); // Now we know where the client is going to go we can authenticate them.
// We allow the ocelot middleware to be overriden by whatever the
// user wants
if (pipelineConfiguration.AuthenticationMiddleware == null)
{
builder.UseAuthenticationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthenticationMiddleware);
} // The next thing we do is look at any claims transforms in case this is important for authorisation
builder.UseClaimsToClaimsMiddleware(); // Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware); // Now we have authenticated and done any claims transformation we
// can authorise the request
// We allow the ocelot middleware to be overriden by whatever the
// user wants
if (pipelineConfiguration.AuthorisationMiddleware == null)
{
builder.UseAuthorisationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthorisationMiddleware);
} // Now we can run the claims to headers transformation middleware
builder.UseClaimsToHeadersMiddleware(); // Allow the user to implement their own query string manipulation logic
builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware); // Now we can run any claims to query string transformation middleware
builder.UseClaimsToQueryStringMiddleware(); // Get the load balancer for this request
builder.UseLoadBalancingMiddleware(); // This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
builder.UseDownstreamUrlCreatorMiddleware(); // Not sure if this is the best place for this but we use the downstream url
// as the basis for our cache key.
builder.UseOutputCacheMiddleware(); //We fire off the request and set the response on the scoped data repo
builder.UseHttpRequesterMiddleware(); //添加自定义测试中间件
builder.UseTestResponseMiddleware(); return builder.Build();
} private static void UseIfNotNull(this IOcelotPipelineBuilder builder,
Func<DownstreamContext, Func<Task>, Task> middleware)
{
if (middleware != null)
{
builder.Use(middleware);
}
}
}
我们可以看到其实就是一个个的扩展方法的调用,也是我们所说的中间件,我在最后把刚才写的中间件加了上去,就是标红的那里,现在所有进入Ocelot的请求就都会走我们的中间件处理了,使用的时候需要将修改的OcelotPipelineExtensions.cs类文件放在自己项目里哦。
大功告成!
Ocelot自定义管道中间件的更多相关文章
- ASP.NET Core 1.0中的管道-中间件模式
ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middleware)的方式注册在管道中.显而易见这样的设计非常松耦合 ...
- Core 1.0中的管道-中间件模式
ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...
- ocelot 自定义认证和授权
ocelot 自定义认证和授权 Intro 最近又重新启动了网关项目,服务越来越多,每个服务都有一个地址,这无论是对于前端还是后端开发调试都是比较麻烦的,前端需要定义很多 baseUrl,而后端需要没 ...
- 第五节:管道中间件入门(Use、Run、Map)
一. 简介 1.中间件是一种装配到应用管道以处理请求和响应的组件,每个组件可以选择是否把请求传递到管道中的下一个组件.可在管道中的下一个组件的前后执行工作.请求管道中的每一个组件负责调用管道中的下一个 ...
- react+redux教程(七)自定义redux中间件
今天,我们要讲解的是自定义redux中间件这个知识点.本节内容非常抽象,特别是中间件的定义原理,那多层的函数嵌套和串联,需要极强逻辑思维能力才能完全消化吸收.不过我会多罗嗦几句,所以不用担心. 例子 ...
- [转]Angular2 使用管道Pipe以及自定义管道格式数据
本文转自:https://www.pocketdigi.com/20170209/1563.html 管道(Pipe)可以根据开发者的意愿将数据格式化,还可以多个管道串联. 纯管道(Pure Pipe ...
- DotNetCore学习-3.管道中间件
中间件是用于组成应用程序管道来处理请求和响应的组件.管道内的每个组件都可以选择是否将请求交给下一个组件,并在管道中调用下一个组件之前和之后执行一些操作. 请求委托被用来建立请求管道,并处理每一个HTT ...
- 自定义Django中间件(登录验证中间件实例)
前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装饰 ...
- angular自定义管道
原文地址 https://www.jianshu.com/p/5140a91959ca 对自定义管道的认识 管道的定义中体现了几个关键点: 1.管道是一个带有“管道元数据(pipe metadata) ...
随机推荐
- 奶牛跟蜗牛,哪种动物智商更高?——T检验帮你找到答案
奶牛跟蜗牛,都是“牛”,那么哪种动物更“牛”,智商更高呢?此时就能用到T检验来找答案~ T 检验(独立样本 T 检验),用于分析定类数据与定量数据之间的关系情况.例如,在本研究中,我们想探究奶牛跟 ...
- CodeForces 85D Sum of Medians Splay | 线段树
Sum of Medians 题解: 对于这个题目,先想到是建立5棵Splay,然后每次更新把后面一段区间的树切下来,然后再转圈圈把切下来的树和别的树合并. 但是感觉写起来太麻烦就放弃了. 建立5棵线 ...
- ASP.NET MVC实现依赖注入
在java的spring中有自动注入功能,使得代码变得更加简洁灵活,所以想把这个功能移植到c#中,接下来逐步分析实现过程 1.使用自动注入场景分析 在asp.net mvc中,无论是什么代码逻辑分层, ...
- Intellij IDEA在maven项目中添加外部Jar包运行
一. 问题概述 我们知道Intellij IDEA是非常好用的Java语言开发的集成环境.提供了非常多实用的功能,包括了智能代码助手.代码自动提示.代码重构.各种插件等,当然也集成了maven 正常情 ...
- 012 模块1-turtle库的使用
目录 一.概述 二.turtle库基本介绍 2.1 turtle库概述 2.2 标准库 2.3 turtle的原(wan)理(fa) 2.4 turtle的魅力 三.turtle绘图窗体布局 3.1 ...
- Stanford公开课《编译原理》学习笔记(1~4课)
目录 一. 编译的基本流程 二. Lexical Analysis(词法分析阶段) 2.1 Lexical Specification(分词原则) 2.2 Finite Automata (典型分词算 ...
- mybatis if判断两个值是否相等存在的坑啊
1.使用“==”比较 字符类型 的值 用“==”比较的使用场景: 不管你用的什么类型的变量,只要变量的值是字符类型就用“==” 产生原因: 在mybatis中如果<if>标签用一个“=”判 ...
- 第二次实验报告:使用Packet Tracer分析应用层协议
个人信息: • 姓名:李微微 • 班级:计算1811 • 学号:201821121001 一.摘要 本文描述使用Packet Tracer,正确配置网络参数,抓 ...
- 007:CSS字体图标
目录 理论 一:字体图标 图片是有诸多优点的,但是缺点很明显,比如图片不但增加了总文件的大小,还增加了很多额外的"http请求",这都会大大降低网页的性能的.更重要的是图片不能很好 ...
- JS实现数组去重的方法
1.使用ES6的Set进行去重 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...