Documentation
¶
Overview ¶
Package pipproxy implements proxies.CacheProxy for the Python ecosystem.
It is a pull-through cache for the PEP 503 "simple" index and the distribution files that index points at:
GET /simple/ the root project list — MUTABLE GET /simple/<project>/ a project's file list — MUTABLE GET /_ephemerd/dl/… wheels and sdists — IMMUTABLE
WHY THE SIMPLE INDEX RATHER THAN THE JSON API ¶
The simple index is the only surface pip is guaranteed to use, and it is the one PIP_INDEX_URL redirects. It also covers uv, Poetry and pip-tools, all of which speak PEP 503/691 to whatever index URL they are given.
WHAT IS CACHED AND WHY ¶
Wheels and sdists are immutable in the strongest sense in any ecosystem: PyPI refuses to let a file be re-uploaded even after deletion, the filename encodes name + version + ABI tags, and the index publishes a sha256 for each one. They are cached permanently, never revalidated, and are essentially all of the bytes — a single `torch` wheel is larger than most projects' entire metadata history.
Index pages are mutable: a project page gains a row on every release. They are cached with a short TTL (default 5 minutes) and then revalidated with a conditional GET, so a release published minutes ago is never invisible for long and an unchanged page costs one 304.
WHY PROJECT PAGES ARE REWRITTEN ¶
A project page's links point at files.pythonhosted.org. Left alone, pip would take metadata from the cache and every byte from the CDN. Each file link on a project page is therefore rewritten to this proxy's artifact route, with the "#sha256=…" fragment preserved so pip still verifies what it downloads. The ROOT index is deliberately NOT rewritten: its links are project pages, not files, and they must keep resolving against this proxy.
Index ¶
Constants ¶
const ( // DefaultUpstream is PyPI. DefaultUpstream = "https://pypi.org" // DefaultIndexTTL is how long a cached index page is served before // revalidation. DefaultIndexTTL = 5 * time.Minute )
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/pip).
CacheDir string
// Upstream is the index origin. The simple index is expected at
// <upstream>/simple/.
Upstream string
// ListenAddr is the address to bind and advertise.
ListenAddr string
// IndexTTL is the revalidation interval for index pages. Zero takes
// DefaultIndexTTL; negative means "revalidate every request".
IndexTTL time.Duration
// MaxBytes is the cache disk budget.
MaxBytes int64
// AllowedHosts extends the artifact-fetch allowlist.
AllowedHosts []string
// Cleanup wipes the cache on Stop. Default false.
Cleanup bool
Log *slog.Logger
}
Config for the pip caching proxy.
type Proxy ¶
type Proxy struct {
// contains filtered or unexported fields
}
Proxy is the PyPI caching proxy.
func (*Proxy) EnvVars ¶
EnvVars returns the environment variables to inject into job containers.
PIP_INDEX_URL is pip's own config channel — no pip.conf, no CLI flag. PIP_TRUSTED_HOST is required because the proxy speaks plain HTTP on a private address: without it pip refuses the index as insecure. Both the bare host and the host:port form are listed because pip matches trusted-host entries against either, depending on version; pip splits append-style env values on whitespace, so one variable carries both.
NOT covered, and documented as such: a repo's pip.conf / requirements.txt "--index-url" line, which wins over the environment; Poetry's pyproject-declared sources; uv, which reads UV_INDEX_URL rather than PIP_INDEX_URL; and any authenticated index (this proxy forwards no credentials).