diff --git a/internal/middleware/cache/jwt_blacklist.go b/internal/middleware/cache/jwt_blacklist.go index abf82ed..864d299 100644 --- a/internal/middleware/cache/jwt_blacklist.go +++ b/internal/middleware/cache/jwt_blacklist.go @@ -9,7 +9,7 @@ import ( ) // JWTBlacklist 检查JWT是否在黑名单中 -func JWTBlacklist(redisClient *cache.Client, enableBlacklist bool) gin.HandlerFunc { +func JWTBlacklist(redisClient *cache.Client, addBlacklist bool) gin.HandlerFunc { return func(c *gin.Context) { // 从输入的 url 中查询 token 值 token := c.Query("token") @@ -37,7 +37,7 @@ func JWTBlacklist(redisClient *cache.Client, enableBlacklist bool) gin.HandlerFu c.Next() // 如果启用拉黑模式,处理请求拉黑 Token - if enableBlacklist { + if addBlacklist { err := redisClient.Set(token, "", jwt.GetJWTTokenExpiredDuration()).Err() if err != nil { log.Logger.Error("Error adding token to blacklist: " + err.Error()) diff --git a/internal/middleware/cache/response.go b/internal/middleware/cache/response.go new file mode 100644 index 0000000..0f300ec --- /dev/null +++ b/internal/middleware/cache/response.go @@ -0,0 +1,35 @@ +package cache + +import ( + "github.com/TensoRaws/NuxBT-Backend/module/cache" + "github.com/TensoRaws/NuxBT-Backend/module/log" + "github.com/TensoRaws/NuxBT-Backend/module/util" + "github.com/gin-gonic/gin" + "time" +) + +// Response 缓存接口响应的中间件 +func Response(redisClient *cache.Client, ttl time.Duration) gin.HandlerFunc { + return func(c *gin.Context) { + // 生成缓存键,使用请求的 URL 和方法 + cacheKey := c.Request.Method + ":" + c.Request.URL.String() + + // 尝试从缓存中获取响应 + cachedResponse, err := redisClient.Get(cacheKey).Result() + if err == nil { + // 缓存命中,直接返回缓存的响应 + util.OKWithCache(c, cachedResponse) + log.Logger.Debug("Cache hit: " + cacheKey) + return + } + + // 缓存未命中,调用后续的处理函数 + c.Next() + + // 调用结束后,将结果存入缓存 + result, exists := c.Get("cache") + if exists { + redisClient.Set(cacheKey, result, ttl) + } + } +} diff --git a/internal/router/api/v1/api.go b/internal/router/api/v1/api.go index eb2143f..07b3505 100644 --- a/internal/router/api/v1/api.go +++ b/internal/router/api/v1/api.go @@ -43,6 +43,7 @@ func NewAPI() *gin.Engine { user.GET("profile/me", middleware_cache.JWTBlacklist(cache.Clients[cache.JWTBlacklist], false), jwt.RequireAuth(), + middleware_cache.Response(cache.Clients[cache.RespCache], 1*time.Minute), user_service.ProfileMe, ) } diff --git a/internal/service/user/login.go b/internal/service/user/login.go index 8bcd944..340b25a 100644 --- a/internal/service/user/login.go +++ b/internal/service/user/login.go @@ -12,6 +12,10 @@ type LoginRequest struct { Password string `form:"password" binding:"required"` } +type LoginResponse struct { + Token string `json:"token"` +} + // Login 用户登录 (POST /login) func Login(c *gin.Context) { var req LoginRequest @@ -33,9 +37,8 @@ func Login(c *gin.Context) { // 注册之后的下次登录成功,才会为其生成 token token := jwt.GenerateToken(user) // 打印相应信息和用户信息以及生成的 token 值 - util.OKWithData(c, map[string]interface{}{ - "user_id": user.UserID, - "token": token, + util.OKWithData(c, false, LoginResponse{ + Token: token, }) } else { util.AbortWithMsg(c, "Invalid Username or Password") diff --git a/internal/service/user/profile.go b/internal/service/user/profile.go index 1fe9d62..0dce396 100644 --- a/internal/service/user/profile.go +++ b/internal/service/user/profile.go @@ -43,7 +43,7 @@ func ProfileMe(c *gin.Context) { roles = []string{} } - util.OKWithDataStruct(c, ProfileMeResponse{ + util.OKWithData(c, true, ProfileMeResponse{ Avatar: user.Avatar, Background: user.Background, CreatedAt: user.CreatedAt.Format("2006-01-02 15:04:05"), diff --git a/internal/service/user/register.go b/internal/service/user/register.go index 83379f7..10b6100 100644 --- a/internal/service/user/register.go +++ b/internal/service/user/register.go @@ -73,7 +73,7 @@ func Register(c *gin.Context) { return } - util.OKWithDataStruct(c, RegisterDataResponse{ + util.OKWithData(c, false, RegisterDataResponse{ Email: user.Email, UserID: strconv.FormatInt(int64(user.UserID), 10), Username: user.Username, diff --git a/module/cache/cache.go b/module/cache/cache.go index 5fa180e..35ca038 100644 --- a/module/cache/cache.go +++ b/module/cache/cache.go @@ -16,11 +16,13 @@ type RDB uint8 const ( IPLimit RDB = iota JWTBlacklist + RespCache ) var Clients = map[RDB]*Client{ IPLimit: {}, JWTBlacklist: {}, + RespCache: {}, } type Client struct { diff --git a/module/cache/redis.go b/module/cache/redis.go index 28fa4bf..a8cb10a 100644 --- a/module/cache/redis.go +++ b/module/cache/redis.go @@ -112,3 +112,7 @@ func (c Client) SAdd(key string, members ...interface{}) *redis.IntCmd { func (c Client) Set(key string, value interface{}, expiration time.Duration) *redis.StatusCmd { return c.C.Set(c.Ctx, key, value, expiration) } + +func (c Client) Get(key string) *redis.StringCmd { + return c.C.Get(c.Ctx, key) +} diff --git a/module/util/gin.go b/module/util/gin.go index 898336c..8e5fe17 100644 --- a/module/util/gin.go +++ b/module/util/gin.go @@ -5,6 +5,7 @@ import ( "net/http" "strconv" + "github.com/TensoRaws/NuxBT-Backend/module/log" "github.com/gin-gonic/gin" ) @@ -30,30 +31,44 @@ func OKWithMsg(c *gin.Context, ok string) { c.JSON(http.StatusOK, resp) } -// OKWithData 返回成功信息,携带自定义数据 -func OKWithData(c *gin.Context, data map[string]interface{}) { +func AbortWithMsg(c *gin.Context, msg string) { resp := map[string]interface{}{ - "success": true, - "message": "ok", - "data": data, + "success": false, + "message": msg, } - c.JSON(http.StatusOK, resp) + c.AbortWithStatusJSON(http.StatusOK, resp) } -// OKWithDataStruct 返回成功信息,携带自定义数据(结构体) -func OKWithDataStruct(c *gin.Context, data interface{}) { +// OKWithData 返回成功信息,携带自定义数据(结构体) +func OKWithData(c *gin.Context, cache bool, data interface{}) { resp := map[string]interface{}{ "success": true, "message": "ok", "data": data, } + if cache { + c.Set("cache", + StructToString( + map[string]interface{}{ + "success": true, + "message": "cache", + "data": data, + }, + ), + ) + } + c.JSON(http.StatusOK, resp) } -func AbortWithMsg(c *gin.Context, msg string) { - resp := map[string]interface{}{ - "success": false, - "message": msg, +// OKWithCache 返回缓存数据,终止请求 +func OKWithCache(c *gin.Context, cache string) { + var resp interface{} + err := StringToStruct(cache, &resp) + if err != nil { + log.Logger.Error(err) + return } - c.AbortWithStatusJSON(http.StatusOK, resp) + c.JSON(http.StatusOK, resp) + c.Abort() } diff --git a/module/util/print.go b/module/util/print.go index 231e047..3d4e212 100644 --- a/module/util/print.go +++ b/module/util/print.go @@ -42,3 +42,9 @@ func StructToString(s interface{}) string { v, _ := sonic.Marshal(s) return string(v) } + +// StringToStruct 字符串转结构体 +func StringToStruct(str string, s interface{}) error { + // return json.Unmarshal([]byte(str), s) + return sonic.Unmarshal([]byte(str), s) +}