1
+ # vim: set ft=nginx:
2
+
3
+ {{- $chosenBackend := default "" .Env.STACK_PAGE_CACHE_BACKEND }}
4
+ {{- $allowedBackends := list "redis" "memcached" "custom" }}
5
+ {{- $memcachedHost := default "127.0.0.1" .Env.STACK_PAGE_CACHE_MEMCACHED_HOST }}
6
+ {{- $memcachedPort := default "11211" .Env.STACK_PAGE_CACHE_MEMCACHED_PORT }}
7
+ {{- $truthStrings := list "true" "on" "yes" -}}
8
+ {{- $keyPrefix := default "nginx-cache:" .Env.STACK_PAGE_CACHE_KEY_PREFIX }}
9
+ {{- $keyUID := default "https$request_method$host$request_uri " .Env.STACK_PAGE_CACHE_KEY_UID }}
10
+
11
+ {{- if has $chosenBackend $allowedBackends }}
12
+ set $skip_cache 0 ;
13
+
14
+ set_by_lua_block $skip_cache {
15
+ local scheme = ngx.var.scheme
16
+ local uri = ngx.var.request_uri
17
+ local request = ngx.ctx.request or {}
18
+ ngx.ctx.request = request
19
+ local user_agent = ngx.var.http_user_agent or ''
20
+ local request_method = ngx.req.get_method()
21
+
22
+ re = {}
23
+ re.wp_loggedin = [[wordpress_logged_in|wordpress_no_cache|comment_author_|wp-postpass_|wp_gdsr_|fbs_|wp-query_monitor_]]
24
+ re.woocommerce_cookies = [[woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_]]
25
+ re.woocommerce_args = [[remove_item|removed_item|remove_coupon|undo_item|order|add-to-cart|added-to-cart|revoke-key]]
26
+ re.bbpress_cookies = [[EmailID]]
27
+
28
+ function find_plain(s, sub)
29
+ if string.find(s, sub, 1, true) == nil then
30
+ return false
31
+ end
32
+
33
+ return true
34
+ end
35
+
36
+ request.is_wp_admin = (
37
+ not ngx.re.match(uri, "^.*/wp-admin/admin-ajax.php" )
38
+ and ngx.re.match(uri, "^.*/(wp-admin/|wp-login.php|wp-signup.php|wp-cron.php|xmlrpc.php|git-webhook.php|feed/|sitemap.xml|sitemap_index.xml)" , "o" )
39
+ )
40
+
41
+ request.wp_loggedin = (ngx.re.match(ngx.var.http_cookie or '' , re.wp_loggedin, 'io' ) and true or false)
42
+
43
+ request.query_string = (ngx.var.is_args or '' ) .. (ngx.var.args or '' )
44
+
45
+ request.is_woocommerce = (
46
+ ngx.re.match(request.query_string or '' , re.woocommerce_args, 'io' ) or
47
+ (ngx.re.match(ngx.var.http_cookie or '' , re.woocommerce_cookies, 'io' ) and true) or
48
+ (find_plain(uri, '/wc-api/' ) or ngx.re.match(request.query_string, 'wc-api=' , 'o' ))
49
+ )
50
+
51
+ request.is_dynamic = (
52
+ request.is_wp_admin or
53
+ request.wp_loggedin or
54
+ request.is_woocommerce or
55
+ (request_method ~ = 'GET' and
56
+ request_method ~ = 'HEAD' ) or
57
+ -- skip cache if there are query strings (TODO: improve this logic for better cache hit)
58
+ request.query_string ~ = ''
59
+ )
60
+
61
+ local cache_bypass = (ngx.var.skip_cache or '0' ) ~ = '0'
62
+ or (ngx.re.match(ngx.var.http_cookie or '' , re.bbpress_cookies, 'io' ) and true)
63
+ or false
64
+
65
+ local skip_cache = 0
66
+ if request.is_dynamic or cache_bypass then
67
+ skip_cache = 1
68
+ end
69
+
70
+ return skip_cache
71
+ }
72
+
73
+ set $key "" ;
74
+ set $key_prefix {{ $keyPrefix }};
75
+ set $key_uid {{ $keyUID }};
76
+ set $escaped_key "" ;
77
+ set_escape_uri $escaped_key_prefix $key_prefix ;
78
+ set_escape_uri $escaped_key_uid $key_uid ;
79
+
80
+ # Use versioned keys with memcached by default, for implementing cache flush
81
+ {{- if and (eq $chosenBackend "memcached" ) ( has (default "on" .Env.STACK_PAGE_CACHE_MEMCACHED_USE_VERSION) $truthStrings ) }}
82
+ rewrite_by_lua_block {
83
+ if ngx.var.skip_cache == "1" then
84
+ return
85
+ end
86
+
87
+ local memcached = require "resty.memcached"
88
+
89
+ local function identity(key) return key end
90
+
91
+ local memc, err = memcached:new{
92
+ -- don't escape/unescape keys
93
+ key_transform = { identity, identity }
94
+ }
95
+
96
+ if not memc then
97
+ ngx.log(ngx.ERR, "failed to instantiate memcached: ", err)
98
+ return
99
+ end
100
+
101
+ memc:set_timeout(1000)
102
+
103
+ local ok, err = memc:connect("{{ $memcachedHost }}:{{ $memcachedPort }}")
104
+ if not ok then
105
+ ngx.log(ngx.ERR, "failed to connect to memcached: ", err)
106
+ return
107
+ end
108
+
109
+ local versionKey = ngx.var.key_prefix .. "version"
110
+
111
+ local version, flags, err = memc:get(versionKey)
112
+ if err then
113
+ ngx.log(ngx.ERR, "failed to get memcached version: ", err)
114
+ return
115
+ end
116
+
117
+ if not version then
118
+ ngx.log(ngx.INFO, "memcached version not found, attempting to set one...")
119
+
120
+ version = tostring(os.time()) .. ":"
121
+ local ok, err = memc:set(versionKey, version)
122
+ if not ok then
123
+ ngx.log(ngx.ERR, "failed to set memcached version: ", err)
124
+ return
125
+ end
126
+ end
127
+
128
+ ngx.var.key = ngx.var.key_prefix .. version .. ngx.var.key_uid
129
+ ngx.var.escaped_key = ngx.var.escaped_key_prefix .. ngx.escape_uri(version) .. ngx.var.escaped_key_uid
130
+
131
+ local ok, err = memc:close()
132
+ if not ok then
133
+ ngx.say("failed to close memcached: ", err)
134
+ return
135
+ end
136
+ }
137
+
138
+ {{- else }}
139
+ # default key is nginx-cache:https$request_method$host$request_uri
140
+ set $key $key_prefix$key_uid ;
141
+ set $escaped_key $escaped_key_prefix$escaped_key_uid ;
142
+ {{- end }}
143
+
144
+ srcache_fetch_skip $skip_cache ;
145
+ srcache_store_skip $skip_cache ;
146
+ srcache_store_statuses {{ default "200 301 302" .Env.STACK_PAGE_CACHE_STORE_STATUSES }};
147
+
148
+ # https://github.com/openresty/srcache-nginx-module#srcache_response_cache_control
149
+ srcache_response_cache_control {{ default "on" .Env.STACK_PAGE_CACHE_RESPONSE_CACHE_CONTROL }};
150
+
151
+ srcache_fetch GET /.stack-cache-fetch $key ;
152
+ srcache_store PUT /.stack-cache-store key=$escaped_key &exptime={{ default "360" .Env.STACK_PAGE_CACHE_EXPIRE_SECONDS | atoi }};
153
+
154
+ more_set_headers "x-cache-fetch $srcache_fetch_status ";
155
+
156
+ {{- end }}
0 commit comments