Documentation
¶
Overview ¶
Package npmproxy implements proxies.CacheProxy for the npm ecosystem.
It is a pull-through cache for the two request shapes an `npm install` makes, which are cached very differently:
GET /<pkg> packument (metadata) — MUTABLE GET /<pkg>/-/<pkg>-<ver>.tgz package tarball — IMMUTABLE
WHAT IS CACHED AND WHY ¶
Tarballs are the bytes: a cold `npm ci` on a mid-sized project pulls hundreds of megabytes of them, and a published (name, version) tarball is never re-published with different content — npm's registry forbids it and every lockfile in the world pins its integrity hash. Those are cached permanently and never revalidated.
Packuments are NOT immutable. A packument gains a version every time anyone publishes, and `dist-tags.latest` moves. Caching one forever would pin every job on the node to whatever versions existed when the daemon started — a job asking for a version published an hour ago would get ETARGET. So packuments are cached with a SHORT TTL (default 5 minutes) and then revalidated with a conditional GET. npm's registry serves strong ETags, so the steady-state cost of a stale-but-unchanged packument is one 304, not a re-download.
WHY THE PACKUMENT IS REWRITTEN ¶
Every packument carries ABSOLUTE tarball URLs (dist.tarball) pointing at the upstream registry. Left alone, npm would fetch metadata from the cache and then every byte straight from registry.npmjs.org — the cache would hold only the cheap part. dist.tarball is therefore rewritten to point at this proxy's artifact route. dist.integrity/dist.shasum are untouched and still verified by npm against the bytes we serve, so the rewrite cannot smuggle in a different tarball.
Index ¶
Constants ¶
const ( // DefaultUpstream is the public npm registry. DefaultUpstream = "https://registry.npmjs.org" // DefaultPackumentTTL is how long a cached packument is served before // revalidation. Short by design: a dependency published minutes ago // must not be invisible to the node for an hour. DefaultPackumentTTL = 5 * time.Minute )
Defaults. Kept here rather than in the config package so the proxy is usable (and testable) standalone.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// CacheDir is the on-disk cache root (e.g. <data>/cache/npm).
CacheDir string
// Upstream is the registry to pull through to.
Upstream string
// ListenAddr is the address to bind and advertise (e.g. "10.88.0.1:8084").
ListenAddr string
// PackumentTTL is the revalidation interval for packuments. Zero takes
// DefaultPackumentTTL; negative means "revalidate every request".
PackumentTTL time.Duration
// MaxBytes is the cache disk budget. Zero takes pkgcache.DefaultMaxBytes.
MaxBytes int64
// AllowedHosts extends the artifact-fetch allowlist. The upstream's own
// host is always allowed.
AllowedHosts []string
// Cleanup wipes the cache on Stop. Default false.
Cleanup bool
Log *slog.Logger
}
Config for the npm caching proxy.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is the npm registry caching proxy.
func (*Proxy) EnvVars ¶
EnvVars returns the environment variables to inject into job containers.
- npm_config_registry is npm's own config channel and needs no .npmrc. pnpm reads it too, and Yarn Classic (v1) picks it up through its npm config compatibility layer.
- YARN_NPM_REGISTRY_SERVER is what Yarn Berry (v2+) reads instead; it ignores npm_config_* entirely.
NOT covered, and documented as such: a repo-committed .npmrc or .yarnrc.yml with an explicit `registry`, which wins over the environment; private/scoped registries with auth (this proxy forwards no credentials); and Yarn Berry's offline mirror / zero-installs, which bypasses the network altogether — all of those simply keep working, uncached.