Skip to content

Request npm packuments in one format for downloads too - #496

Open
simonchrz wants to merge 1 commit into
git-pkgs:mainfrom
simonchrz:fix/npm-packument-accept
Open

simonchrz wants to merge 1 commit into
git-pkgs:mainfrom
simonchrz:fix/npm-packument-accept

Conversation

@simonchrz

Copy link
Copy Markdown
Contributor

The metadata route requests packuments with npmAcceptDefault (abbreviated install format, falling back to application/json), or plain application/json when cooldown or npm_full_metadata needs the full document. Tarball downloads read the packument from the same cache row (cacheKey) but always asked for application/json.

So once the row was past metadata_ttl, a download of a tarball the proxy hadn't cached yet revalidated with the abbreviated document's ETag while asking for the full one. On npmjs that's a 200 with the full packument, which cacheMetadataBlob stored over the abbreviated one. Until the next refresh the metadata route then rewrote and served the full document to every client, typically several times the size for large packages, and the rewrite-cache entry changed with it. The next metadata refresh flipped it back, so the row alternated between formats during installs.

Both paths now use packumentAccept(), which holds the existing logic and comment. Downloads only read dist.tarball, dist.integrity and dist.shasum, which the abbreviated format carries, and the publish times versionInCooldown needs come with the full format that cooldown selects anyway.

Test

TestNPMTarballKeepsCachedPackumentFormat serves the abbreviated and full formats with different ETags, fetches the metadata, and then downloads a tarball after the TTL. It checks that every packument request used the same Accept and that the cache row still holds the abbreviated document. On main it fails on both counts. go test -race ./... and golangci-lint pass.

The metadata route caches a package's packument in the abbreviated
install format, unless cooldown or npm_full_metadata needs the full one.
Tarball downloads read the packument from the same cache row but asked
for application/json. Once the row was due for revalidation, a tarball
the proxy had not cached yet fetched the full packument, which did not
match the abbreviated document's ETag, and stored it in its place. Until
the next refresh every client was then served the full document,
typically several times the size.

Both now use packumentAccept. Downloads read only dist.tarball,
dist.integrity and dist.shasum, which the abbreviated format carries; the
publish times the cooldown needs come with the full format it selects.
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.

1 participant