中间件 其实是一个 echo.MiddlewareFunc 类型的实例,
// MiddlewareFunc defines a function to process middleware. type MiddlewareFunc func(HandlerFunc) HandlerFunc // HandlerFunc defines a function to serve HTTP requests. type HandlerFunc func(Context) error
实例1: 记录客户端请求日志
package webMiddlewares import ( "github.com/gw123/GMQ/core/interfaces" "github.com/gw123/GMQ/modules/webModule/db_models" "github.com/labstack/echo" "strconv" "time" ) func NewPingMiddleware(app interfaces.App) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) (err error) { req := c.Request() res := c.Response() start := time.Now() if err = next(c); err != nil { c.Error(err) } stop := time.Now() clientId := c.QueryParam("clientId") payload := c.QueryParam("payload") sendAt := c.QueryParam("sendAt") sendAtTIme, _ := time.Parse("2019-08-24", sendAt) if sendAtTIme.IsZero() { sendAtTIme = time.Now() } l := stop.Sub(start) if l != 0 { l = l / time.Millisecond } byteIn, _ := strconv.Atoi(req.Header.Get(echo.HeaderContentLength)) pingLog := &db_models.PingLog{ Ip: c.RealIP(), ClientSendAt: sendAtTIme, CreatedAt: time.Now(), Payload: payload, ClientId: clientId, Latency: uint(l), BytesIn: uint(byteIn), BytesOut: uint(res.Size), } db, err := app.GetDefaultDb() if err != nil { } else { if err = db.Save(pingLog).Error; err != nil { } } return nil } } }
实例2: 为客户端请求生产一个唯一的request_id,方便后面日志追踪
package webMiddlewares import ( "github.com/labstack/echo" "github.com/labstack/echo/middleware" "github.com/labstack/gommon/random" ) type ( // RequestIDConfig defines the config for RequestID middleware. RequestIDConfig struct { // Skipper defines a function to skip middleware. Skipper middleware.Skipper // Generator defines a function to generate an ID. // Optional. Default value random.String(32). Generator func() string } ) var ( // DefaultRequestIDConfig is the default RequestID middleware config. DefaultRequestIDConfig = RequestIDConfig{ Skipper: middleware.DefaultSkipper, Generator: generator, } ) // RequestID returns a X-Request-ID middleware. func RequestID() echo.MiddlewareFunc { return RequestIDWithConfig(DefaultRequestIDConfig) } // RequestIDWithConfig returns a X-Request-ID middleware with config. func RequestIDWithConfig(config RequestIDConfig) echo.MiddlewareFunc { // Defaults if config.Skipper == nil { config.Skipper = DefaultRequestIDConfig.Skipper } if config.Generator == nil { config.Generator = generator } return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { if config.Skipper(c) { return next(c) } req := c.Request() //res := c.Response() rid := req.Header.Get(echo.HeaderXRequestID) if rid == "" { rid = config.Generator() } req.Header.Set(echo.HeaderXRequestID, rid) c.Set(echo.HeaderXRequestID, rid) return next(c) } } } func generator() string { return random.String(32) }
echo 中间件使用
e := echo.New() e.Use(webMiddlewares.RequestID())
echo 中间件实现
// ServeHTTP implements `http.Handler` interface, which serves HTTP requests. func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Acquire context c := e.pool.Get().(*context) c.Reset(r, w) h := NotFoundHandler if e.premiddleware == nil { e.router.Find(r.Method, getPath(r), c) h = c.Handler() for i := len(e.middleware) - 1; i >= 0; i-- { h = e.middleware[i](h) } } else { h = func(c Context) error { e.router.Find(r.Method, getPath(r), c) h := c.Handler() for i := len(e.middleware) - 1; i >= 0; i-- { h = e.middleware[i](h) } return h(c) } for i := len(e.premiddleware) - 1; i >= 0; i-- { h = e.premiddleware[i](h) } } // Execute chain if err := h(c); err != nil { e.HTTPErrorHandler(err, c) } // Release context e.pool.Put(c) }