Java 套接字编程 - HTTP 1.1 的 301 错误

Java Socket Programming - 301 Error with HTTP 1.1

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

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

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

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 中吗?

谢谢。

This will give me "301 Moved Permanently" code with both HTTP 1.1 and 1.0.

HTTP status code 301 是重定向到新的 URL:

The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. This response is cacheable unless indicated otherwise.

The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s).

If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

Note: When automatically redirecting a POST request after receiving a 301 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request.

服务器告诉您,您向其发送 GET 请求的 URL 不再有效。您需要从服务器的响应中提取 Location header 的值,然后对指定的 URL.

重复相同的请求

It would give me "HTTP/1.1 400 Bad Request" for HTTP 1.1 and "HTTP/1.1 200 OK" for HTTP 1.0.

Why does it have such behavior? Does this happen because we have the request in HTTP 1.0 and the response is in HTTP 1.1?

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

A client MUST include a Host header field in all HTTP/1.1 request messages. If the requested URI does not include an Internet host name for the service being requested, then the Host header field MUST be given with an empty value. An HTTP/1.1 proxy MUST ensure that any request message it forwards does contain an appropriate Host header field that identifies the service being requested by the proxy. All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad Request) status code to any HTTP/1.1 request message which lacks a Host header field.

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

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

两者都有效。

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

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

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

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