Drupal Mountain Camp, Davos
March 8th, 2024
httpstatusdogs.com
1 | GET /path |
2 | Accept-Encoding: text/html |
1 | HTTP/1.1 200 OK |
2 | Content-Type: text/html |
3 |
4 | <html>...</html> |
twitter.com/stevelosh/status/372740571749572610
HTTP 1.1, RFC 2616, Sections 13.2 and 13.3
1 | Cache-Control: s-maxage=3600, max-age=900 |
2 | Expires: Sat, 10 Mar 2024 08:00:00 GMT |
ETag: 82901821233
If-None-Match: 82901821233
304 Not Modified
1 | Cache-Control: s-maxage=0, private, no-cache |
Header specific for your reverse proxy, different from third party caches
1 | Cache-Control: no-store |
2 | Surrogate-Control: max-age=3600 |
1 | Cache-Control: stale-while-revalidate=3600; |
2 | Cache-Control: stale-if-error=3600; |
1 | Cache-Control: must-revalidate; |
Response content depends on request headers
Requests
1 | GET /resource |
2 | Accept: application/json |
1 | GET /resource |
2 | Accept: text/xml |
Response
1 | Vary: Accept |
Varnish does what you tell it
Think carefully and test thoroughly
1 | sub vcl_backend_response { |
2 | set beresp.http.TTL = beresp.ttl; |
3 | } |
01 | backend default { |
02 | .host = "127.0.0.1"; .port = "8080";} |
03 | backend legacy { |
04 | .host = "127.0.0.1"; .port = "8000";} |
05 |
06 | sub vcl_recv { |
07 | if (req.url ~ "^/archive/") { |
08 | set req.backend_hint = legacy; |
09 | } else { |
10 | set req.backend_hint = default; |
11 | } |
12 | } |
But first make your application behave correctly!
1 | < link rel = "stylesheet" href = "/css/style.css?v1" type = "text/css" /> |
2 | ... |
3 | < script src = "/js/scripts.js?v1" ></ script > |
01 | acl invalidators { |
02 | "localhost"; |
03 | } |
04 |
05 | if (req.method == "PURGE") { |
06 | if (!client.ip ~ invalidators) { |
07 | return (synth(405, "Not allowed")); |
08 | } |
09 | return (purge); |
10 | } |
11 |
12 | ... |
01 | acl invalidators { |
02 | "localhost"; |
03 | } |
04 |
05 | if (req.http.Cache-Control ~ "no-cache" |
06 | && client.ip ~ invalidators |
07 | ) { |
08 | set req.hash_always_miss = true; |
09 | } |
10 |
11 | ... |
01 | vcl_backend_response { |
02 | set beresp.http.X-Url = bereq.url; |
03 | set beresp.http.X-Host = bereq.http.host; |
04 | } |
05 |
06 | vcl_recv { |
07 | if (req.method == "BAN") { |
08 | if (!client.ip ~ invalidators) { |
09 | return (synth(405, "Not allowed")); |
10 | } |
11 | ban("obj.http.X-Host ~ " + req.http.X-Host |
12 | + " && obj.http.X-Url ~ " + req.http.X-Url |
13 | ); |
14 | } |
15 | } |
1 | $response ->withHeader( 'xkey' , 'node:2 node:44' ); |
1 | xkey.purge(req.http.xkey-purge); |
You can also use BAN, but its much less efficient
Element | weight | <-> | Element | weight |
---|---|---|---|---|
A | 9 | D | 22 | |
B | 8 | A | 9 | |
C | 7 | B | 8 | |
D | 6 | C | 7 | |
E | 5 | E | 5 | |
F | 4 | F | 4 | |
G | 3 | G | 3 | |
H | 2 | H | 2 | |
I | 1 | I | 1 |
Element | weight | <-> | Element | weight |
---|---|---|---|---|
A | 9 | A | 9 | |
B | 8 | B | 8 | |
C | 7 | D | 6 | |
D | 6 | E | 5 | |
E | 5 | F | 4 | |
F | 4 | G | 3 | |
G | 3 | H | 2 | |
H | 2 | I | 1 | |
I | 1 |