Update deploy/varnish/default.vcl.template
This commit is contained in:
@@ -28,19 +28,28 @@ sub vcl_recv {
|
||||
return (purge);
|
||||
}
|
||||
|
||||
# omijamy cache dla healthchecków / wewnętrznych nagłówków
|
||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) { return (pass); }
|
||||
|
||||
# Specjalna obsługa WebSocket i socket.io
|
||||
# Specjalna obsługa WebSocket i socket.io – BARDZO WCZEŚNIE
|
||||
if (req.http.Upgrade ~ "(?i)websocket" || req.url ~ "^/socket.io/") {
|
||||
return (pipe);
|
||||
}
|
||||
|
||||
# omijamy cache dla healthchecków / wewnętrznych nagłówków
|
||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) {
|
||||
set req.http.X-Pass-Reason = "internal";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# metody inne niż GET/HEAD bez cache
|
||||
if (req.method != "GET" && req.method != "HEAD") { return (pass); }
|
||||
if (req.method != "GET" && req.method != "HEAD") {
|
||||
set req.http.X-Pass-Reason = "method";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# Żądania z Authorization nie są buforowane
|
||||
if (req.http.Authorization) { return (pass); }
|
||||
if (req.http.Authorization) {
|
||||
set req.http.X-Pass-Reason = "auth";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# ---- Normalizacja Accept-Encoding (kolejność: zstd > br > gzip) ----
|
||||
if (req.http.Accept-Encoding) {
|
||||
@@ -55,17 +64,9 @@ sub vcl_recv {
|
||||
}
|
||||
}
|
||||
|
||||
# ---- (Opcjonalnie) Normalizacja Accept dla obrazów generowanych wariantowo ----
|
||||
# if (req.url ~ "\.(png|jpe?g|gif|bmp)$") {
|
||||
# if (req.http.Accept ~ "image/webp") {
|
||||
# set req.http.X-Accept-Image = "modern"; # webp
|
||||
# } else {
|
||||
# set req.http.X-Accept-Image = "legacy"; # jpg/png
|
||||
# }
|
||||
# }
|
||||
|
||||
# ---- STATYCZNE – agresywny cache + ignorujemy sesję ----
|
||||
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpe?g|webp|svg|ico|woff2?)$") {
|
||||
# Użyj double escape jak w działającej wersji!
|
||||
if (req.url ~ "^/static/" || req.url ~ "\\.(css|js|png|jpe?g|webp|svg|ico|woff2?)$") {
|
||||
unset req.http.Cookie;
|
||||
unset req.http.Authorization;
|
||||
return (hash);
|
||||
@@ -75,36 +76,19 @@ sub vcl_recv {
|
||||
set req.http.X-Forwarded-Proto = "https";
|
||||
}
|
||||
|
||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) {
|
||||
set req.http.X-Pass-Reason = "internal";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
if (req.method != "GET" && req.method != "HEAD") {
|
||||
set req.http.X-Pass-Reason = "method";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
if (req.http.Authorization) {
|
||||
set req.http.X-Pass-Reason = "auth";
|
||||
return (pass);
|
||||
}
|
||||
|
||||
# jeśli chcesz PASS przy cookie:
|
||||
# if (req.http.Cookie) {
|
||||
# set req.http.X-Pass-Reason = "cookie";
|
||||
# return (pass);
|
||||
# }
|
||||
|
||||
# BRAK DUPLIKATÓW – koniec wyjątków, reszta do hash
|
||||
return (hash);
|
||||
}
|
||||
|
||||
# ===== PIPE (WebSocket passthrough) =====
|
||||
# ===== PIPE (WebSocket passthrough) – poprawione =====
|
||||
sub vcl_pipe {
|
||||
# Kopiuj WS headers z klienta do backendu
|
||||
if (req.http.Upgrade) {
|
||||
set bereq.http.Upgrade = req.http.Upgrade;
|
||||
set bereq.http.Connection = req.http.Connection;
|
||||
}
|
||||
# WAŻNE: backend nie może reuse połączenia po WS
|
||||
set bereq.http.connection = "close";
|
||||
}
|
||||
|
||||
# ===== HASH =====
|
||||
@@ -140,9 +124,9 @@ sub vcl_backend_response {
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
# Nie cache'uj statyków, jeśli status ≠ 200
|
||||
# Nie cache'uj statyków, jeśli status ≠ 200 – double escape
|
||||
if (bereq.url ~ "^/static/" ||
|
||||
bereq.url ~ "\.(css|js|png|jpe?g|webp|svg|ico|woff2?)($|\?)") {
|
||||
bereq.url ~ "\\.(css|js|png|jpe?g|webp|svg|ico|woff2?)($|\\?)") {
|
||||
if (beresp.status != 200) {
|
||||
set beresp.uncacheable = true;
|
||||
set beresp.ttl = 0s;
|
||||
@@ -151,31 +135,31 @@ sub vcl_backend_response {
|
||||
}
|
||||
|
||||
# Jeśli pod .js przychodzi text/html — też nie cache'uj (to zwykle redirect/login)
|
||||
if (bereq.url ~ "\.js(\?.*)?$" && beresp.http.Content-Type ~ "(?i)text/html") {
|
||||
if (bereq.url ~ "\\.js(\\?.*)?$" && beresp.http.Content-Type ~ "(?i)text/html") {
|
||||
set beresp.uncacheable = true;
|
||||
set beresp.ttl = 0s;
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
# Wymuś poprawny Content-Type dla .js/.css, gdy backend zwróci HTML
|
||||
if (bereq.url ~ "\.js(\?.*)?$") {
|
||||
if (bereq.url ~ "\\.js(\\?.*)?$") {
|
||||
if (!beresp.http.Content-Type || beresp.http.Content-Type ~ "(?i)text/html") {
|
||||
set beresp.http.Content-Type = "application/javascript; charset=utf-8";
|
||||
}
|
||||
}
|
||||
if (bereq.url ~ "\.css(\?.*)?$") {
|
||||
if (bereq.url ~ "\\.css(\\?.*)?$") {
|
||||
if (!beresp.http.Content-Type || beresp.http.Content-Type ~ "(?i)text/html") {
|
||||
set beresp.http.Content-Type = "text/css; charset=utf-8";
|
||||
}
|
||||
}
|
||||
|
||||
# ---- STATYCZNE: zdejmij Set-Cookie i Vary: Cookie, zapewnij TTL ----
|
||||
if (bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpe?g|webp|svg|ico|woff2?)$") {
|
||||
if (bereq.url ~ "^/static/" || bereq.url ~ "\\.(css|js|png|jpe?g|webp|svg|ico|woff2?)$") {
|
||||
unset beresp.http.Set-Cookie;
|
||||
|
||||
# Jeśli backend dodał Vary: Cookie, usuńmy ten element (nie wpływa na statyki)
|
||||
if (beresp.http.Vary) {
|
||||
set beresp.http.Vary = regsuball(beresp.http.Vary, "(?i)(^|,)[[:space:]]*Cookie[[:space:]]*(,|$)", "\1");
|
||||
set beresp.http.Vary = regsuball(beresp.http.Vary, "(?i)(^|,)[[:space:]]*Cookie[[:space:]]*(,|$)", "\\1");
|
||||
set beresp.http.Vary = regsuball(beresp.http.Vary, ",[[:space:]]*,", ",");
|
||||
set beresp.http.Vary = regsub(beresp.http.Vary, "^[[:space:]]*,[[:space:]]*", "");
|
||||
set beresp.http.Vary = regsub(beresp.http.Vary, "[[:space:]]*,[[:space:]]*$", "");
|
||||
@@ -194,9 +178,9 @@ sub vcl_backend_response {
|
||||
|
||||
# ---- Ogólne TTL z nagłówków ----
|
||||
if (beresp.http.Cache-Control ~ "(?i)s-maxage=([0-9]+)") {
|
||||
set beresp.ttl = std.duration(regsub(beresp.http.Cache-Control, "(?i).*s-maxage=([0-9]+).*", "\1") + "s", 0s);
|
||||
set beresp.ttl = std.duration(regsub(beresp.http.Cache-Control, "(?i).*s-maxage=([0-9]+).*", "\\1") + "s", 0s);
|
||||
} else if (beresp.http.Cache-Control ~ "(?i)max-age=([0-9]+)") {
|
||||
set beresp.ttl = std.duration(regsub(beresp.http.Cache-Control, "(?i).*max-age=([0-9]+).*", "\1") + "s", 0s);
|
||||
set beresp.ttl = std.duration(regsub(beresp.http.Cache-Control, "(?i).*max-age=([0-9]+).*", "\\1") + "s", 0s);
|
||||
} else if (beresp.http.Expires) {
|
||||
set beresp.ttl = std.time(beresp.http.Expires, now) - now;
|
||||
if (beresp.ttl < 0s) { set beresp.ttl = 0s; }
|
||||
@@ -211,9 +195,7 @@ sub vcl_backend_response {
|
||||
}
|
||||
|
||||
# Kompresja po stronie Varnisha wyłącznie dla klientów akceptujących gzip
|
||||
# i tylko jeśli backend nie dostarczył już Content-Encoding.
|
||||
if (!beresp.http.Content-Encoding && bereq.http.Accept-Encoding ~ "gzip") {
|
||||
# Kompresujemy tylko „tekstowe” typy; wykluczamy WASM
|
||||
if (beresp.http.Content-Type ~ "(?i)text/|application/(javascript|json|xml)") {
|
||||
set beresp.do_gzip = true;
|
||||
}
|
||||
@@ -225,7 +207,6 @@ sub vcl_backend_response {
|
||||
}
|
||||
}
|
||||
|
||||
# (Opcjonalnie) Serwuj „stale” przy błędach backendu, jeśli jest obiekt w grace
|
||||
sub vcl_backend_error {
|
||||
return (deliver);
|
||||
}
|
||||
@@ -235,7 +216,7 @@ sub vcl_deliver {
|
||||
if (obj.uncacheable) {
|
||||
if (req.http.X-Pass-Reason) {
|
||||
set resp.http.X-Cache = "PASS:" + req.http.X-Pass-Reason;
|
||||
} else if (resp.http.X-Pass-Reason) { # z backendu
|
||||
} else if (resp.http.X-Pass-Reason) {
|
||||
set resp.http.X-Cache = "PASS:" + resp.http.X-Pass-Reason;
|
||||
} else {
|
||||
set resp.http.X-Cache = "PASS";
|
||||
@@ -254,11 +235,32 @@ sub vcl_deliver {
|
||||
unset resp.http.Server;
|
||||
}
|
||||
|
||||
# ===== SYNTH =====
|
||||
sub vcl_synth {
|
||||
unset resp.http.X-Varnish;
|
||||
|
||||
if (resp.status == 429) {
|
||||
set resp.http.Content-Type = "text/html; charset=utf-8";
|
||||
synthetic({"<!DOCTYPE html><html><head><title>429 - To many requests</title><style>body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;margin:0;padding:40px;background:#f8f9fa;color:#333;text-align:center;}.container{max-width:500px;margin:0 auto;background:white;padding:60px 40px;border-radius:12px;box-shadow:0 4px 20px rgba(0,0,0,0.1);}.h1{font-size:72px;font-weight:300;margin:0 0 20px;color:#dc3545;}.h2{font-size:24px;font-weight:400;margin:0 0 30px;color:#495057;}p{font-size:16px;line-height:1.6;margin:0 0 20px;color:#6c757d;}.retry{background:#007bff;color:white;padding:12px 30px;border:none;border-radius:6px;font-size:16px;cursor:pointer;text-decoration:none;display:inline-block;}.retry:hover{background:#0056b3;}</style></head><body><div class=\"container\"><h1 class=\"h1\">429</h1><h2 class=\"h2\">To many requests!</h2><p><strong>Limit:</strong> 200 req / 10 s</p></div></body></html>"});
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
if (resp.status == 405) {
|
||||
set resp.http.Content-Type = "text/plain; charset=utf-8";
|
||||
synthetic("Metoda PURGE dozwolona tylko z localhost");
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
if (resp.status == 200 && req.method == "PURGE") {
|
||||
set resp.http.Content-Type = "text/plain; charset=utf-8";
|
||||
synthetic("Purged");
|
||||
return (deliver);
|
||||
}
|
||||
|
||||
set resp.http.X-Cache = "SYNTH";
|
||||
}
|
||||
|
||||
# ===== PURGE HANDLER =====
|
||||
sub vcl_purge {
|
||||
return (synth(200, "Purged"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user