Middleware, also translated middleware, intermediary layer , is a type of software that provides connection between system software and application software, and facilitates communication between software components. Application software can use middleware in different technical architectures. share information and resources.
Introduction
In the Gin framework, the middleware is essentially gin.HandlerFunc function, if we want to customize the middleware, we only need the return type gin.HandlerFunc to be.
In the Gin framework, the use of middleware can be divided into the following scenarios:
- global use
- single route use
- routing group usage
Use
Global use
In the gin.Default() function, the global middleware is registered by default Logger, Recovery. The specific code is as follows:
func Default() *Engine {
// Print debug information
debugPrintWARNINGDefault()
// Create engine
engine := New()
// Register global middleware
engine.Use(Logger(), Recovery())
return engine
}
Using a single route
func main() {
engine := gin.New()
// Add a middleware: Logger()
engine.GET("/route", gin.Logger(), func(context *gin.Context) {
context.JSON(200, gin.H{" msg": "for a single route"})
})
// Add multiple middleware: Logger(),Recovery()
engine.GET("/route2", gin.Logger(), gin.Recovery(), func(context *gin.Context) {
context.JSON(200, gin.H{" msg": "Add multiple middleware to a single route"})
})
_ = engine.Run(":9090")
}
Routing group usage
func main () {
engine := gin . New ()
// After declaring the route, register the middleware with Use
v1Group := engine . Group ( "/v1" ). Use ( gin . Logger ())
{
v1Group.GET("/middleGroup", func(context *gin.Context) {
context.JSON(200,gin.H{"msg":"succss"})
})
}
_ = engine.Run(":9090")
}
Custom middleware
We can create our own middleware, use it when we need to continue execution in the middleware c.Next()
, and call c.Abort()
the termination request when we want to terminate the execution.
Syntax structure
func MiddleName() gin.HandlerFunc {
return func(context *gin.Context) {
// pre-request business logic...
// continue to execute
context.Next()
// context.Abort() stop executing
// Post-request business logic...
end := time.Now().Unix()
fmt.Printf("Interface time: %v seconds \n", end - t)
}
}
Code Description:
MiddleName
: Custom middleware name.gin.HandlerFunc
: Middleware always returns this type.func(context *gin.Context)
: Anonymous function, the parameter is the context (context *gin.Context
)context.Next()
: Continue to call this function.context.Abort()
: Terminates execution calling this function.
Example
// Declare custom middleware
func MyMiddleware() gin.HandlerFunc {
return func(context *gin.Context) {
// pre-request
fmt.Println("Middleware -- pre-request")
t := time.Now().Unix()
// Continue down the context.Next()
// context.Abort() stop down // After the request end := time.Now().Unix()
fmt.Printf("Interface time: %v seconds \n ", end-t)
}
}
// Custom middleware uses
func RunWithMyMiddle() {
engine := gin.New()
// Register custom middleware
engine.GET("/route", MyMiddleware(), func(context *gin.Context) {
time.Sleep(time.Second * 3)
context.JSON(200, gin.H{"msg": "custom route"})
})
_ = engine.Run(":9090")
}
Multiple middleware
If multiple middleware are registered at the same time, what is the execution order between them?
Code
// Custom Middleware A
func MyMiddleware() gin.HandlerFunc {
return func(context *gin.Context) {
// Before request
fmt.Println("Middleware 1-- Before request")
context.Next()
// post- request
fmt.Println("Middleware 1 -- post-request")
}
}
// Custom Middleware B
func MyMiddleware2() gin.HandlerFunc {
return func(context *gin.Context) {
// Before request
fmt.Println("Middleware 2-- Before request")
context.Next()
// post- request
fmt.Println("Middleware 2 -- post-request")
}
}
// start service
func main() {
engine := gin.New()
// use multiple middleware
engine.GET("/route", MyMiddleware(), MyMiddleware2(), func(context *gin.Context) {
time.Sleep(time.Second * 3)
context.JSON(200, gin.H{"msg": "custom route"})
})
_ = engine.Run(":9090")
}
- Request console output:
Middleware 1--before request
Middleware 2 -- before the request
Middleware 2 -- after the request
Middleware 1 -- after the request
Practice
Create custom middleware to determine Token whether it is valid (whether it is a login state).
Source code
./main.go
Code:
package main
import "go_use/practise"
func main() {
practise.RunServeWithCheckToken()
}
./practise/check_token.go
Code:
package main
import (
"github.com/gin-gonic/gin"
)
// Check token
func CheckTokenMiddle() gin.HandlerFunc {
return func(context *gin.Context) {
// Get token
token := context.DefaultQuery("token", "")
// Check token
if token != "abcd " {
context.JSON(500, gin.H{"msg": "Please log in first!"})
// Terminate the request
context.Abort()
}
// If the token is valid, continue to execute
context.Next()
}
}
// Start the service
func main() {
engine := gin.Default()
// The login interface does not need to add Token detection middleware
engine.GET("/user/login", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "Login successful!", "token": "abcd"})
})
// Routing
user := engine.Group("/user").Use(CheckTokenMiddle())
{
// User basic information
user.GET("/info", func(context *gin.Context) {
data := map[string]interface{}{
"name": "Marsero",
"age": 25,
" likes": []string{"books", "traveling"},
}
context.JSON(200, gin.H{"msg": "request succeeded", "data": data})
})
// update user
user.GET("/update", func(context *gin.Context) {
context.JSON(200, gin.H{"msg": "Request successful"})
})
}
// start the service
_ = engine.Run(":9090")
}
- Request
# No need to verify the interface of the token
$ curl -X GET http://127.0.0.1:9090/user/login
{"msg":"Login successful!","token":"abcd"}
# Token verification is required, but it is not passed
$ curl -X GET http://127.0.0.1:9090/user/info
{"msg":"Please log in first!"}
# Token verification is required, and when it has been uploaded
$ curl -X GET http://127.0.0.1:9090/user/info?token=abcd
{"data":{"age":25,"likes":["books","traveling"],"name":"Marsero"},"msg":"Request successful"}
Use Goroutines
When starting a new in middleware or handler, Goroutine the original context cannot be used, a read-only copy must be used.
- Code Examples
// Use Goroutine in middleware
func main() {
engine := gin.Default()
engine.Use(MyMiddleWithGoRoutine())
engine.GET("/useGo", func(context *gin.Context) {
context.JSON(200, gin.H{" msg": "success"})
})
_ = engine.Run(":9090")
}
// use Goroutine in middleware
func MyMiddleWithGoRoutine() gin.HandlerFunc {
return func(context *gin.Context) {
// copy context
cpContext := context.Copy()
go func() {
time.Sleep(3 * time.Second)
fmt.Println(cpContext.Request.URL.Path)
}()
context.Next()
}
}
Popular middleware
Organize many common middleware in the gin-gonic/contrib library, which can be used directly. The specific middleware is as follows:
List of external middleware
- RestGate - Secure authentication for REST API endpoints
- staticbin - middleware/handler for serving static files from binary data
- gin-cors - Official CORS gin’s middleware
- gin-csrf - CSRF protection
- gin-health - middleware that simplifies stat reporting via gocraft/health
- gin-merry - middleware for pretty-printing merry errors with context
- gin-revision - Revision middleware for Gin framework
- gin-jwt - JWT Middleware for Gin Framework
- gin-sessions - session middleware based on mongodb and mysql
- gin-location - middleware for exposing the server’s hostname and scheme
- gin-nice-recovery - panic recovery middleware that lets you build a nicer user experience
- gin-limiter - A simple gin middleware for ip limiter based on redis.
- gin-limit - limits simultaneous requests; can help with high traffic load
- gin-limit-by-key - An in-memory middleware to limit access rate by custom key and rate.
- ez-gin-template - easy template wrap for gin
- gin-hydra - Hydra middleware for Gin
- gin-glog - meant as drop-in replacement for Gin’s default logger
- gin-gomonitor - for exposing metrics with Go-Monitor
- gin-oauth2 - for working with OAuth2
- static An alternative static assets handler for the gin framework.
- xss-mw - XssMw is a middleware designed to “auto remove XSS” from user submitted input
- gin-helmet - Collection of simple security middleware.
- gin-jwt-session - middleware to provide JWT/Session/Flashes, easy to use while also provide options for adjust if necessary. Provide sample too.
- gin-template - Easy and simple to use html/template for gin framework.
- pongo2gin - Package pongo2gin is a template renderer that can be used with the Gin web framework [pongo2 like django templates]
- gin-redis-ip-limiter - Request limiter based on ip address. It works with redis and with a sliding-window mechanism.
- gin-method-override - Method override by POST form param
_method
, inspired by Ruby’s same name rack - gin-access-limit - An access-control middleware by specifying allowed source CIDR notations.
- gin-session - Session middleware for Gin
- gin-stats - Lightweight and useful request metrics middleware
- gin-statsd - A Gin middleware for reporting to statsd deamon
- gin-health-check - A health check middleware for Gin
- gin-session-middleware - A efficient, safely and easy-to-use session library for Go.
- ginception - Nice looking exception page
- gin-inspector - Gin middleware for investigating http request.
- gin-dump - Gin middleware/handler to dump header/body of request and response. Very helpful for debugging your applications.
- go-gin-prometheus - Gin Prometheus metrics exporter
- ginprom - Prometheus metrics exporter for Gin
- gin-go-metrics - Gin middleware to gather and store metrics using rcrowley/go-metrics
- ginrpc - Gin middleware/handler auto binding tools. support object register by annotated route like beego
- goscope - Watch incoming requests, outgoing responses and logs of your Gin application with this plug and play middleware inspired by Laravel Telescope.
- gin-nocache - NoCache is a simple piece of middleware that sets a number of HTTP headers to prevent a router (or subrouter) from being cached by an upstream proxy and/or client.
- logging - logging provide GinLogger uses zap to log detailed access logs in JSON or text format with trace id, supports flexible and rich configuration, and supports automatic reporting of log events above error level to sentry
- ratelimiter - Gin middleware for token bucket ratelimiter.
- servefiles - serving static files with performance-enhancing cache control headers; also handles gzip & brotli compressed files