149 lines
3.8 KiB
Plaintext
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);
|
|
}
|