考虑一个为三个虚拟主机提供服务的网络服务器:
- mysite.com
- myothersite.com
- imnotcreative.com
现在假设服务器接收到以下原始请求消息(代码格式化删除了终止 \r\n
序列):
GET / HTTP/1.1
Host: nothostedhere.com
我在 RFC 2616 中没有看到任何关于如何响应当前服务器上不存在的主机名请求的指南(也许我错过了?)。例如,Apache 将简单地使用其配置中定义的第一个虚拟主机作为“主要主机”,并假装客户端请求该主机。显然,这比返回 400 Bad Request
响应更可靠,并保证客户端始终看到一些表示。
所以我的问题是......
如果客户端在使用HTTP/1.1协议(protocol)?
请注意,所有 HTTP/1.1 请求必须根据 RFC 2616 指定一个 Host:
header 。对于 HTTP/1.0 请求,唯一真正的选择是为“主要"主机结果。这个问题专门针对 HTTP/1.1 协议(protocol)请求。
最佳答案
在这种情况下,400 并不是真正语义正确的响应代码。
The request could not be understood by the server due to malformed syntax.
事实并非如此。该请求在语法上是有效的,并且当您的服务器到达路由阶段时(当您检查 header 的值时),这已经确定了。
我会说这里正确的响应代码是 403:
The server understood the request, but is refusing to fulfill it.
这更准确地描述了发生的事情。服务器拒绝满足请求,因为它不能,并且可以在消息实体中提供更详细的错误消息。
还有一种说法认为 404 是可以接受/正确的,因为找不到满足请求的合适文档,但我个人认为这不是正确的选择,因为 404 指出:
The server has not found anything matching the Request-URI
这明确提到了 Request-URI 的问题,在路由阶段的早期阶段,您可能对 URI 不感兴趣,因为您首先需要将请求分配给主机,然后它才能确定它是否具有一个合适的文档来处理 URI 路径。
在 HTTP/1.1 中,Host:
header 是强制性的。如果客户端声明它正在使用 1.1 版并且不提供 Host:
header ,那么 400 绝对是正确的响应代码。如果客户端声明它使用的是 1.0 版,则不需要提供主机 header ,这应该得到妥善处理 - 这种情况与无法识别的域的情况相同。
实际上,在此事件中您有两个选择:将请求路由到默认的虚拟主机容器,或者以错误响应。如上所述,如果您要响应错误,我认为错误应该是 403。
关于http - 在主机 header 不匹配的虚拟主机环境中返回 400,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14705659/