首页 > 解决方案 > Apache htaccess 将根和所有根文件夹重写到子文件夹而不重定向

问题描述

Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteRule ^$ /subdir/ [L,NC]

我想在不更改浏览器中的 URL 的情况下将根域重写为子文件夹。上面的代码仅适用于根域,但不适用于任何文件夹和文件。

例如,我有https://example.com/https://example.com/subdir/

将上面的代码放在.htaccess文件中,当我去的时候,https://example.com/我看到其中的内容https://example.com/subdir/是好的。

但是当我去https://example.com/test.txt我应该看到https://example.com/subdir/test.txt但我得到了在此服务器上找不到请求的 URL。

当我https://example.com/abc期待看到的内容时也会发生同样的情况https://example.com/subdir/abc

任何的想法?

标签: apache.htaccessurl-rewriting

解决方案


RewriteRule ^$ /subdir/ [L,NC]

将其更改为:

RewriteRule !^subdir/ subdir%{REQUEST_URI} [L]

任何启动/subdir/的请求都会在内部重写为/subdir/<url>. REQUEST_URI服务器变量包含完整的 URL 路径(包括斜杠前缀)。

我从替换字符串中删除了斜杠前缀,因为您已经定义了RewriteBase /. (尽管这里两者都不是绝对必要的。)

更新:

...当我去的时候,example.com/s我被重定向到example.com/subdir/s/
s是一个子文件夹subdir,这有什么区别吗?

是的,如果/s是子目录,那么 mod_dir 将在尾部斜杠(以“修复”URL)后附加外部 301 重定向。此重定向发生在 URL 被重写之后/subdir/s- 从而暴露了/subdir子目录。

为了处理这种情况,我们可以在现有重写之前添加另一个规则(重定向),首先检查请求是否会映射到/subdir子目录中的目录,如果省略则附加斜杠(在 mod_dir 将斜杠附加到重写的 URL 之前)。

例如:

RewriteCond %{REQUEST_URI} !/$
RewriteCond %{DOCUMENT_ROOT}/subdir%{REQUEST_URI} -d
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}/ [R=301,L]

这表明......对于任何请求:

  • !\.\w{2,4}$- 不包含(看起来像)2 到 4 个字符的文件扩展名(假设您的目录不是这样命名的)
  • !/$- 并且当前不以斜线结尾。
  • -d- 并作为物理目录存在于/subdir子目录中。
  • 然后重定向以在原始请求上附加斜杠

虽然这可能应该是 301(永久)重定向,但您应该首先使用 302(临时)重定向进行测试以避免潜在的缓存问题。

您需要在测试之前清除浏览器缓存,因为错误的 301 重定向 from /sto/subdir/s/将被浏览器缓存。

一个潜在的优化是删除文件系统检查并简单地假设任何不包含文件扩展名的请求都应该映射到一个目录。(但这取决于您是否以任何其他方式处理这些 URL。)

概括

Options +FollowSymLinks -MultiViews

# Turn mod_rewrite on
RewriteEngine On

# If the requested URL exists as a directory in "/subdir" then append a slash
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{DOCUMENT_ROOT}/subdir%{REQUEST_URI} -d
RewriteRule !\.\w{2,4}$ %{REQUEST_URI}/ [R=301,L]

# Rewrite everything to "/subdir"
RewriteRule !^subdir/ subdir%{REQUEST_URI} [L]

推荐阅读