内置中间件 #

一、内置中间件概述 #

Echo提供了丰富的内置中间件,覆盖日志、认证、安全、性能等各个方面。

1.1 内置中间件列表 #

中间件 功能
Logger 请求日志记录
Recover Panic恢复
CORS 跨域处理
Gzip 响应压缩
JWT JWT认证
BasicAuth 基础认证
RateLimiter 请求限流
RequestID 请求ID
Secure 安全头
Static 静态文件
BodyLimit 请求体大小限制
CSRF CSRF防护
Proxy 反向代理
Rewrite URL重写
RequestLogger 请求日志
Timeout 请求超时

二、Logger - 日志中间件 #

2.1 基本使用 #

go
e := echo.New()
e.Use(middleware.Logger())

2.2 自定义格式 #

go
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Format: "time=${time_rfc3339}, method=${method}, uri=${uri}, status=${status}, latency=${latency_human}\n",
}))

2.3 可用变量 #

变量 说明
${time_rfc3339} RFC3339格式时间
${time_rfc3339_nano} 纳秒精度时间
${time_custom} 自定义格式时间
${id} 请求ID
${remote_ip} 客户端IP
${host} 主机名
${method} HTTP方法
${uri} 请求URI
${path} 请求路径
${protocol} 协议版本
${status} 状态码
${error} 错误信息
${latency} 响应时间(纳秒)
${latency_human} 响应时间(可读)
${bytes_in} 请求体大小
${bytes_out} 响应体大小
${header:X-Custom} 自定义请求头

2.4 输出到文件 #

go
file, err := os.OpenFile("logs/app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
    panic(err)
}

e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Output: file,
}))

2.5 跳过特定路由 #

go
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Skipper: func(c echo.Context) bool {
        return c.Path() == "/health" || c.Path() == "/metrics"
    },
}))

三、Recover - 错误恢复 #

3.1 基本使用 #

go
e.Use(middleware.Recover())

3.2 自定义配置 #

go
e.Use(middleware.RecoverWithConfig(middleware.RecoverConfig{
    DisablePrintStack: false,
    LogLevel:          1,
    LogErrorFunc: func(c echo.Context, err error, stack []byte) error {
        log.Printf("Panic: %v\n%s", err, stack)
        return nil
    },
}))

3.3 配置选项 #

选项 说明
DisablePrintStack 禁用打印堆栈
LogLevel 日志级别
LogErrorFunc 自定义错误处理

四、CORS - 跨域处理 #

4.1 基本使用 #

go
e.Use(middleware.CORS())

4.2 自定义配置 #

go
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
    AllowOrigins: []string{"https://example.com", "https://api.example.com"},
    AllowMethods: []string{echo.GET, echo.POST, echo.PUT, echo.DELETE, echo.PATCH},
    AllowHeaders: []string{
        echo.HeaderOrigin,
        echo.HeaderContentType,
        echo.HeaderAccept,
        echo.HeaderAuthorization,
    },
    AllowCredentials: true,
    MaxAge:           3600,
}))

4.3 配置选项 #

选项 说明
AllowOrigins 允许的域名
AllowMethods 允许的方法
AllowHeaders 允许的请求头
AllowCredentials 允许携带凭证
ExposeHeaders 暴露的响应头
MaxAge 预检缓存时间

4.4 动态域名 #

go
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
    AllowOriginFunc: func(origin string) (bool, error) {
        return strings.HasSuffix(origin, ".example.com"), nil
    },
}))

五、Gzip - 响应压缩 #

5.1 基本使用 #

go
e.Use(middleware.Gzip())

5.2 自定义配置 #

go
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
    Level: 5,
    Skipper: func(c echo.Context) bool {
        return strings.Contains(c.Request().URL.Path, "metrics")
    },
}))

5.3 压缩级别 #

级别 说明
-1 默认级别
0 不压缩
1 最快压缩
9 最佳压缩

六、JWT - JWT认证 #

6.1 基本使用 #

go
e.Use(middleware.JWT([]byte("secret")))

6.2 自定义配置 #

go
e.Use(middleware.JWTWithConfig(middleware.JWTConfig{
    SigningKey:  []byte("secret"),
    TokenLookup: "header:Authorization:Bearer ",
    AuthScheme:  "Bearer",
    ContextKey:  "user",
}))

6.3 获取用户信息 #

go
e.GET("/profile", func(c echo.Context) error {
    user := c.Get("user").(*jwt.Token)
    claims := user.Claims.(jwt.MapClaims)
    name := claims["name"].(string)
    
    return c.String(http.StatusOK, "Welcome "+name)
}, middleware.JWT([]byte("secret")))

6.4 配置选项 #

选项 说明
SigningKey 签名密钥
TokenLookup Token位置
AuthScheme 认证方案
ContextKey 上下文键名
Claims 自定义Claims

6.5 多种Token位置 #

go
// 从Header获取
TokenLookup: "header:Authorization:Bearer "

// 从Query参数获取
TokenLookup: "query:token"

// 从Cookie获取
TokenLookup: "cookie:jwt"

// 从多个位置获取
TokenLookup: "header:Authorization:Bearer ,query:token"

七、BasicAuth - 基础认证 #

7.1 基本使用 #

go
e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
    if username == "admin" && password == "secret" {
        return true, nil
    }
    return false, nil
}))

7.2 数据库验证 #

go
e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
    user, err := getUserByUsername(username)
    if err != nil {
        return false, nil
    }
    
    if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
        return false, nil
    }
    
    c.Set("user", user)
    return true, nil
}))

八、RateLimiter - 请求限流 #

8.1 基本使用 #

go
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)))

8.2 自定义配置 #

