Search code examples
javaspring-bootkotlinhttp-status-codes

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


Solution

  • 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.