我正在使用 nginx 来检测浏览器中的 webp 支持:
# Check if client is capable of handling webp
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
Run Code Online (Sandbox Code Playgroud)
此代码工作正常,并在客户端支持图像/webp 时将 .webp 分配给 $webp_suffix
然后几行之后我在以下配置中使用这个变量:
location ~ ^/imgs/([0-9]*)/(.*?)(\..+)$ {
add_header X-webp $webp_suffix;
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
}
Run Code Online (Sandbox Code Playgroud)
即使两个文件都存在,它总是会导致 e404。标题 X-webp 设置为“.webp”,因此地图工作正常。
更奇怪的是 - 如果我交换 try_files 参数的顺序:
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
Run Code Online (Sandbox Code Playgroud)
到
try_files /imgs/$1$3 /imgs/$1$webp_suffix =404;
Run Code Online (Sandbox Code Playgroud)
然后它开始工作并将文件 /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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
EDIT2:更奇怪的是 - 如果我改变:
try_files /imgs/$1$webp_suffix /imgs/$1$3 =404;
Run Code Online (Sandbox Code Playgroud)
到:
try_files /imgs/$1.webp /imgs/$1$3 =404;
Run Code Online (Sandbox Code Playgroud)
然后 try_files 按预期工作(但我们现在不检查客户端中的 webp 支持,只是假设它确实支持它)。请记住:
add_header X-webp $webp_suffix;
Run Code Online (Sandbox Code Playgroud)
在同一位置导致添加标题:X-webp .webp
那么为什么 /imgs/$1$webp_suffix 不起作用而 /imgs/$1.webp 起作用呢?
我测试过的:
这完全没有意义
编辑3:
为了测试我打开:http://test:8888/imgs/10/whatever.jpg
文件 /srv/imgs/10.jpg 和 /srv/imgs/10.webp 确实存在。
该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;
}
Run Code Online (Sandbox Code Playgroud)