1.1. 中间件

1.1.1. 怎样自己写一个中间件?

比如有以下需求

  • 通过该中间件去统计请求数目、状态和时间。
  • 中间件把写过写回响应。

Server

server.go

package main

import (
    "net/http"
    "strconv"
    "sync"
    "time"

    "github.com/labstack/echo"
)

type (
    Stats struct {
        Uptime       time.Time      `json:"uptime"`
        RequestCount uint64         `json:"requestCount"`
        Statuses     map[string]int `json:"statuses"`
        mutex        sync.RWMutex
    }
)

func NewStats() *Stats {
    return &Stats{
        Uptime:   time.Now(),
        Statuses: make(map[string]int),
    }
}

// Process is the middleware function.
func (s *Stats) Process(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        if err := next(c); err != nil {
            c.Error(err)
        }
        s.mutex.Lock()
        defer s.mutex.Unlock()
        s.RequestCount++
        status := strconv.Itoa(c.Response().Status)
        s.Statuses[status]++
        return nil
    }
}

// Handle is the endpoint to get stats.
func (s *Stats) Handle(c echo.Context) error {
    s.mutex.RLock()
    defer s.mutex.RUnlock()
    return c.JSON(http.StatusOK, s)
}

// ServerHeader middleware adds a `Server` header to the response.
func ServerHeader(next echo.HandlerFunc) echo.HandlerFunc {
    return func(c echo.Context) error {
        c.Response().Header().Set(echo.HeaderServer, "Echo/3.0")
        return next(c)
    }
}

func main() {
    e := echo.New()

    // Debug mode
    e.Debug = true

    //-------------------
    // Custom middleware
    //-------------------
    // Stats
    s := NewStats()
    e.Use(s.Process)
    e.GET("/stats", s.Handle) // Endpoint to get stats

    // Server header
    e.Use(ServerHeader)

    // Handler
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })

    // Start server
    e.Logger.Fatal(e.Start(":1323"))
}

响应

响应头

Content-Length:122
Content-Type:application/json; charset=utf-8
Date:Thu, 14 Apr 2016 20:31:46 GMT
Server:Echo/2.0

响应体

{
  "uptime": "2016-04-14T13:28:48.486548936-07:00",
  "requestCount": 5,
  "statuses": {
    "200": 4,
    "404": 1
  }
}

results matching ""

    No results matching ""