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 时,会发生以下情况。

  1. /donate1 不映射到目录(第一个条件)或文件(第二个条件),因此在内部被此规则重写为 donate1.php。这是不正确的(但这就是这条规则的作用)。
  2. L 标志然后导致当前轮处理停止并且重写引擎重新开始,通过重写的 URL,即。 donate1.php 重新加入组合。
  3. /donate1.php 未映射到目录或文件,因此被重写为 donate1.php.php.
  4. 重写引擎重新开始...
  5. /donate1.php.php 未映射到目录或文件,因此被重写为 donate1.php.php.php.
  6. 重写引擎重新开始...
  7. 等等

这将重复进行,直到达到 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.jpgstyles.css 等):

RewriteRule ([^.]+) .php [L]

参考: