pipproxy

package
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 10 Imported by: 0

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

View Source
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 New

func New(cfg Config) (*Proxy, error)

New creates a pip caching proxy. Call Start() to begin serving.

func (*Proxy) Addr

func (p *Proxy) Addr() string

Addr returns the bound address.

func (*Proxy) EnvVars

func (p *Proxy) EnvVars() []string

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).

func (*Proxy) Healthy

func (p *Proxy) Healthy() bool

Healthy reports whether the proxy answers its own health probe.

func (*Proxy) Name

func (p *Proxy) Name() string

Name returns the proxy name for logging.

func (*Proxy) Start

func (p *Proxy) Start() error

Start begins serving. Returns after the listener is bound.

func (*Proxy) Stop

func (p *Proxy) Stop() error

Stop shuts the proxy down.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL