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