Files
zbiorki_app/deploy/varnish/default.vcl.template
Mateusz Gruszczyński 72b82ae40c varnish throttle
2025-09-24 16:06:57 +02:00

93 lines
2.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

vcl 4.1;
import vsthrottle;
import std;
backend app {
.host = "app";
.port = "${APP_PORT}";
}
/* unikamy duplikatu; dodajemy IPv6 */
acl purge { "127.0.0.1"; "::1"; }
sub vcl_recv {
# RATE LIMIT: 100 żądań / 10s, blokada 60s
if (vsthrottle.is_denied(client.identity, 100, 10s, 60s)) {
return (synth(429, "Too Many Requests"));
}
# PURGE tylko lokalnie
if (req.method == "PURGE") {
if (!client.ip ~ purge) { return (synth(405, "Not allowed")); }
return (purge);
}
# omijamy cache dla healthchecków / wewn. nagłówka
if (req.url == "/healthcheck" || req.http.X-Internal-Check) { return (pass); }
# metody inne niż GET/HEAD bez cache
if (req.method != "GET" && req.method != "HEAD") { return (pass); }
# statyczne agresywny cache
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
return (hash);
}
return (hash);
}
sub vcl_backend_response {
# Treści prywatne / zakazane do cache
if (beresp.http.Cache-Control ~ "(?i)no-store|private") {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
return (deliver);
}
# Preferuj s-maxage, potem max-age
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);
} 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);
} else if (beresp.http.Expires) {
# fallback na Expires
set beresp.ttl = std.time(beresp.http.Expires, now, 0s) - now;
} else {
# ostateczny fallback
set beresp.ttl = 60s;
}
# Jeśli immutable zwiększ grace/keep
if (beresp.http.Cache-Control ~ "(?i)immutable") {
set beresp.grace = 1h;
set beresp.keep = 24h;
}
# statykom daj minimalne TTL, gdy backend NIE ustawił CC
if ((bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$")
&& !(beresp.http.Cache-Control ~ "(?i)(s-maxage|max-age)")) {
set beresp.ttl = 24h;
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
# ukryj niepotrzebny nagłówek z MISS
#} else {
# set resp.http.X-Cache = "MISS";
}
# Nagłówki rate limit MUSZĄ używać tej samej czwórki parametrów co is_denied()
#set resp.http.X-RateLimit-Limit = "100";
#set resp.http.X-RateLimit-Window = "10s";
#set resp.http.X-RateLimit-Remaining = vsthrottle.remaining(client.identity, 100, 10s, 60s);
#set resp.http.Retry-After = vsthrottle.blocked(client.identity, 100, 10s, 60s);
unset resp.http.Via;
unset resp.http.X-Varnish;
#unset resp.http.Age;
unset resp.http.Server;
}