Gin framework [middleware] collection in Go language (7)

What is middleware?

The Gin framework is a Go language framework for building web applications. Middleware is an important concept in the Gin framework, used to add some extra functionality or processing logic during request processing.

Middleware in the Gin framework can perform some operations before or after the request is processed. Typically, middleware is used to handle request verification, logging, error handling and other functions. The Gin framework provides a simple and flexible way to define and use middleware.

Middleware principle?

The middleware principle of the Gin framework can be simply summarized as follows: through the function wrapper, the middleware function is embedded into the request processing chain to perform some additional functions before or after the request is processed.

The middleware in the Gin framework is a function with the following characteristics:

  1. Function signature: The signature of the middleware function is func(c *gin.Context), accepting a *gin.Contexttype parameter indicating the request context.

  2. Execution order: Middleware functions are executed in the order of registration. Before the request is processed, the pre-middleware is executed in the order in which it was registered; after the request is processed, the post-middleware is executed in the reverse order.

  3. Request processing chain: The Gin framework maintains a request processing chain, packaging the registered middleware functions into links in the processing chain in turn. Each link can perform some operations before or after the request is processed.

  4. Context passing: Middleware functions can access and modify data in the request context. The Gin framework uses *gin.Contextobjects to represent request context, and middleware functions can use this object to obtain request information, set response information, etc.

package main

import (
	"20230615/routers"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
)

// 定义一个 userinfo 表单结构体对象
type UserInfo struct {
	UserName string `json:"username" form:"username"`
	Password string `json:"password" form:"password"`
	Age      string `json:"age" form:"age"`
}

// 路由中间件 在路由中走的 initMiddleWares
func initMiddleWares(c *gin.Context) {
	start := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----1", start)
	// c.Next()它在调用处理程序内部执行链中的挂起处理程序。Next只能在中间件内部使用
	c.Next()
	end := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----2", end)
}
func main() {
	// 定义一个路由引擎对象
	router := gin.Default()
	// 加载 渲染模板 全局
	router.LoadHTMLGlob("*templates/**/*")
	// 路由 get请求后 返回数据到模板渲染
	router.GET("/", initMiddleWares, func(c *gin.Context) {
		fmt.Println("------页面首页--------")
		c.String(200, "message")
	})

	routers.LoginRouterInit(router) // init router 初始化路由包

	router.Run(":8080")
}

Output result:

init middleware----路由-中间件----1 1687681850770421700
------页面首页--------
init middleware----路由-中间件----2 1687681850771422200

What is here is that the Next() method is added inside the middleware to suspend the program and allow it to continue executing.

By ctrl + left mouse button click, you can trace back to the source code to view other methods of the code; Abort () method: Abort can prevent the pending handler from being called. Note that this does not stop the current handler.

package main

import (
	"20230615/routers"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
)

// 定义一个 userinfo 表单结构体对象
type UserInfo struct {
	UserName string `json:"username" form:"username"`
	Password string `json:"password" form:"password"`
	Age      string `json:"age" form:"age"`
}

// 路由中间件 在路由中走的 initMiddleWares
func initMiddleWares(c *gin.Context) {
	start := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----1", start)
	// // c.Next()它在调用处理程序内部执行链中的挂起处理程序。Next只能在中间件内部使用
	// c.Next()
	// Abort可防止调用挂起的处理程序。请注意,这不会停止当前处理程序。
	c.Abort()
	end := time.Now().UnixNano()
	fmt.Println("init middleware----路由-中间件----2", end)
}
func main() {
	// 定义一个路由引擎对象
	router := gin.Default()
	// 加载 渲染模板 全局
	router.LoadHTMLGlob("*templates/**/*")
	// 路由 get请求后 返回数据到模板渲染
	router.GET("/", initMiddleWares, func(c *gin.Context) {
		fmt.Println("------页面首页--------")
		c.String(200, "message")
	})

	routers.LoginRouterInit(router) // init router 初始化路由包

	router.Run(":8080")
}

Output:

init middleware----路由-中间件----1 1687684669762450500
init middleware----路由-中间件----2 1687684669762450500

Of course, the demonstrations are only some simple and temporary methods we use. There are many internal methods, so I will not demonstrate them one by one. You can check the use of the methods by yourself, and you can view the traceback code snippets.

Global middleware code demonstration:

