varnish throttle

This commit is contained in:
Mateusz Gruszczyński
2025-09-24 15:53:43 +02:00
parent b45a259455
commit 56c02e072d
4 changed files with 29 additions and 129 deletions

3
.gitignore vendored
View File

@@ -3,4 +3,5 @@ data/
instance/
venv/
.env
version.txt
version.txt
deploy/varnish/default.vcl

View File

@@ -1,56 +0,0 @@
vcl 4.1;
backend app {
.host = "app";
.port = "8080";
}
acl purge { "127.0.0.1"; }
sub vcl_recv {
# 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);
}
# static agresywnie cacheujemy
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
return (hash);
}
return (hash);
}
sub vcl_backend_response {
if (bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
set beresp.ttl = 24h;
} else {
if (beresp.http.Cache-Control ~ "no-cache|no-store|private") {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
} else {
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
}
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}

View File

@@ -1,34 +1,35 @@
vcl 4.1;
import vsthrottle;
backend app {
.host = "app";
.port = "${APP_PORT}";
}
acl purge { "127.0.0.1"; }
acl purge { "localhost"; "127.0.0.1"; }
sub vcl_recv {
# RATE LIMIT: 10 żądań / 10s, po przekroczeniu blokada na 30s
if (vsthrottle.is_denied(client.identity, 10, 10s, 30s)) {
return (synth(429, "Too Many Requests"));
}
# PURGE tylko lokalnie
if (req.method == "PURGE") {
if (!client.ip ~ purge) {
return (synth(405, "Not allowed"));
}
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);
}
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);
}
if (req.method != "GET" && req.method != "HEAD") { return (pass); }
# static agresywnie cacheujemy
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
return (hash);
# statyczne agresywny cache
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
return (hash);
}
return (hash);
@@ -42,15 +43,27 @@ sub vcl_backend_response {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
} else {
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
set beresp.ttl = 60s; # domyślny TTL
}
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} 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 = "10";
set resp.http.X-RateLimit-Window = "10s";
set resp.http.X-RateLimit-Remaining = vsthrottle.remaining(client.identity, 10, 10s, 30s);
set resp.http.Retry-After = vsthrottle.blocked(client.identity, 10, 10s, 30s);
unset resp.http.Via;
unset resp.http.X-Varnish;
#unset resp.http.Age;
unset resp.http.Server;
}

View File

@@ -1,58 +0,0 @@
vcl 4.1;
import vsthrottle;
backend app {
.host = "app";
.port = "8080";
}
acl purge { "localhost"; "127.0.0.1"; }
sub vcl_recv {
# RATE LIMIT
if (!vsthrottle.is_allowed(client.ip, 10, 10s)) {
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); }
# static agresywnie cacheujemy
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") { return (hash); }
return (hash);
}
sub vcl_backend_response {
if (bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
set beresp.ttl = 24h;
} else {
if (beresp.http.Cache-Control ~ "no-cache|no-store|private") {
set beresp.uncacheable = true;
set beresp.ttl = 0s;
} else {
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
}
}
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.X-RateLimit-Limit = "10";
set resp.http.X-RateLimit-Window = "10s";
}