在我的 Web 服务器上,我在位于文档根目录的 .htaccess 文件中添加了一些重写规则(在我的例子中为/var/www/main/public_html/.htaccess
)。这些重写规则的目的是消除 URL 中对 .php 和 .html 文件扩展名的需要。
问题是:它对于大多数URL 都适用。但是,当尝试访问实际上是文件的子目录时,重写规则会不断将 .php 添加到末尾,直到服务器放弃并抛出错误500
。
为了更好地解释这个问题......可以说我的文件结构如下所示:
/index.php
/file.php
/folder/index.php
/folder/file.php
这些 URL 正确显示页面:
example.com
example.com/index
example.com/file
example.com/folder
example.com/folder/index
example.com/folder/file
然而,这种奇怪的循环发生在这样的 URL 上:
example.com/index/file
example.com/file/index
在 的情况下/index/file
,日志显示:
[core:debug] [pid 253721] core.c(3849): [client #####] AH00121: r->uri = /index/file.php.php.php.php.php.php.php.php.php.php
预期结果是这样的 URLexample.com/index/file
会导致404
错误
其他一切都按预期显示 404:
example.com/badfile
example.com/folder/badfile
example.com/badfolder/file
我对重写规则不是很有经验,并且真的不知道我在做什么:D 我几乎可以肯定我在某个地方犯了一个愚蠢的错误。任何帮助,将不胜感激!
该服务器是自托管的,在 Ubuntu 20.04 和 Apache2 上运行。
这是我的 .htaccess 文件包含的内容:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# External Redirect
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=302,L,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R=302,L,NE]
# Internal Redirect
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_URI}.php [L]
# Error Documents
ErrorDocument 403 /errors/403.php
ErrorDocument 404 /errors/404.php
ErrorDocument 500 /errors/500.php
问题是你的“内部重定向/重写”。条件(例如。)不一定测试您最终在替换字符串(例如。 )中重写的相同内容,这会在某些情况下导致无限的重写循环。(是的,使用该标志 - 正如评论中提到的 - 会阻止重写循环,但是,这并不能解决根本问题,并且仍然会导致不正确的重写以及“错误的 URL”被记录为 404。)
%{REQUEST_FILENAME}.html
%{REQUEST_URI}.html
END
当请求表单的 URL
example.com/index/file
(其中index
也映射到.php
或.html
文件并且不是物理目录)时,REQUEST_FILENAME
服务器变量的表单为/path/to/index
(注意缺少/file
),但是REQUEST_URI
是/index/file
(请求的 URL)。因此,条件(RewriteCond
指令)成功(因为/path/to/index.php
存在),但请求被错误地重写为/index/file.php
- 不存在。然后重写引擎重新启动并出现相同的问题。(该END
标志导致重写引擎在第一次“不正确”重写后停止。)这些规则应该这样写:
前面的条件现在正在测试我们最终在替换字符串中重写的相同文件路径。