Apache2 htaccess RewriteCond 与 ErrorDocument 404
Aapche2 htaccess RewriteCond with ErrorDocument 404
Aapche2 htaccess RewriteCond
我发现了一些有效的条件,但我不知道为什么 :)
文件
/error.php
/donate.php
/test/index.php
在我使用的 htaccess 文件中
ErrorDocument 404 /error.php
RewriteEngine On
# WHY THIS LINE NEEDED TO GET IT WORKS
RewriteCond %{REQUEST_FILENAME} ^$
#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) .php [L]
这个.
http://localhost/donate calls internal http://localhost/donate.php
而
http://localhost/donate1 calls internal http://localhost/error.php
和
http://localhost/test/ call internal http://localhost/test/index.php
到目前为止一切顺利
但是当我把它注释掉时
#RewriteCond %{REQUEST_FILENAME} ^$
然后我在调用时收到内部服务器错误
/donate1 而不是 /error.php
谁能解释一下步骤,为什么会这样?
#RewriteCond %{REQUEST_FILENAME} ^$
因为你的指令实际上并没有按照你认为的那样去做。事实上,对于那个“hacky”condition 取消注释,他们根本没有做任何事情,除了防止 500 内部服务器错误(这是由于内部重写循环,因为规则是严格的不正确)。
该条件检查 REQUEST_FILENAME
服务器变量是否为空。它是 never 空的,所以总是失败,所以永远不会触发后面的 RewriteRule
指令。
您可以完全删除 mod_rewrite 指令,您会得到相同的结果。
http://localhost/donate
calls internal http://localhost/donate.php
很可能是 MultiViews (mod_negotiation) 正在将 /donate
重写为 /donate.php
。不是您发布的指令(正如我提到的,实际上没有做任何事情)。
http://localhost/test/
call internal http://localhost/test/index.php
这是由mod_dir (DirectoryIndex
) 引起的。同样,与您发布的指令无关。
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) .php [L]
then i get internal server error while call /donate1
and not the /error.php
因为当您请求 /donate1
时,上述指令会触发内部重写循环(导致 500 Internal Server Error 响应)。 /donate1
到 /donate1.php
到 /donate1.php.php
到 /donate1.php.php.php
等(见下文)。
MultiViews 在这里不适用,因为没有 /donate1
可以明显映射到的文件,例如。 /donate1.php
或 /donate1.html
或其他一些可识别的资源,具有不同的文件扩展名,即 returns 一个 text/html
mime 类型。
当您请求 /donate1
时,会发生以下情况。
/donate1
不映射到目录(第一个条件)或文件(第二个条件),因此在内部被此规则重写为 donate1.php
。这是不正确的(但这就是这条规则的作用)。
-
L
标志然后导致当前轮处理停止并且重写引擎重新开始,通过重写的 URL,即。 donate1.php
重新加入组合。
/donate1.php
未映射到目录或文件,因此被重写为 donate1.php.php
.
- 重写引擎重新开始...
/donate1.php.php
未映射到目录或文件,因此被重写为 donate1.php.php.php
.
- 重写引擎重新开始...
- 等等
这将重复进行,直到达到 10 次(默认)内部重写并且服务器“中断”并返回 500 错误响应。服务器错误日志将包含此错误的详细信息,例如:
AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
(尽管您很少需要更改此内部重定向限制 - 它几乎总是表示您的脚本中存在错误。)
解决方案
你要么完全删除你的 mod_rewrite 指令,让 MultiViews 做它的事情,要么你禁用 MultiViews 并“纠正”你的 mod_rewrite 指令。
例如:
Options -MultiViews
ErrorDocument 404 /error.php
RewriteEngine On
# Rewrite extensionless URLs to ".php" if they exist
RewriteCond %{DOCUMENT_ROOT}/.php -f
RewriteRule (.+) .php [L]
优化...如果您的 URLs(映射到 .php
文件)不包含点,那么您可以简单地排除包含点的 URLs,这样您不要不必要地测试已经包含文件扩展名(自然在文件扩展名前包含一个点)的静态资源请求(例如 image.jpg
、styles.css
等):
RewriteRule ([^.]+) .php [L]
参考:
Aapche2 htaccess RewriteCond
我发现了一些有效的条件,但我不知道为什么 :)
文件
/error.php
/donate.php
/test/index.php
在我使用的 htaccess 文件中
ErrorDocument 404 /error.php
RewriteEngine On
# WHY THIS LINE NEEDED TO GET IT WORKS
RewriteCond %{REQUEST_FILENAME} ^$
#
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) .php [L]
这个.
http://localhost/donate calls internal http://localhost/donate.php
而
http://localhost/donate1 calls internal http://localhost/error.php
和
http://localhost/test/ call internal http://localhost/test/index.php
到目前为止一切顺利
但是当我把它注释掉时
#RewriteCond %{REQUEST_FILENAME} ^$
然后我在调用时收到内部服务器错误 /donate1 而不是 /error.php
谁能解释一下步骤,为什么会这样?
#RewriteCond %{REQUEST_FILENAME} ^$
因为你的指令实际上并没有按照你认为的那样去做。事实上,对于那个“hacky”condition 取消注释,他们根本没有做任何事情,除了防止 500 内部服务器错误(这是由于内部重写循环,因为规则是严格的不正确)。
该条件检查 REQUEST_FILENAME
服务器变量是否为空。它是 never 空的,所以总是失败,所以永远不会触发后面的 RewriteRule
指令。
您可以完全删除 mod_rewrite 指令,您会得到相同的结果。
http://localhost/donate
calls internalhttp://localhost/donate.php
很可能是 MultiViews (mod_negotiation) 正在将 /donate
重写为 /donate.php
。不是您发布的指令(正如我提到的,实际上没有做任何事情)。
http://localhost/test/
call internalhttp://localhost/test/index.php
这是由mod_dir (DirectoryIndex
) 引起的。同样,与您发布的指令无关。
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule (.*) .php [L]
then i get internal server error while call
/donate1
and not the/error.php
因为当您请求 /donate1
时,上述指令会触发内部重写循环(导致 500 Internal Server Error 响应)。 /donate1
到 /donate1.php
到 /donate1.php.php
到 /donate1.php.php.php
等(见下文)。
MultiViews 在这里不适用,因为没有 /donate1
可以明显映射到的文件,例如。 /donate1.php
或 /donate1.html
或其他一些可识别的资源,具有不同的文件扩展名,即 returns 一个 text/html
mime 类型。
当您请求 /donate1
时,会发生以下情况。
/donate1
不映射到目录(第一个条件)或文件(第二个条件),因此在内部被此规则重写为donate1.php
。这是不正确的(但这就是这条规则的作用)。-
L
标志然后导致当前轮处理停止并且重写引擎重新开始,通过重写的 URL,即。donate1.php
重新加入组合。 /donate1.php
未映射到目录或文件,因此被重写为donate1.php.php
.- 重写引擎重新开始...
/donate1.php.php
未映射到目录或文件,因此被重写为donate1.php.php.php
.- 重写引擎重新开始...
- 等等
这将重复进行,直到达到 10 次(默认)内部重写并且服务器“中断”并返回 500 错误响应。服务器错误日志将包含此错误的详细信息,例如:
AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
(尽管您很少需要更改此内部重定向限制 - 它几乎总是表示您的脚本中存在错误。)
解决方案
你要么完全删除你的 mod_rewrite 指令,让 MultiViews 做它的事情,要么你禁用 MultiViews 并“纠正”你的 mod_rewrite 指令。
例如:
Options -MultiViews
ErrorDocument 404 /error.php
RewriteEngine On
# Rewrite extensionless URLs to ".php" if they exist
RewriteCond %{DOCUMENT_ROOT}/.php -f
RewriteRule (.+) .php [L]
优化...如果您的 URLs(映射到 .php
文件)不包含点,那么您可以简单地排除包含点的 URLs,这样您不要不必要地测试已经包含文件扩展名(自然在文件扩展名前包含一个点)的静态资源请求(例如 image.jpg
、styles.css
等):
RewriteRule ([^.]+) .php [L]
参考: