将子域重定向到文件夹时,如何避免带有尾部斜杠的 URL 的文件夹子域重复

When redirecting subdomains to folders, how can I avoid folder-subdomain duplication for URLs with trailing slash

我在 Apache 2.4 上遇到内部 mod_rewrte 重定向的奇怪问题。

在我的 .htaccess 文件中,我使用以下指令将子域 sub 重定向到文件夹 /sub

RewriteCond %{HTTP_HOST} ^sub.mydomain.com$ [NC]
RewriteRule ^((?!sub).*)$ /sub/  [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 的默认行为造成的,即在 external 重定向时向无斜杠目录请求添加斜杠。添加斜杠对我来说没问题,但我当然想避免文件夹子域重复。 - 我该怎么做?

是的,这是由于 mod_dir 在重写发生后向目录附加斜线(带有 301 重定向),暴露了内部重写的 URL/directory。

因此,规范的 URL 需要是 /articles/(带有尾部斜杠),而不是 /articles。我们可以在 重写发生之前使用外部重定向 来纠正此问题。

(这避免了您必须禁用 DirectorySlash - 这仍然会给您带来规范化/重复内容问题。)

例如,在现有重写之前,测试请求的 URL-path(缺少尾部斜杠)是否作为目录存在于 /sub 目录中,如果存在则附加斜杠是这样的。

# Redirect to append trailing slash if exists as a dir inside "/sub"
RewriteCond %{HTTP_HOST} ^sub\.mydomain\.com [NC]
RewriteCond %{DOCUMENT_ROOT}/sub/ -d
RewriteRule ^((?!sub/).*[^/])$ //  [R=301,L]

作为额外的优化,您可以通过排除看起来像它们的 URL 来避免对静态资产(自然不会以尾部斜杠结尾)执行不必要的文件系统检查(这相对昂贵)有一个file-extension。 (这假设您没有物理目录,看起来像文件扩展名,例如 /sub/somedir.xyz

在上面的规则中添加以下作为第二个条件(文件系统检查之前):

RewriteCond %{REQUEST_URI} !\.\w{2,4}$

旁白:

RewriteCond %{HTTP_HOST} ^sub.mydomain.com$ [NC]
RewriteRule ^((?!sub).*)$ /sub/  [NC]

您可能应该在此 RewriteRule 指令上使用 L 标志。 (并且 NC 标志应该是不必要的。)

正则表达式 ^((?!sub).*)$ 排除任何仅以 sub 开头的 URL-path,其中包括 /subfoo/subbar 等(这自然会阻止这些/sub 目录中无法访问的目录)。任何有效的请求都将以 /sub/ 开头(尾部斜杠),因此应该包含在否定前瞻中,就像我在上面的规则中所做的那样。

如果还没有,如果这个目录应该是 exposed/discovered.

,还可以考虑重定向以从直接请求中删除 /sub/