Apache已验证.htaccess重写规则异常:SVG请求未按预期重写
为什么请求带扩展名的文件时Apache重写规则未触发?
问题场景
在Apache虚拟主机的httpd.conf的<Directory>段配置了基于HTTP_ACCEPT的图片格式重写规则:仅当请求为不带扩展名的文件名时,根据请求头返回对应格式的图片(avif/webp/jpeg优先级依次降低)。原本目录中只有这三种格式的文件,规则运行正常。但添加dm_schrift.svg文件后,请求https://<my domain>/images/dm_schrift.svg时,服务器直接返回了SVG文件,而非预期的重写为dm_schrift.jpeg并返回404。
原因分析
你的重写规则核心问题在于正则表达式的匹配范围:
- 三条
RewriteRule的匹配模式都是^([^\.]+)$,其中[^\.]+表示匹配完全不包含点字符的字符串。也就是说,只有像dm_schrift这种不带扩展名的请求才会被规则捕获。 - 当请求
dm_schrift.svg时,路径中包含点字符,完全不匹配规则的正则表达式,因此所有重写规则都不会执行。 - Apache的默认行为是:如果请求的路径对应磁盘上实际存在的文件,会直接返回该文件,不会触发未匹配的重写规则。
解决方案
根据你的需求选择对应方案:
方案1:保留原规则逻辑(仅处理不带扩展名的请求)
当前行为是符合规则设计的,无需修改。带扩展名的请求会直接返回磁盘上的对应文件,这是Apache的正常机制。
方案2:强制所有请求(无论是否带扩展名)都按规则重写
如果需要让带扩展名的请求也被重写(比如把dm_schrift.svg强制转为dm_schrift.avif/webp/jpeg),需要修改正则表达式并添加防循环重写的条件:
<Directory "/var/www/<document root>/images"> RewriteEngine On # 防循环:如果请求的文件已经是目标格式,直接跳过重写 RewriteCond %{REQUEST_FILENAME} \.(avif|webp|jpeg)$ RewriteRule ^ - [L] # 匹配所有请求,提取文件名部分(忽略原有扩展名) 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>
^(.+?)(\..*)?$会匹配所有请求路径,捕获文件名部分(无论后面是否带扩展名),替换为目标格式的文件名。- 第一条规则用于避免循环重写:如果请求的已经是avif/webp/jpeg格式的文件,直接终止重写流程。
内容的提问来源于stack exchange,提问作者jamacoe
相关产品推荐
相关产品推荐

