Files
be.ems/src/framework/middleware/repeat_submit.go
TsMask 80d612c56c Refactor error handling in system and trace controllers
- Updated error response codes for various validation errors from 400 to 422 to better reflect the nature of the errors.
- Changed error messages for empty parameters (e.g., userId, menuId, roleId) to use a consistent error code format.
- Improved error handling in the IPerf, Ping, and WS controllers to provide more informative error messages.
- Ensured that all controllers return appropriate error messages when binding JSON or query parameters fails.
2025-04-27 16:38:19 +08:00

85 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package middleware
import (
"encoding/json"
"strconv"
"time"
"github.com/gin-gonic/gin"
"be.ems/src/framework/constants"
"be.ems/src/framework/database/redis"
"be.ems/src/framework/ip2region"
"be.ems/src/framework/logger"
"be.ems/src/framework/reqctx"
"be.ems/src/framework/resp"
)
// repeatParam 重复提交参数的类型定义
type repeatParam struct {
Time int64 `json:"time"`
Params string `json:"params"`
}
// RepeatSubmit 防止表单重复提交,小于间隔时间视为重复提交
//
// 间隔时间(单位秒) 默认:5
//
// 注意之后JSON反序列使用c.ShouldBindBodyWithJSON(&params)
func RepeatSubmit(interval int64) gin.HandlerFunc {
return func(c *gin.Context) {
if interval < 5 {
interval = 5
}
// 提交参数
params := reqctx.RequestParamsMap(c)
paramsJSONByte, err := json.Marshal(params)
if err != nil {
logger.Errorf("RepeatSubmit params json marshal err: %v", err)
}
paramsJSONStr := string(paramsJSONByte)
// 唯一标识指定key + 客户端IP + 请求地址)
clientIP := ip2region.ClientIP(c.ClientIP())
repeatKey := constants.CACHE_REPEAT_SUBMIT + ":" + clientIP + ":" + c.Request.RequestURI
// 在Redis查询并记录请求次数
repeatStr, _ := redis.Get("", repeatKey)
if repeatStr != "" {
var rp repeatParam
err := json.Unmarshal([]byte(repeatStr), &rp)
if err != nil {
logger.Errorf("RepeatSubmit repeatStr json unmarshal err: %v", err)
}
compareTime := time.Now().Unix() - rp.Time
compareParams := rp.Params == paramsJSONStr
// 设置重复提交声明响应头(毫秒)
c.Header("X-RepeatSubmit-Rest", strconv.FormatInt(time.Now().Add(time.Duration(compareTime)*time.Second).UnixNano()/int64(time.Millisecond), 10))
// 小于间隔时间且参数内容一致
if compareTime < interval && compareParams {
c.JSON(200, resp.ErrMsg("repeat submissions are not allowed. Please try again later."))
c.Abort()
return
}
}
// 当前请求参数
rp := repeatParam{
Time: time.Now().Unix(),
Params: paramsJSONStr,
}
rpJSON, err := json.Marshal(rp)
if err != nil {
logger.Errorf("RepeatSubmit rp json marshal err: %v", err)
}
// 保存请求时间和参数
_ = redis.Set("", repeatKey, string(rpJSON), time.Duration(interval)*time.Second)
// 调用下一个处理程序
c.Next()
}
}