Golang学习实战笔记-基础 > golang实战之web服务器
echo 中间件编写

中间件 其实是一个 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)
}