限流改为全局应用

This commit is contained in:
user123456
2025-06-18 19:44:32 +08:00
parent acc63d7b68
commit 4c6751b862
4 changed files with 43 additions and 37 deletions

View File

@@ -596,9 +596,9 @@ func formatPlatformText(platform string) string {
func initImageTarRoutes(router *gin.Engine) {
imageAPI := router.Group("/api/image")
{
imageAPI.GET("/download/:image", RateLimitMiddleware(globalLimiter), handleDirectImageDownload)
imageAPI.GET("/info/:image", RateLimitMiddleware(globalLimiter), handleImageInfo)
imageAPI.POST("/batch", RateLimitMiddleware(globalLimiter), handleSimpleBatchDownload)
imageAPI.GET("/download/:image", handleDirectImageDownload)
imageAPI.GET("/info/:image", handleImageInfo)
imageAPI.POST("/batch", handleSimpleBatchDownload)
}
}

View File

@@ -84,6 +84,9 @@ func main() {
})
}))
// 全局限流中间件 - 应用到所有路由
router.Use(RateLimitMiddleware(globalLimiter))
// 初始化监控端点
initHealthRoutes(router)
@@ -113,15 +116,15 @@ func main() {
RegisterSearchRoute(router)
// 注册Docker认证路由/token*
router.Any("/token", RateLimitMiddleware(globalLimiter), ProxyDockerAuthGin)
router.Any("/token/*path", RateLimitMiddleware(globalLimiter), ProxyDockerAuthGin)
router.Any("/token", ProxyDockerAuthGin)
router.Any("/token/*path", ProxyDockerAuthGin)
// 注册Docker Registry代理路由
router.Any("/v2/*path", RateLimitMiddleware(globalLimiter), ProxyDockerRegistryGin)
router.Any("/v2/*path", ProxyDockerRegistryGin)
// 注册NoRoute处理器
router.NoRoute(RateLimitMiddleware(globalLimiter), handler)
router.NoRoute(handler)
cfg := GetConfig()
fmt.Printf("🚀 HubProxy 启动成功\n")

View File

@@ -230,6 +230,14 @@ func (i *IPRateLimiter) GetLimiter(ip string) (*rate.Limiter, bool) {
// RateLimitMiddleware 速率限制中间件
func RateLimitMiddleware(limiter *IPRateLimiter) gin.HandlerFunc {
return func(c *gin.Context) {
// 静态文件豁免:跳过限流检查
path := c.Request.URL.Path
if path == "/" || path == "/favicon.ico" || path == "/images.html" || path == "/search.html" ||
strings.HasPrefix(path, "/public/") {
c.Next()
return
}
// 获取客户端真实IP
var ip string
@@ -295,25 +303,4 @@ func RateLimitMiddleware(limiter *IPRateLimiter) gin.HandlerFunc {
}
}
// ApplyRateLimit 应用限流到特定路由
func ApplyRateLimit(router *gin.Engine, path string, method string, handler gin.HandlerFunc) {
// 使用全局限流器
limiter := globalLimiter
if limiter == nil {
limiter = initGlobalLimiter()
}
// 根据HTTP方法应用限流
switch method {
case "GET":
router.GET(path, RateLimitMiddleware(limiter), handler)
case "POST":
router.POST(path, RateLimitMiddleware(limiter), handler)
case "PUT":
router.PUT(path, RateLimitMiddleware(limiter), handler)
case "DELETE":
router.DELETE(path, RateLimitMiddleware(limiter), handler)
default:
router.Any(path, RateLimitMiddleware(limiter), handler)
}
}

View File

@@ -71,14 +71,6 @@ func buildManifestCacheKey(imageRef, reference string) string {
return buildCacheKey("manifest", key)
}
func buildManifestCacheKeyWithPlatform(imageRef, reference, platform string) string {
if platform == "" {
platform = "default"
}
key := fmt.Sprintf("%s:%s@%s", imageRef, reference, platform)
return buildCacheKey("manifest", key)
}
func getManifestTTL(reference string) time.Duration {
cfg := GetConfig()
defaultTTL := 30 * time.Minute
@@ -149,4 +141,28 @@ func isCacheEnabled() bool {
// isTokenCacheEnabled 检查token缓存是否启用(向后兼容)
func isTokenCacheEnabled() bool {
return isCacheEnabled()
}
// 定期清理过期缓存,防止内存泄漏
func init() {
go func() {
ticker := time.NewTicker(20 * time.Minute)
defer ticker.Stop()
for range ticker.C {
now := time.Now()
expiredKeys := make([]string, 0)
globalCache.cache.Range(func(key, value interface{}) bool {
if cached := value.(*CachedItem); now.After(cached.ExpiresAt) {
expiredKeys = append(expiredKeys, key.(string))
}
return true
})
for _, key := range expiredKeys {
globalCache.cache.Delete(key)
}
}
}()
}