package main import ( "log" "net/http" "time" "git.toowon.com/jimmy/go-common/config" commonhttp "git.toowon.com/jimmy/go-common/http" "git.toowon.com/jimmy/go-common/logger" "git.toowon.com/jimmy/go-common/middleware" ) // 示例:完整的中间件配置 // 包括:Recovery、Logging、RateLimit、CORS、Timezone func main() { // 1. 配置logger(异步模式,输出到文件和stdout) loggerConfig := &logger.LoggerConfig{ Level: "info", Output: "both", // 同时输出到stdout和文件 FilePath: "./logs/app.log", Async: true, // 异步模式 BufferSize: 1000, // 缓冲区大小 Prefix: "[API]", // 日志前缀 } myLogger, err := logger.NewLogger(loggerConfig) if err != nil { log.Fatal("Failed to create logger:", err) } defer myLogger.Close() // 确保程序退出时关闭logger // 2. 配置CORS corsConfig := &middleware.CORSConfig{ AllowedOrigins: []string{"*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"Content-Type", "Authorization", "X-Timezone"}, ExposedHeaders: []string{"X-Total-Count"}, AllowCredentials: false, MaxAge: 3600, // 1小时 } // 3. 配置日志中间件 loggingConfig := &middleware.LoggingConfig{ Logger: myLogger, SkipPaths: []string{"/health", "/metrics"}, // 跳过健康检查和监控接口 } // 4. 配置Recovery中间件 recoveryConfig := &middleware.RecoveryConfig{ Logger: myLogger, EnableStackTrace: true, // 启用堆栈跟踪 CustomHandler: func(w http.ResponseWriter, r *http.Request, err interface{}) { // 使用统一的JSON响应格式 h := commonhttp.NewHandler(w, r) h.SystemError("服务器内部错误,请稍后重试") }, } // 5. 配置限流中间件(100请求/分钟) rateLimiter := middleware.NewTokenBucketLimiter(100, time.Minute) rateLimitConfig := &middleware.RateLimitConfig{ Limiter: rateLimiter, OnRateLimitExceeded: func(w http.ResponseWriter, r *http.Request, key string) { // 记录限流事件 myLogger.Warnf(map[string]interface{}{ "key": key, "path": r.URL.Path, "ip": r.RemoteAddr, }, "Rate limit exceeded") }, } // 6. 创建中间件链(顺序很重要!) // 顺序:Recovery -> Logging -> RateLimit -> CORS -> Timezone chain := middleware.NewChain( middleware.Recovery(recoveryConfig), // 1. 最外层:捕获panic middleware.Logging(loggingConfig), // 2. 日志记录 middleware.RateLimit(rateLimitConfig), // 3. 限流保护 middleware.CORS(corsConfig), // 4. CORS处理 middleware.Timezone, // 5. 时区处理 ) // 7. 定义路由 mux := http.NewServeMux() // API路由(应用所有中间件) mux.Handle("/api/hello", chain.ThenFunc(handleHello)) mux.Handle("/api/panic", chain.ThenFunc(handlePanic)) // 测试panic恢复 mux.Handle("/api/users", chain.ThenFunc(handleUsers)) // 健康检查(不应用中间件链,直接处理) mux.HandleFunc("/health", handleHealth) mux.HandleFunc("/metrics", handleMetrics) // 8. 启动服务器 addr := ":8080" log.Printf("Server starting on %s", addr) log.Printf("Try: http://localhost%s/api/hello", addr) log.Printf("Health: http://localhost%s/health", addr) if err := http.ListenAndServe(addr, mux); err != nil { log.Fatal("Server failed:", err) } } // handleHello 示例处理器:返回问候信息 func handleHello(w http.ResponseWriter, r *http.Request) { h := commonhttp.NewHandler(w, r) // 从Handler获取时区 timezone := h.GetTimezone() h.Success(map[string]interface{}{ "message": "Hello, World!", "timezone": timezone, "method": r.Method, "path": r.URL.Path, }) } // handlePanic 示例处理器:测试panic恢复 func handlePanic(w http.ResponseWriter, r *http.Request) { // 故意触发panic,测试Recovery中间件 panic("This is a test panic!") } // handleUsers 示例处理器:返回用户列表 func handleUsers(w http.ResponseWriter, r *http.Request) { h := commonhttp.NewHandler(w, r) // 模拟用户数据 users := []map[string]interface{}{ {"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 3, "name": "Charlie"}, } h.Success(users) } // handleHealth 健康检查处理器(不应用中间件) func handleHealth(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } // handleMetrics 监控指标处理器(不应用中间件) func handleMetrics(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) w.Write([]byte("metrics: ok")) }