0

我刚开始用 Java 学习套接字编程,我已经遇到了一个不寻常的行为。这是代码片段

writer.println("GET " + path + " " + protocol);
//writer.println();
writer.println("Host: " + hostname);
writer.println();
writer.flush();

这将为我提供带有 HTTP 1.1 和 1.0 的“301 永久移动”代码。如果我取消注释请求和主机名之间的空行

writer.println("GET " + path + " " + protocol);
writer.println();
writer.println("Host: " + hostname);
writer.println();
writer.flush();

它会给我HTTP 1.1 的“HTTP/1.1 400 Bad Request”和 HTTP 1.0 的“HTTP/1.1 200 OK”

为什么会有这样的行为?发生这种情况是因为我们有 HTTP 1.0 中的请求而响应是 HTTP 1.1 中的吗?

谢谢。

4

1 回答 1

4

这将为我提供带有 HTTP 1.1 和 1.0 的“301 永久移动”代码。

HTTP 状态码 301是指向新 URL 的重定向:

请求的资源已被分配一个新的永久 URI,并且任何将来对该资源的引用都应该使用返回的 URI 之一。 如果可能,具有链接编辑功能的客户端应该自动将对 Request-URI 的引用重新链接到服务器返回的一个或多个新引用。除非另有说明,否则此响应是可缓存的。

新的永久 URI 应该由响应中的 Location 字段给出。除非请求方法是 HEAD,否则响应的实体应该包含一个简短的超文本注释,其中包含指向新 URI 的超链接。

如果收到 301 状态代码以响应 GET 或 HEAD 以外的请求,用户代理不得自动重定向请求,除非用户可以确认,因为这可能会改变发出请求的条件。

注意:当收到 301 状态码后自动重定向 POST 请求时,一些现有的 HTTP/1.0 用户代理会错误地将其更改为 GET 请求。

服务器告诉您,您发送GET请求的 URL 不再有效。您需要Location从服务器的响应中提取标头的值,然后对指定的 URL 重复相同的请求。

它会给我 HTTP 1.1 的“HTTP/1.1 400 Bad Request”和 HTTP 1.0 的“HTTP/1.1 200 OK”。

为什么会有这样的行为?发生这种情况是因为我们有 HTTP 1.0 中的请求而响应是 HTTP 1.1 中的吗?

Host头在 HTTP 1.0 中是可选的,但在 HTTP 1.1 中是必需的:

客户端必须在所有 HTTP/1.1 请求消息中包含 Host 头字段。如果请求的 URI 不包括被请求服务的 Internet 主机名,则主机头字段必须为空值。HTTP/1.1 代理必须确保它转发的任何请求消息都包含适当的主机头字段,该字段标识代理正在请求的服务。所有基于 Internet 的 HTTP/1.1 服务器必须以 400(错误请求)状态代码响应任何缺少 Host 头字段的 HTTP/1.1 请求消息。

因此,当您不插入额外的空白行时,您最终会分别发送这些请求:

GET /path HTTP/1.0
Host: hostname
GET /path HTTP/1.1
Host: hostname

两者都是有效的。

但是,当您插入额外的空白行时,您实际上是一次发送两个单独的请求:

GET /path HTTP/1.x;
Host: hostname

请求头和请求体之间用空行分隔,GET请求没有请求体,所以第一个空行结束请求。

因此,在这种情况下,第一个请求仅对 HTTP 1.0 有效,而对 HTTP 1.1 无效,因为Host缺少标头。第二个请求在任一版本中都是无效的。

于 2016-05-17T03:00:32.013 回答