Index: trunk/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/data/oauth/SignpostAdapters.java	(revision 9309)
@@ -40,4 +40,6 @@
             if (response != null) {
                 ((HttpResponse) response).response.disconnect();
+            } else if (request != null) {
+                ((HttpRequest) request).request.disconnect();
             }
         }
Index: trunk/src/org/openstreetmap/josm/gui/download/PlaceSelection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/PlaceSelection.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/gui/download/PlaceSelection.java	(revision 9309)
@@ -325,5 +325,5 @@
 
         private final String searchExpression;
-        private HttpClient.Response connection;
+        private HttpClient connection;
         private List<SearchResult> data;
         private boolean canceled;
@@ -368,7 +368,8 @@
                 URL url = new URL(urlString);
                 synchronized (this) {
-                    connection = HttpClient.create(url).connect();
-                }
-                try (Reader reader = connection.getContentReader()) {
+                    connection = HttpClient.create(url);
+                    connection.connect();
+                }
+                try (Reader reader = connection.getResponse().getContentReader()) {
                     InputSource inputSource = new InputSource(reader);
                     NameFinderResultParser parser = new NameFinderResultParser();
Index: trunk/src/org/openstreetmap/josm/gui/io/DownloadFileTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/DownloadFileTask.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/gui/io/DownloadFileTask.java	(revision 9309)
@@ -69,5 +69,5 @@
 
     private boolean canceled;
-    private HttpClient.Response downloadConnection;
+    private HttpClient downloadConnection;
 
     private synchronized void closeConnectionIfNeeded() {
@@ -103,6 +103,7 @@
             long size;
             synchronized (this) {
-                downloadConnection = HttpClient.create(url).useCache(false).connect();
-                size = downloadConnection.getContentLength();
+                downloadConnection = HttpClient.create(url).useCache(false);
+                downloadConnection.connect();
+                size = downloadConnection.getResponse().getContentLength();
             }
 
@@ -111,5 +112,5 @@
 
             try (
-                InputStream in = downloadConnection.getContent();
+                InputStream in = downloadConnection.getResponse().getContent();
                 OutputStream out = new FileOutputStream(file)
             ) {
Index: trunk/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/gui/oauth/OsmOAuthAuthorizationClient.java	(revision 9309)
@@ -44,5 +44,5 @@
     private final OAuthProvider provider;
     private boolean canceled;
-    private HttpClient.Response connection;
+    private HttpClient connection;
 
     private static class SessionId {
@@ -183,5 +183,5 @@
 
     protected String extractToken() {
-        try (BufferedReader r = connection.getContentReader()) {
+        try (BufferedReader r = connection.getResponse().getContentReader()) {
             String c;
             Pattern p = Pattern.compile(".*authenticity_token.*value=\"([^\"]+)\".*");
@@ -200,5 +200,5 @@
 
     protected SessionId extractOsmSession() {
-        List<String> setCookies = connection.getHeaderFields().get("Set-Cookie");
+        List<String> setCookies = connection.getResponse().getHeaderFields().get("Set-Cookie");
         if (setCookies == null)
             // no cookies set
@@ -293,5 +293,6 @@
             URL url = new URL(sb.toString());
             synchronized (this) {
-                connection = HttpClient.create(url).connect();
+                connection = HttpClient.create(url);
+                connection.connect();
             }
             SessionId sessionId = extractOsmSession();
@@ -322,6 +323,6 @@
             synchronized (this) {
                 connection = HttpClient.create(url)
-                        .setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName)
-                        .connect();
+                        .setHeader("Cookie", "_osm_session=" + sessionId.id + "; _osm_username=" + sessionId.userName);
+                connection.connect();
             }
             sessionId.token = extractToken();
@@ -357,5 +358,6 @@
 
             synchronized (this) {
-                connection = client.connect();
+                connection = client;
+                connection.connect();
             }
 
@@ -364,5 +366,5 @@
             // an error page is sent to back to the user.
             //
-            int retCode = connection.getResponseCode();
+            int retCode = connection.getResponse().getResponseCode();
             if (retCode != HttpURLConnection.HTTP_MOVED_TEMP)
                 throw new OsmOAuthAuthorizationException(tr("Failed to authenticate user ''{0}'' with password ''***'' as OAuth user",
@@ -383,5 +385,6 @@
             URL url = new URL(buildOsmLogoutUrl());
             synchronized (this) {
-                connection = HttpClient.create(url).setMaxRedirects(-1).connect();
+                connection = HttpClient.create(url).setMaxRedirects(-1);
+                connection.connect();
             }
         } catch (IOException e) {
@@ -432,8 +435,9 @@
 
             synchronized (this) {
-                connection = client.connect();
-            }
-
-            int retCode = connection.getResponseCode();
+                connection = client;
+                connection.connect();
+            }
+
+            int retCode = connection.getResponse().getResponseCode();
             if (retCode != HttpURLConnection.HTTP_OK)
                 throw new OsmOAuthAuthorizationException(tr("Failed to authorize OAuth request  ''{0}''", requestToken.getKey()));
Index: trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java	(revision 9309)
@@ -46,5 +46,5 @@
     private final Component parent;
     private final String apiUrl;
-    private HttpClient.Response connection;
+    private HttpClient connection;
 
     /**
@@ -107,18 +107,20 @@
             sign(client);
             synchronized (this) {
-                connection = client.connect();
+                connection = client;
+                connection.connect();
             }
 
-            if (connection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
+            if (connection.getResponse().getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
                 throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED,
                         tr("Retrieving user details with Access Token Key ''{0}'' was rejected.", token.getKey()), null);
 
-            if (connection.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN)
+            if (connection.getResponse().getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN)
                 throw new OsmApiException(HttpURLConnection.HTTP_FORBIDDEN,
                         tr("Retrieving user details with Access Token Key ''{0}'' was forbidden.", token.getKey()), null);
 
-            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
-                throw new OsmApiException(connection.getResponseCode(), connection.getHeaderField("Error"), null);
-            Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(connection.getContent());
+            if (connection.getResponse().getResponseCode() != HttpURLConnection.HTTP_OK)
+                throw new OsmApiException(connection.getResponse().getResponseCode(),
+                        connection.getResponse().getHeaderField("Error"), null);
+            Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(connection.getResponse().getContent());
             return OsmServerUserInfoReader.buildFromXML(d);
         } catch (SAXException | ParserConfigurationException e) {
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/ApiUrlTestTask.java	(revision 9309)
@@ -36,5 +36,5 @@
     private boolean success;
     private final Component parent;
-    private HttpClient.Response connection;
+    private HttpClient connection;
 
     /**
@@ -177,14 +177,15 @@
 
             synchronized (this) {
-                connection = HttpClient.create(capabilitiesUrl).connect();
-            }
-
-            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                alertInvalidServerResult(connection.getResponseCode());
+                connection = HttpClient.create(capabilitiesUrl);
+                connection.connect();
+            }
+
+            if (connection.getResponse().getResponseCode() != HttpURLConnection.HTTP_OK) {
+                alertInvalidServerResult(connection.getResponse().getResponseCode());
                 return;
             }
 
             try {
-                Capabilities.CapabilitiesParser.parse(new InputSource(connection.getContent()));
+                Capabilities.CapabilitiesParser.parse(new InputSource(connection.getResponse().getContent()));
             } catch (SAXException | ParserConfigurationException e) {
                 Main.warn(e.getMessage());
Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 9309)
@@ -618,4 +618,5 @@
                 url = new URL(new URL(getBaseUrl()), urlSuffix);
                 final HttpClient client = HttpClient.create(url, requestMethod).keepAlive(false);
+                activeConnection = client;
                 if (fastFail) {
                     client.setConnectTimeout(1000);
@@ -640,7 +641,7 @@
                 }
 
-                activeConnection = client.connect();
-                Main.info(activeConnection.getResponseMessage());
-                int retCode = activeConnection.getResponseCode();
+                final HttpClient.Response response = client.connect();
+                Main.info(response.getResponseMessage());
+                int retCode = response.getResponseCode();
 
                 if (retCode >= 500) {
@@ -652,10 +653,10 @@
                 }
 
-                final String responseBody = activeConnection.fetchContent();
+                final String responseBody = response.fetchContent();
 
                 String errorHeader = null;
                 // Look for a detailed error message from the server
-                if (activeConnection.getHeaderField("Error") != null) {
-                    errorHeader = activeConnection.getHeaderField("Error");
+                if (response.getHeaderField("Error") != null) {
+                    errorHeader = response.getHeaderField("Error");
                     Main.error("Error header: " + errorHeader);
                 } else if (retCode != HttpURLConnection.HTTP_OK && responseBody.length() > 0) {
Index: trunk/src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 9309)
@@ -31,5 +31,5 @@
 public class OsmConnection {
     protected boolean cancel;
-    protected HttpClient.Response activeConnection;
+    protected HttpClient activeConnection;
     protected OAuthParameters oauthParameters;
 
Index: trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 9309)
@@ -123,4 +123,5 @@
 
             final HttpClient client = HttpClient.create(url);
+            activeConnection = client;
             client.setReasonForRequest(reason);
             adaptRequest(client);
@@ -131,6 +132,7 @@
                 throw new OsmTransferCanceledException("Operation canceled");
 
+            final HttpClient.Response response;
             try {
-                activeConnection = client.connect(progressMonitor);
+                response = client.connect(progressMonitor);
             } catch (Exception e) {
                 Main.error(e);
@@ -141,23 +143,23 @@
             }
             try {
-                if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
+                if (response.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED)
                     throw new OsmApiException(HttpURLConnection.HTTP_UNAUTHORIZED, null, null);
 
-                if (activeConnection.getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH)
+                if (response.getResponseCode() == HttpURLConnection.HTTP_PROXY_AUTH)
                     throw new OsmTransferCanceledException("Proxy Authentication Required");
 
-                if (activeConnection.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                    String errorHeader = activeConnection.getHeaderField("Error");
+                if (response.getResponseCode() != HttpURLConnection.HTTP_OK) {
+                    String errorHeader = response.getHeaderField("Error");
                     String errorBody;
                     try {
-                        errorBody = activeConnection.fetchContent();
+                        errorBody = response.fetchContent();
                     } catch (Exception e) {
                         errorBody = tr("Reading error text failed.");
                     }
-                    throw new OsmApiException(activeConnection.getResponseCode(), errorHeader, errorBody, url.toString());
+                    throw new OsmApiException(response.getResponseCode(), errorHeader, errorBody, url.toString());
                 }
 
-                activeConnection.uncompressAccordingToContentDisposition(uncompressAccordingToContentDisposition);
-                return activeConnection.getContent();
+                response.uncompressAccordingToContentDisposition(uncompressAccordingToContentDisposition);
+                return response.getContent();
             } catch (OsmTransferException e) {
                 throw e;
Index: trunk/src/org/openstreetmap/josm/plugins/PluginDownloadTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginDownloadTask.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginDownloadTask.java	(revision 9309)
@@ -44,5 +44,5 @@
     private final Collection<PluginInformation> downloaded = new LinkedList<>();
     private boolean canceled;
-    private HttpClient.Response downloadConnection;
+    private HttpClient downloadConnection;
 
     /**
@@ -124,8 +124,8 @@
             synchronized (this) {
                 downloadConnection = HttpClient.create(url)
-                        .setAccept(PLUGIN_MIME_TYPES)
-                        .connect();
-            }
-            try (InputStream in = downloadConnection.getContent()) {
+                        .setAccept(PLUGIN_MIME_TYPES);
+                downloadConnection.connect();
+            }
+            try (InputStream in = downloadConnection.getResponse().getContent()) {
                 Files.copy(in, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
             }
Index: trunk/src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/plugins/ReadRemotePluginInformationTask.java	(revision 9309)
@@ -51,5 +51,5 @@
     private Collection<String> sites;
     private boolean canceled;
-    private HttpClient.Response connection;
+    private HttpClient connection;
     private List<PluginInformation> availablePlugins;
     private boolean displayErrMsg;
@@ -157,7 +157,8 @@
 
             URL url = new URL(site);
-            connection = HttpClient.create(url).useCache(false).connect();
-            content = connection.fetchContent();
-            if (connection.getResponseCode() != 200) {
+            connection = HttpClient.create(url).useCache(false);
+            final HttpClient.Response response = connection.connect();
+            content = response.fetchContent();
+            if (response.getResponseCode() != 200) {
                 throw new IOException(tr("Unsuccessful HTTP request"));
             }
Index: trunk/src/org/openstreetmap/josm/tools/HttpClient.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/HttpClient.java	(revision 9308)
+++ trunk/src/org/openstreetmap/josm/tools/HttpClient.java	(revision 9309)
@@ -47,4 +47,6 @@
     private boolean useCache;
     private String reasonForRequest;
+    private transient HttpURLConnection connection; // to allow disconnecting before `response` is set
+    private transient Response response;
 
     private HttpClient(URL url, String requestMethod) {
@@ -75,4 +77,5 @@
         }
         final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        this.connection = connection;
         connection.setRequestMethod(requestMethod);
         connection.setRequestProperty("User-Agent", Version.getInstance().getFullAgentString());
@@ -148,5 +151,5 @@
                 }
             }
-            Response response = new Response(connection, progressMonitor);
+            response = new Response(connection, progressMonitor);
             successfulConnection = true;
             return response;
@@ -156,4 +159,15 @@
             }
         }
+    }
+
+    /**
+     * Returns the HTTP response which is set only after calling {@link #connect()}.
+     * Calling this method again, returns the identical object (unless another {@link #connect()} is performed).
+     *
+     * @return the HTTP response
+     * @since 9309
+     */
+    public Response getResponse() {
+        return response;
     }
 
@@ -381,15 +395,5 @@
          */
         public void disconnect() {
-            // TODO is this block necessary for disconnecting?
-            // Fix upload aborts - see #263
-            connection.setConnectTimeout(100);
-            connection.setReadTimeout(100);
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException ex) {
-                Main.warn("InterruptedException in " + getClass().getSimpleName() + " during cancel");
-            }
-
-            connection.disconnect();
+            HttpClient.disconnect(connection);
         }
     }
@@ -611,3 +615,23 @@
         }
     }
+
+    /**
+     * @see HttpURLConnection#disconnect()
+     * @since 9309
+     */
+    public void disconnect() {
+        HttpClient.disconnect(connection);
+    }
+
+    private static void disconnect(final HttpURLConnection connection) {
+        // Fix upload aborts - see #263
+        connection.setConnectTimeout(100);
+        connection.setReadTimeout(100);
+        try {
+            Thread.sleep(100);
+        } catch (InterruptedException ex) {
+            Main.warn("InterruptedException in " + HttpClient.class + " during cancel");
+        }
+        connection.disconnect();
+    }
 }
