Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use java http connection instance after exception

Is the following code safe:

try {
    URL url = new URL(urlRequest);
    conn = (HttpURLConnection)url.openConnection();
    conn.setConnectTimeout(30000);
    conn.setReadTimeout(30000);
    conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
    String encoding = conn.getContentEncoding();
    return Utils.wrapCompressedStream(conn.getInputStream(), encoding);
} catch (IOException e) {
    if(conn != null) {
        conn.getContentEncoding();
        conn.getErrorStream();
        conn.whateverOtherMethodThere();
        ...
    }
}

Particularly, is it safe in case of InterruptedIOException (say, read timeout) to call methods like getContentEncoding()? As far as I understand this method requires live connection to read HTTP(S) headers.

Update (additional info):

This question originates from a real-system experience. I believe, the system was run on Oracle/Sun JVM 1.6 then. The code is almost the same:

...    
} catch (IOException e) {
    if(conn != null) {
         try {
             String response = tryGetResponse(conn);
...

The problem happened in the tryGetResponse on HTTPS requests:

 private static String tryGetResponse(HttpURLConnection conn) {
    if(conn == null) return "(failed to get)";
    InputStream in = null;
    try {
        InputStream err = conn.getErrorStream();
        if (err != null) {
            in = Utils.wrapCompressedStream(err, conn.getContentEncoding());
        }
        return Utils.inputStreamToString(in);
    } catch (IOException e) {
        return "(failed to get)";
    } finally {
        Utils.closeQuitely(in);
    }
}

Spontaneously system hanged on the socket connect (or read) in the getContentEncoding() call:

in = Utils.wrapCompressedStream(err, conn.getContentEncoding());

exactly after SocketTimeoutException is thrown in the initial code.

So, it seems that getContentEncoding() tries (or tried in Java 6) to establish a new connection without timeouts being set.

like image 364
Shcheklein Avatar asked Jan 22 '14 15:01

Shcheklein


People also ask

Can I use HttpURLConnection for https?

HttpsURLConnection extends HttpURLConnection with support for https-specific features. See http://www.w3.org/pub/WWW/Protocols/ and RFC 2818 for more details on the https specification. This class uses HostnameVerifier and SSLSocketFactory . There are default implementations defined for both classes.

What is the use of HttpURLConnection in Java?

HttpURLConnection class is an abstract class directly extending from URLConnection class. It includes all the functionality of its parent class with additional HTTP-specific features. HttpsURLConnection is another class that is used for the more secured HTTPS protocol.

What is the difference between HttpURLConnection and HttpsURLConnection?

URLConnection is the base class. HttpURLConnection is a derived class which you can use when you need the extra API and you are dealing with HTTP or HTTPS only. HttpsURLConnection is a 'more derived' class which you can use when you need the 'more extra' API and you are dealing with HTTPS only.


1 Answers

No. It is not safe in general. The behavior might differ between JVM implementations (think IBM J9 vs. Oracle VM vs. Open JDK) and change between versions of the same VM without notice.

The reason for this is that the API specification makes no guarantees.

If you tell me which specific implementation in which particular version you are using, I could look in the sources and try to make some conclusions. But I would strongly advise against relying about the behavior you find there.

With regards to HTTPS: There seem still to be some bugs with SSL. For example OpenSSL has made a public announcement, that they will reveal a security bug end of this week. The bug fixes for that might change the behavior of a HTTPS connection in some error cases. It's possible that whatever we find in the sources will be moot at the end of this week. If not, it might change with the next security fix.

Update:

I've tried to find the sources that correspond to the version of Java you have referenced in your updated question. Finding the Java-Sources is not a big problem, but the code goes very quickly into native parts. This alone is a good hint, that the answer would not only be version specific, but also platform specfic (Linux, Windows, Mac, etc). You can check yourself on the OpenJDK sources for Java 1.6, e.g. for the network stack for Windows.

Beware: You have very likely used the Sun JDK 1.6. OpenJDK 1.6 is besed on the Sun/Oracle JDK, but on JDK 1.7. The Open JDK 1.6 is code form Sun/Oracle JDK 1.7 backportet to Java 1.6. So there still might be some small differences, that nevertheless can be significant regarding the usage of the connection after an error occured.

like image 110
stefan.schwetschke Avatar answered Oct 22 '22 21:10

stefan.schwetschke