Apache 2.4上的内部mod_rewrte重定向出现了一个奇怪的问题。
在我的.htaccess
文件中,我使用以下指令将子域sub
重定向到文件夹/sub
:
RewriteCond %{HTTP_HOST} ^sub.mydomain.com$ [NC]
RewriteRule ^((?!sub).*)$ /sub/$1 [NC]
Thos非常适用于https://sub.mydomain.com/articles/
——URL在浏览器的地址字段中保持这样,并且不出所料,来自/sub/articles/index.html
位置的数据将被提供/
但是,当我在浏览器中键入https://sub.mydomain.com/articles
(注意缺少斜线(时,浏览器中的URL将更改为https://sub.mydomain.com/sub/articles/
(注意重复的sub
作为文件夹和子域!(。
我想这是由Apache的默认行为引起的,即在无斜杠目录请求中添加斜杠作为外部重定向。斜杠的添加对我来说是可以的,但当然我想避免文件夹子域的重复。-我该怎么做?
是的,这是由于mod_dir在重写发生后向目录添加了一个斜杠(带有301重定向(,从而暴露了内部重写的URL/目录。
因此,规范URL需要是/articles/
(带有尾部斜杠(,而不是/articles
。我们可以在重写发生之前通过外部重定向来纠正这一问题。
(这避免了您必须禁用DirectorySlash
,这仍然会给您留下规范化/重复内容的问题。(
例如,在现有重写之前,测试请求的URL路径(缺少尾部斜杠(是否作为目录存在于/sub
目录中,如果是这样的话,请附加一个斜杠。
# Redirect to append trailing slash if exists as a dir inside "/sub"
RewriteCond %{HTTP_HOST} ^sub.mydomain.com [NC]
RewriteCond %{DOCUMENT_ROOT}/sub/$1 -d
RewriteRule ^((?!sub/).*[^/])$ /$1/ [R=301,L]
作为额外的优化,您可以通过排除看起来有文件扩展名的URL来避免对静态资产(自然不会以斜杠结尾(执行不必要的文件系统检查(这相对昂贵(。(这假设您没有具有文件扩展名的物理目录,例如/sub/somedir.xyz
(
在上述规则中添加以下内容作为第二个条件(在文件系统检查之前(:
RewriteCond %{REQUEST_URI} !.w{2,4}$
旁白:
RewriteCond %{HTTP_HOST} ^sub.mydomain.com$ [NC] RewriteRule ^((?!sub).*)$ /sub/$1 [NC]
您可能应该在此RewriteRule
指令上使用L
标志。(NC
标志应该是不必要的。(
正则表达式^((?!sub).*)$
排除了任何简单启动sub
的URL路径,该路径将包括/subfoo
和/subbar
等(这自然会阻止在/sub
目录中访问这些目录(。任何有效的请求都会以/sub/
开头(后面有一个斜杠(,因此应该包括在负前瞻中,就像我在上面的规则中所做的那样。
如果还没有,如果应该公开/发现该目录,还可以考虑重定向以从直接请求中删除/sub/
。