Created
September 18, 2025 16:28
-
-
Save brianmichel/b555eb64956ec867575cee05aa4c1c39 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # A simple proxy that matches the interface for a Swift Package Registry. | |
| # make sure to `export GITHUB_TOKEN` in your environment and it should be a fine-grained token with: | |
| # - `content:read` scope on the browser company organization. | |
| # | |
| # Then run `caddy run --config Caddyfile` to start the proxy. | |
| { | |
| # Enable extra diagnostics in logs | |
| debug | |
| } | |
| :8080 { | |
| encode zstd gzip | |
| # -------------------------------------------- | |
| # ZIP downloads | |
| # /{owner}/{repo}/{version}.zip | |
| # where {version} may include slashes (e.g., release/v0.78.1) | |
| # → https://codeload.github.com/{owner}/{repo}/zip/refs/tags/{version} | |
| # -------------------------------------------- | |
| @zip path_regexp zipre ^/(?P<owner>[^/]+)/(?P<repo>[^/]+)/(?P<ver>.+)\.zip$ | |
| handle @zip { | |
| # https://api.github.com/repos/${scope}/${pkg}/zipball/refs/tags/${version} | |
| # https://api.github.com/repos/thebrowsercompany/browser-swift-test-data/zipball/refs/tags/release/v0.78.1 | |
| rewrite * /repos/{http.regexp.zipre.owner}/{http.regexp.zipre.repo}/zipball/refs/tags/{http.regexp.zipre.ver} | |
| reverse_proxy https://api.github.com { | |
| header_up Host api.github.com | |
| header_up -X-Forwarded-Host | |
| header_up X-Forwarded-Proto https | |
| # For private ZIPs only (leave off for public): | |
| header_up Authorization "Bearer {$GITHUB_TOKEN}" | |
| header_up User-Agent "swift-pkg-proxy" | |
| header_down -Server | |
| } | |
| } | |
| # -------------------------------------------- | |
| # Package.swift | |
| # /{owner}/{repo}/{version}/Package.swift | |
| # where {version} may include slashes | |
| # → https://raw.githubusercontent.com/{owner}/{repo}/refs/tags/{version}/Package.swift | |
| # -------------------------------------------- | |
| @manifest path_regexp manre ^/(?P<owner>[^/]+)/(?P<repo>[^/]+)/(?P<ver>.+)/Package\.swift$ | |
| # If ?swift-version=* is present, spec allows a 303 to the "unqualified" manifest URL. | |
| @manifest_with_swift { | |
| path_regexp mansw ^/(?P<owner>[^/]+)/(?P<repo>[^/]+)/(?P<ver>.+)/Package\.swift$ | |
| expression {query.swift-version} != "" | |
| } | |
| handle @manifest_with_swift { | |
| header Location "/{http.regexp.mansw.owner}/{http.regexp.mansw.repo}/{http.regexp.mansw.ver}/Package.swift" | |
| header Content-Version "1" | |
| respond 303 | |
| } | |
| handle @manifest { | |
| rewrite * /{http.regexp.manre.owner}/{http.regexp.manre.repo}/refs/tags/{http.regexp.manre.ver}/Package.swift | |
| reverse_proxy https://raw.githubusercontent.com { | |
| header_up Host raw.githubusercontent.com | |
| header_up -X-Forwarded-Host | |
| header_up X-Forwarded-Proto https | |
| # Keep Authorization OFF for public raw; enable only when needed: | |
| header_up Authorization "Bearer {$GITHUB_TOKEN}" | |
| header_up User-Agent "swift-pkg-proxy" | |
| header_down -Server | |
| } | |
| } | |
| # -------------------------------------------- | |
| # Not-implemented endpoints (widened to handle slashed versions) | |
| # -------------------------------------------- | |
| # List releases (GET /{scope}/{name}) → 404 | |
| @list path_regexp list ^/[^/]+/[^/]+$ | |
| handle @list { | |
| header Content-Type application/problem+json | |
| header Content-Version "1" | |
| respond 404 "{\"type\":\"about:blank\",\"title\":\"Not Found\",\"status\":404,\"detail\":\"Listing releases is not supported by this proxy.\"}" | |
| } | |
| # Release metadata (GET /{scope}/{name}/{version...}) → 404 | |
| @metadata path_regexp meta ^/[^/]+/[^/]+/.+$ | |
| handle @metadata { | |
| header Content-Type application/problem+json | |
| header Content-Version "1" | |
| respond 404 "{\"type\":\"about:blank\",\"title\":\"Not Found\",\"status\":404,\"detail\":\"Release metadata is not available from GitHub without a backend.\"}" | |
| } | |
| # Publish (PUT /{scope}/{name}/{version...}) → 405 | |
| @publish { | |
| method PUT | |
| path_regexp pub ^/[^/]+/[^/]+/.+$ | |
| } | |
| handle @publish { | |
| header Content-Type application/problem+json | |
| respond 405 "{\"type\":\"about:blank\",\"title\":\"Method Not Allowed\",\"status\":405,\"detail\":\"Publishing is not supported on this server.\"}" | |
| } | |
| # Login → 501 | |
| @login { | |
| path /login | |
| method POST | |
| } | |
| handle @login { | |
| respond 501 | |
| } | |
| # Single-URL identifiers: | |
| # /identifiers?url=https://github.com/SDWebImage/SDWebImage.git | |
| @identifiers path /identifiers | |
| handle @identifiers { | |
| # Run the body as a template (so we can transform the query string) | |
| templates { | |
| mime application/json | |
| } | |
| header Content-Type application/json | |
| header Content-Version "1" | |
| respond 200 { | |
| body <<JSON | |
| {{- $u := (index (index .Req.URL.Query "url") 0) -}} | |
| {{- $s := $u | trimPrefix "https://github.com/" | trimPrefix "http://github.com/" -}} | |
| {{- $s = $s | trimSuffix ".git" | trimSuffix "/" -}} | |
| {{- $id := replace "/" "." $s -}} | |
| {{- dict "identifiers" (list $id) | toJson -}} | |
| JSON | |
| } | |
| } | |
| # Fallback | |
| handle { | |
| respond 404 | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment