fix:: 请求响应码用常量

This commit is contained in:
TsMask
2025-06-07 16:32:04 +08:00
parent c67fbb7998
commit 33b95a6e30
73 changed files with 441 additions and 375 deletions

View File

@@ -20,14 +20,14 @@ func ErrorCatch() gin.HandlerFunc {
// 返回错误响应给客户端
if config.Env() == "prod" {
c.JSON(500, resp.CodeMsg(500001, "Internal Server Errors"))
c.JSON(500, resp.CodeMsg(resp.CODE_INTERNAL, resp.MSG_INTERNAL))
} else {
// 通过实现 error 接口的 Error() 方法自定义错误类型进行捕获
switch v := err.(type) {
case error:
c.JSON(500, resp.CodeMsg(500001, v.Error()))
c.JSON(500, resp.CodeMsg(resp.CODE_INTERNAL, v.Error()))
default:
c.JSON(500, resp.CodeMsg(500001, fmt.Sprint(err)))
c.JSON(500, resp.CodeMsg(resp.CODE_INTERNAL, fmt.Sprint(err)))
}
}

View File

@@ -19,7 +19,7 @@ func AuthorizeOauth2(scope []string) gin.HandlerFunc {
// 获取请求头标识信息
tokenStr := reqctx.Authorization(c)
if tokenStr == "" {
c.JSON(401, resp.CodeMsg(401003, "authorization token is empty"))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_NOTOKEN, "authorization token is empty"))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -27,7 +27,7 @@ func AuthorizeOauth2(scope []string) gin.HandlerFunc {
// 验证令牌
claims, err := token.Oauth2TokenVerify(tokenStr, "access")
if err != nil {
c.JSON(401, resp.CodeMsg(401001, err.Error()))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH, err.Error()))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -35,7 +35,7 @@ func AuthorizeOauth2(scope []string) gin.HandlerFunc {
// 获取缓存的用户信息
info := token.Oauth2InfoGet(claims)
if info.ClientId == "" {
c.JSON(401, resp.CodeMsg(401002, "invalid login user information"))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, "invalid login user information"))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -54,7 +54,7 @@ func AuthorizeOauth2(scope []string) gin.HandlerFunc {
}
if !hasScope {
msg := fmt.Sprintf("unauthorized access %s %s", c.Request.Method, c.Request.RequestURI)
c.JSON(403, resp.CodeMsg(403001, msg))
c.JSON(403, resp.CodeMsg(resp.CODE_PERMISSION, msg))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -68,7 +68,7 @@ func AuthorizeUser(options map[string][]string) gin.HandlerFunc {
// 获取请求头标识信息
tokenStr := reqctx.Authorization(c)
if tokenStr == "" {
c.JSON(401, resp.CodeMsg(401003, "authorization token is empty"))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_NOTOKEN, "authorization token is empty"))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -76,7 +76,7 @@ func AuthorizeUser(options map[string][]string) gin.HandlerFunc {
// 验证令牌
claims, err := token.UserTokenVerify(tokenStr, "access")
if err != nil {
c.JSON(401, resp.CodeMsg(401001, err.Error()))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH, err.Error()))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -84,7 +84,7 @@ func AuthorizeUser(options map[string][]string) gin.HandlerFunc {
// 获取缓存的用户信息
info := token.UserInfoGet(claims)
if info.UserId <= 0 {
c.JSON(401, resp.CodeMsg(401002, "invalid login user information"))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, "invalid login user information"))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -100,7 +100,7 @@ func AuthorizeUser(options map[string][]string) gin.HandlerFunc {
verifyOk := verifyRolePermission(roles, perms, options)
if !verifyOk {
msg := fmt.Sprintf("unauthorized access %s %s", c.Request.Method, c.Request.RequestURI)
c.JSON(403, resp.CodeMsg(403001, msg))
c.JSON(403, resp.CodeMsg(resp.CODE_PERMISSION, msg))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -103,7 +103,7 @@ func OperateLog(options Options) gin.HandlerFunc {
// 获取登录用户信息
loginUser, err := reqctx.LoginUser(c)
if err != nil {
c.JSON(401, resp.CodeMsg(401002, i18n.TKey(language, err.Error())))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, i18n.TKey(language, err.Error())))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -51,7 +51,7 @@ func CryptoApi(requestDecrypt, responseEncrypt bool) gin.HandlerFunc {
// 是否存在data字段数据
if contentDe == "" {
c.JSON(422, resp.CodeMsg(422002, "decrypt not found field data"))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_CHEACK, "decrypt not found field data"))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -61,7 +61,7 @@ func CryptoApi(requestDecrypt, responseEncrypt bool) gin.HandlerFunc {
dataBodyStr, err := crypto.AESDecryptBase64(contentDe, apiKey)
if err != nil {
logger.Errorf("CryptoApi decrypt err => %v", err)
c.JSON(422, resp.CodeMsg(422001, "decrypted data could not be parsed"))
c.JSON(422, resp.CodeMsg(resp.CODE_PARAM_PARSER, "decrypted data could not be parsed"))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -88,7 +88,7 @@ func OperateLog(options Options) gin.HandlerFunc {
// 获取登录用户信息
loginUser, err := reqctx.LoginUser(c)
if err != nil {
c.JSON(401, resp.CodeMsg(401002, "invalid login user information"))
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, "invalid login user information"))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -2,7 +2,6 @@ package middleware
import (
"fmt"
"strings"
"time"
"github.com/gin-gonic/gin"
@@ -12,6 +11,7 @@ import (
"be.ems/src/framework/ip2region"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/crypto"
)
const (
@@ -39,7 +39,7 @@ type LimitOption struct {
// 参数表示5秒内最多请求10次限制类型为 IP
//
// 使用 USER 时,请在用户身份授权认证校验后使用
// 以便获取登录用户信息,无用户信息时默认为 GLOBAL
// 以便获取登录用户信息,无用户信息时默认为 LIMIT_GLOBAL
func RateLimit(option LimitOption) gin.HandlerFunc {
return func(c *gin.Context) {
// 初始可选参数数据
@@ -55,38 +55,38 @@ func RateLimit(option LimitOption) gin.HandlerFunc {
// 获取执行函数名称
funcName := c.HandlerName()
lastDotIndex := strings.LastIndex(funcName, "/")
funcName = funcName[lastDotIndex+1:]
// 生成限流key
limitKey := constants.CACHE_RATE_LIMIT + ":" + funcName
limitKey := constants.CACHE_RATE_LIMIT + ":" + crypto.MD5(funcName)
// 用户
if option.Type == LIMIT_USER {
loginUser, err := reqctx.LoginUser(c)
if err != nil {
c.JSON(401, resp.CodeMsg(401002, "invalid login user information"))
userId := reqctx.LoginUserToUserID(c)
if userId <= 0 {
c.JSON(401, resp.CodeMsg(resp.CODE_AUTH_INVALID, "invalid login user information"))
c.Abort() // 停止执行后续的处理函数
return
}
limitKey = fmt.Sprintf("%s:%d:%s", constants.CACHE_RATE_LIMIT, loginUser.UserId, funcName)
funcMd5 := crypto.MD5(fmt.Sprintf("%d:%s", userId, funcName))
limitKey = constants.CACHE_RATE_LIMIT + ":" + funcMd5
}
// IP
if option.Type == LIMIT_IP {
clientIP := ip2region.ClientIP(c.ClientIP())
limitKey = constants.CACHE_RATE_LIMIT + ":" + clientIP + ":" + funcName
funcMd5 := crypto.MD5(fmt.Sprintf("%s:%s", clientIP, funcName))
limitKey = constants.CACHE_RATE_LIMIT + ":" + funcMd5
}
// 在Redis查询并记录请求次数
rateCount, err := redis.RateLimit("", limitKey, option.Time, option.Count)
if err != nil {
c.JSON(200, resp.ErrMsg("access too often, please try again later"))
c.JSON(200, resp.CodeMsg(resp.CODE_RATELIMIT, resp.MSG_RATELIMIT))
c.Abort() // 停止执行后续的处理函数
return
}
rateTime, err := redis.GetExpire("", limitKey)
if err != nil {
c.JSON(200, resp.ErrMsg("access too often, please try again later"))
c.JSON(200, resp.CodeMsg(resp.CODE_RATELIMIT, resp.MSG_RATELIMIT))
c.Abort() // 停止执行后续的处理函数
return
}
@@ -97,7 +97,7 @@ func RateLimit(option LimitOption) gin.HandlerFunc {
c.Header("X-RateLimit-Reset", fmt.Sprintf("%d", time.Now().Unix()+rateTime)) // 重置时间戳
if rateCount >= option.Count {
c.JSON(200, resp.ErrMsg("access too often, please try again later"))
c.JSON(200, resp.CodeMsg(resp.CODE_RATELIMIT, resp.MSG_RATELIMIT))
c.Abort() // 停止执行后续的处理函数
return
}

View File

@@ -2,7 +2,7 @@ package middleware
import (
"encoding/json"
"strconv"
"fmt"
"time"
"github.com/gin-gonic/gin"
@@ -13,6 +13,7 @@ import (
"be.ems/src/framework/logger"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
"be.ems/src/framework/utils/crypto"
)
// repeatParam 重复提交参数的类型定义
@@ -40,9 +41,12 @@ func RepeatSubmit(interval int64) gin.HandlerFunc {
}
paramsJSONStr := string(paramsJSONByte)
// 获取执行函数名称
funcName := c.HandlerName()
// 唯一标识指定key + 客户端IP + 请求地址)
clientIP := ip2region.ClientIP(c.ClientIP())
repeatKey := constants.CACHE_REPEAT_SUBMIT + ":" + clientIP + ":" + c.Request.RequestURI
funcMd5 := crypto.MD5(fmt.Sprintf("%s:%s", clientIP, funcName))
repeatKey := constants.CACHE_REPEAT_SUBMIT + ":" + funcMd5
// 在Redis查询并记录请求次数
repeatStr, _ := redis.Get("", repeatKey)
@@ -56,7 +60,8 @@ func RepeatSubmit(interval int64) gin.HandlerFunc {
compareParams := rp.Params == paramsJSONStr
// 设置重复提交声明响应头(毫秒)
c.Header("X-RepeatSubmit-Rest", strconv.FormatInt(time.Now().Add(time.Duration(compareTime)*time.Second).UnixNano()/int64(time.Millisecond), 10))
t := time.Now().Add(time.Duration(compareTime) * time.Second)
c.Header("X-RepeatSubmit-Rest", fmt.Sprint(t.UnixMilli()))
// 小于间隔时间且参数内容一致
if compareTime < interval && compareParams {

View File

@@ -1,22 +1,5 @@
package resp
const (
// CODE_ERROR 响应-code错误失败
CODE_ERROR = 400001
// MSG_ERROR 响应-msg错误失败
MSG_ERROR = "error"
// CODE_SUCCESS 响应-msg正常成功
CODE_SUCCESS = 200001
// MSG_SUCCCESS 响应-code正常成功
MSG_SUCCCESS = "success"
// 响应-code加密数据
CODE_ENCRYPT = 200999
// 响应-msg加密数据
MSG_ENCRYPT = "encrypt"
)
// Resp 响应结构体
type Resp struct {
Code int `json:"code"` // 响应状态码

View File

@@ -0,0 +1,78 @@
package resp
// |HTTP|状态码|描述|排查建议|
// |----|----|----|----|
// |500 |500001 |internal error|服务内部错误|
// |200 |200999 |encrypt|正常请求加密数据|
// |200 |200001 |request success|正常请求成功|
// |200 |400001 |exist error|正常请求错误信息|
// |200 |400002 |ratelimit over|请求限流|
// |401 |401001 |authentication error|身份认证失败或者过期|
// |401 |401002 |authentication invalid error|无效身份信息|
// |401 |401003 |authorization token error|令牌字符为空|
// |401 |401004 |device fingerprint mismatch|设备指纹信息不匹配|
// |403 |403001 |permission error|权限未分配|
// |422 |422001 |params error|参数接收解析错误|
// |422 |422002 |params error|参数属性传入错误|
// ====== 500 ======
const (
// CODE_ERROR_INTERNAL 响应-code服务内部错误
CODE_INTERNAL = 500001
// MSG_ERROR_INTERNAL 响应-msg服务内部错误
MSG_INTERNAL = "internal error"
)
// ====== 200 ======
const (
// CODE_ENCRYPT 响应-code加密数据
CODE_ENCRYPT = 200999
// MSG_ENCRYPT 响应-msg加密数据
MSG_ENCRYPT = "encrypt"
// CODE_SUCCESS 响应-code正常成功
CODE_SUCCESS = 200001
// MSG_SUCCCESS 响应-msg正常成功
MSG_SUCCCESS = "success"
// CODE_ERROR 响应-code错误失败
CODE_ERROR = 400001
// MSG_ERROR 响应-msg错误失败
MSG_ERROR = "error"
// CODE_RATELIMIT 响应-code错误失败
CODE_RATELIMIT = 400002
// MSG_RATELIMIT 响应-msg错误失败
MSG_RATELIMIT = "access too often, please try again later"
)
// ====== 401 ======
const (
// CODE_ERROR 响应-code身份认证失败或者过期
CODE_AUTH = 401001
// CODE_AUTH_INVALID 响应-code无效身份信息
CODE_AUTH_INVALID = 401002
// CODE_AUTH_NOTOKEN 响应-code令牌字符为空
CODE_AUTH_NOTOKEN = 401003
// CODE_AUTH_DEVICE 响应-code设备指纹信息不匹配
CODE_AUTH_DEVICE = 401004
// MSG_AUTH_DEVICE 响应-msg设备指纹信息不匹配
MSG_AUTH_DEVICE = "device fingerprint mismatch"
)
// ====== 403 ======
const (
// CODE_PERMISSION 响应-code权限未分配
CODE_PERMISSION = 403001
)
// ====== 422 ======
const (
// CODE_PARAM_PARSER 响应-code参数接收解析错误
CODE_PARAM_PARSER = 422001
// CODE_PARAM_CHEACK 响应-code参数属性传入错误
CODE_PARAM_CHEACK = 422002
)