Empty InputStream with Spring MVC

The other day, I was trying to build a simple batch upload interface for a Java web application running Spring Boot with Spring MVC on Apache Tomcat. But when I tried reading the InputStream in my controller, it was always empty. Fortunately, this turned out to be quite easy to fix.

This is the command line I used to upload the data:

curl -X POST localhost:8080/ --data-binary @- < input.txt

And that's the Java code:

@RestController
public class MyController {
    @PostMapping("/")
    public String batchUpload(InputStream in) throws IOException {
        // do something with the InputStream
    }
}

Spring MVC supports InputStream and Reader for accessing the request body, but it didn't make a difference here, no matter which I used they were both empty. For larger amounts of data (more than 2 MB in my tests), the input was always complete, however.

It turns out that there's a mechanism at work that consumes at least part of the body, but only if the Content-Type header is set to application/x-www-form-urlencoded, which is the default that browsers and tools like curl use.

The workaround is trivial - just use a different Content-Typeheader, which in my case is the proper solution anyway:

curl -X POST localhost:8080/ -H "Content-Type: application/octet-stream" --data-binary @- < input.txt

I usually restrict the endpoint to only accept a custom Content-Type, so this is a problem that only shows up during prototyping.

social