[Demonstration 1]

[Buggy Method]
public void get(URL url, RestResponse response, Map<String, String> requestHeaders) throws IOException, HttpStatusError {
    HttpURLConnection conn;
    try {
        conn = (HttpURLConnection) url.openConnection();
    } catch (ClassCastException e) {
        throw new RuntimeException("Non-HTTP protocols not supported. Got URL: " + url);
    } catch (IOException e) {
        throw check(e);
    }
    // authentication and some settings is static for URLConnection, preserver current setting
    conn.setInstanceFollowRedirects(true);
    configure(conn);
    for (String h : requestHeaders.keySet()) {
        conn.setRequestProperty(h, requestHeaders.get(h));
    }
    logger.info("GET connection to {}", url);
    try {
        conn.connect();
    } catch (IOException e) {
        throw check(e);
    }
    // response should be ok regardless of status, get content
    ResponseHeaders headers = new URLConnectionResponseHeaders(conn);
    int responseCode = conn.getResponseCode();
    // check status code before trying to get response body
    // to avoid the unclassified IOException
    // Currently getting body only for 200 OK.
    // There might be more 2xx responses with a valuable body.
    if (responseCode == HttpURLConnection.HTTP_OK) {
        OutputStream receiver = response.getResponseStream(headers);
        try {
            InputStream body = conn.getInputStream();
            pipe(body, receiver);
            body.close();
        } catch (IOException e) {
            throw check(e);
        } finally {
            conn.disconnect();
        }
    }
    if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {
        logger.info("Server responded with redirect ({}): {}", responseCode, headers.get("Location"));
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        try {
            InputStream body = conn.getInputStream();
            if (body == null) {
                logger.warn("Redirect did not contain a body.");
            }
            pipe(body, b);
            body.close();
        } catch (IOException e) {
            throw check(e);
        } finally {
            conn.disconnect();
        }
        throw new HttpStatusError(url.toString(), headers, b.toString());
    } else if (responseCode < 400) {
        // Other non-error responses.
        // Do we need to consume a stream if the server sends one? Important when using keep-alive?
        conn.disconnect();
    } else {
        // Error stream expected for 4xx and 5xx.
        ByteArrayOutputStream b = new ByteArrayOutputStream();
        try {
            InputStream body = conn.getErrorStream();
            if (body == null) {
                throw new RuntimeException("Response error could not be read for status " + conn.getResponseCode());
            }
            pipe(body, b);
            body.close();
        } catch (IOException e) {
            throw check(e);
        } finally {
            conn.disconnect();
        }
        throw new HttpStatusError(url.toString(), headers, b.toString());
    }
}

[Buggy Hunk]
} if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {

[Patch]
} else if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) {

[Demonstration 2]

[Buggy Method]
protected URLConnection connect(DownloadJob job, URL src) throws IOException {
    URLConnection conn = ProxyConfiguration.open(src);
    if (conn instanceof HttpURLConnection) {
        HttpURLConnection httpConn = (HttpURLConnection) conn;
        if (httpConn.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP || httpConn.getResponseCode() == HttpURLConnection.HTTP_MOVED_PERM) {
            // TODO maybe need to resolve recursive redirect
            try {
                URL redirectUrl = new URL(httpConn.getHeaderField("location"));
                conn = connect(job, redirectUrl);
            } finally {
                Util.closeAndLogFailures(httpConn.getInputStream(), LOGGER, job.getDestination().getName(), src.toString());
                ;
            }
        }
    }
    return conn;
}

[Buggy Hunk]
Util.closeAndLogFailures(httpConn.getInputStream(), LOGGER, job.getDestination().getName(), src.toString());;

[Patch]
Util.closeAndLogFailures(httpConn.getInputStream(), LOGGER, job.getDestination().getName(), src.toString());

[Demonstration 3]

[Buggy Method]
private void getCliRunnerCommands() {
    String urlString = baseUrl + URL_SUFFIC_CLI_RUNNER_COMMANDS;
    makeRestCall(REQ_POST, urlString, getAuthenticationTicket(), null);
}

[Buggy Hunk]
makeRestCall(REQ_POST, urlString, getAuthenticationTicket(), null);

[Patch]
makeRestCall(REQ_GET, urlString, getAuthenticationTicket(), null);