diff --git a/internal/handler/cargo.go b/internal/handler/cargo.go index 98b3069..8aab5f0 100644 --- a/internal/handler/cargo.go +++ b/internal/handler/cargo.go @@ -90,7 +90,7 @@ func (h *CargoHandler) handleIndex(w http.ResponseWriter, r *http.Request) { return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch upstream index", "error", err) http.Error(w, "failed to fetch from upstream", http.StatusBadGateway) diff --git a/internal/handler/cargo_test.go b/internal/handler/cargo_test.go index a2146f3..3fe0307 100644 --- a/internal/handler/cargo_test.go +++ b/internal/handler/cargo_test.go @@ -10,7 +10,8 @@ import ( func cargoTestProxy() *Proxy { return &Proxy{ - Logger: slog.Default(), + Logger: slog.Default(), + HTTPClient: http.DefaultClient, } } diff --git a/internal/handler/composer.go b/internal/handler/composer.go index d7bbc5d..2753e4a 100644 --- a/internal/handler/composer.go +++ b/internal/handler/composer.go @@ -94,7 +94,7 @@ func (h *ComposerHandler) handlePackageMetadata(w http.ResponseWriter, r *http.R return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) @@ -221,7 +221,7 @@ func (h *ComposerHandler) handleDownload(w http.ResponseWriter, r *http.Request) return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch metadata", "error", err) http.Error(w, "failed to fetch metadata", http.StatusBadGateway) @@ -302,7 +302,7 @@ func (h *ComposerHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/conan.go b/internal/handler/conan.go index 0a7dd8e..b91f7c3 100644 --- a/internal/handler/conan.go +++ b/internal/handler/conan.go @@ -167,7 +167,7 @@ func (h *ConanHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { req.Header.Set("Authorization", auth) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/conda.go b/internal/handler/conda.go index bf2c0e8..303ec0d 100644 --- a/internal/handler/conda.go +++ b/internal/handler/conda.go @@ -136,7 +136,7 @@ func (h *CondaHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { req.Header.Set("Accept-Encoding", ae) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/container.go b/internal/handler/container.go index 349d857..0669b12 100644 --- a/internal/handler/container.go +++ b/internal/handler/container.go @@ -172,7 +172,7 @@ func (h *ContainerHandler) handleManifest(w http.ResponseWriter, r *http.Request }, ", ")) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch manifest", "error", err) h.containerError(w, http.StatusBadGateway, "INTERNAL_ERROR", "failed to fetch from upstream") @@ -224,7 +224,7 @@ func (h *ContainerHandler) handleTagsList(w http.ResponseWriter, r *http.Request req.Header.Set("Authorization", "Bearer "+token) - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.containerError(w, http.StatusBadGateway, "INTERNAL_ERROR", "failed to fetch from upstream") return @@ -248,7 +248,7 @@ func (h *ContainerHandler) getAuthToken(_ interface{ Done() <-chan struct{} }, r return "", err } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { return "", err } @@ -285,7 +285,7 @@ func (h *ContainerHandler) proxyBlobHead(w http.ResponseWriter, r *http.Request, req.Header.Set("Authorization", "Bearer "+token) - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.containerError(w, http.StatusBadGateway, "INTERNAL_ERROR", "failed to fetch from upstream") return @@ -313,7 +313,7 @@ func (h *ContainerHandler) proxyBlobWithAuth(w http.ResponseWriter, r *http.Requ req.Header.Set("Authorization", "Bearer "+token) - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.containerError(w, http.StatusBadGateway, "INTERNAL_ERROR", "failed to fetch from upstream") return diff --git a/internal/handler/cran.go b/internal/handler/cran.go index e10887f..4702473 100644 --- a/internal/handler/cran.go +++ b/internal/handler/cran.go @@ -167,7 +167,7 @@ func (h *CRANHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { req.Header.Set("Accept-Encoding", ae) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/debian.go b/internal/handler/debian.go index 1fc7c36..bada1af 100644 --- a/internal/handler/debian.go +++ b/internal/handler/debian.go @@ -110,7 +110,7 @@ func (h *DebianHandler) handleMetadata(w http.ResponseWriter, r *http.Request, p } } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch upstream metadata", "error", err) http.Error(w, "failed to fetch from upstream", http.StatusBadGateway) @@ -139,7 +139,7 @@ func (h *DebianHandler) proxyFile(w http.ResponseWriter, r *http.Request, path s return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { http.Error(w, "failed to fetch from upstream", http.StatusBadGateway) return diff --git a/internal/handler/gem.go b/internal/handler/gem.go index bd47d6f..997e956 100644 --- a/internal/handler/gem.go +++ b/internal/handler/gem.go @@ -120,7 +120,7 @@ func (h *GemHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { } } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/go.go b/internal/handler/go.go index 9b43e8f..d64ded3 100644 --- a/internal/handler/go.go +++ b/internal/handler/go.go @@ -118,7 +118,7 @@ func (h *GoHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/handler.go b/internal/handler/handler.go index 3bd49f8..9205008 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -43,12 +43,13 @@ func ReadMetadata(r io.Reader) ([]byte, error) { // Proxy provides shared functionality for protocol handlers. type Proxy struct { - DB *database.DB - Storage storage.Storage - Fetcher fetch.FetcherInterface - Resolver *fetch.Resolver - Logger *slog.Logger - Cooldown *cooldown.Config + DB *database.DB + Storage storage.Storage + Fetcher fetch.FetcherInterface + Resolver *fetch.Resolver + Logger *slog.Logger + Cooldown *cooldown.Config + HTTPClient *http.Client } // NewProxy creates a new Proxy with the given dependencies. @@ -62,6 +63,9 @@ func NewProxy(db *database.DB, store storage.Storage, fetcher fetch.FetcherInter Fetcher: fetcher, Resolver: resolver, Logger: logger, + HTTPClient: &http.Client{ + Timeout: 30 * time.Second, + }, } } diff --git a/internal/handler/hex.go b/internal/handler/hex.go index 7a34795..2e972f0 100644 --- a/internal/handler/hex.go +++ b/internal/handler/hex.go @@ -104,7 +104,7 @@ func (h *HexHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { req.Header.Set("Accept", accept) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/maven.go b/internal/handler/maven.go index 5c8f949..2c7214f 100644 --- a/internal/handler/maven.go +++ b/internal/handler/maven.go @@ -146,7 +146,7 @@ func (h *MavenHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/npm.go b/internal/handler/npm.go index fc23927..99a2bb9 100644 --- a/internal/handler/npm.go +++ b/internal/handler/npm.go @@ -74,7 +74,7 @@ func (h *NPMHandler) handlePackageMetadata(w http.ResponseWriter, r *http.Reques } req.Header.Set("Accept", "application/json") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch upstream metadata", "error", err) JSONError(w, http.StatusBadGateway, "failed to fetch from upstream") diff --git a/internal/handler/npm_test.go b/internal/handler/npm_test.go index 5012f53..90616d7 100644 --- a/internal/handler/npm_test.go +++ b/internal/handler/npm_test.go @@ -13,7 +13,8 @@ import ( func testProxy() *Proxy { return &Proxy{ - Logger: slog.Default(), + Logger: slog.Default(), + HTTPClient: http.DefaultClient, } } diff --git a/internal/handler/nuget.go b/internal/handler/nuget.go index fafdebb..39d56cf 100644 --- a/internal/handler/nuget.go +++ b/internal/handler/nuget.go @@ -63,7 +63,7 @@ func (h *NuGetHandler) handleServiceIndex(w http.ResponseWriter, r *http.Request return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) @@ -219,7 +219,7 @@ func (h *NuGetHandler) proxyUpstream(w http.ResponseWriter, r *http.Request) { req.Header.Set("Accept-Encoding", ae) } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/pub.go b/internal/handler/pub.go index efb4211..53c3a4f 100644 --- a/internal/handler/pub.go +++ b/internal/handler/pub.go @@ -95,7 +95,7 @@ func (h *PubHandler) handlePackageMetadata(w http.ResponseWriter, r *http.Reques } req.Header.Set("Accept", "application/json") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/pypi.go b/internal/handler/pypi.go index a4deb7d..4a4232c 100644 --- a/internal/handler/pypi.go +++ b/internal/handler/pypi.go @@ -78,7 +78,7 @@ func (h *PyPIHandler) handleSimplePackage(w http.ResponseWriter, r *http.Request } req.Header.Set("Accept", "text/html") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) @@ -121,7 +121,7 @@ func (h *PyPIHandler) fetchFilteredVersions(r *http.Request, name string) map[st } req.Header.Set("Accept", "application/json") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { return nil } @@ -245,7 +245,7 @@ func (h *PyPIHandler) proxyAndRewriteJSON(w http.ResponseWriter, r *http.Request } req.Header.Set("Accept", "application/json") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) @@ -505,7 +505,7 @@ func (h *PyPIHandler) proxySimple(w http.ResponseWriter, r *http.Request, path s } req.Header.Set("Accept", "text/html") - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("upstream request failed", "error", err) http.Error(w, "upstream request failed", http.StatusBadGateway) diff --git a/internal/handler/rpm.go b/internal/handler/rpm.go index 12ce9dc..de4295a 100644 --- a/internal/handler/rpm.go +++ b/internal/handler/rpm.go @@ -112,7 +112,7 @@ func (h *RPMHandler) handleMetadata(w http.ResponseWriter, r *http.Request, path } } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { h.proxy.Logger.Error("failed to fetch upstream metadata", "error", err) http.Error(w, "failed to fetch from upstream", http.StatusBadGateway) @@ -141,7 +141,7 @@ func (h *RPMHandler) proxyFile(w http.ResponseWriter, r *http.Request, path stri return } - resp, err := http.DefaultClient.Do(req) + resp, err := h.proxy.HTTPClient.Do(req) if err != nil { http.Error(w, "failed to fetch from upstream", http.StatusBadGateway) return