Skip to content

Commit cd67461

Browse files
committed
Add support for page cache
1 parent 87a009e commit cd67461

File tree

4 files changed

+225
-3
lines changed

4 files changed

+225
-3
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# vim: set ft=nginx:
2+
3+
{{- if eq .Env.STACK_PAGE_CACHE_BACKEND "redis" }}
4+
5+
location = /.stack-cache-fetch {
6+
internal;
7+
8+
set $redis_key $args;
9+
redis_pass {{ default "localhost:6379" .Env.STACK_PAGE_CACHE_REDIS_HOST_PATH }};
10+
}
11+
12+
location = /.stack-cache-store {
13+
internal;
14+
15+
set_unescape_uri $exptime $arg_exptime;
16+
set_unescape_uri $key $arg_key;
17+
18+
redis2_query set $key $echo_request_body;
19+
redis2_query expire $key $exptime;
20+
redis2_pass {{ default "localhost:6379" .Env.STACK_PAGE_CACHE_REDIS_HOST_PATH }};
21+
}
22+
23+
{{- else if eq .Env.STACK_PAGE_CACHE_BACKEND "memcached" }}
24+
location = /.stack-cache-fetch {
25+
internal;
26+
27+
set $memc_key $args;
28+
29+
memc_connect_timeout 500ms;
30+
memc_read_timeout 500ms;
31+
memc_ignore_client_abort on;
32+
33+
memc_pass {{ default "127.0.0.1:11211" .Env.STACK_PAGE_CACHE_MEMCACHED_HOST_PATH }};
34+
}
35+
36+
location = /.stack-cache-store {
37+
internal;
38+
39+
set_unescape_uri $exptime $arg_exptime;
40+
set_unescape_uri $key $arg_key;
41+
42+
set $memc_key $key;
43+
set $memc_exptime $exptime;
44+
45+
memc_connect_timeout 500ms;
46+
memc_send_timeout 500ms;
47+
memc_ignore_client_abort on;
48+
49+
memc_pass {{ default "127.0.0.1:11211" .Env.STACK_PAGE_CACHE_MEMCACHED_HOST_PATH }};
50+
}
51+
{{- end }}

php/docker/templates/nginx-vhost-conf.d/80-index.conf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ location / {
55
}
66

77
location ~ \.php$ {
8-
fastcgi_pass $upstream;
8+
include /usr/local/docker/etc/nginx-vhost-conf.d/page-cache.d/*.conf;
9+
fastcgi_pass $upstream;
910
fastcgi_read_timeout {{ max 60 (add 10 (default "30" .Env.PHP_REQUEST_TIMEOUT | atoi)) }};
10-
fastcgi_index index.php;
11-
include /usr/local/openresty/nginx/conf/fastcgi.conf;
11+
fastcgi_index index.php;
12+
include /usr/local/openresty/nginx/conf/fastcgi.conf;
1213
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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

Comments
 (0)