【问题标题】:Spring boot request hang there when return 1xx status code返回 1xx 状态码时 Spring Boot 请求挂在那里
【发布时间】:2017-09-18 15:29:30
【问题描述】:

我有一个使用自定义状态码的小演示。

有趣的是,如果状态低于 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 与嵌入式 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 之后,我可以看到状态,但是响应没有完成。参考下图:

【问题讨论】:

  • 如果您尝试状态 103,它是否有效?
  • @VHS 不,它不起作用。
  • 试试ResponseEntity.status(HttpStatus.CHECKPOINT).build();怎么样?
  • 还是没有运气。
  • 恐怕我无法提供进一步的帮助。希望您能尽快找到解决方案。

标签: java spring-boot kotlin http-status-codes


【解决方案1】:

我也遇到了这个问题,发现不是 Spring 造成了这种行为。它是Tomcat。

curl -v --header "Expect: 100-continue" http://localhost:8080

像这样调用任何已配置的端点将返回一个不会终止请求的额外响应代码。

  % 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

此响应来自该项目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 响应应该发生在同一个请求中。它挂起的原因是因为它期望客户端响应请求的内容。

查看其他 1XX 响应代码的 wiki,似乎在没有关闭请求的情况下返回了一些信息。我的猜测是 Tomcat 期望所有 1xx 响应代码都以这种方式运行。

【讨论】:

  • 我们通过使用 RemoveRequestHeader GatewayFilter 剥离 Spring Cloud Gateway 中的 http 标头“Expect: 100-continue”来解决此方案。
【解决方案2】:

据我所知,Spring DispacherServlet 正在以完全相同的方式处理不同的返回码。我认为发生的事情是 curl 只是让连接保持打开状态,因为响应在 1xx 范围内。

This article 提供了一个很好的状态码入门。这句话尤其相关:

100–199 100 中的代码是信息性的,表示客户端应该以其他一些操作进行响应。

如果您运行 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

所以我认为正在发生的事情是返回响应,客户端应该用其他一些操作(但没有)做出响应,所以看起来事情已经挂起。

这里真正的问题可能是您为什么要尝试返回105 状态以及您希望发生什么?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 2020-11-27
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多