Max Peng
Max Peng

Reputation: 3257

Spring boot request hang there when return 1xx status code

I have a small demo to play with customized status code.

The interesting part is the request will always hang there if the status is below 200, like 105, 199, etc. But works for any status greater than 200, like 209, 789 etc.

Http status code registry, refer to https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml

Spring boot: 1.5.4.RELEASE with embedded tomcat

Java: 8

Controller:

@RestController
public class DemoController {

    @GetMapping("/hello")
    public ResponseEntity get() {
        return ResponseEntity.status(105).build();
    }
}

Can anyone give me a clear explanation?

I create a gist at here: https://gist.github.com/pengisgood/dbea1fcdc45c2bb5809871c7f020b800

Update:

I also create a small demo to reproduce it at here: https://github.com/pengisgood/springboot-customize-status-code

Update:

After I run curl -v localhost:8080/hello, I can see the status, but the response doesn't finish. Refer to the gif below:

curl result

Upvotes: 3

Views: 4323

Answers (2)

Tiris
Tiris

Reputation: 170

I also ran into this issue and found that it is not Spring that creates this behavior. It is Tomcat.

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

Calling any configured endpoint like this will return an extra response code that doesn't terminate the request.

  % 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

note the HTTP/1.1 100

This response came from this project https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat which doesn't have spring. If I modify the HelloServlet to include a response code of 100 it just hangs.

Looking deeper: https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3

The specification makes it clear that the 100 response is supposed to happen in the same request. The reason it hangs is because it is expecting the client to respond with the content of the request.

Looking at the wiki for other 1XX response codes, it appears to also be true that some information is returned without closing the request. My guess is that Tomcat expects all 1xx response codes to act in this manner.

Upvotes: 2

Phil Webb
Phil Webb

Reputation: 8642

As far as I can tell the Spring DispacherServlet is handling the different return codes in exactly the same way. I think what's happening is curl is just leaving the connection open because the response is in the 1xx range.

This article provides a good primer on status codes. This sentence in particular is relevant:

100–199 Codes in the 100s are informational, indicating that the client should respond with some other action.

If you run curl with --trace you'll see that the 105 response does actually arrive:

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

So what I think is happening is the response is returned, the client should respond with some other action (but doesn't) so it looks like the thing has hung.

Probably the real question here is why are you trying to return a 105 status and what do you expect to happen?

Upvotes: 2

Related Questions