Spring 当 return 1xx 状态代码时引导请求挂在那里
Spring boot request hang there when return 1xx status code
我有一个使用自定义状态码的小演示。
有趣的是,如果状态低于 200,如 105、199 等,请求将始终挂在那里。但适用于任何大于 200 的状态,如 209、789 等。
Http状态码注册,参考https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Spring boot: 1.5.4.RELEASE with embedded tomcat
Java: 8
控制器:
@RestController
public class DemoController {
@GetMapping("/hello")
public ResponseEntity get() {
return ResponseEntity.status(105).build();
}
}
谁能给我一个明确的解释?
我在这里创建一个要点:https://gist.github.com/pengisgood/dbea1fcdc45c2bb5809871c7f020b800
更新:
我还创建了一个小演示来重现它:
https://github.com/pengisgood/springboot-customize-status-code
更新:
在我运行curl -v localhost:8080/hello
之后,我可以看到状态,但是响应没有完成。参考下面的动图:
据我所知,Spring DispacherServlet
以完全相同的方式处理不同的 return 代码。我认为正在发生的事情是 curl 只是让连接保持打开状态,因为响应在 1xx
范围内。
This article 提供了一个很好的状态代码入门。这句话特别相关:
100–199 Codes in the 100s are informational, indicating that the client should respond with some other action.
如果你 运行 curl
和 --trace
你会看到 105
响应确实到达了:
curl -v -trace http://localhost:8080/hello
Trying ::1...
TCP_NODELAY set
Connected to localhost (::1) port 8080 (#0)
> GET /hello HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 105
< Date: Tue, 19 Sep 2017 18:07:04 GMT
^C
所以我认为正在发生的是响应是 returned,客户端应该响应一些其他操作(但没有)所以看起来事情已经挂起。
可能这里真正的问题是你为什么要 return 一个 105
状态,你期望发生什么?
我也 运行 解决了这个问题,发现并不是 Spring 造成了这种行为。是Tomcat.
curl -v --header "Expect: 100-continue" http://localhost:8080
像这样调用任何配置的端点将return一个不会终止请求的额外响应代码。
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0*
Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.56.1
> Accept: */*
> Expect: 100-continue
>
< HTTP/1.1 100
< HTTP/1.1 200
< Set-Cookie: JSESSIONID=9355141A10CF546E9A9A43F5A5C0B1A4; Path=/; HttpOnly
< Content-Type: text/html;charset=ISO-8859-1
< Content-Length: 58
< Date: Tue, 31 Jul 2018 17:27:52 GMT
<
{ [58 bytes data]
100 58 100 58 0 0 58 0 0:00:01 --:--:-- 0:00:01 82<html>
<body>
<h2>Hello Heroku!</h2>
</body>
</html>
* Connection #0 to host localhost left intact
注意 HTTP/1.1 100
此回复来自没有 spring 的项目 https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat。如果我修改 HelloServlet
以包含 100 的响应代码,它就会挂起。
深入观察:
https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3
规范明确指出 100 响应应该发生在同一个请求中。它挂起的原因是因为它期望客户端响应请求的内容。
在 wiki 上查看其他 1XX 响应代码,似乎也确实 return 编辑了某些信息而没有关闭请求。我的猜测是 Tomcat 期望所有 1xx 响应代码都以这种方式运行。
我有一个使用自定义状态码的小演示。
有趣的是,如果状态低于 200,如 105、199 等,请求将始终挂在那里。但适用于任何大于 200 的状态,如 209、789 等。
Http状态码注册,参考https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
Spring boot: 1.5.4.RELEASE with embedded tomcat
Java: 8
控制器:
@RestController
public class DemoController {
@GetMapping("/hello")
public ResponseEntity get() {
return ResponseEntity.status(105).build();
}
}
谁能给我一个明确的解释?
我在这里创建一个要点:https://gist.github.com/pengisgood/dbea1fcdc45c2bb5809871c7f020b800
更新:
我还创建了一个小演示来重现它: https://github.com/pengisgood/springboot-customize-status-code
更新:
在我运行curl -v localhost:8080/hello
之后,我可以看到状态,但是响应没有完成。参考下面的动图:
据我所知,Spring DispacherServlet
以完全相同的方式处理不同的 return 代码。我认为正在发生的事情是 curl 只是让连接保持打开状态,因为响应在 1xx
范围内。
This article 提供了一个很好的状态代码入门。这句话特别相关:
100–199 Codes in the 100s are informational, indicating that the client should respond with some other action.
如果你 运行 curl
和 --trace
你会看到 105
响应确实到达了:
curl -v -trace http://localhost:8080/hello
Trying ::1...
TCP_NODELAY set
Connected to localhost (::1) port 8080 (#0)
> GET /hello HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 105
< Date: Tue, 19 Sep 2017 18:07:04 GMT
^C
所以我认为正在发生的是响应是 returned,客户端应该响应一些其他操作(但没有)所以看起来事情已经挂起。
可能这里真正的问题是你为什么要 return 一个 105
状态,你期望发生什么?
我也 运行 解决了这个问题,发现并不是 Spring 造成了这种行为。是Tomcat.
curl -v --header "Expect: 100-continue" http://localhost:8080
像这样调用任何配置的端点将return一个不会终止请求的额外响应代码。
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0*
Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.56.1
> Accept: */*
> Expect: 100-continue
>
< HTTP/1.1 100
< HTTP/1.1 200
< Set-Cookie: JSESSIONID=9355141A10CF546E9A9A43F5A5C0B1A4; Path=/; HttpOnly
< Content-Type: text/html;charset=ISO-8859-1
< Content-Length: 58
< Date: Tue, 31 Jul 2018 17:27:52 GMT
<
{ [58 bytes data]
100 58 100 58 0 0 58 0 0:00:01 --:--:-- 0:00:01 82<html>
<body>
<h2>Hello Heroku!</h2>
</body>
</html>
* Connection #0 to host localhost left intact
注意 HTTP/1.1 100
此回复来自没有 spring 的项目 https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat。如果我修改 HelloServlet
以包含 100 的响应代码,它就会挂起。
深入观察: https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3
规范明确指出 100 响应应该发生在同一个请求中。它挂起的原因是因为它期望客户端响应请求的内容。
在 wiki 上查看其他 1XX 响应代码,似乎也确实 return 编辑了某些信息而没有关闭请求。我的猜测是 Tomcat 期望所有 1xx 响应代码都以这种方式运行。