有一个域
example.com
,它是主域的别名。
我的目标是将 example.com
指向主站点的子目录 example.com/
。
这个子目录还有一个子目录
test/
。
.htaccess
是
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteRule ^(.*)?$ example.com/$1 [L,NC]
https://example.com/test/
-> 这效果很好,它显示 ./example.com/test/index.html
,没有任何重定向按原样显示 URL。
https://example.com/test
(末尾没有斜杠)-> 可以重定向到 https://example.com/example.com/test/
,但它会更改 URL 并添加不必要的目录路径,为什么?
如何使其在两种情况下都像#1 那样工作?
“问题”是 mod_dir 在内部重写发生后将尾部斜杠附加到 文件系统目录(使用 301 重定向)(只有这样 Apache 才知道它映射到目录)。为了能够从该目录(也由 mod_dir 处理)提供
DirectoryIndex
(即 index.html
),这是必要的。
要解决此问题,您需要在内部重写之前手动附加尾部斜杠(如果请求最终映射到目录),以便规范化 URL。不用说,包含尾部斜杠的 URL 是规范的,这是您应该在内部链接到的 URL。
例如:
# Append trailing slash if the file-path that the URL maps to is a directory
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteCond %{DOCUMENT_ROOT}/example.com/$1 -d
RewriteRule (.+[^/])$ /example.com/$1/ [R=301,L]
# Rewrite Requests to subdirectory
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule (.*) example.com/$1 [L]
注意:正则表达式 ^(.*)?$
与简单的
(.*)
相同,并且该规则不需要
NC
标志,因为正则表达式本质上不区分大小写。
旁白: 事实上,您现有的重写规则完全有效(并且不会导致重写循环)取决于 .htaccess
子目录中存在的另一个
/example.com
文件,该文件也包含 mod_rewrite 指令。我在上面的规则中也使用了这个假设。否则,您将需要额外的检查以避免重写循环(以及不必要的文件系统检查)。首先使用 302(临时)重定向进行测试,以避免潜在的缓存问题。您需要确保清除所有(浏览器)缓存,因为早期(错误的)301 重定向已被浏览器缓存。
旁白:
有一个域假设您位于共享托管平台上,并且根据您拥有的托管类型,您通常可以将辅助域设置为“附加”域(而不是“别名”),这可以有效地允许您指向辅助域名直接位于子目录(有自己的
example.com
,它是主域的别名。
DocumentRoot
) - 因此无需在
.htaccess
中手动重写 URL。