go
e.Use(middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{
    Store: middleware.NewRateLimiterMemoryStoreWithConfig(
        middleware.RateLimiterMemoryStoreConfig{Rate: 10, Burst: 30, ExpiresIn: 3 * time.Minute},
    ),
    IdentifierExtractor: func(ctx echo.Context) (string, error) {
        id := ctx.RealIP()
        return id, nil
    },
    ErrorHandler: func(context echo.Context, err error) error {
        return context.JSON(http.StatusTooManyRequests, map[string]string{
            "error": "请求过于频繁",
        })
    },
}))

8.3 基于用户限流 #

go
e.Use(middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{
    Store: middleware.NewRateLimiterMemoryStore(10),
    IdentifierExtractor: func(ctx echo.Context) (string, error) {
        if user := ctx.Get("user"); user != nil {
            return user.(*User).ID, nil
        }
        return ctx.RealIP(), nil
    },
}))

九、RequestID - 请求ID #

9.1 基本使用 #

go
e.Use(middleware.RequestID())

9.2 获取请求ID #

go
e.GET("/", func(c echo.Context) error {
    requestID := c.Response().Header().Get(echo.HeaderXRequestID)
    return c.String(http.StatusOK, "Request ID: "+requestID)
})

9.3 自定义生成器 #

go
e.Use(middleware.RequestIDWithConfig(middleware.RequestIDConfig{
    Generator: func() string {
        return uuid.New().String()
    },
}))

十、Secure - 安全头 #

10.1 基本使用 #

go
e.Use(middleware.Secure())

10.2 自定义配置 #

go
e.Use(middleware.SecureWithConfig(middleware.SecureConfig{
    XSSProtection:         "1; mode=block",
    ContentTypeNosniff:    "nosniff",
    XFrameOptions:         "DENY",
    HSTSMaxAge:            3600,
    ContentSecurityPolicy: "default-src 'self'",
}))

10.3 安全头说明 #

说明
X-XSS-Protection XSS保护
X-Content-Type-Options 内容类型嗅探
X-Frame-Options 点击劫持防护
Strict-Transport-Security HTTPS强制
Content-Security-Policy 内容安全策略

十一、BodyLimit - 请求体限制 #

11.1 基本使用 #

go
e.Use(middleware.BodyLimit("2M"))

11.2 路由级别 #

go
e.POST("/upload", uploadHandler, middleware.BodyLimit("10M"))

11.3 大小格式 #

格式 说明
1K 1KB
2M 2MB
1G 1GB

十二、CSRF - CSRF防护 #

12.1 基本使用 #

go
e.Use(middleware.CSRF())

12.2 自定义配置 #

go
e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
    TokenLookup: "form:_csrf",
    ContextKey:  "csrf",
    CookieName:  "_csrf",
    Cookie: &http.Cookie{
        Path:     "/",
        Secure:   true,
        HttpOnly: true,
    },
}))

12.3 获取Token #

go
e.GET("/form", func(c echo.Context) error {
    csrf := c.Get("csrf").(string)
    return c.HTML(http.StatusOK, fmt.Sprintf(`
        <form method="POST" action="/submit">
            <input type="hidden" name="_csrf" value="%s">
            <input type="text" name="name">
            <button type="submit">Submit</button>
        </form>
    `, csrf))
}, middleware.CSRF())

十三、Timeout - 请求超时 #

13.1 基本使用 #

go
e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{
    Timeout: 30 * time.Second,
}))

13.2 自定义错误处理 #

go
e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{
    Timeout: 10 * time.Second,
    OnTimeoutRouteErrorHandler: func(err error, c echo.Context) error {
        return c.JSON(http.StatusRequestTimeout, map[string]string{
            "error": "请求超时",
        })
    },
}))

十四、完整示例 #

go
package main

import (
    "net/http"
    "time"
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    e := echo.New()
    
    e.Use(middleware.RequestID())
    e.Use(middleware.Recover())
    e.Use(middleware.Logger())
    e.Use(middleware.Gzip())
    e.Use(middleware.Secure())
    e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
        AllowOrigins: []string{"*"},
        AllowMethods: []string{echo.GET, echo.POST, echo.PUT, echo.DELETE},
    }))
    e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(100)))
    
    e.GET("/health", health)
    
    api := e.Group("/api")
    api.Use(middleware.JWT([]byte("secret")))
    
    api.GET("/users", getUsers)
    api.GET("/profile", getProfile)
    
    admin := e.Group("/admin")
    admin.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
        if username == "admin" && password == "secret" {
            return true, nil
        }
        return false, nil
    }))
    
    admin.GET("/stats", getStats)
    
    e.Logger.Fatal(e.Start(":8080"))
}

func health(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]string{
        "status": "healthy",
        "time":   time.Now().Format(time.RFC3339),
    })
}

func getUsers(c echo.Context) error {
    return c.JSON(http.StatusOK, []map[string]string{
        {"id": "1", "name": "张三"},
        {"id": "2", "name": "李四"},
    })
}

func getProfile(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]string{
        "id":   "1",
        "name": "张三",
    })
}

func getStats(c echo.Context) error {
    return c.JSON(http.StatusOK, map[string]int{
        "users":  100,
        "posts":  500,
        "visits": 10000,
    })
}

十五、总结 #

内置中间件要点:

中间件 用途
Logger 日志记录
Recover 错误恢复
CORS 跨域处理
Gzip 响应压缩
JWT JWT认证
BasicAuth 基础认证
RateLimiter 请求限流
RequestID 请求ID
Secure 安全头
BodyLimit 请求体限制
CSRF CSRF防护
Timeout 请求超时

准备好学习自定义中间件了吗?让我们进入下一章!

最后更新:2026-03-28