Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpURLConnection.getResponseCode() throws IOException when code is known

How come HttpURLConnection.getResponseCode() throws IOException even if the status is known?

Caused by: java.io.IOException: Server returned HTTP response code: 412 for URL: <my url>

It's not a problem of getting the response code because it is written in the exception message.

I would expect to have an option to get the status code (even if it's not ~200) without getting an exception, so I'll be able to decide in my code what to do.

Full stack trace:

Caused by: java.io.IOException: Server returned HTTP response code: 412 for URL: <my url>
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1625)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:468)
... my code

UPDATE I changed the server side implementation to return a different status code (303), and it's working now (not throwing IOException). Meaning it is specifically related to 412.

like image 960
danieln Avatar asked Feb 24 '14 14:02

danieln


People also ask

How do I get HttpURLConnection response code?

Set the request method in HttpURLConnection instance, default value is GET. Call setRequestProperty() method on HttpURLConnection instance to set request header values, such as “User-Agent” and “Accept-Language” etc. We can call getResponseCode() to get the response HTTP code.

How do I set up HttpURLConnection?

We can create an HttpUrlConnection instance using the openConnection() method of the URL class. Note that this method only creates a connection object but doesn't establish the connection yet.


2 Answers

I encountered the same problem today at work — our code was calling HttpURLConnection.getResponseCode() and ending up with Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: ... — and after some quality time diving through the JDK source code, I ended up figuring out the following:

  • getResponseCode() isn't actually throwing an exception!
  • An exception gets thrown from deep inside getResponseCode(), but it gets caught.
    • Before it's caught, some fields get set inside HttpURLConnection that allow getResponseCode() to succeed, which it does.
    • Also before it's caught, the exception gets saved to a field in a subclass of HttpURLConnection (specifically: sun.net.www.protocol.http.HttpURLConnection.rememberedException).
  • Subsequently, our code called getInputStream() directly, which is supposed to throw an exception in this case. (You're supposed to call getErrorStream() instead.)
  • getInputStream() throws an exception that wraps the original thrown-and-caught exception.
  • So we ended up getting a stacktrace with Caused by-s that referred to our line of code where we were calling getResponseCode(), even though our actual issue was later, in our line of code where we were calling getInputStream() directly.
    • The stacktrace also mentions that later line of code, but I didn't notice that at first.

I'm betting that your case was the same.

like image 105
ruakh Avatar answered Oct 25 '22 15:10

ruakh


ATTENTION: this may depend on the JVM version you are running!!! as tests of @SotiriosDelimanolis gave different results

The answer is in the source code of the HttpURLConnection and is related to all the errors that have error code > 400

If error code is equal 404 or 410 a FileNotFoundException is thrown else an IOException as

    if (respCode >= 400) {
        if (respCode == 404 || respCode == 410) {
            throw new FileNotFoundException(url.toString());
        } else {
            throw new java.io.IOException("Server returned HTTP" +
              " response code: " + respCode + " for URL: " +
              url.toString());
        }
    }

sun.net.www.protocol.http.HttpURLConnection Source code at line 1625:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/sun/net/www/protocol/http/HttpURLConnection.java#HttpURLConnection

My test on http://media.jarnbjo.de/412.php using :

Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

on Windows 64 bit

enter image description here

like image 23
piacente.cristian Avatar answered Oct 25 '22 16:10

piacente.cristian