为什么这个 -f 标志返回 true?

为什么这个 -f 标志返回 true?

我最近设置了一个重写,.webp尽可能地用文件代替.jpg文件。它似乎工作正常,直到今天我们注意到,新上传的图像即使存在也.jpg返回了。我做了一些检查,发现服务器正在将URL 重写为,然后因为尚未创建而获取了。404.jpg.webp404.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,不是%1RewriteCond 测试字符串。虽然不清楚为什么这种行为最近才发生改变(或者可能没有改变?)。


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 会被浏览器永久缓存,因此以后可能会导致缓存问题。(事实上,当请求到达浏览器缓存时,这可以解释“间歇性”行为。)

相关内容