1
+ # vim: set ft=nginx:
2
+
3
+ {{- $stackBackends := list "redis" "memcached" "custom" }}
4
+ {{- $truthStrings := list "true" "on" "yes" -}}
5
+ {{- $keyPrefix := default "nginx-cache:" .Env.STACK_PAGE_CACHE_KEY_PREFIX }}
6
+ {{- $keyUID := default "https$request_method$host$request_uri " .Env.STACK_PAGE_CACHE_KEY_UID }}
7
+
8
+ {{- if has .Env.STACK_PAGE_CACHE_BACKEND $stackBackends }}
9
+ set $skip_cache 0 ;
10
+
11
+ set_by_lua_block $skip_cache {
12
+ local scheme = ngx.var.scheme
13
+ local uri = ngx.var.request_uri
14
+ local request = ngx.ctx.request or {}
15
+ ngx.ctx.request = request
16
+ local user_agent = ngx.var.http_user_agent or ''
17
+ local request_method = ngx.req.get_method()
18
+
19
+ re = {}
20
+ re.static_extension = [[\.(jpg|jpeg|png|gif|svg|swf|pdf|tar|gz|bz2|exe|sh|zip|rar|arj|css|js|jsx|bin|dmg|dll|pkg|apk|bin|rpm|deb|msi|woff|woff2|ttf|eot|otf|mp3|avi|mp4|mpeg|tif|tiff|bmp|webp)$]]
21
+ re.wp_loggedin = [[wordpress_logged_in|wordpress_no_cache|comment_author_|wp-postpass_|wp_gdsr_|fbs_|wp-query_monitor_]]
22
+ re.woocommerce_cookies = [[woocommerce_cart_hash|woocommerce_items_in_cart|wp_woocommerce_session_]]
23
+ re.woocommerce_args = [[remove_item|removed_item|remove_coupon|undo_item|order|add-to-cart|added-to-cart|revoke-key]]
24
+ re.bbpress_cookies = [[EmailID]]
25
+
26
+ function find_plain(s, sub)
27
+ if string.find(s, sub, 1, true) == nil then
28
+ return false
29
+ end
30
+
31
+ return true
32
+ end
33
+
34
+ request.is_acme_challenge = find_plain(uri, '/.well-known/acme-challenge/' )
35
+
36
+ request.is_asset_path = find_plain(uri, '/wp-content/themes/' )
37
+ or find_plain(uri, '/wp-content/plugins/' )
38
+ or find_plain(uri, '/wp-content/mu-plugins/' )
39
+ or find_plain(uri, '/wp-includes/' )
40
+ or find_plain(uri, '/wp-admin/' )
41
+
42
+ request.is_static = (find_plain(uri, '/wp-content/' ) and not request.is_asset_path)
43
+ or (ngx.re.match(uri, re.static_extension, 'io' ) and true)
44
+
45
+ request.is_asset = request.is_static and is_asset_path
46
+
47
+ request.is_wp_admin = not request.is_asset
48
+ and not ngx.re.match(uri, "^.*/wp-admin/admin-ajax.php" )
49
+ 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" )
50
+
51
+ request.wp_loggedin = (ngx.re.match(ngx.var.http_cookie or '' , re.wp_loggedin, 'io' ) and true or false)
52
+
53
+ request.query_string = (ngx.var.is_args or '' ) .. (ngx.var.args or '' )
54
+
55
+ request.is_woocommerce = (
56
+ ngx.re.match(request.query_string or '' , re.woocommerce_args, 'io' ) or
57
+ (ngx.re.match(ngx.var.http_cookie or '' , re.woocommerce_cookies, 'io' ) and true) or
58
+ (find_plain(uri, '/wc-api/' ) or ngx.re.match(request.query_string, 'wc-api=' , 'o' ))
59
+ )
60
+
61
+ request.is_dynamic = not request.is_static and (
62
+ request.is_wp_admin or
63
+ request.wp_loggedin or
64
+ request.is_woocommerce or
65
+ (request_method ~ = 'GET' and
66
+ request_method ~ = 'HEAD' ) or
67
+ -- ACME challenge requests
68
+ request.is_acme_challenge or
69
+ -- skip cache if there are query strings (TODO: improve this logic for better cache hit)
70
+ request.query_string ~ = ''
71
+ )
72
+
73
+ local cache_bypass = (ngx.var.skip_cache or '0' ) ~ = '0'
74
+ or (ngx.re.match(ngx.var.http_cookie or '' , re.bbpress_cookies, 'io' ) and true)
75
+ or false
76
+
77
+ local skip_cache = 0
78
+ if request.is_dynamic or cache_bypass then
79
+ skip_cache = 1
80
+ end
81
+
82
+ return skip_cache
83
+ }
84
+
85
+ set $key "" ;
86
+ set $key_prefix {{ $keyPrefix }};
87
+ set $key_uid {{ $keyUID }};
88
+ set $escaped_key "" ;
89
+ set_escape_uri $escaped_key_prefix $key_prefix ;
90
+ set_escape_uri $escaped_key_uid $key_uid ;
91
+
92
+ # Use versioned keys with memcached by default, for implementing cache flush
93
+ {{- if and (eq .Env.STACK_PAGE_CACHE_BACKEND "memcached" ) ( has (default "on" .Env.STACK_PAGE_CACHE_MEMCACHED_USE_VERSION) $truthStrings ) }}
94
+ rewrite_by_lua_block {
95
+ if ngx.var.skip_cache == "1" then
96
+ return
97
+ end
98
+
99
+ local memcached = require "resty.memcached"
100
+
101
+ local function identity(key) return key end
102
+
103
+ local memc, err = memcached:new{
104
+ -- don't escape/unescape keys
105
+ key_transform = { identity, identity }
106
+ }
107
+
108
+ if not memc then
109
+ ngx.log(ngx.ERR, "failed to instantiate memcached: ", err)
110
+ return
111
+ end
112
+
113
+ memc:set_timeout(1000)
114
+
115
+ local ok, err = memc:connect("{{ default "127.0.0.1:11211" .Env.STACK_PAGE_CACHE_MEMCACHED_HOST_PATH }}")
116
+ if not ok then
117
+ ngx.log(ngx.ERR, "failed to connect to memcached: ", err)
118
+ return
119
+ end
120
+
121
+ local versionKey = ngx.var.key_prefix .. "version"
122
+
123
+ local version, flags, err = memc:get(versionKey)
124
+ if err then
125
+ ngx.log(ngx.ERR, "failed to get memcached version: ", err)
126
+ return
127
+ end
128
+
129
+ if not version then
130
+ ngx.log(ngx.INFO, "memcached version not found, attempting to set one...")
131
+
132
+ version = tostring(os.time()) .. ":"
133
+ local ok, err = memc:set(versionKey, version)
134
+ if not ok then
135
+ ngx.log(ngx.ERR, "failed to set memcached version: ", err)
136
+ return
137
+ end
138
+ end
139
+
140
+ ngx.var.key = ngx.var.key_prefix .. version .. ngx.var.key_uid
141
+ ngx.var.escaped_key = ngx.var.escaped_key_prefix .. ngx.escape_uri(version) .. ngx.var.escaped_key_uid
142
+
143
+ local ok, err = memc:close()
144
+ if not ok then
145
+ ngx.say("failed to close memcached: ", err)
146
+ return
147
+ end
148
+ }
149
+
150
+ {{- else }}
151
+ # default key is nginx-cache:https$request_method$host$request_uri
152
+ set $key $key_prefix$key_uid ;
153
+ set $escaped_key $escaped_key_prefix$escaped_key_uid ;
154
+ {{- end }}
155
+
156
+ try_files $uri =404;
157
+
158
+ srcache_fetch_skip $skip_cache ;
159
+ srcache_store_skip $skip_cache ;
160
+ srcache_store_statuses {{ default "200 301 302" .Env.STACK_PAGE_CACHE_STORE_STATUSES }};
161
+
162
+ # https://github.com/openresty/srcache-nginx-module#srcache_response_cache_control
163
+ srcache_response_cache_control {{ default "on" .Env.STACK_PAGE_CACHE_RESPONSE_CACHE_CONTROL }};
164
+
165
+ srcache_fetch GET /.stack-cache-fetch $key ;
166
+ srcache_store PUT /.stack-cache-store key=$escaped_key &exptime={{ default "360" .Env.STACK_PAGE_CACHE_EXPIRE_SECONDS | atoi }};
167
+
168
+ more_set_headers "x-cache-fetch $srcache_fetch_status ";
169
+
170
+ {{- end }}
0 commit comments