初始化v1
This commit is contained in:
80
api/middleware/auth.go
Normal file
80
api/middleware/auth.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"nl-video-api/internal/consts"
|
||||
"nl-video-api/utility/jwt"
|
||||
"nl-video-api/utility/response"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
// Auth JWT认证中间件
|
||||
func Auth(r *ghttp.Request) {
|
||||
// 获取Authorization头
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader == "" {
|
||||
response.Error(r, response.CodeUnauthorized, "请提供认证令牌")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查Bearer前缀
|
||||
if !strings.HasPrefix(authHeader, "Bearer ") {
|
||||
response.Error(r, response.CodeUnauthorized, "认证令牌格式错误")
|
||||
return
|
||||
}
|
||||
|
||||
// 提取token
|
||||
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
if tokenString == "" {
|
||||
response.Error(r, response.CodeUnauthorized, "认证令牌不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 解析token
|
||||
claims, err := jwt.ParseToken(tokenString)
|
||||
if err != nil {
|
||||
response.Error(r, response.CodeTokenInvalid, "认证令牌无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 将用户信息存储到上下文
|
||||
r.SetCtxVar("user_id", claims.UserID)
|
||||
r.SetCtxVar("username", claims.Username)
|
||||
r.SetCtxVar("user_type", claims.UserType)
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// AdminAuth 管理员认证中间件
|
||||
func AdminAuth(r *ghttp.Request) {
|
||||
// 先执行基础认证
|
||||
Auth(r)
|
||||
if r.Response.Status >= 400 {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户类型
|
||||
userType := r.GetCtxVar("user_type").String()
|
||||
if userType != consts.UserTypeAdmin {
|
||||
response.Error(r, response.CodeForbidden, "需要管理员权限")
|
||||
return
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// OptionalAuth 可选认证中间件(不强制要求登录)
|
||||
func OptionalAuth(r *ghttp.Request) {
|
||||
authHeader := r.Header.Get("Authorization")
|
||||
if authHeader != "" && strings.HasPrefix(authHeader, "Bearer ") {
|
||||
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
if claims, err := jwt.ParseToken(tokenString); err == nil {
|
||||
r.SetCtxVar("user_id", claims.UserID)
|
||||
r.SetCtxVar("username", claims.Username)
|
||||
r.SetCtxVar("user_type", claims.UserType)
|
||||
}
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
19
api/middleware/cors.go
Normal file
19
api/middleware/cors.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
// CORS 跨域处理中间件
|
||||
func CORS(r *ghttp.Request) {
|
||||
// 设置CORS头
|
||||
r.Response.CORSDefault()
|
||||
|
||||
// 处理预检请求
|
||||
if r.Method == "OPTIONS" {
|
||||
r.Response.WriteHeader(200)
|
||||
return
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
54
api/middleware/log.go
Normal file
54
api/middleware/log.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// RequestLog 请求日志中间件
|
||||
func RequestLog(r *ghttp.Request) {
|
||||
start := time.Now()
|
||||
|
||||
// 记录请求开始
|
||||
g.Log().Info(r.Context(),
|
||||
"请求开始",
|
||||
"method", r.Method,
|
||||
"uri", r.RequestURI,
|
||||
"ip", r.GetClientIp(),
|
||||
"user_agent", r.Header.Get("User-Agent"),
|
||||
)
|
||||
|
||||
r.Middleware.Next()
|
||||
|
||||
// 记录请求结束
|
||||
duration := time.Since(start)
|
||||
g.Log().Info(r.Context(),
|
||||
"请求结束",
|
||||
"method", r.Method,
|
||||
"uri", r.RequestURI,
|
||||
"status", r.Response.Status,
|
||||
"duration", duration.String(),
|
||||
"ip", r.GetClientIp(),
|
||||
)
|
||||
}
|
||||
|
||||
// ErrorLog 错误日志中间件
|
||||
func ErrorLog(r *ghttp.Request) {
|
||||
r.Middleware.Next()
|
||||
|
||||
// 如果有错误,记录详细信息
|
||||
if r.Response.Status >= 400 {
|
||||
g.Log().Error(r.Context(),
|
||||
"请求错误",
|
||||
"method", r.Method,
|
||||
"uri", r.RequestURI,
|
||||
"status", r.Response.Status,
|
||||
"ip", r.GetClientIp(),
|
||||
"user_agent", r.Header.Get("User-Agent"),
|
||||
"time", gtime.Now().String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
221
api/middleware/permission.go
Normal file
221
api/middleware/permission.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"nl-video-api/internal/service/auth"
|
||||
"nl-video-api/utility/jwt"
|
||||
"nl-video-api/utility/response"
|
||||
)
|
||||
|
||||
// PermissionMiddleware 权限验证中间件
|
||||
func PermissionMiddleware(r *ghttp.Request) {
|
||||
// 获取请求路径和方法
|
||||
apiPath := r.URL.Path
|
||||
method := r.Method
|
||||
|
||||
// 跳过不需要权限验证的路径
|
||||
skipPaths := []string{
|
||||
"/api/v1/auth/login",
|
||||
"/api/v1/auth/register",
|
||||
"/api/v1/admin/login",
|
||||
"/api/v1/admin/register",
|
||||
}
|
||||
|
||||
for _, skipPath := range skipPaths {
|
||||
if apiPath == skipPath {
|
||||
r.Middleware.Next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 获取Token
|
||||
token := r.Header.Get("Authorization")
|
||||
if token == "" {
|
||||
response.Error(r, 1002, "请先登录")
|
||||
return
|
||||
}
|
||||
|
||||
// 移除Bearer前缀
|
||||
if strings.HasPrefix(token, "Bearer ") {
|
||||
token = strings.TrimPrefix(token, "Bearer ")
|
||||
}
|
||||
|
||||
// 验证Token
|
||||
claims, err := jwt.ParseToken(token)
|
||||
if err != nil {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户ID
|
||||
userId := int(claims.UserID)
|
||||
if userId <= 0 {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查API权限
|
||||
hasPermission, err := auth.Permission.CheckApiPermission(r.Context(), userId, apiPath, method)
|
||||
if err != nil {
|
||||
g.Log().Errorf(r.Context(), "权限检查失败: %v", err)
|
||||
response.Error(r, 1004, "权限检查失败")
|
||||
return
|
||||
}
|
||||
|
||||
if !hasPermission {
|
||||
response.Error(r, 1004, "没有访问权限")
|
||||
return
|
||||
}
|
||||
|
||||
// 将用户ID存储到上下文中
|
||||
r.SetCtxVar("user_id", userId)
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// RolePermissionMiddleware 角色权限验证中间件
|
||||
func RolePermissionMiddleware(requiredRole string) func(r *ghttp.Request) {
|
||||
return func(r *ghttp.Request) {
|
||||
// 获取Token
|
||||
token := r.Header.Get("Authorization")
|
||||
if token == "" {
|
||||
response.Error(r, 1002, "请先登录")
|
||||
return
|
||||
}
|
||||
|
||||
// 移除Bearer前缀
|
||||
if strings.HasPrefix(token, "Bearer ") {
|
||||
token = strings.TrimPrefix(token, "Bearer ")
|
||||
}
|
||||
|
||||
// 验证Token
|
||||
claims, err := jwt.ParseToken(token)
|
||||
if err != nil {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取用户角色
|
||||
userRole := claims.UserType
|
||||
if userRole == "" {
|
||||
response.Error(r, 1004, "用户角色信息无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查角色权限
|
||||
if userRole != requiredRole && userRole != "super_admin" {
|
||||
response.Error(r, 1004, "没有访问权限")
|
||||
return
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// AdminPermissionMiddleware 管理员权限验证中间件
|
||||
func AdminPermissionMiddleware(r *ghttp.Request) {
|
||||
// 获取Token
|
||||
token := r.Header.Get("Authorization")
|
||||
if token == "" {
|
||||
response.Error(r, 1002, "请先登录")
|
||||
return
|
||||
}
|
||||
|
||||
// 移除Bearer前缀
|
||||
if strings.HasPrefix(token, "Bearer ") {
|
||||
token = strings.TrimPrefix(token, "Bearer ")
|
||||
}
|
||||
|
||||
// 验证Token
|
||||
claims, err := jwt.ParseToken(token)
|
||||
if err != nil {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为管理员Token
|
||||
userType := claims.UserType
|
||||
if userType != "admin" {
|
||||
response.Error(r, 1004, "需要管理员权限")
|
||||
return
|
||||
}
|
||||
|
||||
// 获取管理员ID
|
||||
adminId := int(claims.UserID)
|
||||
if adminId <= 0 {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 将管理员ID存储到上下文中
|
||||
r.SetCtxVar("admin_id", adminId)
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// CheckPermissionCode 检查权限编码中间件
|
||||
func CheckPermissionCode(permissionCode string) func(r *ghttp.Request) {
|
||||
return func(r *ghttp.Request) {
|
||||
// 获取用户ID
|
||||
userId := r.GetCtxVar("user_id")
|
||||
if userId == nil {
|
||||
response.Error(r, 1002, "请先登录")
|
||||
return
|
||||
}
|
||||
|
||||
userIdInt := userId.Int()
|
||||
if userIdInt <= 0 {
|
||||
response.Error(r, 1002, "用户信息无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查权限
|
||||
hasPermission, err := auth.Permission.CheckUserPermission(r.Context(), userIdInt, permissionCode)
|
||||
if err != nil {
|
||||
g.Log().Errorf(r.Context(), "权限检查失败: %v", err)
|
||||
response.Error(r, 1004, "权限检查失败")
|
||||
return
|
||||
}
|
||||
|
||||
if !hasPermission {
|
||||
response.Error(r, 1004, "没有访问权限")
|
||||
return
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// SuperAdminMiddleware 超级管理员权限验证中间件
|
||||
func SuperAdminMiddleware(r *ghttp.Request) {
|
||||
// 获取Token
|
||||
token := r.Header.Get("Authorization")
|
||||
if token == "" {
|
||||
response.Error(r, 1002, "请先登录")
|
||||
return
|
||||
}
|
||||
|
||||
// 移除Bearer前缀
|
||||
if strings.HasPrefix(token, "Bearer ") {
|
||||
token = strings.TrimPrefix(token, "Bearer ")
|
||||
}
|
||||
|
||||
// 验证Token
|
||||
claims, err := jwt.ParseToken(token)
|
||||
if err != nil {
|
||||
response.Error(r, 1003, "Token无效")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否为超级管理员
|
||||
role := claims.UserType
|
||||
if role != "super_admin" {
|
||||
response.Error(r, 1004, "需要超级管理员权限")
|
||||
return
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
60
api/middleware/rate_limit.go
Normal file
60
api/middleware/rate_limit.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nl-video-api/utility/response"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gredis"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
// RateLimit 限流中间件
|
||||
func RateLimit(maxRequests int, window time.Duration) func(r *ghttp.Request) {
|
||||
return func(r *ghttp.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
client = g.Redis()
|
||||
key = fmt.Sprintf("rate_limit:%s", r.GetClientIp())
|
||||
)
|
||||
|
||||
// 获取当前请求次数
|
||||
count, err := client.Get(ctx, key)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, "Redis获取失败:", err)
|
||||
r.Middleware.Next()
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否超过限制
|
||||
if count.Int() >= maxRequests {
|
||||
response.Error(r, response.CodeError, "请求过于频繁,请稍后再试")
|
||||
return
|
||||
}
|
||||
|
||||
// 增加计数
|
||||
if count.Int() == 0 {
|
||||
// 第一次请求,设置过期时间
|
||||
seconds := int64(window.Seconds())
|
||||
client.Set(ctx, key, 1, gredis.SetOption{
|
||||
TTLOption: gredis.TTLOption{EX: &seconds},
|
||||
})
|
||||
} else {
|
||||
// 增加计数
|
||||
client.Incr(ctx, key)
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// APIRateLimit API接口限流(每分钟60次)
|
||||
func APIRateLimit(r *ghttp.Request) {
|
||||
RateLimit(60, time.Minute)(r)
|
||||
}
|
||||
|
||||
// LoginRateLimit 登录接口限流(每分钟5次)
|
||||
func LoginRateLimit(r *ghttp.Request) {
|
||||
RateLimit(5, time.Minute)(r)
|
||||
}
|
||||
160
api/middleware/request_log.go
Normal file
160
api/middleware/request_log.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"nl-video-api/utility/logger"
|
||||
)
|
||||
|
||||
// RequestLogger 请求日志中间件
|
||||
func RequestLogger(r *ghttp.Request) {
|
||||
// 记录请求开始时间
|
||||
startTime := time.Now()
|
||||
|
||||
// 获取请求信息
|
||||
method := r.Method
|
||||
uri := r.RequestURI
|
||||
ip := r.GetClientIp()
|
||||
userAgent := r.Header.Get("User-Agent")
|
||||
|
||||
// 读取请求体
|
||||
var requestBody []byte
|
||||
if r.GetBodyString() != "" {
|
||||
requestBody = []byte(r.GetBodyString())
|
||||
}
|
||||
|
||||
// 记录请求开始日志
|
||||
logger.LogInfo(r.Context(), "请求开始 | Method: %s | URI: %s | IP: %s | UserAgent: %s | Body: %s",
|
||||
method, uri, ip, userAgent, string(requestBody))
|
||||
|
||||
// 继续处理请求
|
||||
r.Middleware.Next()
|
||||
|
||||
// 计算请求处理时间
|
||||
duration := time.Since(startTime)
|
||||
|
||||
// 获取响应状态码
|
||||
status := r.Response.Status
|
||||
|
||||
// 获取响应内容(简化处理)
|
||||
responseBody := ""
|
||||
|
||||
// 记录请求完成日志
|
||||
logger.LogInfo(r.Context(), "请求完成 | Method: %s | URI: %s | IP: %s | Status: %d | Duration: %v | Response: %s",
|
||||
method, uri, ip, status, duration, responseBody)
|
||||
|
||||
// 如果是错误状态码,记录错误日志
|
||||
if status >= 400 {
|
||||
logger.LogError(r.Context(), "请求错误 | Method: %s | URI: %s | IP: %s | Status: %d | Duration: %v | Response: %s",
|
||||
method, uri, ip, status, duration, responseBody)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ErrorLogger 错误日志中间件
|
||||
func ErrorLogger(r *ghttp.Request) {
|
||||
// 使用defer捕获panic
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
// 记录panic错误
|
||||
logger.LogPanic(r.Context(), "请求panic | Method: %s | URI: %s | IP: %s | Error: %v",
|
||||
r.Method, r.RequestURI, r.GetClientIp(), err)
|
||||
|
||||
// 返回统一错误响应
|
||||
r.Response.WriteJsonExit(g.Map{
|
||||
"code": 5000,
|
||||
"msg": "服务器内部错误",
|
||||
"result": nil,
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
// 继续处理请求
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
// BusinessLogger 业务日志记录器
|
||||
func LogBusinessOperation(ctx context.Context, module string, operation string, userId interface{}, params interface{}, result interface{}, err error) {
|
||||
fields := g.Map{
|
||||
"module": module,
|
||||
"operation": operation,
|
||||
"user_id": userId,
|
||||
"params": gconv.String(params),
|
||||
"result": gconv.String(result),
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fields["error"] = err.Error()
|
||||
logger.LogWithFields(ctx, "error", "error", "业务操作失败", fields)
|
||||
} else {
|
||||
logger.LogWithFields(ctx, "log", "info", "业务操作成功", fields)
|
||||
}
|
||||
}
|
||||
|
||||
// AuthLogger 认证日志记录器
|
||||
func LogAuthOperation(ctx context.Context, operation string, username string, ip string, userAgent string, success bool, err error) {
|
||||
fields := g.Map{
|
||||
"operation": operation,
|
||||
"username": username,
|
||||
"ip": ip,
|
||||
"user_agent": userAgent,
|
||||
"success": success,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fields["error"] = err.Error()
|
||||
logger.LogWithFields(ctx, "error", "error", "认证操作失败", fields)
|
||||
} else {
|
||||
logger.LogWithFields(ctx, "log", "info", "认证操作成功", fields)
|
||||
}
|
||||
}
|
||||
|
||||
// APILogger API调用日志记录器
|
||||
func LogAPICall(ctx context.Context, api string, method string, params interface{}, response interface{}, duration time.Duration, err error) {
|
||||
fields := g.Map{
|
||||
"api": api,
|
||||
"method": method,
|
||||
"params": gconv.String(params),
|
||||
"response": gconv.String(response),
|
||||
"duration": duration.String(),
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fields["error"] = err.Error()
|
||||
logger.LogWithFields(ctx, "error", "error", "API调用失败", fields)
|
||||
} else {
|
||||
logger.LogWithFields(ctx, "log", "info", "API调用成功", fields)
|
||||
}
|
||||
}
|
||||
|
||||
// ValidationLogger 参数验证日志记录器
|
||||
func LogValidationError(ctx context.Context, field string, value interface{}, rule string, message string) {
|
||||
fields := g.Map{
|
||||
"field": field,
|
||||
"value": gconv.String(value),
|
||||
"rule": rule,
|
||||
"message": message,
|
||||
}
|
||||
|
||||
logger.LogWithFields(ctx, "error", "warn", "参数验证失败", fields)
|
||||
}
|
||||
|
||||
// PerformanceLogger 性能日志记录器
|
||||
func LogPerformance(ctx context.Context, operation string, duration time.Duration, threshold time.Duration) {
|
||||
fields := g.Map{
|
||||
"operation": operation,
|
||||
"duration": duration.String(),
|
||||
"threshold": threshold.String(),
|
||||
"slow": duration > threshold,
|
||||
}
|
||||
|
||||
if duration > threshold {
|
||||
logger.LogWithFields(ctx, "error", "warn", "慢操作检测", fields)
|
||||
} else {
|
||||
logger.LogWithFields(ctx, "log", "debug", "性能监控", fields)
|
||||
}
|
||||
}
|
||||
74
api/middleware/response.go
Normal file
74
api/middleware/response.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"nl-video-api/utility/response"
|
||||
)
|
||||
|
||||
// ResponseHandler 全局响应处理中间件
|
||||
// 确保所有响应都返回HTTP 200状态码,错误信息通过code和message字段传递
|
||||
func ResponseHandler(r *ghttp.Request) {
|
||||
// 设置默认响应头
|
||||
r.Response.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// 继续执行后续中间件和处理函数
|
||||
r.Middleware.Next()
|
||||
|
||||
// 检查响应状态码,如果不是200,则转换为统一格式
|
||||
if r.Response.Status != 200 {
|
||||
// 获取原始状态码
|
||||
originalStatus := r.Response.Status
|
||||
|
||||
// 根据HTTP状态码映射到业务错误码
|
||||
var businessCode int
|
||||
var message string
|
||||
|
||||
switch originalStatus {
|
||||
case 400:
|
||||
businessCode = response.CodeInvalidParam
|
||||
message = "请求参数错误"
|
||||
case 401:
|
||||
businessCode = response.CodeUnauthorized
|
||||
message = "未授权访问"
|
||||
case 403:
|
||||
businessCode = response.CodeForbidden
|
||||
message = "权限不足"
|
||||
case 404:
|
||||
businessCode = response.CodeNotFound
|
||||
message = "资源不存在"
|
||||
case 500:
|
||||
businessCode = response.CodeServerError
|
||||
message = "服务器内部错误"
|
||||
default:
|
||||
businessCode = response.CodeError
|
||||
message = "请求处理失败"
|
||||
}
|
||||
|
||||
// 清空原有响应内容
|
||||
r.Response.ClearBuffer()
|
||||
|
||||
// 返回统一格式的错误响应,HTTP状态码为200
|
||||
response.Error(r, businessCode, message)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorHandler 错误处理中间件
|
||||
// 捕获panic和其他未处理的错误,统一返回格式
|
||||
func ErrorHandler(r *ghttp.Request) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
// 记录错误日志
|
||||
g.Log().Errorf(r.Context(), "Panic recovered: %v", err)
|
||||
|
||||
// 清空响应缓冲区
|
||||
r.Response.ClearBuffer()
|
||||
|
||||
// 返回统一格式的错误响应
|
||||
response.Error(r, response.CodeServerError, "系统内部错误")
|
||||
}
|
||||
}()
|
||||
|
||||
// 继续执行后续中间件和处理函数
|
||||
r.Middleware.Next()
|
||||
}
|
||||
Reference in New Issue
Block a user