Java Socket 编程 - HTTP 1.1 的 301 错误

标签 java sockets http-headers http-1.1 http-1.0

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

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

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

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

它会给我“HTTP/1.1 400 Bad Request”(对于HTTP 1.1)和“HTTP/1.1 200 OK”(对于HTTP 1.0)。

为什么会有这样的行为?发生这种情况是因为我们的请求采用 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

请求头和请求正文之间用空行分隔,GET请求没有请求正文,因此第一个空行结束请求。

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

关于Java Socket 编程 - HTTP 1.1 的 301 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37265835/

相关文章:

java - 单击recyclerView新 Activity 尝试调用虚拟方法时出错

java - Mockito单元测试: on all method invocations of a class,返回 "true"

java - 与 Jersey 客户端的 POST 请求

if-statement - 仅当 cookie 存在时,如何有条件地覆盖 nginx 中的 header ?

java - 为什么我的 Spring Boot POST 输出 "Whitelabel Error Page"?

java - 无法从静态上下文中引用非静态方法 isGooglePlayServicesAvailable 和 getErrorDialog

python-3.x - 将 Scapy L3socket 与 WSL 结合使用时,协议(protocol)不支持地址族

html - Perl-我如何知道套接字客户端何时断开连接(用户关闭窗口/浏览器时)

Python:Selenium 无法在 UDOO 上找到空闲端口

javascript - 是否应该使用响应 header (即 400)来指示错误(特别是 x-editable)