go fmt .
This commit is contained in:
@@ -385,12 +385,11 @@ func (is *ImageStreamer) streamDockerFormatWithReturn(ctx context.Context, tarWr
|
|||||||
log.Printf("已处理层 %d/%d", i+1, len(layers))
|
log.Printf("已处理层 %d/%d", i+1, len(layers))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 构建单个镜像的manifest信息
|
// 构建单个镜像的manifest信息
|
||||||
singleManifest := map[string]interface{}{
|
singleManifest := map[string]interface{}{
|
||||||
"Config": configDigest.String() + ".json",
|
"Config": configDigest.String() + ".json",
|
||||||
"RepoTags": []string{imageRef},
|
"RepoTags": []string{imageRef},
|
||||||
"Layers": func() []string {
|
"Layers": func() []string {
|
||||||
var layers []string
|
var layers []string
|
||||||
for _, digest := range layerDigests {
|
for _, digest := range layerDigests {
|
||||||
layers = append(layers, digest+"/layer.tar")
|
layers = append(layers, digest+"/layer.tar")
|
||||||
@@ -549,8 +548,8 @@ func (is *ImageStreamer) selectPlatformImage(desc *remote.Descriptor, options *S
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m.Platform.OS == targetOS &&
|
if m.Platform.OS == targetOS &&
|
||||||
m.Platform.Architecture == targetArch &&
|
m.Platform.Architecture == targetArch &&
|
||||||
m.Platform.Variant == targetVariant {
|
m.Platform.Variant == targetVariant {
|
||||||
selectedDesc = &m
|
selectedDesc = &m
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -632,7 +631,7 @@ func handleDirectImageDownload(c *gin.Context) {
|
|||||||
|
|
||||||
if !singleImageDebouncer.ShouldAllow(userID, contentKey) {
|
if !singleImageDebouncer.ShouldAllow(userID, contentKey) {
|
||||||
c.JSON(http.StatusTooManyRequests, gin.H{
|
c.JSON(http.StatusTooManyRequests, gin.H{
|
||||||
"error": "请求过于频繁,请稍后再试",
|
"error": "请求过于频繁,请稍后再试",
|
||||||
"retry_after": 5,
|
"retry_after": 5,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -692,7 +691,7 @@ func handleSimpleBatchDownload(c *gin.Context) {
|
|||||||
|
|
||||||
if !batchImageDebouncer.ShouldAllow(userID, contentKey) {
|
if !batchImageDebouncer.ShouldAllow(userID, contentKey) {
|
||||||
c.JSON(http.StatusTooManyRequests, gin.H{
|
c.JSON(http.StatusTooManyRequests, gin.H{
|
||||||
"error": "批量下载请求过于频繁,请稍后再试",
|
"error": "批量下载请求过于频繁,请稍后再试",
|
||||||
"retry_after": 60,
|
"retry_after": 60,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ func main() {
|
|||||||
// 注册Docker Registry代理路由
|
// 注册Docker Registry代理路由
|
||||||
router.Any("/v2/*path", ProxyDockerRegistryGin)
|
router.Any("/v2/*path", ProxyDockerRegistryGin)
|
||||||
|
|
||||||
|
|
||||||
// 注册NoRoute处理器
|
// 注册NoRoute处理器
|
||||||
router.NoRoute(handler)
|
router.NoRoute(handler)
|
||||||
|
|
||||||
@@ -177,12 +176,10 @@ func handler(c *gin.Context) {
|
|||||||
proxyRequest(c, rawPath)
|
proxyRequest(c, rawPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func proxyRequest(c *gin.Context, u string) {
|
func proxyRequest(c *gin.Context, u string) {
|
||||||
proxyWithRedirect(c, u, 0)
|
proxyWithRedirect(c, u, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func proxyWithRedirect(c *gin.Context, u string, redirectCount int) {
|
func proxyWithRedirect(c *gin.Context, u string, redirectCount int) {
|
||||||
// 限制最大重定向次数,防止无限递归
|
// 限制最大重定向次数,防止无限递归
|
||||||
const maxRedirects = 20
|
const maxRedirects = 20
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
// 清理间隔
|
// 清理间隔
|
||||||
CleanupInterval = 10 * time.Minute
|
CleanupInterval = 10 * time.Minute
|
||||||
MaxIPCacheSize = 10000
|
MaxIPCacheSize = 10000
|
||||||
)
|
)
|
||||||
|
|
||||||
// IPRateLimiter IP限流器结构体
|
// IPRateLimiter IP限流器结构体
|
||||||
@@ -233,7 +233,7 @@ func RateLimitMiddleware(limiter *IPRateLimiter) gin.HandlerFunc {
|
|||||||
// 静态文件豁免:跳过限流检查
|
// 静态文件豁免:跳过限流检查
|
||||||
path := c.Request.URL.Path
|
path := c.Request.URL.Path
|
||||||
if path == "/" || path == "/favicon.ico" || path == "/images.html" || path == "/search.html" ||
|
if path == "/" || path == "/favicon.ico" || path == "/images.html" || path == "/search.html" ||
|
||||||
strings.HasPrefix(path, "/public/") {
|
strings.HasPrefix(path, "/public/") {
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -299,5 +299,3 @@ func RateLimitMiddleware(limiter *IPRateLimiter) gin.HandlerFunc {
|
|||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,27 +25,27 @@ type SearchResult struct {
|
|||||||
|
|
||||||
// Repository 仓库信息
|
// Repository 仓库信息
|
||||||
type Repository struct {
|
type Repository struct {
|
||||||
Name string `json:"repo_name"`
|
Name string `json:"repo_name"`
|
||||||
Description string `json:"short_description"`
|
Description string `json:"short_description"`
|
||||||
IsOfficial bool `json:"is_official"`
|
IsOfficial bool `json:"is_official"`
|
||||||
IsAutomated bool `json:"is_automated"`
|
IsAutomated bool `json:"is_automated"`
|
||||||
StarCount int `json:"star_count"`
|
StarCount int `json:"star_count"`
|
||||||
PullCount int `json:"pull_count"`
|
PullCount int `json:"pull_count"`
|
||||||
RepoOwner string `json:"repo_owner"`
|
RepoOwner string `json:"repo_owner"`
|
||||||
LastUpdated string `json:"last_updated"`
|
LastUpdated string `json:"last_updated"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
Organization string `json:"affiliation"`
|
Organization string `json:"affiliation"`
|
||||||
PullsLastWeek int `json:"pulls_last_week"`
|
PullsLastWeek int `json:"pulls_last_week"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagInfo 标签信息
|
// TagInfo 标签信息
|
||||||
type TagInfo struct {
|
type TagInfo struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
FullSize int64 `json:"full_size"`
|
FullSize int64 `json:"full_size"`
|
||||||
LastUpdated time.Time `json:"last_updated"`
|
LastUpdated time.Time `json:"last_updated"`
|
||||||
LastPusher string `json:"last_pusher"`
|
LastPusher string `json:"last_pusher"`
|
||||||
Images []Image `json:"images"`
|
Images []Image `json:"images"`
|
||||||
Vulnerabilities struct {
|
Vulnerabilities struct {
|
||||||
Critical int `json:"critical"`
|
Critical int `json:"critical"`
|
||||||
High int `json:"high"`
|
High int `json:"high"`
|
||||||
@@ -77,9 +77,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
data map[string]cacheEntry
|
data map[string]cacheEntry
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
maxSize int
|
maxSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -385,9 +385,9 @@ func isRetryableError(err error) bool {
|
|||||||
|
|
||||||
// 网络错误、超时等可以重试
|
// 网络错误、超时等可以重试
|
||||||
if strings.Contains(err.Error(), "timeout") ||
|
if strings.Contains(err.Error(), "timeout") ||
|
||||||
strings.Contains(err.Error(), "connection refused") ||
|
strings.Contains(err.Error(), "connection refused") ||
|
||||||
strings.Contains(err.Error(), "no such host") ||
|
strings.Contains(err.Error(), "no such host") ||
|
||||||
strings.Contains(err.Error(), "too many requests") {
|
strings.Contains(err.Error(), "too many requests") {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import (
|
|||||||
|
|
||||||
// CachedItem 通用缓存项,支持Token和Manifest
|
// CachedItem 通用缓存项,支持Token和Manifest
|
||||||
type CachedItem struct {
|
type CachedItem struct {
|
||||||
Data []byte // 缓存数据(token字符串或manifest字节)
|
Data []byte // 缓存数据(token字符串或manifest字节)
|
||||||
ContentType string // 内容类型
|
ContentType string // 内容类型
|
||||||
Headers map[string]string // 额外的响应头
|
Headers map[string]string // 额外的响应头
|
||||||
ExpiresAt time.Time // 过期时间
|
ExpiresAt time.Time // 过期时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// UniversalCache 通用缓存,支持Token和Manifest
|
// UniversalCache 通用缓存,支持Token和Manifest
|
||||||
@@ -86,7 +86,7 @@ func getManifestTTL(reference string) time.Duration {
|
|||||||
|
|
||||||
// mutable tag的智能判断
|
// mutable tag的智能判断
|
||||||
if reference == "latest" || reference == "main" || reference == "master" ||
|
if reference == "latest" || reference == "main" || reference == "master" ||
|
||||||
reference == "dev" || reference == "develop" {
|
reference == "dev" || reference == "develop" {
|
||||||
// 热门可变标签: 短期缓存
|
// 热门可变标签: 短期缓存
|
||||||
return 10 * time.Minute
|
return 10 * time.Minute
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user