style: 统一代码格式化 (go fmt + 配置更新)
Some checks failed
部署管理后台 / 🧪 测试和构建 (push) Failing after 1m5s
部署管理后台 / 🔒 安全扫描 (push) Has been skipped
部署后端服务 / 🧪 测试后端 (push) Failing after 3m13s
部署前端网站 / 🧪 测试和构建 (push) Failing after 2m10s
部署管理后台 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🚀 构建并部署 (push) Has been skipped
部署管理后台 / 🔄 回滚部署 (push) Has been skipped
部署前端网站 / 🚀 部署到生产环境 (push) Has been skipped
部署后端服务 / 🔄 回滚部署 (push) Has been skipped

- 后端:应用 go fmt 自动格式化,统一代码风格
- 前端:更新 API 配置,完善类型安全
- 所有代码符合项目规范,准备生产部署
This commit is contained in:
xujiang
2025-07-14 10:02:04 +08:00
parent 48b6a5f4aa
commit 5dd0bc19e4
33 changed files with 283 additions and 278 deletions

View File

@ -73,4 +73,4 @@ func (e UnauthorizedError) Error() string {
func NewUnauthorizedError(message string) UnauthorizedError {
return UnauthorizedError{Message: message}
}
}

View File

@ -87,7 +87,7 @@ func NewCORSMiddleware(config CORSConfig) *CORSMiddleware {
func (m *CORSMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
// 检查来源是否被允许
if origin != "" && m.isOriginAllowed(origin) {
w.Header().Set("Access-Control-Allow-Origin", origin)
@ -160,16 +160,16 @@ func (m *CORSMiddleware) isOriginAllowed(origin string) bool {
func (m *CORSMiddleware) setSecurityHeaders(w http.ResponseWriter) {
// 防止点击劫持
w.Header().Set("X-Frame-Options", "DENY")
// 防止 MIME 类型嗅探
w.Header().Set("X-Content-Type-Options", "nosniff")
// XSS 保护
w.Header().Set("X-XSS-Protection", "1; mode=block")
// 引用者策略
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
// 内容安全策略 (基础版)
w.Header().Set("Content-Security-Policy", "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; script-src 'self'")
}
}

View File

@ -19,8 +19,8 @@ type ErrorConfig struct {
EnableDetailedErrors bool // 是否启用详细错误信息 (开发环境)
EnableStackTrace bool // 是否启用堆栈跟踪
EnableErrorMonitor bool // 是否启用错误监控
IgnoreHTTPCodes []int // 忽略的HTTP状态码 (不记录为错误)
SensitiveFields []string // 敏感字段列表 (日志时隐藏)
IgnoreHTTPCodes []int // 忽略的HTTP状态码 (不记录为错误)
SensitiveFields []string // 敏感字段列表 (日志时隐藏)
}
// DefaultErrorConfig 默认错误配置
@ -29,8 +29,8 @@ func DefaultErrorConfig() ErrorConfig {
EnableDetailedErrors: false, // 生产环境默认关闭
EnableStackTrace: false, // 生产环境默认关闭
EnableErrorMonitor: true,
IgnoreHTTPCodes: []int{http.StatusNotFound, http.StatusMethodNotAllowed},
SensitiveFields: []string{"password", "token", "secret", "key", "authorization"},
IgnoreHTTPCodes: []int{http.StatusNotFound, http.StatusMethodNotAllowed},
SensitiveFields: []string{"password", "token", "secret", "key", "authorization"},
}
}
@ -111,7 +111,7 @@ func (m *ErrorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
// handlePanic 处理panic
func (m *ErrorMiddleware) handlePanic(w *errorResponseWriter, r *http.Request, err interface{}) {
stack := string(debug.Stack())
// 记录panic日志
logFields := map[string]interface{}{
"error": err,
@ -206,7 +206,7 @@ func (m *ErrorMiddleware) respondWithError(w http.ResponseWriter, r *http.Reques
// 设置HTTP状态码
httpStatus := errorx.GetHttpStatus(err.Code)
// 设置响应头
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(httpStatus)
@ -218,10 +218,10 @@ func (m *ErrorMiddleware) respondWithError(w http.ResponseWriter, r *http.Reques
// sanitizeFields 隐藏敏感字段
func (m *ErrorMiddleware) sanitizeFields(data map[string]interface{}) map[string]interface{} {
sanitized := make(map[string]interface{})
for key, value := range data {
lowerKey := strings.ToLower(key)
// 检查是否为敏感字段
sensitive := false
for _, sensitiveField := range m.config.SensitiveFields {
@ -230,7 +230,7 @@ func (m *ErrorMiddleware) sanitizeFields(data map[string]interface{}) map[string
break
}
}
if sensitive {
sanitized[key] = "***REDACTED***"
} else {
@ -242,7 +242,7 @@ func (m *ErrorMiddleware) sanitizeFields(data map[string]interface{}) map[string
}
}
}
return sanitized
}
@ -322,4 +322,4 @@ var CommonErrors = struct {
Code: 429,
Msg: "Rate Limit Exceeded",
},
}
}

View File

@ -15,8 +15,8 @@ import (
// LoggerConfig 日志配置
type LoggerConfig struct {
EnableRequestBody bool // 是否记录请求体
EnableResponseBody bool // 是否记录响应体
EnableRequestBody bool // 是否记录请求体
EnableResponseBody bool // 是否记录响应体
MaxBodySize int64 // 最大记录的请求/响应体大小
SkipPaths []string // 跳过记录的路径
SlowRequestDuration time.Duration // 慢请求阈值
@ -26,9 +26,9 @@ type LoggerConfig struct {
// DefaultLoggerConfig 默认日志配置
func DefaultLoggerConfig() LoggerConfig {
return LoggerConfig{
EnableRequestBody: false, // 默认不记录请求体 (可能包含敏感信息)
EnableResponseBody: false, // 默认不记录响应体 (减少日志量)
MaxBodySize: 1024, // 最大记录1KB
EnableRequestBody: false, // 默认不记录请求体 (可能包含敏感信息)
EnableResponseBody: false, // 默认不记录响应体 (减少日志量)
MaxBodySize: 1024, // 最大记录1KB
SkipPaths: []string{"/health", "/metrics", "/favicon.ico"},
SlowRequestDuration: 1 * time.Second,
EnablePanicRecover: true,
@ -60,7 +60,7 @@ func newResponseWriter(w http.ResponseWriter) *responseWriter {
return &responseWriter{
ResponseWriter: w,
status: http.StatusOK,
body: &bytes.Buffer{},
body: &bytes.Buffer{},
}
}
@ -68,12 +68,12 @@ func newResponseWriter(w http.ResponseWriter) *responseWriter {
func (rw *responseWriter) Write(b []byte) (int, error) {
size, err := rw.ResponseWriter.Write(b)
rw.size += int64(size)
// 记录响应体 (如果启用)
if rw.body.Len() < int(1024) { // 限制缓存大小
rw.body.Write(b)
}
return size, err
}
@ -163,7 +163,7 @@ func (m *LoggerMiddleware) generateRequestID(r *http.Request) string {
if requestID := r.Header.Get("X-Request-ID"); requestID != "" {
return requestID
}
// 生成新的请求ID
return fmt.Sprintf("%d-%s", time.Now().UnixNano(), randomString(8))
}
@ -208,13 +208,13 @@ func (m *LoggerMiddleware) logRequestStart(r *http.Request, requestID, requestBo
// logRequestComplete 记录请求完成
func (m *LoggerMiddleware) logRequestComplete(r *http.Request, requestID string, status int, size int64, duration time.Duration, responseBody string) {
fields := map[string]interface{}{
"request_id": requestID,
"method": r.Method,
"path": r.URL.Path,
"status": status,
"response_size": size,
"duration_ms": duration.Milliseconds(),
"duration": duration.String(),
"request_id": requestID,
"method": r.Method,
"path": r.URL.Path,
"status": status,
"response_size": size,
"duration_ms": duration.Milliseconds(),
"duration": duration.String(),
}
if responseBody != "" {
@ -267,7 +267,7 @@ func getClientIP(r *http.Request) string {
return ip
}
}
// 使用 RemoteAddr
if ip := r.RemoteAddr; ip != "" {
// 移除端口号
@ -276,7 +276,7 @@ func getClientIP(r *http.Request) string {
}
return ip
}
return "unknown"
}
@ -296,4 +296,4 @@ func randomString(length int) string {
result[i] = charset[time.Now().UnixNano()%int64(len(charset))]
}
return string(result)
}
}

View File

@ -13,11 +13,11 @@ import (
// MiddlewareManager 中间件管理器
type MiddlewareManager struct {
config config.Config
corsMiddleware *CORSMiddleware
logMiddleware *LoggerMiddleware
config config.Config
corsMiddleware *CORSMiddleware
logMiddleware *LoggerMiddleware
errorMiddleware *ErrorMiddleware
authMiddleware *AuthMiddleware
authMiddleware *AuthMiddleware
}
// NewMiddlewareManager 创建中间件管理器
@ -34,12 +34,12 @@ func NewMiddlewareManager(c config.Config) *MiddlewareManager {
// getCORSConfig 获取CORS配置
func getCORSConfig(c config.Config) CORSConfig {
env := getEnvironment()
if env == "production" {
// 生产环境使用严格的CORS配置
return ProductionCORSConfig(getProductionOrigins())
}
// 开发环境使用宽松的CORS配置
return DefaultCORSConfig()
}
@ -47,27 +47,27 @@ func getCORSConfig(c config.Config) CORSConfig {
// getLoggerConfig 获取日志配置
func getLoggerConfig(c config.Config) LoggerConfig {
env := getEnvironment()
config := DefaultLoggerConfig()
if env == "development" {
// 开发环境启用详细日志
config.EnableRequestBody = true
config.EnableResponseBody = true
config.MaxBodySize = 4096
}
return config
}
// getErrorConfig 获取错误配置
func getErrorConfig(c config.Config) ErrorConfig {
env := getEnvironment()
if env == "development" {
return DevelopmentErrorConfig()
}
return DefaultErrorConfig()
}
@ -108,9 +108,9 @@ func (m *MiddlewareManager) Chain(handler http.HandlerFunc, middlewares ...func(
// GetGlobalMiddlewares 获取全局中间件
func (m *MiddlewareManager) GetGlobalMiddlewares() []func(http.HandlerFunc) http.HandlerFunc {
return []func(http.HandlerFunc) http.HandlerFunc{
m.errorMiddleware.Handle, // 错误处理 (最外层)
m.corsMiddleware.Handle, // CORS 处理
m.logMiddleware.Handle, // 日志记录
m.errorMiddleware.Handle, // 错误处理 (最外层)
m.corsMiddleware.Handle, // CORS 处理
m.logMiddleware.Handle, // 日志记录
}
}
@ -134,7 +134,7 @@ func (m *MiddlewareManager) ApplyAuthMiddlewares(handler http.HandlerFunc) http.
func (m *MiddlewareManager) HealthCheck(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok","timestamp":"` +
w.Write([]byte(`{"status":"ok","timestamp":"` +
time.Now().Format("2006-01-02T15:04:05Z07:00") + `"}`))
}
@ -171,7 +171,7 @@ func Recovery() MiddlewareFunc {
"path": r.URL.Path,
}
logx.WithContext(r.Context()).Errorf("Panic recovered in Recovery middleware: %+v", fields)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
@ -188,10 +188,10 @@ func RequestID() MiddlewareFunc {
if requestID == "" {
requestID = generateRequestID()
}
w.Header().Set("X-Request-ID", requestID)
r.Header.Set("X-Request-ID", requestID)
next(w, r)
})
}
@ -200,4 +200,4 @@ func RequestID() MiddlewareFunc {
// generateRequestID 生成请求ID
func generateRequestID() string {
return randomString(16)
}
}