Gin 中间件与配置集成
将中间件行为与配置文件关联,实现灵活的中间件配置管理。
配置驱动的中间件
中间件配置结构
YAML
# config/production.yaml
middleware:
cors:
enabled: true
origins:
- https://example.com
- https://admin.example.com
methods:
- GET
- POST
- PUT
- DELETE
headers:
- Content-Type
- Authorization
credentials: true
max_age: 3600
rate_limit:
enabled: true
requests_per_minute: 100
burst: 20
by_ip: true
jwt:
enabled: true
secret: ${JWT_SECRET}
skip_paths:
- /api/login
- /api/register
- /api/health
logging:
enabled: true
level: info
format: json
skip_paths:
- /api/health
- /metrics
security_headers:
enabled: true
headers:
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
中间件配置结构体
Go
type MiddlewareConfig struct {
CORS CORSConfig `mapstructure:"cors"`
RateLimit RateLimitConfig `mapstructure:"rate_limit"`
JWT JWTConfig `mapstructure:"jwt"`
Logging LoggingConfig `mapstructure:"logging"`
SecurityHeaders SecurityHeadersConfig `mapstructure:"security_headers"`
}
type CORSConfig struct {
Enabled bool `mapstructure:"enabled"`
Origins []string `mapstructure:"origins"`
Methods []string `mapstructure:"methods"`
Headers []string `mapstructure:"headers"`
Credentials bool `mapstructure:"credentials"`
MaxAge int `mapstructure:"max_age"`
}
type RateLimitConfig struct {
Enabled bool `mapstructure:"enabled"`
RequestsPerMin int `mapstructure:"requests_per_minute"`
Burst int `mapstructure:"burst"`
ByIP bool `mapstructure:"by_ip"`
}
type JWTConfig struct {
Enabled bool `mapstructure:"enabled"`
Secret string `mapstructure:"secret"`
SkipPaths []string `mapstructure:"skip_paths"`
}
配置集成中间件
CORS 中间件配置集成
Go
func CORSMiddlewareFromConfig(config CORSConfig) gin.HandlerFunc {
if !config.Enabled {
return func(c *gin.Context) { c.Next() }
}
return func(c *gin.Context) {
origin := c.GetHeader("Origin")
// 检查是否为允许的来源
allowed := false
for _, o := range config.Origins {
if o == origin || o == "*" {
allowed = true
break
}
}
if allowed {
c.Header("Access-Control-Allow-Origin", origin)
c.Header("Access-Control-Allow-Methods", strings.Join(config.Methods, ", "))
c.Header("Access-Control-Allow-Headers", strings.Join(config.Headers, ", "))
c.Header("Access-Control-Allow-Credentials", strconv.FormatBool(config.Credentials))
c.Header("Access-Control-Max-Age", strconv.Itoa(config.MaxAge))
}
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
速率限制中间件配置集成
Go
func RateLimitMiddlewareFromConfig(config RateLimitConfig) gin.HandlerFunc {
if !config.Enabled {
return func(c *gin.Context) { c.Next() }
}
limiter := NewIPRateLimiter(config.Burst, config.RequestsPerMin/60)
return func(c *gin.Context) {
if config.ByIP {
if !limiter.GetLimiter(c.ClientIP()).Allow() {
c.JSON(429, gin.H{"error": "请求过于频繁"})
c.Abort()
return
}
}
c.Next()
}
}
JWT 中间件配置集成
Go
func JWTMiddlewareFromConfig(config JWTConfig) gin.HandlerFunc {
if !config.Enabled {
return func(c *gin.Context) { c.Next() }
}
// 构建跳过路径集合
skipPaths := make(map[string]bool)
for _, path := range config.SkipPaths {
skipPaths[path] = true
}
return func(c *gin.Context) {
// 跳过指定路径
if skipPaths[c.Request.URL.Path] {
c.Next()
return
}
token := c.GetHeader("Authorization")
if token == "" {
c.JSON(401, gin.H{"error": "未认证"})
c.Abort()
return
}
claims, err := ParseToken(strings.TrimPrefix(token, "Bearer "), config.Secret)
if err != nil {
c.JSON(401, gin.H{"error": "无效令牌"})
c.Abort()
return
}
c.Set("user_id", claims.UserID)
c.Next()
}
}
安全头部中间件配置集成
Go
func SecurityHeadersMiddlewareFromConfig(config SecurityHeadersConfig) gin.HandlerFunc {
if !config.Enabled {
return func(c *gin.Context) { c.Next() }
}
return func(c *gin.Context) {
for key, value := range config.Headers {
c.Header(key, value)
}
c.Next()
}
}
配置驱动的路由设置
Go
func SetupMiddlewareFromConfig(r *gin.Engine, config *Config) {
// 按配置顺序注册中间件
if config.Middleware.Logging.Enabled {
r.Use(LoggingMiddlewareFromConfig(config.Middleware.Logging))
}
if config.Middleware.SecurityHeaders.Enabled {
r.Use(SecurityHeadersMiddlewareFromConfig(config.Middleware.SecurityHeaders))
}
if config.Middleware.CORS.Enabled {
r.Use(CORSMiddlewareFromConfig(config.Middleware.CORS))
}
if config.Middleware.RateLimit.Enabled {
r.Use(RateLimitMiddlewareFromConfig(config.Middleware.RateLimit))
}
if config.Middleware.JWT.Enabled {
r.Use(JWTMiddlewareFromConfig(config.Middleware.JWT))
}
}
func main() {
config, _ := LoadConfig()
r := gin.New()
SetupMiddlewareFromConfig(r, config)
// 业务路由
r.GET("/api/data", DataHandler)
r.Run(fmt.Sprintf(":%d", config.App.Port))
}
动态配置更新
配置变更中间件响应
Go
type DynamicMiddlewareManager struct {
config *MiddlewareConfig
corsHandler gin.HandlerFunc
rateLimitHandler gin.HandlerFunc
jwtHandler gin.HandlerFunc
}
func NewDynamicMiddlewareManager(config *MiddlewareConfig) *DynamicMiddlewareManager {
mm := &DynamicMiddlewareManager{config: config}
mm.UpdateHandlers()
return mm
}
func (mm *DynamicMiddlewareManager) UpdateHandlers() {
mm.corsHandler = CORSMiddlewareFromConfig(mm.config.CORS)
mm.rateLimitHandler = RateLimitMiddlewareFromConfig(mm.config.RateLimit)
mm.jwtHandler = JWTMiddlewareFromConfig(mm.config.JWT)
}
func (mm *DynamicMiddlewareManager) UpdateConfig(newConfig *MiddlewareConfig) {
mm.config = newConfig
mm.UpdateHandlers()
}
func (mm *DynamicMiddlewareManager) CORS() gin.HandlerFunc {
return func(c *gin.Context) {
mm.corsHandler(c)
}
}
func (mm *DynamicMiddlewareManager) RateLimit() gin.HandlerFunc {
return func(c *gin.Context) {
mm.rateLimitHandler(c)
}
}
热更新配置集成
Go
func SetupDynamicMiddleware(r *gin.Engine, configManager *ConfigManager) {
mm := NewDynamicMiddlewareManager(&configManager.Get().Middleware)
// 注册动态中间件
r.Use(mm.CORS())
r.Use(mm.RateLimit())
// 监听配置变更
configManager.OnChange(func(newConfig *Config) {
mm.UpdateConfig(&newConfig.Middleware)
log.Println("Middleware config updated")
})
}
路径匹配配置
YAML
# config/production.yaml
middleware:
paths:
public:
- /api/login
- /api/register
- /api/health
- /metrics
protected:
- /api/users/*
- /api/admin/*
admin:
- /api/admin/*
Go
type PathConfig struct {
Public []string `mapstructure:"public"`
Protected []string `mapstructure:"protected"`
Admin []string `mapstructure:"admin"`
}
func PathMatchMiddleware(config PathConfig) gin.HandlerFunc {
return func(c *gin.Context) {
path := c.Request.URL.Path
// 检查路径类型
isPublic := matchPaths(config.Public, path)
isAdmin := matchPaths(config.Admin, path)
c.Set("is_public", isPublic)
c.Set("is_admin", isAdmin)
c.Next()
}
}
func matchPaths(patterns []string, path string) bool {
for _, pattern := range patterns {
if strings.HasSuffix(pattern, "*") {
prefix := strings.TrimSuffix(pattern, "*")
if strings.HasPrefix(path, prefix) {
return true
}
}
if path == pattern {
return true
}
}
return false
}
配置验证
Go
func ValidateMiddlewareConfig(config *MiddlewareConfig) error {
// CORS 验证
if config.CORS.Enabled {
if len(config.CORS.Origins) == 0 {
return errors.New("CORS origins required when enabled")
}
}
// Rate Limit 验证
if config.RateLimit.Enabled {
if config.RateLimit.RequestsPerMin < 1 {
return errors.New("rate limit must be positive")
}
}
// JWT 验证
if config.JWT.Enabled {
if config.JWT.Secret == "" {
return errors.New("JWT secret required when enabled")
}
}
return nil
}
配置与中间件映射
| 配置项 | 中间件功能 | 配置参数 |
|---|---|---|
| cors.enabled | CORS 控制 | origins, methods |
| rate_limit.enabled | 速率限制 | requests_per_minute |
| jwt.enabled | JWT 认证 | secret, skip_paths |
| logging.enabled | 日志记录 | level, format |
注意:配置变更后需重新生成中间件处理器,否则使用旧配置。
要点总结
- 配置结构:每个中间件独立配置块
- 开关控制:enabled 字段控制是否启用
- 参数注入:中间件参数从配置读取
- 动态更新:监听配置变更重建中间件
- 路径配置:灵活配置公开/保护路径
- 配置验证:加载后验证必要参数
📝 发现内容有误?点击此处直接编辑