昨天小光认识了路由,所以很好奇为什麽可以做到这样的功能,然後又回想老K说明的请求流水线这时发现了Custom Middlewares这个东西,所以一大早就跟大头请教这跟路由有甚麽关联。
「前辈,路由跟中介软件有甚麽关系阿。」
一大早小光就迫不及待的问大头这个问题,然後今天大头似乎把手上的需求都做完了,所以很悠哉的在上网,所以一听到小光这麽说他就这样回答他。
「哈哈哈,你眼睛蛮锐利的喔,其实老K那天在说明请求流水线时讲的那些都是中介软件的一种,只不过是dotnetcore内建的中介软件。」
听到大头这样回答,小光思考了一下就这麽说。
「如果是这样的话,那如果我想要做每个请求都要做的事我可以自己定义一个中介软件吗?」
「哈哈哈,你想要自己做一个吗,那我们就来学习一下怎麽做一个自订义中介软件。」
所以我们今天来学习一下如何自订义一个中介软件,但是在那之前我们再来看一次中介软件这篇文章,这篇文章内介绍的除了请求流水线之外还有介绍关於中介软件的处理方式,这里请先看下图。
就如同上次说明请求流水线时一样,请求会依序通过一层层中介软件,直到通过最後一个中介软件後才会到达Action的处理,待Action的处理完成後才会在一层层的返还到最後才会把反应回馈给使用者,如此就是中介软件的作用,接下来大家可以先看一下自订义一个中介软件这篇文章,然後下面我们会一步一步来学习如何自订义中介软件。
首先是较简易的一个方法,就是直接在StartUp内加入中介层的逻辑,加入的方式如下。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) =>
{
// 处理资料
// 可以针对context做处理
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
// 丢给下一个middleware或是进入MVC的action内
return next();
});
}
这边的Use可以一直串下去,第一个做完了会做下一个,如下列所示。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
return next();
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello World!");
});
app.Use((context, next) =>
{
context.Response.Headers.Add("X-Xss-Protection", "1");
return next();
});
}
不过上述例子只是执行请求进去的行动,如果这边中介层要处理进去跟返还使用者的资讯时要如下所示。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware in. \r\n");
await next.Invoke();
await context.Response.WriteAsync("Middleware out. \r\n");
});
}
接下来要介绍的跟Use很类似,不同的地方是这个方法只会被执行一次,而且後续的动作也都不会执行,请看下列例子
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware in. \r\n");
await next.Invoke();
await context.Response.WriteAsync("Middleware out. \r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware Second in. \r\n");
await next.Invoke();
await context.Response.WriteAsync("Middleware Second out. \r\n");
});
}
所以上述例子的结果会是如下
Middleware in.
Hello from 2nd delegate.
Middleware out.
而第二个Use
的动作会完全因为Run
而被取消了。
接下来要处理的是Map跟MapWhen,这都是会因为使用特定的Url而进入的中介层,接下来让大家看下列的例子来说明两个的差异。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// 针对特定url
app.Map("/blog", myApp =>
{
myApp.Run(async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
// 条件成立则执行
app.MapWhen(context => context.Request.Query.ContainsKey("blog"), myApp =>
{
myApp.Run(async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
由上述例子可以知道两个的差别。
自订义中介层类别可以分成两个步骤,第一个是宣告并实作类别,第二个是使用该类别,接下来分别说明。
宣告及实作中介层类别的例子如下
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext)
{
// 做某些事情
if (!CheckSomething())
{
// 结束不再往下走
return;
}
// 继续往下走
return _next(httpContext);
}
}
使用自订义中介层类别的方式有两种,一种是注册全域的中介层类别,另一种是针对特定类别挂上属性attribute
的方式。首先下列例子是注册全域的方式。
app.UseMiddleware<CustomMiddleware>();
这样所有的请求都会进到自订义的中介层。然後接下来看一下如何针对特定类别挂上属性的方式来使用中介层。
[MiddlewareFilter(typeof(ControllerMiddleware))]
public class HomeController : Controller
{
[MiddlewareFilter(typeof(ActionMiddleware))]
public IActionResult Index()
{
// ...
}
}
上述例子中,进入此Controller的所有Action都会经过ControllerMiddleware
中介层,而进入Index这个Action时会经过ActionMiddleware
这个中介层。
相信读者们应该看很多UseXXX的使用中介层的方式,这其实只是因应dotnetcore的习惯透过extension的方式来注册中介层,其实实际背後里是执行下列的动作。
public static class CustomMiddlewareExtensions
{
public static IApplicationBuilder UseCustomMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomMiddleware>();
}
}
如此在使用中介层也只需要使用下列方式
app.UseCustomMiddleware();
今天小光跟大头学习到如何自订义一个中介软件,以及如何使用一个自订义的中介软件,并且认识了使用中介软件时有甚麽注意事项。
<<: 2021-Day24. Serverless(十 二): Amazon Elastic Container Registry
首先,先来看看一个简单、特殊的创造物件的模式。 In software engineering, t...
前言 今天是铁人赛的第十二天,内容是如何解决实作上发现的问题 自学的人如何解决问题,原本就是打算要写...
好奇是知识的萌芽,萌芽之後,就要给予养分,让知识茁壮,没有养分的知识,只是一个没有办法萌芽的种子而已...
自动转型 续前文所述,当我们使用两个等号(==)作比较运算时,深受JavaScript「自动转型」的...
这系列主要就是讲Amazon ECS Anywhere 所以先来看看阳春版怎麽建立出来 基础运行元件...