Search code examples
javasocketshttpinputstreamhttpurlconnection

Close HttpURLConnection without closing InputStream?


I have a method that opens a HttpURLConnection and then returns the InputStream from the response to the caller:

// Callers are responsible for closing the returned input stream
public InputStream get()
{
    final URL url= new URL("http://example.com");
    HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
    httpUrlConnection.setRequestMethod("GET");
    return httpUrlConnection.getInputStream();
    
    // Don't close httpUrlConnection as that will close the returned input stream
    // which the caller is responsible for closing.
}

My problem is I cannot close the HttpURLConnection in this method as that would close the underlying InputStream, which the caller of this method is responsible for closing. I have no control over the callers.

How bad is it that the HttpUrlConnection is not closed? Will it eventually be closed? Or should I implement some mechanism to close it after a period of time has elapsed? Or maybe copy/clone the InputStream and return the copy, which would allow me to close the HttpURLConnection?


Solution

  • You do not want to leave the connection open. That will present the risk of a resource leak. I would recommend creating a custom InputStream implementation that automatically closes the connection when the stream is closed:

    public class HttpURLConnectionInputStream extends InputStream {
    
        private HttpURLConnection connection;
        private InputStream stream;
    
        public HttpURLConnectionInputStream(HttpURLConnection connection) throws IOException {
            this.connection = connection;
            this.stream = connection.getInputStream();
        }
    
        @Override
        public int read() throws IOException {
            return stream.read();
        }
    
        @Override
        public void close() throws IOException {
            connection.disconnect();
        }
    }
    

    Then just pass your HttpURLConnection to the constructor and return the custom input stream:

    public InputStream get() throws IOException {
        final URL url = new URL("http://example.com");
        HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
        httpUrlConnection.setRequestMethod("GET");
        httpUrlConnection.connect();
        return new HttpURLConnectionInputStream(httpUrlConnection);
    }