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_asset_path = find_plain(uri, '/wp-content/themes/' )
35
+ or find_plain(uri, '/wp-content/plugins/' )
36
+ or find_plain(uri, '/wp-content/mu-plugins/' )
37
+ or find_plain(uri, '/wp-includes/' )
38
+ or find_plain(uri, '/wp-admin/' )
39
+
40
+ request.is_static = (find_plain(uri, '/wp-content/' ) and not request.is_asset_path)
41
+ or (ngx.re.match(uri, re.static_extension, 'io' ) and true)
42
+
43
+ request.is_asset = request.is_static and is_asset_path
44
+
45
+ request.is_wp_admin = not request.is_asset
46
+ and not ngx.re.match(uri, "^.*/wp-admin/admin-ajax.php" )
47
+ 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" )
48
+
49
+ request.wp_loggedin = (ngx.re.match(ngx.var.http_cookie or '' , re.wp_loggedin, 'io' ) and true or false)
50
+
51
+ request.query_string = (ngx.var.is_args or '' ) .. (ngx.var.args or '' )
52
+
53
+ request.is_woocommerce = (
54
+ ngx.re.match(request.query_string or '' , re.woocommerce_args, 'io' ) or
55
+ (ngx.re.match(ngx.var.http_cookie or '' , re.woocommerce_cookies, 'io' ) and true) or
56
+ (find_plain(uri, '/wc-api/' ) or ngx.re.match(request.query_string, 'wc-api=' , 'o' ))
57
+ )
58
+
59
+ request.is_dynamic = not request.is_static and (
60
+ request.is_wp_admin or
61
+ request.wp_loggedin or
62
+ request.is_woocommerce or
63
+ (request_method ~ = 'GET' and
64
+ request_method ~ = 'HEAD' ) or
65
+ -- skip cache if there are query strings (TODO: improve this logic for better cache hit)
66
+ request.query_string ~ = ''
67
+ )
68
+
69
+ local cache_bypass = (ngx.var.skip_cache or '0' ) ~ = '0'
70
+ or (ngx.re.match(ngx.var.http_cookie or '' , re.bbpress_cookies, 'io' ) and true)
71
+ or false
72
+
73
+ local skip_cache = 0
74
+ if request.is_dynamic or cache_bypass then
75
+ skip_cache = 1
76
+ end
77
+
78
+ return skip_cache
79
+ }
80
+
81
+ set $key "" ;
82
+ set $key_prefix {{ $keyPrefix }};
83
+ set $key_uid {{ $keyUID }};
84
+ set $escaped_key "" ;
85
+ set_escape_uri $escaped_key_prefix $key_prefix ;
86
+ set_escape_uri $escaped_key_uid $key_uid ;
87
+
88
+ # Use versioned keys with memcached by default, for implementing cache flush
89
+ {{- if and (eq .Env.STACK_PAGE_CACHE_BACKEND "memcached" ) ( has (default "on" .Env.STACK_PAGE_CACHE_MEMCACHED_USE_VERSION) $truthStrings ) }}
90
+ rewrite_by_lua_block {
91
+ if ngx.var.skip_cache == "1" then
92
+ return
93
+ end
94
+
95
+ local memcached = require "resty.memcached"
96
+
97
+ local function identity(key) return key end
98
+
99
+ local memc, err = memcached:new{
100
+ -- don't escape/unescape keys
101
+ key_transform = { identity, identity }
102
+ }
103
+
104
+ if not memc then
105
+ ngx.log(ngx.ERR, "failed to instantiate memcached: ", err)
106
+ return
107
+ end
108
+
109
+ memc:set_timeout(1000)
110
+
111
+ local ok, err = memc:connect("{{ default "127.0.0.1:11211" .Env.STACK_PAGE_CACHE_MEMCACHED_HOST_PATH }}")
112
+ if not ok then
113
+ ngx.log(ngx.ERR, "failed to connect to memcached: ", err)
114
+ return
115
+ end
116
+
117
+ local versionKey = ngx.var.key_prefix .. "version"
118
+
119
+ local version, flags, err = memc:get(versionKey)
120
+ if err then
121
+ ngx.log(ngx.ERR, "failed to get memcached version: ", err)
122
+ return
123
+ end
124
+
125
+ if not version then
126
+ ngx.log(ngx.INFO, "memcached version not found, attempting to set one...")
127
+
128
+ version = tostring(os.time()) .. ":"
129
+ local ok, err = memc:set(versionKey, version)
130
+ if not ok then
131
+ ngx.log(ngx.ERR, "failed to set memcached version: ", err)
132
+ return
133
+ end
134
+ end
135
+
136
+ ngx.var.key = ngx.var.key_prefix .. version .. ngx.var.key_uid
137
+ ngx.var.escaped_key = ngx.var.escaped_key_prefix .. ngx.escape_uri(version) .. ngx.var.escaped_key_uid
138
+
139
+ local ok, err = memc:close()
140
+ if not ok then
141
+ ngx.say("failed to close memcached: ", err)
142
+ return
143
+ end
144
+ }
145
+
146
+ {{- else }}
147
+ # default key is nginx-cache:https$request_method$host$request_uri
148
+ set $key $key_prefix$key_uid ;
149
+ set $escaped_key $escaped_key_prefix$escaped_key_uid ;
150
+ {{- end }}
151
+
152
+ try_files $uri =404;
153
+
154
+ srcache_fetch_skip $skip_cache ;
155
+ srcache_store_skip $skip_cache ;
156
+ srcache_store_statuses {{ default "200 301 302" .Env.STACK_PAGE_CACHE_STORE_STATUSES }};
157
+
158
+ # https://github.com/openresty/srcache-nginx-module#srcache_response_cache_control
159
+ srcache_response_cache_control {{ default "on" .Env.STACK_PAGE_CACHE_RESPONSE_CACHE_CONTROL }};
160
+
161
+ srcache_fetch GET /.stack-cache-fetch $key ;
162
+ srcache_store PUT /.stack-cache-store key=$escaped_key &exptime={{ default "360" .Env.STACK_PAGE_CACHE_EXPIRE_SECONDS | atoi }};
163
+
164
+ more_set_headers "x-cache-fetch $srcache_fetch_status ";
165
+
166
+ {{- end }}
0 commit comments