今天在配置nginx缓存图片时发现,一旦加上缓存配置,请求图片就会报错404。后发现在错误日志中图片的请求路径发生了奇怪的变化。
期望的请求地址:/user/apps/luwuer.com/img/xxx.jpg
实际请求地址却变作:/user/apps/jpg/luwuer.com/img/xxx.jpg
此时的nginx配置:
server {
listen 80 default_server;
server_name ~^(\w+\.)?(luwuer\.com)$; # $1 = 'blog.' || 'img.' || '' ; $2 = 'luwuer.com'
root /root/apps/$1$2;
location ~* \.(jpeg|png|gif|jpg)$ {
expires 14d; # 缓存14天
log_not_found on; # 是否在error.log中记录不存在的错误, 默认是
access_log off; # 是否在access.log中记录
}
# ...
}
最终发现导致问题的原因,是root /root/apps/$1$2;
,总结说来是两个原因。
-
$1|$2|$3 ...
是nginx在匹配正则时生成的变量,用于捕获一个正则表达式括号中匹配的字符串(从左到右依次存储在$1|$2|$3 ...
中),新值覆盖旧值。 - location块中未设置root时,会取外层(server块)的root,但server.root明显不是先生成字符串然后赋值给location.root,而是直接把模板串交给location.root。
本配置中server.root被设置为/root/apps/$1$2
(/root/apps/luwuer.com
,$1 = '',$2 = 'luwuer.com'
),在匹配到图片请求时$1
被改变为图片的后缀名(/root/apps/jpg/luwuer.com
,# $1 = 'jpg',$2 = 'luwuer.com'
),故访问地址错误找不到图片。
既然知道了原理,要修改也是简单,只需把第一次匹配到的$1,$2
保存到自定义变量中。
修改后配置:
server {
listen 80 default_server;
server_name ~^(\w+\.)?(luwuer\.com)$; # $1 = 'blog.' || 'img.' || '' ; $2 = 'luwuer.com'
set $pre $1;
set $next $2;
root /root/apps/$pre$next;
location ~* \.(jpeg|png|gif|jpg)$ {
expires 14d; # 缓存14天
log_not_found on; # 是否在error.log中记录不存在的错误, 默认是
access_log off; # 是否在access.log中记录
}
# ...
}