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