Skip to content

Add Homebrew JSON API and bottle proxy support - #254

Merged
andrew merged 5 commits into
mainfrom
homebrew-proxy-247
Sep 3, 2026
Merged

Add Homebrew JSON API and bottle proxy support#254
andrew merged 5 commits into
mainfrom
homebrew-proxy-247

Conversation

@andrew

@andrew andrew commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Adds first-class Homebrew JSON API and bottle proxy support for #247.

Signed API responses are cached without rewriting. homebrew/core manifests and blobs are served offline from cache and checked against their content digests before cache records are written.

The API and artifact upstreams default to https://formulae.brew.sh/api and https://ghcr.io. Both can be configured through YAML or environment variables, so one proxy can use another proxy as its upstream.

Client setup and upstream configuration are documented in the README.

Closes #247

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class proxying for Homebrew’s JSON API and homebrew/core OCI bottles, building on the existing metadata cache + OCI artifact store to support offline use while preserving signed API payload bytes and validating digest-addressed OCI content before caching.

Changes:

  • Adds /homebrew/* handler to proxy Homebrew JSON API responses (including signed JWS) with optional metadata caching.
  • Extends OCI /v2/* routing to support per-repository upstream registries (used to send homebrew/core to GHCR by default).
  • Adds digest verification for cached OCI blobs/manifests and expands validator handling (ETag/Last-Modified, HEAD behavior) across metadata + OCI manifest responses.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Documents Homebrew client configuration and upstream chaining.
internal/server/server.go Wires /homebrew routing and registers homebrew/core registry override for /v2.
internal/handler/homebrew.go New Homebrew JSON API handler and homebrew/core OCI registry registration helper.
internal/handler/homebrew_test.go Tests byte-for-byte signed response preservation, validators, offline stale serving, and path/method rejection.
internal/handler/handler.go Improves validator usage, HEAD behavior, and adds artifact digest verification before caching.
internal/handler/handler_test.go Updates mock storage hashing to SHA-256 to support new digest verification behavior.
internal/handler/container.go Adds per-repository registry routing and digest verification for blob fetches; improves HEAD response header handling.
internal/handler/container_test.go Adds tests for longest-prefix registry routing, credential non-forwarding, and digest mismatch non-caching.
internal/handler/container_manifest.go Adds registry-scoped manifest cache keys, Last-Modified handling, conditional 304 support, and manifest digest verification.
internal/config/config.go Adds configurable Homebrew API + artifact upstreams with defaults and env var support.
internal/config/config_test.go Verifies defaults + YAML/env loading for new Homebrew upstream config.
docs/configuration.md Documents new upstream config keys.
config.example.yaml Adds example Homebrew upstream configuration entries.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/handler/container.go Outdated
Comment thread internal/handler/container.go Outdated
Comment thread internal/handler/homebrew.go Outdated
@andrew
andrew force-pushed the homebrew-proxy-247 branch from ad13676 to 2e672fc Compare August 17, 2026 08:40
@andrew
andrew force-pushed the homebrew-proxy-247 branch from 7693321 to 5daabf3 Compare September 2, 2026 20:24
Route Homebrew API HEAD requests through ProxyCached so a warm cache
answers without an upstream call and stale entries are served when the
upstream is unreachable. HEAD still reaches upstream as HEAD when
metadata caching is disabled.

Limit OCI manifest digest verification to sha256 references and
Docker-Content-Digest headers so other digest algorithms are proxied
instead of rejected, and log the failing expected value.
Compute real manifest digests in #280's fixture upstreams so the new
verification accepts them, and add headerETag / headerLastModified to
The Homebrew API cache key does not include Accept, so replaying the
client header could serve one representation under another; the API
does not negotiate anyway. Compare If-None-Match with weak comparison,
list splitting and "*" per RFC 7232 instead of string equality, and
apply the same helper to the metadata and swift responders.
Move the configureScanning doc comment back to its function after the
auto-merge stacked it on mountProtocolHandlers, and drop the second
ETag/Last-Modified set in writeMetadataCachedResponse now that the
pre-304 set covers both response paths.
@andrew
andrew force-pushed the homebrew-proxy-247 branch from 54106fe to 211fc3e Compare September 3, 2026 09:23
@andrew
andrew merged commit b67cfb1 into main Sep 3, 2026
8 checks passed
@andrew
andrew deleted the homebrew-proxy-247 branch September 3, 2026 15:59
pinguinfuss added a commit to pinguinfuss/proxy that referenced this pull request Sep 6, 2026
Homebrew (git-pkgs#254) routes every API path through ProxyCached and so, since
git-pkgs#304, fetches formula.jws.json (~33 MB plain, ~5 MB gzip) uncompressed on
every refresh -- the case that motivated git-pkgs#305.

Request gzip for the JSON API via proxyCachedWithEncoding: brew fetches
every API download with curl --compressed and decodes Content-Encoding
itself, so the compressed bytes and header are cached and served as-is
and both hops stay compressed. The analytics endpoints are the one brew
consumer fetched without --compressed; they stay on identity.
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.

Add Homebrew JSON API and bottle proxy support

2 participants