htaccess 无提示重定向到子目录:当没有尾随 '/' 时显示子目录

发布于 2024-12-14 08:28:18 字数 1098 浏览 0 评论 0 原文

我在 Google 和 StackOverflow 上四处搜寻,试图找出我的问题,尝试了无数的解决方案,但没有一个完全奏效。

我希望将服务器上主域的 Web 根目录移动到子目录。目前我的网络根目录的服务器路径有什么:

/home/user/public_html/MyWebFilesHere

我想要什么:

/home/user/public_html/subdir/MyWebfilesHere

当我浏览到 mydomain.com 时,应该没有明显的差异(即重定向后“子目录”不可见)。

不幸的是,我仅限于纯粹使用 .htaccess 文件来执行此操作,因为我位于共享主机上并且无权访问 Apache 配置文件等。 :(

我目前在 public_html 的 .htaccess 中的内容是:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteRule ^(.*)$ /subdir/$1 [L]

这成功地将所有查询重定向到子目录,但是有一个非常奇怪的问题。如果我去

mydomain.com/Contact/

它工作得很好,将查询重定向到路径 /subdir/Contact / 但如果我去

mydomain.com/Contact

(注意缺少尾随“/”),地址栏中显示的内容

mydomain.com/subdir/Contact/

不是我想要的,因为显示了“subdir”

。在我的实际网站上,尝试浏览与

colincwilliams.com/Contact/

比较

colincwilliams.com/Contact

你们对如何在有或没有尾部斜杠的情况下默默地完成这项工作有什么想法吗?

I have dug high and low around Google and StackOverflow to try and figure out my problem, trying countless solutions but nothing has completely worked.

I'm looking to move the web root of the main domain on my server to a sub-directory. What I have currently for a server path to my web root:

/home/user/public_html/MyWebFilesHere

What I'm looking to have:

/home/user/public_html/subdir/MyWebfilesHere

When I browse to mydomain.com, there should be no visible difference though (i.e. "subdir" not visible after redirect).

Unfortunately, I am restricted to doing this purely with a .htaccess file since I'm on shared hosting and don't have access to Apache config files and such. :(

What I currently have in my .htaccess in public_html is:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteRule ^(.*)$ /subdir/$1 [L]

This successfully redirects all queries to the sub-directory, however there's a really weird issue. If I go to

mydomain.com/Contact/

it works great, redirecting the query to the path /subdir/Contact/ but leaving the address bar alone. If I go to

mydomain.com/Contact

(Note the lack of a trailing '/') though, what shows in the address bar is

mydomain.com/subdir/Contact/

which isn't what I want since "subdir" is showing.

For a working example on my actual site, try browsing to

colincwilliams.com/Contact/

compared with

colincwilliams.com/Contact

Do you guys have any ideas on how to make this work silently both with and without a trailing slash?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七度光 2024-12-21 08:28:18

发生这种情况可能是因为 mod_dir (如果对目录的请求缺少尾部斜杠,该模块会自动重定向浏览器到相同的内容尾部斜杠。请参阅 mod_dir 中的 DirectorySlash 指令

发生的情况是:

  1. 您请求: mydomain.com/Contact
  2. mod_dir 不会触及此内容,因为 /Contact 不是目录
  3. /Contact 会被重写为 /subdir /Contact内部重定向的
  4. mod_dir 发现 /subdir/Contact 是一个目录并且缺少尾部斜杠,因此它重定向浏览器mydomain.com/subdir/Contact/
  5. 现在,您的浏览器的地址栏中包含 /subdir/,

您可以在 .htaccess 中添加 DirectorySlash off 来关闭。 mod_dir 来自重定向,但是如果您希望目录具有尾部斜杠,您可以为其添加单独的条件。根据您已有的内容,我们可以将其扩展为:

RewriteEngine on

# Has a trailing slash, don't append one when rewriting
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteCond %{THE_REQUEST} ./\ HTTP/1\.[01]$ [OR]
# OR if it's a file that ends with one of these extensions
RewriteCond %{REQUEST_URI} \.(php|html?|jpg|gif|css)$
RewriteRule ^(.*)$ /subdir/$1 [L]

# Missing trailing slash, append one
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteCond %{THE_REQUEST} [^/]\ HTTP/1\.[01]$
# But only if it's not a file that ends with one of these extensions
RewriteCond %{REQUEST_URI} !\.(php|html?|jpg|gif|css)$
RewriteRule ^(.*)$ /subdir/$1/ [L]

注意:我将 !^/mydomain/ 更改为 !^/subdir/,认为这是一个拼写错误,因为如果没有它,mod_rewrite 将无限期地在内部循环(foo -> /subdir/foo -> /subdir/subdir/foo -> /subdir/subdir/subdir/foo 等)。如果我错了,你可以改回来。

编辑:请参阅我添加的 RewriteCond 与 \.(php|html?|jpg|gif|css) 匹配的内容。这些是在不添加尾部斜杠的情况下传递的文件扩展名。您可以添加/删除以满足您的需要。

This is probably happening because mod_dir (the module that automatically redirects the browser if a request for a directory is missing a trailing slash to the same thing with a trailing slash. See the DirectorySlash directive in mod_dir

What's happening is:

  1. You request: mydomain.com/Contact
  2. mod_dir doesn't touch this since /Contact isn't a directory
  3. /Contact gets rewritten to /subdir/Contact and internally redirected
  4. mod_dir sees that /subdir/Contact is a directory and missing the trailing slash so it redirects the browser to mydomain.com/subdir/Contact/
  5. So now, your browser's location bar has the /subdir/ in it.

You can add DirectorySlash off in your .htaccess to turn off mod_dir from redirecting. But if you want directories to have trailing slashes, you can add a separate condition for it. Based on what you already have, we can expand it to this:

RewriteEngine on

# Has a trailing slash, don't append one when rewriting
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteCond %{THE_REQUEST} ./\ HTTP/1\.[01]$ [OR]
# OR if it's a file that ends with one of these extensions
RewriteCond %{REQUEST_URI} \.(php|html?|jpg|gif|css)$
RewriteRule ^(.*)$ /subdir/$1 [L]

# Missing trailing slash, append one
RewriteCond %{HTTP_HOST} ^(www\.)?mydomain\.com$
RewriteCond %{REQUEST_URI} !^/subdir/
RewriteCond %{THE_REQUEST} [^/]\ HTTP/1\.[01]$
# But only if it's not a file that ends with one of these extensions
RewriteCond %{REQUEST_URI} !\.(php|html?|jpg|gif|css)$
RewriteRule ^(.*)$ /subdir/$1/ [L]

Note: I changed !^/mydomain/ to !^/subdir/, figured it was a typo because without it, mod_rewrite would loop internally indefinitely (foo -> /subdir/foo -> /subdir/subdir/foo -> /subdir/subdir/subdir/foo, etc). If I got that wrong, you can change it back.

Edit: See my additions of RewriteCond's matching against \.(php|html?|jpg|gif|css). These are the file extensions that get passed through without getting trailing slashes added. You can add/remove to suit your needs.

喜爱皱眉﹌ 2024-12-21 08:28:18

Jon Lin 的回答对于确定在我非常相似的设置中导致问题的原因非常有帮助。为了完整起见,我将包含他的回答中的相关信息:

发生这种情况可能是因为 mod_dir (如果对目录的请求缺少尾部斜杠,该模块会自动重定向浏览器到带有尾部斜杠的相同内容。请参阅 mod_dir 中的 DirectorySlash 指令

发生的事情是:

  1. 您请求:mydomain.com/Contact
  2. mod_dir 不会触及此内容,因为 /Contact 不是目录
  3. /Contact 被重写为 /subdir/Contact 并在内部重定向
  4. mod_dir 发现 /subdir/Contact 是一个目录,并且缺少尾部斜杠,因此它将浏览器重定向到 mydomain.com/subdir/Contact/
  5. 现在,您的浏览器的地址栏中包含 /subdir/。

,我的请求被重定向到 /subdir,但有一些例外,并且不想通过

允许 为每个例外重新启用 DirectorySlash。 RewriteEngine 在初始重定向到 /subdir 后继续,可以在 mod_dir 看到它之前模仿 mod_dir 的行为,同时也考虑到 /subdir

RewriteEngine on

RewriteCond %{REQUEST_URI} !^/exception1|exception2|...
RewriteRule ^(.*)$ /subdir/$1

RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^subdir/(.*) $1/ [R,L]

注意:如果有进一步的规则,您可能需要小心允许 RewriteEngine 继续。不匹配第二条规则将继续执行任何进一步的规则,这可能会产生不同的结果。

如果发生重定向到 /subdir ,可以通过使用第三条规则来停止 RewriteEngine 处理来避免这种情况:

RewriteCond %{REQUEST_URI} ^subdir
RewriteRule .* - [L]

Jon Lin's answer was very helpful in determining what was causing the problem in my very similar setup. For completeness I will include the relevant information from his answer:

This is probably happening because mod_dir (the module that automatically redirects the browser if a request for a directory is missing a trailing slash to the same thing with a trailing slash. See the DirectorySlash directive in mod_dir

What's happening is:

  1. You request: mydomain.com/Contact
  2. mod_dir doesn't touch this since /Contact isn't a directory
  3. /Contact gets rewritten to /subdir/Contact and internally redirected
  4. mod_dir sees that /subdir/Contact is a directory and missing the trailing slash so it redirects the browser to mydomain.com/subdir/Contact/
  5. So now, your browser's location bar has the /subdir/ in it.

In my case, I had requests being redirected to /subdir with a few exceptions and didn't want to have to re-enable DirectorySlash for each of those exceptions.

By allowing RewriteEngine to continue after the initial redirect to /subdir, it's possible to mimic what mod_dir would be doing while also taking /subdir into account, before mod_dir gets to see it.

RewriteEngine on

RewriteCond %{REQUEST_URI} !^/exception1|exception2|...
RewriteRule ^(.*)$ /subdir/$1

RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^subdir/(.*) $1/ [R,L]

Note: You may need to be careful about allowing RewriteEngine to continue if there are further rules. Not matching the second rule will continue on to any further rules which may produce a different result.

This can be avoided by using a third rule to stop RewriteEngine processing if the redirect into /subdir has happened:

RewriteCond %{REQUEST_URI} ^subdir
RewriteRule .* - [L]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文