Refactor module binding to rely on Type
This commit is contained in:
@@ -25,72 +25,49 @@ func normalizePath(_ *hooks.RequestContext, p string, rawQuery []byte) (string,
|
||||
|
||||
func cachePolicy(_ *hooks.RequestContext, locatorPath string, current hooks.CachePolicy) hooks.CachePolicy {
|
||||
clean := canonicalPath(locatorPath)
|
||||
switch {
|
||||
case isAptIndexPath(clean):
|
||||
// 索引类(Release/Packages)需要 If-None-Match/If-Modified-Since 再验证。
|
||||
current.AllowCache = true
|
||||
current.AllowStore = true
|
||||
current.RequireRevalidate = true
|
||||
case isAptImmutablePath(clean):
|
||||
if strings.Contains(clean, "/by-hash/") || strings.Contains(clean, "/pool/") {
|
||||
// pool/*.deb 与 by-hash 路径视为不可变,直接缓存后续不再 HEAD。
|
||||
current.AllowCache = true
|
||||
current.AllowStore = true
|
||||
current.RequireRevalidate = false
|
||||
default:
|
||||
current.AllowCache = false
|
||||
current.AllowStore = false
|
||||
current.RequireRevalidate = false
|
||||
return current
|
||||
}
|
||||
|
||||
if strings.Contains(clean, "/dists/") {
|
||||
// 索引类(Release/Packages/Contents)需要 If-None-Match/If-Modified-Since 再验证。
|
||||
if strings.HasSuffix(clean, "/release") ||
|
||||
strings.HasSuffix(clean, "/inrelease") ||
|
||||
strings.HasSuffix(clean, "/release.gpg") {
|
||||
current.AllowCache = true
|
||||
current.AllowStore = true
|
||||
current.RequireRevalidate = true
|
||||
return current
|
||||
}
|
||||
}
|
||||
|
||||
current.AllowCache = false
|
||||
current.AllowStore = false
|
||||
current.RequireRevalidate = false
|
||||
return current
|
||||
}
|
||||
|
||||
func contentType(_ *hooks.RequestContext, locatorPath string) string {
|
||||
clean := canonicalPath(locatorPath)
|
||||
switch {
|
||||
case strings.HasSuffix(locatorPath, ".gz"):
|
||||
case strings.HasSuffix(clean, ".gz"):
|
||||
return "application/gzip"
|
||||
case strings.HasSuffix(locatorPath, ".xz"):
|
||||
case strings.HasSuffix(clean, ".xz"):
|
||||
return "application/x-xz"
|
||||
case strings.HasSuffix(locatorPath, "Release.gpg"):
|
||||
case strings.HasSuffix(clean, "release.gpg"):
|
||||
return "application/pgp-signature"
|
||||
case isAptIndexPath(locatorPath):
|
||||
case strings.Contains(clean, "/dists/") &&
|
||||
(strings.HasSuffix(clean, "/release") || strings.HasSuffix(clean, "/inrelease")):
|
||||
return "text/plain"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func isAptIndexPath(p string) bool {
|
||||
clean := canonicalPath(p)
|
||||
if isByHashPath(clean) {
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.Contains(clean, "/dists/") {
|
||||
if strings.HasSuffix(clean, "/release") ||
|
||||
strings.HasSuffix(clean, "/inrelease") ||
|
||||
strings.HasSuffix(clean, "/release.gpg") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isAptImmutablePath(p string) bool {
|
||||
clean := canonicalPath(p)
|
||||
if isByHashPath(clean) {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(clean, "/pool/") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isByHashPath(p string) bool {
|
||||
clean := canonicalPath(p)
|
||||
return strings.Contains(clean, "/by-hash/")
|
||||
}
|
||||
|
||||
func canonicalPath(p string) string {
|
||||
if p == "" {
|
||||
return "/"
|
||||
|
||||
@@ -35,7 +35,7 @@ func RegisterModuleHandler(key string, handler server.ProxyHandler) {
|
||||
MustRegisterModule(ModuleRegistration{Key: key, Handler: handler})
|
||||
}
|
||||
|
||||
// Handle 实现 server.ProxyHandler,根据 route.ModuleKey 选择 handler。
|
||||
// Handle 实现 server.ProxyHandler,根据 route.Module.Key 选择 handler。
|
||||
func (f *Forwarder) Handle(c fiber.Ctx, route *server.HubRoute) error {
|
||||
requestID := server.RequestID(c)
|
||||
handler := f.lookup(route)
|
||||
@@ -90,7 +90,7 @@ func (f *Forwarder) logModuleError(route *server.HubRoute, code string, err erro
|
||||
|
||||
func (f *Forwarder) lookup(route *server.HubRoute) server.ProxyHandler {
|
||||
if route != nil {
|
||||
if handler := lookupModuleHandler(route.ModuleKey); handler != nil {
|
||||
if handler := lookupModuleHandler(route.Module.Key); handler != nil {
|
||||
return handler
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (f *Forwarder) routeFields(route *server.HubRoute, requestID string) logrus
|
||||
route.Config.Domain,
|
||||
route.Config.Type,
|
||||
route.Config.AuthMode(),
|
||||
route.ModuleKey,
|
||||
route.Module.Key,
|
||||
false,
|
||||
)
|
||||
if requestID != "" {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/valyala/fasthttp"
|
||||
|
||||
"github.com/any-hub/any-hub/internal/config"
|
||||
"github.com/any-hub/any-hub/internal/hubmodule"
|
||||
"github.com/any-hub/any-hub/internal/server"
|
||||
)
|
||||
|
||||
@@ -102,6 +103,8 @@ func testRouteWithModule(moduleKey string) *server.HubRoute {
|
||||
Domain: "test.local",
|
||||
Type: "custom",
|
||||
},
|
||||
ModuleKey: moduleKey,
|
||||
Module: hubmodule.ModuleMetadata{
|
||||
Key: moduleKey,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func buildHookContext(route *server.HubRoute, c fiber.Ctx) *hooks.RequestContext
|
||||
HubName: route.Config.Name,
|
||||
Domain: route.Config.Domain,
|
||||
HubType: route.Config.Type,
|
||||
ModuleKey: route.ModuleKey,
|
||||
ModuleKey: route.Module.Key,
|
||||
UpstreamHost: baseHost,
|
||||
Method: c.Method(),
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func hasHook(def hooks.Hooks) bool {
|
||||
func (h *Handler) Handle(c fiber.Ctx, route *server.HubRoute) error {
|
||||
started := time.Now()
|
||||
requestID := server.RequestID(c)
|
||||
hooksDef, ok := hooks.Fetch(route.ModuleKey)
|
||||
hooksDef, ok := hooks.Fetch(route.Module.Key)
|
||||
hookCtx := buildHookContext(route, c)
|
||||
rawQuery := append([]byte(nil), c.Request().URI().QueryString()...)
|
||||
cleanPath := normalizeRequestPath(route, string(c.Request().URI().Path()))
|
||||
@@ -120,7 +120,7 @@ func (h *Handler) Handle(c fiber.Ctx, route *server.HubRoute) error {
|
||||
// miss, continue
|
||||
default:
|
||||
h.logger.WithError(err).
|
||||
WithFields(logrus.Fields{"hub": route.Config.Name, "module_key": route.ModuleKey}).
|
||||
WithFields(logrus.Fields{"hub": route.Config.Name, "module_key": route.Module.Key}).
|
||||
Warn("cache_get_failed")
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func (h *Handler) Handle(c fiber.Ctx, route *server.HubRoute) error {
|
||||
fresh, err := h.isCacheFresh(c, route, locator, cached.Entry, &hookState)
|
||||
if err != nil {
|
||||
h.logger.WithError(err).
|
||||
WithFields(logrus.Fields{"hub": route.Config.Name, "module_key": route.ModuleKey}).
|
||||
WithFields(logrus.Fields{"hub": route.Config.Name, "module_key": route.Module.Key}).
|
||||
Warn("cache_revalidate_failed")
|
||||
serve = false
|
||||
} else if !fresh {
|
||||
@@ -517,7 +517,7 @@ func (h *Handler) logResult(
|
||||
route.Config.Domain,
|
||||
route.Config.Type,
|
||||
route.Config.AuthMode(),
|
||||
route.ModuleKey,
|
||||
route.Module.Key,
|
||||
cacheHit,
|
||||
)
|
||||
fields["action"] = "proxy"
|
||||
@@ -968,7 +968,7 @@ func (h *Handler) logAuthRetry(route *server.HubRoute, upstream string, requestI
|
||||
route.Config.Domain,
|
||||
route.Config.Type,
|
||||
route.Config.AuthMode(),
|
||||
route.ModuleKey,
|
||||
route.Module.Key,
|
||||
false,
|
||||
)
|
||||
fields["action"] = "proxy_retry"
|
||||
@@ -987,7 +987,7 @@ func (h *Handler) logAuthFailure(route *server.HubRoute, upstream string, reques
|
||||
route.Config.Domain,
|
||||
route.Config.Type,
|
||||
route.Config.AuthMode(),
|
||||
route.ModuleKey,
|
||||
route.Module.Key,
|
||||
false,
|
||||
)
|
||||
fields["action"] = "proxy"
|
||||
|
||||
@@ -25,9 +25,8 @@ type HubRoute struct {
|
||||
// UpstreamURL/ProxyURL 在构造 Registry 时提前解析完成,便于后续请求快速复用。
|
||||
UpstreamURL *url.URL
|
||||
ProxyURL *url.URL
|
||||
// ModuleKey/Module 记录当前 hub 选用的模块及其元数据,便于日志与观测。
|
||||
ModuleKey string
|
||||
Module hubmodule.ModuleMetadata
|
||||
// Module 记录当前 hub 选用的模块元数据,便于日志与观测。
|
||||
Module hubmodule.ModuleMetadata
|
||||
// CacheStrategy 代表模块默认策略与 hub 覆盖后的最终结果。
|
||||
CacheStrategy hubmodule.CacheStrategyProfile
|
||||
}
|
||||
@@ -134,7 +133,6 @@ func buildHubRoute(cfg *config.Config, hub config.HubConfig) (*HubRoute, error)
|
||||
CacheTTL: effectiveTTL,
|
||||
UpstreamURL: upstreamURL,
|
||||
ProxyURL: proxyURL,
|
||||
ModuleKey: runtime.Module.Key,
|
||||
Module: runtime.Module,
|
||||
CacheStrategy: runtime.CacheStrategy,
|
||||
}, nil
|
||||
|
||||
@@ -54,8 +54,8 @@ func TestHubRegistryLookupByHost(t *testing.T) {
|
||||
if route.CacheStrategy.ValidationMode == "" {
|
||||
t.Fatalf("cache strategy validation mode should not be empty")
|
||||
}
|
||||
if route.ModuleKey != "docker" {
|
||||
t.Fatalf("expected docker module, got %s", route.ModuleKey)
|
||||
if route.Module.Key != "docker" {
|
||||
t.Fatalf("expected docker module, got %s", route.Module.Key)
|
||||
}
|
||||
|
||||
if route.UpstreamURL.String() != "https://registry-1.docker.io" {
|
||||
|
||||
@@ -113,7 +113,7 @@ func encodeHubBindings(routes []server.HubRoute) []hubBindingPayload {
|
||||
for _, route := range routes {
|
||||
result = append(result, hubBindingPayload{
|
||||
HubName: route.Config.Name,
|
||||
ModuleKey: route.ModuleKey,
|
||||
ModuleKey: route.Module.Key,
|
||||
Domain: route.Config.Domain,
|
||||
Port: route.ListenPort,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user