内置中间件 #
一、内置中间件概述 #
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