我正在重写从旧开发团队收到的 Apache 2.4 配置。
我有大约 200 行类似的配置,我不明白我需要根据什么原理更改此代码才能将其从.htaccess
虚拟主机移出。
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^(.*)$ /$1/ [R,L,NC]
当我将它移动到虚拟主机时,我的网站在我无法理解的地方崩溃了。
答案1
这取决于<VirtualHost>
将这些指令放置在容器中的什么位置。
如果您使用<Directory>
容器(即目录上下文)和禁用 .htaccess
完全覆盖(否则.htaccess
将覆盖<Directory>
容器!)那么您可以按原样复制指令(假设容器<Directory>
引用与文件相同的目录.htaccess
)。
但是,如果你将这些指令直接放在容器内部<VirtualHost>
(容器外部<Directory>
),即在虚拟主机上下文,那么您需要进行一些更改。这是因为在请求映射到文件系统之前,指令会被更早地处理。
在您发布的指令中,仅需要进行两处更改:
在一个虚拟主机上下文中,
REQUEST_FILENAME
服务器变量尚未解析为文件名REQUEST_URI
。它与(即请求的 URL)相同。因此,您的文件系统检查将始终失败,而条件将始终成功!您要么需要使用前瞻。例如%{LA-U:REQUEST_FILENAME}
,要么自己构建绝对文件名。例如%{DOCUMENT_ROOT}%{REQUEST_URI}
。例如:RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
在一个虚拟主机上下文,与
RewriteRule
图案是相对于根目录的(以斜杠开头)。而相对于.htaccess
包含文件的目录.htaccess
- 减去斜杠前缀。因此,规则的书写方式会导致 URL 路径开头出现双斜杠,应改写为:RewriteRule ^/(.*)$ /$1/ [R,L]
(
NC
这里不需要标志。)或者(最好)不要在这里使用反向引用,而是使用
REQUEST_URI
服务器变量(这自然也可以工作.htaccess
)。例如:RewriteRule ^ %{REQUEST_URI}/ [R,L]
(在旁边:这可能也应该是 301 永久重定向(即
R=301
)。目前,这将默认为 302 临时重定向。但只有在您确认它按预期工作后,才更改为 301(如果这是意图)。)
因此,总而言之,这将是:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^/(.*)$ /$1/ [R,L]
在旁边:
可以通过移动文件系统检查(相对较昂贵的)到最后一个条件并移动状况检查请求是否已以斜线结尾。此外,每个RewriteRule
正则表达式子模式(.*)
状况不是必需的。因此,上面的代码可以更有效地重写:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} !^/application-module/
RewriteCond %{REQUEST_URI} !json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/ [NC]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule !/$ %{REQUEST_URI}/ [R,L]
如果您排除包含(看起来像)文件扩展名的请求,则可以完全删除文件系统检查,但这取决于您的文件结构。
这状况检查!json$
看起来应该真正检查.json
文件扩展名,即。!\.json$
(这与我上面关于排除的评论相联系全部具有“文件扩展名”的请求。)
首先状况检查查询字符串是否为空似乎有点奇怪(因为在 URL 路径附加斜杠时是否存在查询字符串并不重要),但我认为这一定是一个特定的要求?