我正在使用 nginx 检测浏览器中的 webp 支持:
# Check if client is capable of handling webp
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
当客户端支持 image/webp 时,此代码运行正常并将 .webp 分配给 $webp_suffix
几行之后我在以下配置中使用了这个变量:
location ~ ^/imgs/([0-9]*)/(.*?)(\..+)$ {
add_header X-webp $webp_suffix;
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
}
即使两个文件都存在,也总是会导致 e404。标头 X-webp 设置为“.webp”,因此地图工作正常。
更奇怪的是 - 如果我交换 try_files 参数的顺序:
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
到
try_files /imgs/$1$3 /imgs/$1$webp_suffix =404;
然后它开始工作并将文件 /imgs/$1$3 发送到浏览器。这怎么可能?我是否遗漏了此逻辑中的某些内容?
EDIT1:完成 nginx.conf 以重现:
events {
use epoll;
worker_connections 128;
}
http {
# Check if client is capable of handling webp
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
server {
listen *:8888;
server_name test;
root /srv;
location ~ ^/imgs/([0-9]*)/(.*?)(\..+)$ {
add_header X-webp $webp_suffix;
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
}
}
}
EDIT2:更奇怪的是 - 如果我改变:
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
到:
try_files /imgs/$1.webp /imgs/$1$3 =404;
然后 try_files 就可以正常工作了(但我们现在不检查客户端是否支持 webp,只是假设它支持它)。请记住:
add_header X-webp $webp_suffix;
在相同位置会添加标题:X-webp .webp
那么为什么 /imgs/$1$webp_suffix 不起作用而 /imgs/$1.webp 起作用呢?
我已经测试过:
- $webp_suffix = “.webp”(已测试并且有效)
- try_files /imgs/$1$webp_suffix /imgs/$1$3 =404 - 不起作用并返回 404
- try_files /imgs/$1.webp /imgs/$1$3 =404 - 有效并返回 webp 文件
- try_files /imgs/$1$3 /imgs/$1$webp_suffix =404 - 有效并返回 jpg 文件
这毫无意义
编辑3:
为了测试我打开:http://test:8888/imgs/10/whatever.jpg
文件 /srv/imgs/10.jpg 和 /srv/imgs/10.webp 确实存在。
答案1
该try_files
语句正在使用语句中正则表达式的数字捕获location
。数字捕获的问题在于,每当评估正则表达式时,它们都会被覆盖。包含在和语句map
之间评估的正则表达式。location
try_files
解决方案是使用命名捕获:
例如:
location ~ ^/imgs/(?<prefix>[0-9]*)/(.*?)(?<suffix>\..+)$ {
add_header X-webp $webp_suffix;
try_files /imgs/$prefix$webp_suffix /imgs/$prefix$suffix =404;
}