go-proxy-cache v1.3.2 - Upstream Transport Reuse


The project published go-proxy-cache v1.3.2 on 28 September 2026. #289 makes patchProxyTransport share one upstream http.Transport across requests. Under v1.3.1, a new transport per request capped a 303 from the origin near 70 requests per second.

The full release notes and downloads are on the GitHub release page.

patchProxyTransport returned a new http.Transport on every call. That object owns the connection pool, so every proxied request opened a fresh TCP connection to the origin. An HTTPS origin also required a fresh TLS handshake. Idle connections on the discarded transport stayed open until the origin closed them, because IdleConnTimeout was unset. v1.3.1 still shipped that behavior.

The #289 commit records a measurement behind Castellan’s edge. A 303 from the origin topped out near 70 requests per second. Latency moved from about 50 ms to between 2 and 5 seconds as the rate rose. About a quarter of those requests returned 5xx around 74 requests per second.

InsecureBridge was the only per request input. v1.3.2 keeps one transport per value, builds it on first use, and stores it in a sync.Map. Idle connections close after 90 seconds via DefaultTransportIdleConnTimeout. The ordinary proxy path, collapsed forwarding, and websockets all call patchProxyTransport, so they share that pool.

Misses reuse the pool, so origin sockets and TLS handshakes drop. A stalled connection stays until the 90 second idle timeout. The old code threw the transport away with the request. The notes name no new config key. True and false InsecureBridge keep separate transports, so the TLS setting stays with the pool that uses it.

TestUpstreamConnectionsAreReusedAcrossRequests sends 5 requests, each through a fresh RequestCall, and expects the origin to see 1 connection. The old helper showed 5. go test -race -tags unit ./... passed. The author did not run make lint, because the pinned golangci-lint v1.51 image likely predates Go 1.26.

v1.3.1 failed in the release workflow, which is why this tag exists. actions/checkout leaves a lightweight tag on the ref it checked out. When the pushed tag is annotated, the two Git objects differ. The next git fetch --tags exits with the message “would clobber existing tag” and never builds the changelog. That is #282. Tags through v1.3.0 were lightweight, so the clash stayed hidden until the first annotated tag.

#283 says v1.3.1 reached GHCR and Docker Hub unsigned, because cosign never ran. Docker Hub version tags are immutable, so a second push of the same version is a rejection. Buildx publishes every tag in one operation. The rejected version tag took latest down with it, and the job stopped before signing. GHCR had already accepted its copy and stayed unsigned because the other registry refused a tag.

The workflow now skips a version tag Docker Hub already stores. It then tries both signatures, and a failure on one registry does not cancel the signature on the other.

#288 bumps go.opentelemetry.io/otel/sdk from 1.44.0 to 1.45.0. The release line is a dependency update. It names no new exporter, no span field, and no config key.

#287 stops running on main the checks a pull request already ran. The jobs security, code-quality, codeql, and scorecard stop triggering on push. ci.yml stays as the canary that main is green. Weekly schedules remain the path that catches a newly disclosed CVE, which a merge does not. linter.yml ran super-linter with full git history on every branch push. It now runs on pull requests only. The commit counts 634 main branch jobs per merge wave against 466 on the pull request side, and says 26 percent of commits in the prior 90 days were dependency bumps paying for that second run.

Three further lines are maintainer plumbing. #285 posts dependency drift and SBOM diffs to boneyard. #284 posts a gandalf record to proofhouse. #286 declares the repository in the paved catalog. The notes do not say what those systems store, and they name no flag, chart value, or cache setting. Nothing in them changes request handling.

The GitHub release page for this tag pastes the repository history into the body. Redis cluster support, negative caching, byte range caching, collapsed forwarding, JWT validation, Prometheus metrics, and the Helm chart all show up in that list. Those features landed in earlier tags. The commits that make v1.3.2 different from v1.3.1 are #282 through #290, nine commits, ending in the version bump. Anyone moving off v1.3.1 can ignore the Alpine bumps and the Dependabot trail and read those nine.