我最近设置了一个重写,.webp
尽可能地用文件代替.jpg
文件。它似乎工作正常,直到今天我们注意到,新上传的图像即使存在也.jpg
返回了。我做了一些检查,发现服务器正在将URL 重写为,然后因为尚未创建而获取了。404
.jpg
.webp
404
.webp
然后,我将规则从 vhost_ssl.conf 移至 .htaccess,并进行了大量修改,直到找到可行的方法,然后将该解决方案移回 vhost_ssl.conf。但我仍然不明白为什么原始重写有时会失败。有人可以审查并阐明这个问题吗?
原文重写:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]
最终重写:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (.+)\.(?:jpe?g|png)$
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule .* %1.webp [NC,T=image/webp,E=webp,L]
这两种方法之间唯一真正的区别在于,在新方法中,我在检查文件是否存在的重写条件之前检查请求 URI 是否与 jpeg/png 匹配。我认为新方法效率较低,因为重写规则匹配所有内容,但至少上述条件会对其进行过滤,并且它在 vhost_ssl.conf 中,这比 .htaccess 更好。
其他一些注意事项:
- 在测试期间,我将原始重写更改为 301 重定向,这样我就可以看到它认为找到的文件。果然,该文件与 .jpg 文件相同,只是扩展名为 .webp - 路径正确(尽管 .webp 实际上并不存在)。
- 此外,在测试期间,我尝试将重写条件更改为
RewriteCond %{DOCUMENT_ROOT}/%1.webp_asdfasdfasf -f
只是为了验证它确实会失败,结果确实失败了。所以它知道完全虚假的文件不存在,但它仍然认为 .webp 文件确实存在。
答案1
总结
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
应该是$1
,不是%1
在RewriteCond
测试字符串。虽然不清楚为什么这种行为最近才发生改变(或者可能没有改变?)。
RewriteCond %{HTTP_ACCEPT} image/webp RewriteCond %{DOCUMENT_ROOT}/%1.webp -f RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]
这应该绝不除非你有一个名为“ ”的文件.webp
(没有基名(以点开头)位于文档根目录中。如果你这样做了,那么它应该有总是将 jpeg/png URL 重写为<whatever>.webp
,不管它是否存在。
那么,这似乎表明您.webp
在文档根目录中确实有一个名为 (no basename) 的文件?(并且/或者您看到某些请求的缓存重定向?请参见下文......)
%1
第二个中的反向引用RewriteCond
测试字符串应该是$1
,而不是%1
。%1
是对最后匹配的第一个捕获组的反向引用条件模式- 其中没有,所以%1
是总是为空。因此,它将总是测试是否存在/path/to/document-root/.webp
。$1
另一方面是对中第一个捕获组的反向引用RewriteRule
图案,即文件系统路径/基本名称,不包括文件扩展名。
您已$1
使用RewriteRule
代换- 你应该在前面使用相同的状况。
请注意,如果这些指令位于虚拟主机上下文中,那么您应该...删除RewriteCond
测试字符串, 例如:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}$1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]
或者,排除捕获组中的斜线RewriteRule
。例如:
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule ^/(.+)\.(?:jpe?g|png)$ /$1.webp [NC,T=image/webp,E=webp,L]
否则,你最终会在测试字符串操作系统需要解决此问题。
RewriteCond %{HTTP_ACCEPT} image/webp RewriteCond %{REQUEST_URI} (.+)\.(?:jpe?g|png)$ RewriteCond %{DOCUMENT_ROOT}/%1.webp -f RewriteRule .* %1.webp [NC,T=image/webp,E=webp,L]
这与在原始规则块中使用相同$1
(如上所述)。好奇的是,你改变了代换到%1
,但知道保持条件中的反向引用不变(或者这只是被忽略了)?
在测试期间,我将原来的重写更改为 301 重定向...
始终使用 302(临时)重定向进行测试。301 会被浏览器永久缓存,因此以后可能会导致缓存问题。(事实上,当请求到达浏览器缓存时,这可以解释“间歇性”行为。)