Apache上已验证的htaccess重写规则出现意外结果



我在虚拟主机部分(Apache(的httpd.conf中有以下htaccess重写规则。如果请求只是<filename>而没有<extension>,Apache将从请求头中的HTTP_ACCEPT中计算返回哪个文件。在目录/images中,只有.aif、.web和.jpeg文件,每个文件名对应一个版本。

<Directory "/var/www/<document root>/images">
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/avif 
AddType image/avif .avif
RewriteRule ^([^.]+)$ $1.avif [L] 
RewriteCond %{HTTP_ACCEPT} image/webp
AddType image/webp .webp
RewriteRule ^([^.]+)$ $1.webp [L]
AddType image/jpeg .jpeg
RewriteRule ^([^.]+)$ $1.jpeg
</directory>

因此,如果一个文件没有被前两个RewriteCond捕获,它将收到后缀.jjpe.

使用进行测试https://htaccess.madewithlove.com返回完全预期的结果。在野外它也很好用。

现在我放置了一个具有不同<extension>在名为dm_schrift.svg的目录/images中。我希望请求被重写为dm_schrift.peg。相反,服务器返回正确的文件:

$ curl -s -o /dev/null -D - https://<my domain>/images/dm_schrift.svg
HTTP/2 200
date: Thu, 08 Sep 2022 09:12:19 GMT
server: Apache
x-content-type-options: nosniff
strict-transport-security: max-age=15552000; includeSubDomains
last-modified: Tue, 30 Aug 2022 18:30:12 GMT
etag: "356-5e779921d3500"
accept-ranges: bytes
content-length: 854
vary: Accept-Encoding,User-Agent
cache-control: max-age=31536000, public, immutable
content-type: image/svg+xml

(关于"不可变":如果打开一个新的浏览器窗口,在DevTools中禁用缓存,加载文件并验证它是否真的被下载,我会得到同样的结果。响应不是来自缓存(。

我怎么会收到dm_schrift.peg的文件而不是404?

编辑:以下是问题的一部分,已在回答中解决,但基于错误的假设。待放弃:

关于这些重写规则的另一个问题:有了这些,文件请求为"something"将在Chrome中用作"something.avif"。Devtools/Network显示整个名称,包括扩展名。但是这个名字未包含在响应标头中。文件实际上是"avif"可以从"content-type"派生,但是浏览器知道包括扩展名在内的整个文件名吗?

您似乎已经在开头一段中回答了您的问题。。。

如果请求是只有<filename>而没有<extension>,Apache将评估。。。

这遵循规则中的正则表达式。即^([^.]+)$(旁白:此处不需要文字点上的反斜杠转义。

您请求的是示例中的实际文件,包括文件扩展名,例如/images/dm_schrift.svg。正则表达式不匹配,因此规则不适用,因此文件只是直接提供。

我怎么会收到文件而不是dm_schrift.peg的404?

只有当您在没有文件扩展名的情况下(如您最初所述(发出初始请求时,才会发生这种情况。

Devtools/Network显示整个名称,包括扩展名。但该名称没有包含在响应标头中。文件实际上是"avif"可以从"内容类型"派生,但浏览器如何知道包括扩展名在内的整个文件名

根据您发布的规则,浏览器不知道服务器上正在重写的文件的完整文件名(包括文件扩展名(。浏览器只知道mime类型(即来自Content-Type标头(,这与文件扩展名没有任何关系。

我在虚拟主机部分(Apache(的httpd.conf中有以下htaccess重写规则。

为了澄清,您发布的规则位于<Directory>部分(位于虚拟主机部分(内。这与规则直接在virtualhost部分本身内部时非常不同,后者是根据您的描述推断出来的。

<Directory>部分的行为与.htaccess类似,但请注意,任何.htaccess文件都将覆盖服务器配置中相应的<Directory>部分。

最新更新