Files
2025-10-07 10:12:17 +02:00

149 lines
3.8 KiB
Plaintext

vcl 4.1;
# Backend definition - points to our PHP/Apache container
backend default {
.host = "app";
.port = "80";
.connect_timeout = 60s;
.first_byte_timeout = 60s;
.between_bytes_timeout = 60s;
}
# Called at the beginning of a request
sub vcl_recv {
# Remove port from Host header for proper backend routing
if (req.http.Host) {
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
}
# Handle image requests
if (req.url ~ "\.(jpg|jpeg|png|gif|webp|svg|ico)$") {
# Cache images aggressively
set req.http.Cache-Control = "public, max-age=2592000";
return (hash);
}
# Handle API image proxy requests
if (req.url ~ "^/api/image\.php") {
# Cache external images through our proxy
return (hash);
}
# Handle CSS and JS files
if (req.url ~ "\.(css|js)$") {
return (hash);
}
# Don't cache POST, PUT, DELETE requests
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Don't cache requests with cookies (except for images)
if (req.http.Cookie && req.url !~ "\.(jpg|jpeg|png|gif|webp|svg|ico|css|js)$") {
return (pass);
}
# Remove tracking parameters
if (req.url ~ "\?") {
set req.url = regsub(req.url, "\?.*", "");
}
return (hash);
}
# Called after a cache lookup
sub vcl_hit {
# Add cache hit header for debugging
set req.http.X-Cache = "HIT";
return (deliver);
}
# Called after a cache miss
sub vcl_miss {
set req.http.X-Cache = "MISS";
return (fetch);
}
# Called before sending response to client
sub vcl_deliver {
# Add cache status header
if (req.http.X-Cache) {
set resp.http.X-Cache = req.http.X-Cache;
}
# Add CORS headers for images
if (req.url ~ "\.(jpg|jpeg|png|gif|webp|svg|ico)$") {
set resp.http.Access-Control-Allow-Origin = "*";
}
# Remove server identification
unset resp.http.Server;
unset resp.http.X-Powered-By;
unset resp.http.X-Varnish;
return (deliver);
}
# Called after fetching from backend
sub vcl_backend_response {
# Cache images for 30 days
if (bereq.url ~ "\.(jpg|jpeg|png|gif|webp|svg|ico)$") {
set beresp.ttl = 30d;
set beresp.http.Cache-Control = "public, max-age=2592000";
set beresp.http.Expires = beresp.http.Date + 30d;
# Don't cache if backend says not to
if (beresp.http.Cache-Control ~ "no-cache") {
set beresp.ttl = 0s;
}
}
# Cache CSS and JS for 7 days
if (bereq.url ~ "\.(css|js)$") {
set beresp.ttl = 7d;
set beresp.http.Cache-Control = "public, max-age=604800";
}
# Cache API image proxy for 1 day
if (bereq.url ~ "^/api/image\.php") {
set beresp.ttl = 1d;
set beresp.http.Cache-Control = "public, max-age=86400";
}
# Don't cache if there's an error
if (beresp.status >= 400) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
}
# Enable compression
if (beresp.http.Content-Type ~ "text|application|image/svg") {
set beresp.do_gzip = true;
}
return (deliver);
}
# Called when there's an error
sub vcl_backend_error {
set beresp.http.Content-Type = "text/html; charset=utf-8";
set beresp.status = 503;
synthetic( {"<!DOCTYPE html>
<html>
<head>
<title>Service Unavailable</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
h1 { color: #666; }
</style>
</head>
<body>
<h1>Service Temporarily Unavailable</h1>
<p>Please try again in a few moments.</p>
</body>
</html>"} );
return (deliver);
}