Created
February 19, 2021 01:19
-
-
Save DanielThomas/ce0490a3d5ae8bc16852c8465edc7182 to your computer and use it in GitHub Desktop.
Varnish Plus configuration for public NPM registry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vcl 4.1; | |
import edgestash; | |
import goto; | |
import xbody; | |
backend default none; | |
sub vcl_init { | |
new registry = goto.dns_director("https://registry.npmjs.org"); | |
} | |
sub vcl_recv { | |
set req.backend_hint = registry.backend(); | |
if (req.url == "/" || req.url ~ "^/-/npm/v1/security/audits") { | |
if (req.url == "/-/npm/v1/security/audits/quick" && req.http.Npm-In-CI == "true") { | |
set req.http.npm-notice = "quick audits as part of 'npm install' are disabled on this registry. Run 'npm audit' explicitly"; | |
return (synth(404)); | |
} | |
set req.http.X-Cache-Request-Pass = true; | |
} else if (req.url ~ "^/-/npm/v1") { | |
set req.http.npm-notice = "this registry cache only supports pass-through of audit requests"; | |
return (synth(404)); | |
} else if (req.method != "GET" && req.method != "HEAD") { | |
set req.http.npm-notice = "this is a read-only cache of the public npm registry. Add 'publishConfig' pointing to the public registry if you intend you publish there"; | |
return (synth(405)); | |
} else { | |
unset req.http.authorization; | |
unset req.http.cookie; | |
} | |
} | |
sub vcl_hash { | |
// The registry varies responses based on the accept header so normalize to reduce skew | |
if (!req.http.accept) { | |
set req.http.accept = "*/*"; | |
} | |
// The registry supports both encoded and non-encoded request URLs, and the former can be upper or lower-case | |
set req.url = regsub(req.url, "%2(f|F)", "/"); | |
if (req.url != "/") { | |
// The registry serves the same response with and without trailing slashes | |
set req.url = regsub(req.url, "/$", ""); | |
} | |
} | |
sub vcl_synth { | |
set resp.http.npm-notice = req.http.npm-notice; | |
} | |
sub vcl_backend_fetch { | |
set bereq.http.Host = "registry.npmjs.org"; | |
} | |
sub vcl_backend_response { | |
unset beresp.http.CF-Cache-Status; | |
unset beresp.http.CF-Ray; | |
unset beresp.http.CF-Request-Id; | |
unset beresp.http.Expect-CT; | |
unset beresp.http.Set-Cookie; | |
unset beresp.http.Server; | |
unset beresp.http.x-amz-meta-rev; | |
if (beresp.http.Content-Type ~ "json") { | |
xbody.regsub("https:\/\/registry\.npmjs\.org", "{@{proto}@}://{@{host}@}"); | |
// Mustache packument has a mustache template in it's description so we change the default delimiter | |
edgestash.set_delimiter("{@{", "}@}"); | |
edgestash.parse_response(); | |
} | |
if (!bereq.uncacheable) { // avoid hit-for-pass objects as we already pass any request we don't want cached | |
if (beresp.status == 200) { | |
set beresp.ttl = 10m; | |
set beresp.grace = 1h; | |
set beresp.keep = 1d; | |
} else if (beresp.status == 404) { | |
set beresp.ttl = 2m; | |
set beresp.grace = 1h; | |
set beresp.http.npm-notice = "this is a read-only cache of the public npm registry and does not contain internal packages"; | |
} else { | |
set beresp.ttl = 5s; | |
set beresp.grace = 5s; | |
} | |
} | |
} | |
sub vcl_deliver { | |
// npm 4.4.4 chokes on metadata responses with 'Error: unexpected end of file' when 'Content-Encoding: gzip' is seen on 304 responses, so we force uncompressed responses (caused by Varnish 304s returning all response headers, rather than those necessary) | |
if (req.http.If-None-Match || req.http.If-Modified-Since) { | |
unset req.http.Accept-Encoding; | |
} | |
// Apply variables to templated tarball urls | |
if (resp.http.Content-Type ~ "json") { | |
edgestash.add_json({" { "proto": ""} + req.http.X-Forwarded-Proto + {"", "host": ""} + req.http.Host + {"" } "}); | |
edgestash.execute(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment