http中间件的作用
在Go语言的HTTP框架中,中间件(Middleware)是一种在请求到达处理器之前或之后执行特定逻辑的机制。中间件通常用于处理横切关注点,例如日志记录、身份验证、请求处理、错误处理等。
中间件的主要作用包括:
- 请求预处理:如身份验证、请求日志记录、请求数据校验
- 响应后处理:如响应日志记录、错误处理、数据格式化
- 处理链控制:可以决定是否继续处理请求或直接返回响应
常见的中间件实现方式
大多数Go HTTP框架通过HandlerFunc的链式调用来实现中间件模式。基本模式是包装http.Handler或http.HandlerFunc,在调用实际处理函数前后执行额外逻辑。
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 前置处理逻辑
log.Println("Before handler")
// 调用下一个处理程序
next.ServeHTTP(w, r)
// 后置处理逻辑
log.Println("After handler")
})
}
主流框架的中间件实现案例
Gin框架中间件
Gin是流行的Go Web框架,其中间件使用非常简单:
package main
import "github.com/gin-gonic/gin"
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// 请求前处理
start := time.Now()
// 处理请求
c.Next()
// 请求后处理
latency := time.Since(start)
log.Printf("Request took %v", latency)
}
}
func main() {
r := gin.Default()
// 全局中间件
r.Use(LoggerMiddleware())
// 路由特定中间件
r.GET("/ping", LoggerMiddleware(), func(c *gin.Context) {
c.String(200, "pong")
})
r.Run()
}
Echo框架中间件
Echo框架也提供了简洁的中间件机制:
package main
import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func CustomMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// 请求前处理
c.Response().Header().Set("X-Custom-Header", "Middleware")
// 调用下一个处理程序
return next(c)
}
}
func main() {
e := echo.New()
// 内置中间件
e.Use(middleware.Logger())
// 自定义中间件
e.Use(CustomMiddleware)
e.GET("/", func(c echo.Context) error {
return c.String(200, "Hello, Middleware!")
})
e.Start(":8080")
}
标准库net/http中间件
即使不使用框架,标准库也能实现中间件模式:
package main
import (
"log"
"net/http"
"time"
)
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("Started %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("Completed %s in %v", r.URL.Path, time.Since(start))
})
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token != "secret" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
func mainHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Authenticated and Logged"))
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", mainHandler)
// 应用中间件链
handler := loggingMiddleware(authMiddleware(mux))
http.ListenAndServe(":8080", handler)
}
中间件的常见应用场景
认证中间件
验证请求是否具有有效的认证凭据:
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if !isValidToken(token) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
日志记录中间件
记录请求和响应信息:
func LoggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Printf("Incoming request: %s %s", r.Method, r.URL.Path)
rw := &responseWriter{ResponseWriter: w}
next.ServeHTTP(rw, r)
log.Printf("Response: %d %s", rw.status, http.StatusText(rw.status))
})
}
type responseWriter struct {
http.ResponseWriter
status int
}
func (rw *responseWriter) WriteHeader(code int) {
rw.status = code
rw.ResponseWriter.WriteHeader(code)
}
跨域中间件
处理CORS请求:
func CORSMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next.ServeHTTP(w, r)
})
}
限流中间件
限制请求频率:
func RateLimitMiddleware(next http.Handler) http.Handler {
limiter := rate.NewLimiter(100, 30) // 每秒100个请求,突发30个
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
中间件链的最佳实践
在设计中间件时,应遵循以下原则:
- 单一职责:每个中间件应只关注一个功能
- 明确顺序:中间件的执行顺序很重要,如认证应在授权之前
- 性能考虑:避免在中间件中执行耗时操作
- 错误处理:中间件应正确处理错误并适当终止请求处理链
- 可测试性:中间件应设计为可独立测试的单元
通过合理使用中间件,可以构建出结构清晰、功能强大且易于维护的Go HTTP应用。
707

被折叠的 条评论
为什么被折叠?



