How to avoid EOFException for an empty HTTP respon

2019-09-05 09:06发布

问题:

I'm sending an HTTP request to a server which legitimately returns a blank response with HTTP response code = 200 (OK).

But this causes the marked line below to throw an EOFException:

InputStream responseStream = httpURLConnection.getInputStream();
final String contentEncoding = this.connection.getContentEncoding();
if ("gzip".equalsIgnoreCase(contentEncoding)) {
    responseStream = new GZIPInputStream(responseStream); // throws EOFException
}

There may be an obvious way to prevent this but I can't find it. Should I perhaps be checking something like connection.getContentLength() > 0 or responseStream.available() > 0 before creating the GZIPInputStream? Neither of these seem quite right and I haven't come across anything similar in example code fragments...

回答1:

Should I perhaps be checking something like connection.getContentLength() > 0

Yes.

or responseStream.available() > 0

Definitely not. available() == 0 isn't a valid test for EOF, and the Javadoc explicitly says so.



回答2:

Shouldn't your server return HTTP code 204 (No Content), instead of 200? Except for a HEAD request that is. See Http Status Code definition

Apart from that, you could indeed just check to work around what looks like a not-all-too-compliant server implementation, or catch the exception and then determine the proper action depending on the type of request you sent.



回答3:

What I understand from your question is that this exception is being thrown consistently everytime you get a 200 response from the server.

If responseStream.available() > 0 is not an option, it means that the stream actually contains something, but that stream seems to be incomplete or ending prematurely by any other means, since available states that there ARE readable bytes in the stream.


Update

Based on your comment (and after reading InputStream's doc again out of sheer curiosity) I also believe connection.getContentLength() > 0 is the way to go. If you're using Java 7, tough, connection.getContentLengthLong() is preferred over that because it returns a long directly.

Given what the docs say about InputStream#available :

The available method for class InputStream always returns 0.

And

Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

This discards that check as an option.



回答4:

Unless I'm missing something, a response with Content-Encoding "gzip" by definition can not be empty.