npm: support GitHub Packages SHA tarball URLs - #238
Conversation
6b0110f to
f4a64d3
Compare
There was a problem hiding this comment.
Pull request overview
Adds support in the npm proxy handler for registries that publish content-addressed tarball URLs (e.g., GitHub Packages), by rewriting metadata tarball URLs to a conventional *.tgz proxy path and resolving downloads via a shasum-backed lookup against upstream metadata.
Changes:
- Rewrites content-addressed tarball URLs to
{name}-{version}.tgzplus agit-pkgs-shasumquery parameter. - Resolves shasum-based download requests by re-fetching upstream metadata, verifying
dist.shasum, and usingdist.tarball(with upstream-origin validation). - Adds tests covering GitHub Packages-style rewriting, successful fetch, checksum mismatch rejection, and cross-host tarball rejection.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| internal/handler/npm.go | Adds shasum-aware tarball rewrite + download resolution/validation for content-addressed tarball URLs. |
| internal/handler/npm_test.go | Adds test coverage for GitHub Packages tarball rewriting and shasum-based download validation paths. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
andrew
left a comment
There was a problem hiding this comment.
Thanks for this — GitHub Packages as an npm upstream is currently broken exactly as you describe, and it's worth fixing.
I'd like to avoid the git-pkgs-shasum query parameter though. At download time the handler already has packageName and version from the request path, so it can look up versions[version].dist.tarball from cached metadata directly without the client carrying a hint back. A couple of specific concerns with the current shape:
- The shasum comparison doesn't verify anything: both the client-supplied value and
dist.shasumcome from the same upstream packument (one via the rewritten metadata, one via the re-fetch), so it only confirms the metadata agrees with itself. - npm records
resolvedverbatim inpackage-lock.json, so?git-pkgs-shasum=...ends up committed in users' lockfiles, baking a proxy-internal detail into files the proxy doesn't control.
A simpler approach that covers GitHub Packages and any other registry with non-standard tarball paths:
- In
rewriteTarballURLs, when the upstream filename doesn't parse as<shortName>-<version>.tgz, synthesize that filename (as you already do) but with no query string. - In
handleDownload, resolve the upstream URL by readingversions[version].dist.tarballfromFetchOrCacheMetadata, keeping your host/scheme/base-path check invalidateUpstreamTarballURL. Fall back to the currentfmt.Sprintfconstruction only if metadata is unavailable.
This will also need a rebase onto main: #241 removed npmAbbreviatedCT (which tarballURLForShasum references, so it won't compile as-is) and #240 added a cooldown check in handleDownload right where this PR changes the downloadURL assignment.
b0ec489 to
8266cbf
Compare
Summary
Support npm registries that publish content-addressed tarball URLs, including GitHub Packages URLs shaped like:
Previously, the proxy used the final URL segment as the filename. Because GitHub's final segment is a SHA-1 rather than
{package}-{version}.tgz, downloads failed before cache lookup withcould not determine version from filename.This change:
.tgzpath with a privategit-pkgs-shasumquery parameter;dist.shasum;dist.tarballURL rather than reconstructing GitHub's content-addressed path; andRegular npm tarball paths retain their existing rewrite and download behavior.
Tests
go test ./internal/handler -run 'TestNPM'go test ./...go vet ./...go build ./cmd/proxyAdded coverage for GitHub Packages metadata rewriting, fetching the original content-addressed tarball, checksum mismatch rejection, and cross-host tarball rejection.