Search code examples
javaandroidhttpclient

HttpClient: Determine empty entity in response


I'm wondering how to determine an empty http response. With empty http response I mean, that the http response will only have set some headers, but contains an empty http body.

For example: I do a HTTP POST to an webserver, but the webserver will only return an status code for my HTTP POST and nothing else.

The problem is, that I have written a little http framework on top of apache HttpClient to do auto json parsing etc. So the default use case of this framework is to make a request and parse the response. However if the response does not contain data, like mentioned in the example above, I will ensure that my framework skip json parsing.

So I do something like this:

HttpResponse response = httpClient.execute(uriRequest);
HttpEntity entity = response.getEntity();
if (entity != null){
    InputStream in = entity.getContent();
    // json parsing
}

However entity is always != null. And also the retrieved inputstream is != null. Is there a simple way to determine if the http body is empty or not?

The only way I see is that the server response contains the Content-Length header field set to 0. But not every server set this field.

Any suggestions?


Solution

  • In HttpClient, getEntity() can return null. See the latest samples.

    However, there's a difference between an empty entity, and no entity. Sounds like you've got an empty entity. (Sorry to be pedantic -- it's just that HTTP is pedantic. :) With respect to detecting empty entities, have you tried reading from the entity input stream? If the response is an empty entity, you should get an immediate EOF.

    Do you need to determine if the entity is empty without reading any bytes from the entity body? Based on the code above, I don't think you do. If that's the case, you can just wrap the entity InputStream with a PushbackInputStream and check:

    HttpResponse response = httpClient.execute(uriRequest);
    HttpEntity entity = response.getEntity();
    if(entity != null) {
        InputStream in = new PushbackInputStream(entity.getContent());
        try {
            int firstByte=in.read();
            if(firstByte != -1) {
                in.unread(firstByte);
                // json parsing
            }
            else {
                // empty
            }
        }
        finally {
            // Don't close so we can reuse the connection
            EntityUtils.consumeQuietly(entity);
            // Or, if you're sure you won't re-use the connection
            in.close();
        }
    }
    

    It's best not to read the entire response into memory just in case it's large. This solution will test for emptiness using constant memory (4 bytes :).

    EDIT: Pedantry follows below.

    From Section 4.3 of the HTTP/1.1 spec:

    For response messages, whether or not a message-body is included with a message is dependent on both the request method and the response status code (section 6.1.1). All responses to the HEAD request method MUST NOT include a message-body, even though the presence of entity- header fields might lead one to believe they do. All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body. All other responses do include a message-body, although it MAY be of zero length.