vcl 4.1; import std; import vsthrottle; backend default { .host = "plik"; .port = "8080"; .max_connections = 100; .probe = { .url = "/"; .interval = 10s; .timeout = 5s; .window = 5; .threshold = 3; } .connect_timeout = 5s; .first_byte_timeout = 90s; .between_bytes_timeout = 2s; } acl purge { "localhost"; "127.0.0.1"; "::1"; } sub vcl_recv { unset req.http.X-Cache; unset req.http.X-Cache-Hits; set req.http.Host = regsub(req.http.Host, ":[0-9]+", ""); unset req.http.proxy; set req.backend_hint = default; set req.url = std.querysort(req.url); set req.url = regsub(req.url, "\?$", ""); if (req.restarts == 0) { if (req.http.X-Forwarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } if (vsthrottle.is_denied(client.identity, 100, 10s, 10s)) { return (synth(429, "Too Many Requests")); } if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(405, "Not allowed.")); } return (purge); } if (req.method == "BAN") { if (!client.ip ~ purge) { return (synth(405, "Not allowed.")); } ban("req.http.host == " + req.http.host + " && req.url ~ " + req.url); return (synth(200, "Banned")); } if (req.method != "GET" && req.method != "HEAD" && req.method != "OPTIONS") { return (pass); } if (req.http.Authorization) { return (pass); } # upload / status / api / ajax poza cache if ( req.url ~ "(?i)^/(upload|api|status|progress|session|login|logout)(/|$)" || req.url ~ "(?i)/(ajax|ahah)/" ) { return (pass); } if (req.http.Accept-Encoding) { if (req.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|woff2?|ttf|eot|mp4|mp3|pdf|zip|7z|gz|bz2)$") { unset req.http.Accept-Encoding; } elseif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } else { unset req.http.Accept-Encoding; } } # jeśli są cookies, to: # - dla plików statycznych ignorujemy # - dla reszty omijamy cache if (req.http.Cookie) { if (req.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|js|css|woff2?|ttf|eot|pdf|zip|7z|gz|bz2|mp4|mp3)$") { unset req.http.Cookie; } else { return (pass); } } return (hash); } sub vcl_hash { if (req.http.X-Forwarded-Proto) { hash_data(req.http.X-Forwarded-Proto); } } sub vcl_hit { set req.http.X-Cache = "HIT"; if (obj.ttl <= 0s && obj.grace > 0s) { set req.http.X-Cache = "HIT-GRACE"; } return (deliver); } sub vcl_miss { set req.http.X-Cache = "MISS"; return (fetch); } sub vcl_pass { set req.http.X-Cache = "PASS"; return (fetch); } sub vcl_backend_response { # nie cache'uj błędów 5xx if (beresp.status == 500 || beresp.status == 503) { set beresp.uncacheable = true; set beresp.ttl = 0s; return (deliver); } # krótkie cache dla 404, umiarkowane dla redirectów if (beresp.status == 404) { set beresp.ttl = 5s; } elseif (beresp.status == 301 || beresp.status == 302) { set beresp.ttl = 10m; } if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|mp4|mp3|pdf|zip|7z|gz|bz2)$") { set beresp.do_gzip = false; } else { set beresp.do_gzip = true; } if (beresp.http.Cache-Control ~ "(?i)no-store|private") { set beresp.uncacheable = true; set beresp.ttl = 0s; return (deliver); } if (beresp.ttl <= 0s) { if (beresp.http.Cache-Control ~ "(?i)s-maxage=\d+") { set beresp.ttl = std.duration( regsub(beresp.http.Cache-Control, ".*(?i)s-maxage=(\d+).*", "\1") + "s", 0s ); } elseif (beresp.http.Cache-Control ~ "(?i)max-age=\d+") { set beresp.ttl = std.duration( regsub(beresp.http.Cache-Control, ".*(?i)max-age=(\d+).*", "\1") + "s", 0s ); } } if (beresp.ttl <= 0s) { if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|js|css|woff2?|ttf|eot|pdf|zip|7z|gz|bz2|mp4|mp3)$") { set beresp.ttl = 7d; } else { set beresp.ttl = 0s; set beresp.uncacheable = true; return (deliver); } } if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|js|css|woff2?|ttf|eot|pdf|zip|7z|gz|bz2|mp4|mp3)$") { unset beresp.http.Set-Cookie; } if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } if (beresp.ttl > 0s) { set beresp.grace = 10m; if (beresp.ttl > 1h) { set beresp.keep = 1h; } else { set beresp.keep = beresp.ttl; } } else { set beresp.grace = 0s; set beresp.keep = 0s; } if (beresp.http.Content-Length && std.integer(beresp.http.Content-Length, 0) > 1048576) { set beresp.do_stream = true; } return (deliver); } sub vcl_deliver { # Cache-Control tylko dla realnych plików if (req.url ~ "(?i)\.(jpg|jpeg|png|gif|webp|ico|svg|js|css|woff2?|ttf|eot|pdf|zip|7z|gz|bz2|mp4|mp3)$") { set resp.http.Cache-Control = "public, max-age=604800, immutable"; } else { set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; } unset resp.http.Expires; unset resp.http.Pragma; if (resp.status >= 500) { set resp.http.X-Cache = "ERROR"; } elseif (obj.uncacheable) { set resp.http.X-Cache = "PASS"; unset resp.http.Age; } elseif (obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.X-Cache-Hits = obj.hits; } else { set resp.http.X-Cache = "MISS"; unset resp.http.Age; } unset resp.http.X-Url; unset resp.http.X-Host; unset resp.http.Via; unset resp.http.X-Varnish; unset resp.http.Server; unset resp.http.Content-Disposition; set resp.http.X-Frame-Options = "SAMEORIGIN"; } sub vcl_synth { set resp.http.X-Cache = "SYNTH"; unset resp.http.X-Varnish; if (resp.status == 429) { set resp.http.Content-Type = "text/plain; charset=utf-8"; return (deliver); } }