feat: 缓存代理keys
This commit is contained in:
@@ -73,6 +73,8 @@ func (sm *SystemSettingsManager) Initialize(store store.Store, gm groupManager,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settings.ProxyKeysMap = utils.StringToSet(settings.ProxyKeys, ",")
|
||||||
|
|
||||||
sm.DisplaySystemConfig(settings)
|
sm.DisplaySystemConfig(settings)
|
||||||
|
|
||||||
return settings, nil
|
return settings, nil
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"gpt-load/internal/models"
|
"gpt-load/internal/models"
|
||||||
"gpt-load/internal/response"
|
"gpt-load/internal/response"
|
||||||
"gpt-load/internal/utils"
|
"gpt-load/internal/utils"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -51,6 +52,14 @@ func (s *Server) UpdateSettings(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize proxy_keys input
|
||||||
|
if proxyKeys, ok := settingsMap["proxy_keys"]; ok {
|
||||||
|
if proxyKeysStr, ok := proxyKeys.(string); ok {
|
||||||
|
cleanedKeys := utils.SplitAndTrim(proxyKeysStr, ",")
|
||||||
|
settingsMap["proxy_keys"] = strings.Join(cleanedKeys, ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 更新配置
|
// 更新配置
|
||||||
if err := s.SettingsManager.UpdateSettings(settingsMap); err != nil {
|
if err := s.SettingsManager.UpdateSettings(settingsMap); err != nil {
|
||||||
response.Error(c, app_errors.NewAPIError(app_errors.ErrDatabase, err.Error()))
|
response.Error(c, app_errors.NewAPIError(app_errors.ErrDatabase, err.Error()))
|
||||||
|
@@ -3,7 +3,6 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import (
|
|||||||
"gpt-load/internal/response"
|
"gpt-load/internal/response"
|
||||||
"gpt-load/internal/services"
|
"gpt-load/internal/services"
|
||||||
"gpt-load/internal/types"
|
"gpt-load/internal/types"
|
||||||
"gpt-load/internal/utils"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -156,16 +154,14 @@ func ProxyAuth(gm *services.GroupManager) gin.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Group keys first
|
// Then check System-wide keys (O(1) lookup)
|
||||||
groupKeys := utils.SplitAndTrim(group.ProxyKeys, ",")
|
if _, ok := group.EffectiveConfig.ProxyKeysMap[key]; ok {
|
||||||
if slices.Contains(groupKeys, key) {
|
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then check System-wide keys
|
// Check Group keys first (O(1) lookup)
|
||||||
systemKeys := utils.SplitAndTrim(group.EffectiveConfig.ProxyKeys, ",")
|
if _, ok := group.ProxyKeysMap[key]; ok {
|
||||||
if slices.Contains(systemKeys, key) {
|
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@@ -58,6 +58,9 @@ type Group struct {
|
|||||||
LastValidatedAt *time.Time `json:"last_validated_at"`
|
LastValidatedAt *time.Time `json:"last_validated_at"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// For cache
|
||||||
|
ProxyKeysMap map[string]struct{} `gorm:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIKey 对应 api_keys 表
|
// APIKey 对应 api_keys 表
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
"gpt-load/internal/models"
|
"gpt-load/internal/models"
|
||||||
"gpt-load/internal/store"
|
"gpt-load/internal/store"
|
||||||
"gpt-load/internal/syncer"
|
"gpt-load/internal/syncer"
|
||||||
|
"gpt-load/internal/utils"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -47,6 +48,7 @@ func (gm *GroupManager) Initialize() error {
|
|||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
g := *group
|
g := *group
|
||||||
g.EffectiveConfig = gm.settingsManager.GetEffectiveConfig(g.Config)
|
g.EffectiveConfig = gm.settingsManager.GetEffectiveConfig(g.Config)
|
||||||
|
g.ProxyKeysMap = utils.StringToSet(g.ProxyKeys, ",")
|
||||||
groupMap[g.Name] = &g
|
groupMap[g.Name] = &g
|
||||||
logrus.WithFields(logrus.Fields{
|
logrus.WithFields(logrus.Fields{
|
||||||
"group_name": g.Name,
|
"group_name": g.Name,
|
||||||
|
@@ -37,6 +37,9 @@ type SystemSettings struct {
|
|||||||
KeyValidationIntervalMinutes int `json:"key_validation_interval_minutes" default:"60" name:"密钥验证间隔(分钟)" category:"密钥配置" desc:"后台验证密钥的默认间隔(分钟)。" validate:"min=30"`
|
KeyValidationIntervalMinutes int `json:"key_validation_interval_minutes" default:"60" name:"密钥验证间隔(分钟)" category:"密钥配置" desc:"后台验证密钥的默认间隔(分钟)。" validate:"min=30"`
|
||||||
KeyValidationConcurrency int `json:"key_validation_concurrency" default:"10" name:"密钥验证并发数" category:"密钥配置" desc:"后台定时验证无效 Key 时的并发数。" validate:"min=1"`
|
KeyValidationConcurrency int `json:"key_validation_concurrency" default:"10" name:"密钥验证并发数" category:"密钥配置" desc:"后台定时验证无效 Key 时的并发数。" validate:"min=1"`
|
||||||
KeyValidationTimeoutSeconds int `json:"key_validation_timeout_seconds" default:"20" name:"密钥验证超时(秒)" category:"密钥配置" desc:"后台定时验证单个 Key 时的 API 请求超时时间(秒)。" validate:"min=5"`
|
KeyValidationTimeoutSeconds int `json:"key_validation_timeout_seconds" default:"20" name:"密钥验证超时(秒)" category:"密钥配置" desc:"后台定时验证单个 Key 时的 API 请求超时时间(秒)。" validate:"min=5"`
|
||||||
|
|
||||||
|
// For cache
|
||||||
|
ProxyKeysMap map[string]struct{} `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig represents server configuration
|
// ServerConfig represents server configuration
|
||||||
|
@@ -23,7 +23,7 @@ func GenerateSettingsMetadata(s *types.SystemSettings) []models.SystemSettingInf
|
|||||||
fieldValue := v.Field(i)
|
fieldValue := v.Field(i)
|
||||||
|
|
||||||
jsonTag := field.Tag.Get("json")
|
jsonTag := field.Tag.Get("json")
|
||||||
if jsonTag == "" {
|
if jsonTag == "" || jsonTag == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,3 +40,17 @@ func SplitAndTrim(s string, sep string) []string {
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringToSet converts a separator-delimited string into a set
|
||||||
|
func StringToSet(s string, sep string) map[string]struct{} {
|
||||||
|
parts := SplitAndTrim(s, sep)
|
||||||
|
if len(parts) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
set := make(map[string]struct{}, len(parts))
|
||||||
|
for _, part := range parts {
|
||||||
|
set[part] = struct{}{}
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user