当前位置:网站首页>[comparative learning] koa JS, gin and asp Net core - Middleware
[comparative learning] koa JS, gin and asp Net core - Middleware
2022-06-23 19:01:00 【DDGarfield】
web Framework middleware comparison
Programming languages are different , A framework designed by each language to solve the same kind of problem , There is something in common , After all, it's about solving the same kind of problems , The challenges are much the same , Like authentication ,api Authorization and so on , I'm sorry node.js,golang,.net core Get involved , To each other web In the process of learning the framework, we found that there are indeed similarities . Here's how to node.js Of koa、golang Of gin And .net core Of asp.net core Three different web The middleware of the back-end framework is analyzed and compared
Node-Koa.js
Application level middleware
// If you don't write next, It doesn't match down -- Match any route
app.use(async(ctx,next)=>{
console.log(new Date())
await next();
})
Routing level middleware
router.get('/news',async(ctx,next)=>{
console.log("this is news")
await next();
})
Error handling middleware
app.use(async(ctx,next)=>{
// Application level middleware All need to be carried out
/*
1. Execute a number of code
*/
next();//2. perform next() Match other routes
//4. Re execution
if(ctx.status==404){
ctx.status=404
ctx.body=" This is a 404"
}else{
console.log(ctx.url)
}
})
//3. Match the route below
router.get('/news',async(ctx)=>{
console.log("this is news")
ctx.body=" This is a news page "
})
Third-party middleware
Take static resource middleware as an example : Static resource address has no route matching , Blind introduction of static resources , Will be submitted to the 404.
// install
npm install koa-static --save
// Use
// introduce
const static=require('koa-static')
// Use
app.use(static('static')) // Go to static Files will be found in the file directory , If you can find the corresponding file , If you can't find it next()
app.use(static(__dirname+'/static'))
app.use(static(__dirname+'/public'))
Middleware execution sequence
Onion execution : From top to bottom , Match route response , Then return to the middleware to execute middleware ,【 First from the outside in , And then from the inside out 】
Golang-Gin
hook (Hook) function , Middleware function
Define middleware
package main
import(
"github.com/gin-gonic/gin"
)
func main(){
r:=gin.Default()
r.GET("/index",func(c *gin.Context){
//...
})
r.Run()
}
func m1(c *gin.Context){
fmt.Println(" middleware m1")
c.Next()// Call subsequent processing functions
//c.Abort()// Prevent subsequent processing functions from being called
fmt.Println("m1 out...")
}
Register middleware
Global registration - A route is registered separately - Routing group registration
package main
import(
"github.com/gin-gonic/gin"
)
func main(){
r:=gin.Default()
r.GET("/index",func(c *gin.Context){
//...
})
// A route is registered separately -- It can also be called routing level registration middleware
r.GET("/test1",m1,func(c *gin.Context){
//...
})
// Routing group registration
xxGroup:=r.Group("/xx",m1)
{
xxGroup.GET("/index",func(c *gin.Context){
//...
})
}
xx2Group:=r.Group("/xx2")
xx2Group.Use(m1)
{
xxGroup.GET("/index",func(c *gin.Context){
//...
})
}
r.Run()
r.GET("/index",m1)
}
func m1(c *gin.Context){
fmt.Println(" middleware m1")
c.Next()// Call subsequent processing functions
//c.Abort()// Prevent subsequent processing functions from being called
//return Even the one below fmt.Println No more execution , Return immediately
fmt.Println("m1 out...")
}
r.Use(m1)// Global registration
// Multiple middleware registration
r.Use(m1,m2)
Middleware execution sequence
And koa The execution order of middleware is consistent
Middleware is usually written as - Closure
func authMiddleware(doCheck bool) gin.HandlerFunc{
// Connect to database
// Or preparation
return func(c *gin.Context){
// Whether to log in or not
//if It's the login user
//c.Next()
//else
//c.Abort()
}
}
Middleware communication
func m1(c *gin.Context){
fmt.Println("m1 in ...")
start := time.Now()
c.Next()
cost:=time.Since(start)
fmt.Printf("cost:%v\n",cost)
fmt.Println("m1 out...")
}
func m2(c *gin.Context){
fmt.Println("m2 in...")
// Middleware store value
c.Set("name","carfield")
fmt.Println("m2 out...")
// Other middleware values
// c.Get
// c.MustGet
}
Middleware uses goroutine
When in middleware or handler Start a new goroutine when , You can't use the original context
(c *gin.Context)Must use its read-only copyc.Copy(), Otherwise, there will be thread safety problems .
.Net Core-Asp.net core
Create middleware pipeline
Use IApplicationBuilder Create middleware pipeline
//Run
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}
//Use - Run
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do work that doesn't write to the Response.
await next.Invoke();
// Do logging or other work that doesn't write to the Response.
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from 2nd delegate.");
});
}
}
// This Use Is it with koa Application level middleware is very similar to
Create middleware pipeline branches
Map Extensions are used as conventions to create pipe branches .
MapCreate a branch of the request pipeline based on the match of the given request path . If the request path begins with a given path , Execute branch .koa and gin The middle way is to match map such , When not using built-in mvc Template routing , I'll call it custom routing
public class Startup
{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
// The request will match map1...map2... All that do not match the route will execute app.Run
}
// image golang Of gin equally ,map Nesting is also supported
app.Map("/level1", level1App => {
level1App.Map("/level2a", level2AApp => {
// "/level1/level2a" processing
});
level1App.Map("/level2b", level2BApp => {
// "/level1/level2b" processing
});
});
public class Startup
{
private static void HandleMultiSeg(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map multiple segments.");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1/seg1", HandleMultiSeg);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate.");
});
}
}
//MapWhen Create a request pipeline branch based on the result of a given predicate .Func<HttpContext, bool> Any predicate of type can be used to map the request to a new branch of the pipeline . In the following example , Predicates are used to detect query string variables branch Whether there is :
public class Startup
{
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($"Branch used = {branchVer}");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}
//UseWhen It is also based on the result of a given predicate to create a request pipeline branch . And MapWhen The difference is , If this branch is short circuited or contains terminal middleware , The main pipeline will be rejoined :
public class Startup
{
private readonly ILogger<Startup> _logger;
public Startup(ILogger<Startup> logger)
{
_logger = logger;
}
private void HandleBranchAndRejoin(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
var branchVer = context.Request.Query["branch"];
_logger.LogInformation("Branch used = {branchVer}", branchVer);
// Do work that doesn't write to the Response.
await next();
// Do other work that doesn't write to the Response.
});
}
public void Configure(IApplicationBuilder app)
{
app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranchAndRejoin);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from main pipeline.");
});
}
}
Built in middleware
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// Developer exception page middleware Report application runtime errors
app.UseDeveloperExceptionPage();
// Database error page middleware Reports Database runtime errors
app.UseDatabaseErrorPage();
}
else
{
// Exception handler middleware
app.UseExceptionHandler("/Error");
//http Strict transport security protocol middleware
app.UseHsts();
}
//HTTPS Redirection middleware
app.UseHttpsRedirection();
// Static file middleware
app.UseStaticFiles();
//Cookie Policy middleware
app.UseCookiePolicy();
// Routing middleware
app.UseRouting();
// Authentication middleware
app.UseAuthentication();
// Authorization middleware
app.UseAuthorization();
// Session middleware - If you use session, We need to cookie Policy middleware uses , To introduce session middleware , To introduce mvc middleware , After all session It's dependence cookie Realized
app.UseSession();
// Endpoint routing middleware
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
Custom middleware
stay Configure Direct writing
// stay Startup.Configure Direct code
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
// Do something
// Call the next delegate/middleware in the pipeline
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello world");
});
}
Middleware class + Middleware extension method +UseXX
stay
Startup.ConfigureDirect code , When defining multiple middleware , The code will inevitably become bloated , Not conducive to maintenance , Look at the built-in middleware ,app.UseAuthentication();How concise , see asp.net core Source code , The built-in middleware is a middleware classxxMiddleware.csAn extension methodxxMiddlewareExtensions.csAnd then inStartup.ConfigureUsing extended method calls in Usexx()
using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;
namespace Culture
{
public class RequestTestMiddleware
{
private readonly RequestDelegate _next;
// Has the type RequestDelegate The public constructor for the parameter of
public RequestTestMiddleware(RequestDelegate next)
{
_next = next;
}
// be known as Invoke or InvokeAsync The public method of . This method must :
// return Task.
// The type of acceptance HttpContext The first parameter of .
public async Task InvokeAsync(HttpContext context)
{
// Do something
// Call the next delegate/middleware in the pipeline
await _next(context);
}
}
}
// Middleware extension method
using Microsoft.AspNetCore.Builder;
namespace Culture
{
public static class RequestTestMiddlewareExtensions
{
public static IApplicationBuilder UseRequestTest(
this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<RequestTestMiddleware>();
}
}
}
// Call middleware
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseRequestTest();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
});
}
}
.Net -Asp.Net
about asp.net core Middleware and koa.js,gin middleware , The implementation is slightly different , But there is only one ultimate goal , Namely AOP, Section oriented programming , Reduce the amount of code , Instead of writing the same code in a route matching method . stay asp.net core Before , still asp.net When , There are similar ones AOP Realization , To inherit all kinds of FilterAttribute , Rewriting methods , If attribute routing is enabled , Create a custom authorization filter , Create a custom authentication filter , Model validation filters
边栏推荐
- 杰理之串口通信 串口接收 IO 需要设置数字功能【篇】
- 产品设计- 需求分析
- 诺亚财富通过聆讯:年营收43亿 汪静波有49%投票权,红杉是股东
- Product feedback mechanism
- 【One by One系列】IdentityServer4(三)使用用户名和密码
- VirtP4笔记
- CV-卷积神经网络
- When Jerry's serial port is set up, it prints garbled code, and the internal crystal oscillator is not calibrated [chapter]
- Cloud security daily 220623: the red hat database management system has found an arbitrary code execution vulnerability and needs to be upgraded as soon as possible
- 矩阵分析笔记(一)
猜你喜欢
随机推荐
Principles of microcomputer Chapter VIII notes arrangement
一、摘要和简介
The yuan universe killer is coming! Xiao Zha offered 4 VR head displays to challenge the visual Turing test
汇编语言(1)基础知识
User analysis aarrr model (pirate model)
STM32 (VIII) -- PWM output
对比学习(Contrastive Learning)综述
重磅:国产IDE发布,由阿里研发,完全开源!(高性能+高定制性)
企业如何做好业务监控?
高级计网笔记(三)
GES图计算引擎HyG揭秘之图切分
Stream流的使用
vPROM笔记
#19生成器函数经典案例
#20Set介绍与API
云安全日报220623:红帽数据库管理系统发现执行任意代码漏洞,需要尽快升级
Principles of microcomputer Chapter 6 notes arrangement
Borui data attends Alibaba cloud observable technology summit, and digital experience management drives sustainable development
杰理之添加定时器中断【篇】
Revelation: Bezos' business logic and leadership rules









