2

When I look at SO the typical answer to my question is this:

HttpURLConnection httpConn = (HttpURLConnection)_urlConnection;
InputStream _is;
if (httpConn.getResponseCode() == 200) {
    _is = httpConn.getInputStream();
} else {
     /* error from server */
    _is = httpConn.getErrorStream();
}

From Read error response body in Java

This seems quite reasonable, however when I look at the implementation of HttpURLConnection.getResponseCode() the very first thing it does is call getInputStream(). According to the documentation getInputStream() is supposed to throw an IOException if there was an error, hence the solution above will always throw an exception if the response code is not in the 200 range!

Have I missed something here? How am I supposed to get the response code if there is an error, if the very function that gives me the response code will throw in that case?

Here is what getResponseCode() in java.net.HttpURLConnection.java looks like for me:

public int getResponseCode() throws IOException {
    // Call getInputStream() first since getHeaderField() doesn't return
    // exceptions
    getInputStream();
    String response = getHeaderField(0);
    if (response == null) {
        return -1;
    }
    response = response.trim();
    int mark = response.indexOf(" ") + 1;
    if (mark == 0) {
        return -1;
    }
    int last = mark + 3;
    if (last > response.length()) {
        last = response.length();
    }
    responseCode = Integer.parseInt(response.substring(mark, last));
    if (last + 1 <= response.length()) {
        responseMessage = response.substring(last + 1);
    }
    return responseCode;
}
Community
  • 1
  • 1
DaedalusAlpha
  • 1,610
  • 4
  • 20
  • 33

1 Answers1

-2

that what you are showing is sun old implementation of

public abstract class HttpURLConnection extends URLConnection

enter image description here

new HttpURLConnection implementation

https://github.com/square/okhttp/blob/master/okhttp-urlconnection/src/main/java/okhttp3/internal/huc/HttpURLConnectionImpl.java

@Override public final InputStream getInputStream() throws IOException {
    if (!doInput) {
      throw new ProtocolException("This protocol does not support input");
    }

    HttpEngine response = getResponse();

    // if the requested file does not exist, throw an exception formerly the
    // Error page from the server was returned if the requested file was
    // text/html this has changed to return FileNotFoundException for all
    // file types
    if (getResponseCode() >= HTTP_BAD_REQUEST) {
      throw new FileNotFoundException(url.toString());
    }

    return response.getResponse().body().byteStream();
}

 /**
 * Returns an input stream from the server in the case of error such as the requested file (txt,
 * htm, html) is not found on the remote server.
 */
 @Override public final InputStream getErrorStream() {
  try {
  HttpEngine response = getResponse();
      if (HttpEngine.hasBody(response.getResponse())
          && response.getResponse().code() >= HTTP_BAD_REQUEST) {
        return response.getResponse().body().byteStream();
      }
      return null;
    } catch (IOException e) {
      return null;
    }
}

An HTTP & HTTP/2 client for Android and Java applications. For more information see the website and the wiki.

http://square.github.io/okhttp/

ps. if u want read error steam stream:

/**
 *  from sun.misc.IOUtils class.
 *  It's nearly twice as fast as the common implementation using ByteBuffers:
 *  */
public static byte[] readFully(InputStream is, int length, boolean readAll) throws IOException {
    byte[] output = {};
    if (length == -1) length = Integer.MAX_VALUE;
    int pos = 0;
    while (pos < length) {
        int bytesToRead;
        if (pos >= output.length) { // Only expand when there's no room
            bytesToRead = Math.min(length - pos, output.length + 1024);
            if (output.length < pos + bytesToRead) {
                output = Arrays.copyOf(output, pos + bytesToRead);
            }
        } else {
            bytesToRead = output.length - pos;
        }
        int cc = is.read(output, pos, bytesToRead);
        if (cc < 0) {
            if (readAll && length != Integer.MAX_VALUE) {
                throw new EOFException("Detect premature EOF");
            } else {
                if (output.length != pos) {
                    output = Arrays.copyOf(output, pos);
                }
                break;
            }
        }
        pos += cc;
    }
    return output;
}
ceph3us
  • 7,326
  • 3
  • 36
  • 43