summaryrefslogtreecommitdiff
path: root/contrib/varnish/cgit-esi.vcl
blob: d3b54b0187d5b671583b9dbeaaffe1348ac21fbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Varnish configuration for cgit's ESI diff fragments (cgitrc: enable-esi=1).
#
# This file is meant to be included from your own VCL after the "vcl 4.1;"
# line and the backend definition, for example:
#
#	vcl 4.1;
#	backend cgit { .host = "127.0.0.1"; .port = "8080"; }
#	include "cgit-esi.vcl";
#
# With enable-esi=1 the commit and diff pages come back from cgit as a cheap
# repository-specific frame carrying a Surrogate-Control header and an
# <esi:include> of /<repo>/esi-diff/?id=...  The fragment is the expensive
# part (the rendered diff) and its output does not depend on the repository
# or branch it was requested through, so it is hashed on its query string
# alone.  Every fork holding the same commit then shares one cached
# rendering.

sub vcl_recv {
	# Frames follow the built-in VCL: a request carrying a cookie (an
	# Anubis token, say) is passed to cgit, but ESI is still processed on
	# the way out and the fragments below are cached regardless.
	if (req.url ~ "/esi-diff/") {
		# Fragments are only ever fetched by the ESI processor; do not
		# let them become yet another crawlable URL.
		if (req.esi_level == 0) {
			return (synth(403, "Forbidden"));
		}
		# Nothing in the fragment depends on the client.
		unset req.http.Cookie;
		unset req.http.Authorization;
		return (hash);
	}
}

sub vcl_hash {
	if (req.esi_level > 0 && req.url ~ "/esi-diff/") {
		# Strip the repository path: same objects, same output.
		hash_data(regsub(req.url, "^.*/esi-diff/", "/esi-diff/"));
		return (lookup);
	}
}

sub vcl_backend_response {
	if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
		unset beresp.http.Surrogate-Control;
		set beresp.do_esi = true;
		set beresp.do_gzip = true;
		# The frame is per repository and branch and cheap to render.
		# cgit asks for ten years; keep it short so frames do not
		# crowd fragments out of the cache.
		set beresp.ttl = 5m;
		set beresp.grace = 1h;
	} else if (bereq.url ~ "/esi-diff/") {
		set beresp.do_gzip = true;
		if (beresp.status == 200) {
			# Content addressed by object id never changes.
			set beresp.ttl = 30d;
			set beresp.grace = 30d;
		} else {
			set beresp.ttl = 30s;
		}
	}
}