feat: add npm remote type with metadata URL rewriting and caching
- Add `npm` package type to config with no built-in mutable defaults; users set explicit mutable_patterns (e.g. ^(?!.*\.tgz$).*) and immutable_patterns (e.g. \.tgz$) in remotes.yaml - Rewrite dist.tarball URLs in metadata JSON on the fly so tarball downloads pass through the same proxy remote instead of hitting npmjs.org directly - Single-remote design: npm_files_remote points back to itself since both metadata and tarballs are served from registry.npmjs.org - Add .tgz to _get_content_type (application/gzip) - Add example npm remote to remotes.yaml - Add npm proxy section to README covering remotes.yaml config, client setup (npm/yarn/pnpm), rewriting behaviour, and mutable vs immutable path table - Add tests for mutable pattern matching, URL rewriting, content-type, scoped packages, cache miss, and tarball immutability
This commit is contained in:
@@ -21,6 +21,7 @@ _PACKAGE_MUTABLE_PATTERNS: dict[str, list[str]] = {
|
||||
"pypi": [
|
||||
r"simple/", # Per-package and top-level simple index pages
|
||||
],
|
||||
"npm": [],
|
||||
"generic": [],
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -337,7 +337,7 @@ async def handle_expired_mutable(remote_name: str, path: str, remote_url: str) -
|
||||
|
||||
|
||||
def _get_content_type(filename: str) -> str:
|
||||
if filename.endswith(".tar.gz"):
|
||||
if filename.endswith((".tar.gz", ".tgz")):
|
||||
return "application/gzip"
|
||||
if filename.endswith(".zip") or filename.endswith(".whl"):
|
||||
return "application/zip"
|
||||
@@ -369,6 +369,15 @@ def _resolve_content(
|
||||
f"{proxy_base}/api/v1/remote/{files_remote}".encode(),
|
||||
)
|
||||
return data, "text/html; charset=utf-8"
|
||||
if remote_config.get("package") == "npm" and not path.endswith(".tgz"):
|
||||
files_url = remote_config.get("npm_files_url", "https://registry.npmjs.org")
|
||||
files_remote = remote_config.get("npm_files_remote", "npm-files")
|
||||
proxy_base = str(request.base_url).rstrip("/")
|
||||
data = data.replace(
|
||||
files_url.rstrip("/").encode(),
|
||||
f"{proxy_base}/api/v1/remote/{files_remote}".encode(),
|
||||
)
|
||||
return data, "application/json"
|
||||
return data, _get_content_type(filename)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user