所以我有这个 apache 配置,我试图将用户“重写”到自定义错误页面,但它不起作用。我进入http://localhost/index.html/ddgdg%:sdsdfs
浏览器,但没有得到我的错误页面。
我可以通过直接在浏览器中输入其 URL 来查看自定义错误页面(http://localhost/my-error.html
)。
知道我可能做错了什么吗?
我的完整 httpd.conf:链接到httpd.conf
我对默认 httpd.conf 的更改(我还必须取消对 mod_rewrite.so 的 LoadModule 的注释)
RewriteEngine On
LogLevel alert rewrite:info
#if invalid characters are present in the URI, display 404 page
RewriteCond %{REQUEST_URI} ^\/.+[:%].+
RewriteRule "^/$" "http://%{SERVER_NAME}/my-error.html" [L,R=301]
自定义错误页面的内容
$ cat /Library/WebServer/Documents/my-error.html
<html><body><h1>404 error here</h1></body></html>
Apache 版本
$ apachectl -v
Server version: Apache/2.4.34 (Unix)
Server built: Feb 22 2019 20:20:11
编辑1:目前正在运行 macOS Mojave,但稍后会设置 Ubuntu VM。
答案1
这里发生了一些不同的问题……
http://localhost/index.html/ddgdg%:sdsdfs
你实际上并没有说明你得到了什么回应,只是没有发生。但是,由于杂散%
(不在十六进制编码的八位字节前面),此 URL 严格无效,我希望 Apache 以 响应400 Bad Request
。覆盖此问题的唯一方法是创建自定义 400 错误文档,在其中检查请求的 URL 并自定义响应。例如:
ErrorDocument 400 /my-error.html
如果不是因为这个错误,%
您应该能够使用 mod_rewrite 捕获此请求并相应地重定向。但是,您RewriteRule
正在检查 URL 路径是否为空(即"^/$"
),而示例中请求的 URL 远非空(即/index.html/ddgdg%:sdsdfs
)- 因此该RewriteRule
指令永远不会与您的示例 URL 匹配。要检查URL 路径中的任何地方%
是否有:
或并重定向,您可以执行以下操作:
# Checks for a "%" or ":" in the URL-path
RewriteRule [%:] /my-error.html [L,R=302]
但请注意,匹配的 URL 路径RewriteRule
图案(以及REQUEST_URI
服务器变量)已经经过 % 解码,因此这将仅匹配特殊字符已双重编码(罕见)的 URL。(如上所述,否则%
可能会产生 400 响应前mod_rewrite 能够处理该请求。)
我还想问一下,为什么您要“重定向”到您的自定义错误文档(即my-error.html
),而不是直接提供它?重定向有许多缺点:向客户端发送 3xx 响应、丢失有关导致错误的 URL 的信息、向您的服务器发送双倍的请求等。
你可以内部重写/my-error.html
只需删除该标志,即可将请求发送到,而不是重定向R
。例如:
RewriteRule [%:] /my-error.html [L]
但是,除非您手动设置 HTTP 状态,否则my-error.html
用户将看到200 OK
响应 - 这是不可取的。
或者(最好)创建一个自定义 404(看起来像您要执行的操作)并触发该操作。例如:
ErrorDocument 404 /my-error.html
RewriteRule [%:] - [R=404]
然后 Apache 设置“404 Not Found”HTTP 响应状态。
但是,您可能根本不需要在这里使用 mod_rewrite。在您的示例 URL 中,index.html
URL 路径中的 之后的所有内容,即/ddgdg%:sdsdfs
,都是附加路径名信息(又名 path-info / PATH_INFO
)。默认情况下,处理 text/html 响应的处理程序不允许 path-info,并将隐式触发 404(如果不是因为 stray %
- 如上所述),调用您的自定义ErrorDocument
(如果已定义)。因此,RewriteRule
最后一个示例中的指令可以简单地删除,因为 Apache 无论如何都会触发 404(除非您使用 覆盖此行为AcceptPathInfo
)。