我正在尝试将对我的网站的所有请求传递到我的webroot中的子文件夹。
以下是我的文件夹结构:
/webroot
current
releases
release1
index.html
en
index.html
release2
index.html
en
index.html
...
.htaccess
current
文件夹是指向releases
文件夹中的一个文件夹的符号链接。其思想是当我制作一个新版本时,在releases
文件夹中创建一个新文件夹,然后current
符号链接指向这个新文件夹。
在我的.htaccess中,我尝试将所有请求传递给current
符号链接。
现在,只要请求以尾随斜杠结束,例如https://example.com/en/
,这种方法就能很好地工作,但如果我删除尾随斜杠,路由就能工作,但浏览器中的URL将是https://example.com/current/en
下面是我在我的.htaccess中所做的重写:
Options +FollowSymlinks -MultiViews -Indexes
DirectorySlash On
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/current/
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ current/$1 [L]
这是日志文件
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'en'
[perdir /path/to/webroot/] RewriteCond: input='/en' pattern='!^/current/' => matched
[perdir /path/to/webroot/] RewriteCond: input='' pattern='^$' => matched
[perdir /path/to/webroot/] rewrite 'en' -> 'current/en'
[perdir /path/to/webroot/] add per-dir prefix: current/en -> /path/to/webroot/current/en
[perdir /path/to/webroot/] trying to replace prefix /path/to/webroot/ with /
strip matching prefix: /path/to/webroot/current/en -> current/en
add subst prefix: current/en -> /current/en
[perdir /path/to/webroot/] internal redirect with /current/en [INTERNAL REDIRECT]
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en -> current/en
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en'
[perdir /path/to/webroot/] RewriteCond: input='/current/en' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/ -> current/en/
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/index.php -> current/en/index.php
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/index.php'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/index.php' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/index.php
[perdir /path/to/webroot/] strip per-dir prefix: /path/to/webroot/current/en/index.html -> current/en/index.html
[perdir /path/to/webroot/] applying pattern '^(.*)$' to uri 'current/en/index.html'
[perdir /path/to/webroot/] RewriteCond: input='/current/en/index.html' pattern='!^/current/' => not-matched
[perdir /path/to/webroot/] pass through /path/to/webroot/current/en/index.html
1条答案
按热度按时间oyxsuwqo1#
但如果我删除尾部斜杠,路由工作,但在浏览器中的URL将是
https://example.com/current/en
我假设您指的是
https://example.com/current/en/
(后面有一个斜杠)。这是因为mod_dir试图通过在物理目录中添加一个斜杠来“修复”(使用301重定向)URL(这是目录索引正常工作所必需的)。此“修复”发生在URL被重写到子目录之后(因为URL路径
/en
最初没有Map到子目录)。您可以禁用mod_dir的这一行为,以便不附加尾随斜杠;但是这样做会很麻烦(然后需要根据需要手动添加尾部斜杠),并且可能会引发安全问题。
相反,您需要确保链接到的URL * 始终带有 * 尾随斜杠,并在 * mod_dir执行此操作之前手动更正任何在
.htaccess
* 中省略尾随斜杠的URL。重写到
/current
子目录的现有重写看起来没问题,尽管您不需要检查请求是否已经开始/current/
(第一个 * 条件 )。(通过检查请求是否已经开始/current/
,您就允许直接请求实际的符号链接的文件系统位置-尽管这可能是一个要求?)因此, 在 * 现有重写之前,添加以下重定向:
给定一个
/example
的请求,上面的代码首先检查/current/example
是否作为一个目录存在(尽管是一个符号链接的目录)。如果存在,那么它发出一个301重定向,将尾部斜杠附加到原始URL,而不是重写的URL。例如,/example
被重定向到/example/
,然后被重写为/current/example/
。首先测试302(临时)重定向,以避免潜在的缓存问题。
您需要清除浏览器缓存,因为错误的301(永久)mod_dir重定向将被浏览器缓存。
更新日期:
它应该不可能直接访问“当前”文件夹中的任何文件或文件夹。目前,这是可能的...
正如上面所暗示的,您可以简单地删除第一个 condition,它检查
REQUEST_URI
是否已经以/current/
开始。因此,所有直接请求都将无条件地重写为/current/
。因此,对/current/en/
的请求将被重写为/current/current/en
,从而导致404。然而,用户仍然可能直接请求文件系统位置,完全绕过符号链接。例如
/releases/release1/en/
。要阻止直接访问这两个位置,您可以添加以下规则作为第一条规则:
直接请求
/current/...
或/releases/...
将导致“403禁止”。或者将F
更改为R=404
以提供“404未找到”服务(尽管使用了R
标志,但不会发生 redirect)。对
REDIRECT_STATUS
环境变量的检查(如原始规则中所述)确保请求仍然可以在内部重写到这些位置。(REDIRECT_STATUS
env var在来自客户端的初始请求中为空,但在第一次重写后设置为HTTP响应状态(例如“200”)。