Skip to content

Add direct-serve via presigned storage URLs#97

Merged
andrew merged 2 commits into
mainfrom
direct-serve-presigned-urls
Apr 30, 2026
Merged

Add direct-serve via presigned storage URLs#97
andrew merged 2 commits into
mainfrom
direct-serve-presigned-urls

Conversation

@andrew

@andrew andrew commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Closes #96.

When storage.direct_serve is enabled and the backend supports URL signing (S3, Azure), cached artifact downloads return a 302 redirect to a presigned URL instead of streaming bytes through the proxy. Falls back to streaming when the backend can't sign (fileblob, local filesystem) or when signing fails for any reason, so enabling it on a file:// store is harmless.

Configure with storage.direct_serve: true and optionally storage.direct_serve_ttl (default 15m), or via PROXY_STORAGE_DIRECT_SERVE / PROXY_STORAGE_DIRECT_SERVE_TTL.

Also registers the gocloud.dev/blob/azureblob driver so azblob:// storage URLs work.

On the cache-hit accounting point from the issue: RecordCacheHit and RecordArtifactHit were already called in checkCache before io.Copy, so redirects are counted correctly with no refactor needed. The metric calls are pulled into a small helper so the redirect and streaming paths share them.

Went with a single global flag rather than per-handler CanDirectServe() since there's no proxy-side auth today that would make one ecosystem riskier to redirect than another. Happy to revisit if that lands.

When storage.direct_serve is enabled and the backend supports it (S3,
Azure), cached artifact downloads return a 302 redirect to a presigned
URL instead of streaming bytes through the proxy. Falls back to
streaming when the backend can't sign (fileblob, local filesystem) or
signing fails.

Adds the azureblob driver so azblob:// storage URLs work.

Cache-hit accounting already happened before io.Copy so redirects are
counted correctly; the metrics calls are pulled into a helper so both
paths share them.

Closes #96
@kpfleming

Copy link
Copy Markdown
Contributor

It's fairly common in other applications to provide a second configuration item for the URL to be used for constructing presigned URLs, as it is fairly common for the 'public' hostname of the storage system to be different from the 'private' name used by the proxy. In my case the 'private' name is 127.0.0.1 :-)

When the proxy reaches storage at an internal address (127.0.0.1, a
Docker service name) the presigned URLs it generates point there too,
which is useless to external clients. This adds an optional base URL
that replaces the scheme and host of signed URLs before they're returned,
keeping the signed path and query intact.
@andrew

andrew commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

@kpfleming updated

@andrew andrew merged commit fd9b8da into main Apr 30, 2026
5 checks passed
@andrew andrew deleted the direct-serve-presigned-urls branch April 30, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Direct-serve via presigned URL

2 participants