Trust the Content-Length header

Florian Hirsch
2 min readJul 17, 2016

--

When you’re implementing a file upload you most probably want to limit the size of the upload. But how do you know the size? Reading the Content-Length header should be obvious but can you really trust it?
No, the client can send whatever he wants, correct?
There are a lot of creative ways to be really sure for instance (using JAX-RS and Commons IO):

byte[] data = IOUtils.toByteArray(inputStream);
if (data.length > MAX_UPLOAD_SIZE) {
return Response.status(413).build();
}

Don’t do this. You’re loading the whole stream into your servers memory. The memory of your server is limited. It will crash if there’s no memory left. So by trying to validate the upload size you are providing something like a power off button to your users.

The solution is easier. Trust the Content-Length header and validate if the size is ok. The rest should be handled by your server. It will simply stop reading when the Content-Length header size is reached.

You don’t know if your server or application framework really handles this for you? Implement a resource which returns the uploaded data and do a simple test:

$ curl -X POST \
-F 'file=foobar' \
-H 'Content-Length: 90' \
https://myserver/files
$ foo

This will do a multipart/form-data upload with a part named ‘file’ with ‘foobar’ as content. The response should be ‘foo’ without ‘bar’ but why am I using a Content-Length of 90 instead of 3(the length of ‘foo’)? A multipart/form-data request can contain multiple parts separated by a boundary so the request body is a bit longer:

------------------------------123f00f00f00
Content-Disposition: form-data; name="file"
foobar
------------------------------123f00f00f00--

Keep in mind that the Content-Length header covers the whole request data of multiple files.

--

--