docs: private CloseableHttpResponse openConnection(HttpHost httpHost, String file,
              long timestamp, String etag, CloseableHttpClient client) throws IOException {
          //perform preemptive authentication
          HttpClientContext context = null;
          if ((username != null && password != null) || credentials != null) {
              context = HttpClientContext.create();
              AuthScheme as = authScheme;
              if (as == null) {
                  as = new BasicScheme();
              }
              Credentials c;
              if (username != null && password != null) {
                  if (!(as instanceof BasicScheme) && !(as instanceof DigestScheme)) {
                      throw new IllegalArgumentException("If 'username' and "
                              + "'password' are set 'authScheme' must be either "
                              + "'Basic' or 'Digest'.");
                  }
                  c = new UsernamePasswordCredentials(username, password);
              } else {
                  c = credentials;
              }
              addAuthentication(httpHost, c, as, context);
          }
          
          //create request
          HttpGet get = new HttpGet(file);
  
          //configure timeouts
          RequestConfig config = RequestConfig.custom()
                  .setConnectTimeout(timeoutMs)
                  .setConnectionRequestTimeout(timeoutMs)
                  .setCookieSpec(CookieSpecs.STANDARD)
                  .setSocketTimeout(timeoutMs)
                  .build();
          get.setConfig(config);
  
          //add authentication information for proxy
          String scheme = httpHost.getSchemeName();
          String proxyHost = System.getProperty(scheme + ".proxyHost");
          String proxyPort = System.getProperty(scheme + ".proxyPort");
          String proxyUser = System.getProperty(scheme + ".proxyUser");
          String proxyPassword = System.getProperty(scheme + ".proxyPassword");
          if (proxyHost != null && proxyPort != null &&
                  proxyUser != null && proxyPassword != null) {
              if (context == null) {
                  context = HttpClientContext.create();
              }
              int nProxyPort = Integer.parseInt(proxyPort);
              HttpHost proxy = new HttpHost(proxyHost, nProxyPort, scheme);
              Credentials credentials = new UsernamePasswordCredentials(
                      proxyUser, proxyPassword);
              addAuthentication(proxy, credentials, null, context);
          }
          
          //set If-Modified-Since header
          if (timestamp > 0) {
              get.setHeader("If-Modified-Since", DateUtils.formatDate(new Date(timestamp)));
          }
          
          //set If-None-Match header
          if (etag != null) {
              get.setHeader("If-None-Match", etag);
          }
          
          //set headers
          if (headers != null) {
              for (Map.Entry<String, String> headerEntry : headers.entrySet()) {
                  get.addHeader(headerEntry.getKey(), headerEntry.getValue());
              }
          }
          
          //enable compression
          if (compress) {
              get.setHeader("Accept-Encoding", "gzip");
          }
          
          //execute request
          CloseableHttpResponse response = client.execute(httpHost, get, context);
          
          //handle response
          int code = response.getStatusLine().getStatusCode();
          if ((code < 200 || code > 299) && code != HttpStatus.SC_NOT_MODIFIED) {
              String phrase = response.getStatusLine().getReasonPhrase();
              if (phrase == null || phrase.isEmpty()) {
                  phrase = "HTTP status code " + code;
              } else {
                  phrase += " (HTTP status code " + code + ")";
              }
              throw new ClientProtocolException(phrase);
          }
          
          return response;
      }