func initMiddlewareOne(ctx *gin.Context) {
	fmt.Println("-one-中间件-initMiddlewareOne--1")
	// Next() 方法 调用该请求的剩余程序
	ctx.Next()
	fmt.Println("-one-中间件-initMiddlewareOne--2")

}
func initMiddlewareTwo(ctx *gin.Context) {
	fmt.Println("-two--中间件--initMiddlewareTwo--1")
	//终止调用该程序的剩余请求处理程序 abort()方法
	// ctx.Abort()
	ctx.Next()
	fmt.Println("-two--中间件--initMiddlewareTwo--2")
}


func main() {
	r := gin.Default()

	r.SetFuncMap(template.FuncMap{
		"UnitTime": UnitTime,
	})

	r.LoadHTMLGlob("*templates/**/*")

	r.Static("/static", "./static")

	// 通过 use() 方法全局注册中间件
	// r.Use(initMiddlewareOne, initMiddlewareTwo)



	r.GET("/", func(ctx *gin.Context) {
		fmt.Println("这是一个首页")
		ctx.HTML(http.StatusOK, "default/news.html", gin.H{
			"title": "这个是一个首页",
		})
		// ctx.String(200, "这是一个首页")
	})

	// 抽离了 路由,传入了 r;这样就是注册了路由,同时简化了入口文件的大小
	routers.DefaultRoutersInit(r)
	// 登陆路由 抽离 下一步,给路由内部的方法抽离成一个 控制器 controllers
	routers.LoginRoutersinit(r)

	r.Run(":8001")

}

Terminal output:

// 中间件内部都是next方法
-one-中间件-initMiddlewareOne--1
-two--中间件--initMiddlewareTwo--1
-one-中间件-initMiddlewareOne--1
 -two--中间件--initMiddlewareTwo--2
-one-中间件-initMiddlewareOne--2
 -two--中间件--initMiddlewareTwo--2
 -one-中间件-initMiddlewareOne--2

The above is the demonstration of routing middleware, which is used under the main.go main entry file. So how to extract the routing middleware initmiddlewares?

How to register the created file middleware init.go into the current route? 

package middlewares

import (
	"fmt"

	"github.com/gin-gonic/gin"
)

// 方法想要其他包也可以引用,必须要让
func InitMiddlewares(c *gin.Context) {
	url := c.Request.URL.String()

	fmt.Println("路由分组--中间件---", url)
}

Introduce packages/middlewares directly in routes

The specific method of use is as follows:

package routers

import (
	"github.com/gin-gonic/gin"

	"20230619/controllers/login"
	"20230619/middlewares"
)

// 1. 如果我们要全局gold 使用,那么方法的首字母一定是大写
// 2. 路由内部的处理方法 进行抽离 使其成一个控制器 controller 「 首先, 」
func LoginRoutersinit(r *gin.Engine) {
	loginRouters := r.Group("/login", middlewares.InitMiddlewares)
	{
		loginRouters.GET("/", login.LoginControllers{}.Index)
		loginRouters.GET("/edit", login.LoginControllers{}.Edit)

	}
}

Some common operations of Gin framework middleware:

Register middleware: In the Gin framework, you can register middleware by calling the Use method. For example, router.Use(middleware1, middleware2).

Global middleware: By registering middleware on the router, it can be applied to all requests. For example, router.Use(globalMiddleware).

Note: To extend here, there are two ways to define a routing engine, one is New() and default(); it is recommended to use the default mode to create a routing engine (in this way, the default routing engine uses Logger and Rovery middleware).

At the same time, these two middlewares have different functions.

         Logger middleware writes logs to gin.DefaultWriter, that is, configured with GIN_MODE=release.

         Recovery middleware will recover any panic. If there is a panic, a 500 status code value will be written.

However, using the new() method to create a routing engine is a completely new one without any middleware. It can be seen in the source code:

 

 

Route-level middleware: Middleware can be registered in the handler function of each route. For example, router.GET("/api", routeMiddleware, handleFunc).

After defining the middleware method, put it directly into the route, and it will only take effect on this route.

 

Group-level middleware: Middleware can be registered in a routing group to apply to all routes under the group. For example, apiGroup := router.Group("/api", groupMiddleware).

Contextual middleware: Middleware can access and modify data in the request context. For example, authenticate the user and store the user information in the context for use by subsequent processing functions.

Error handling middleware: You can define a middleware to capture and handle errors during request processing. For example, logging errors or returning a specific error response.

Chain middleware: Multiple middleware can be connected to form a middleware chain. For example, router.Use(middleware1, middleware2, middleware3).

In general, middleware is a very useful feature in the Gin framework, which can help developers implement various common functions and processing logic, making the code more modular and maintainable.

I hope it will be helpful to your study!

Guess you like

Origin blog.csdn.net/A_LWIEUI_Learn/article/details/131379589