docs: protected HttpResponse sendImpl() throws IOException {
      HttpURLConnection con = (HttpURLConnection) uri.toURL().openConnection();
      con.setConnectTimeout(connectTimeout);
      con.setReadTimeout(readTimeout);
      con.setRequestMethod(method);
      for (Map.Entry<String, String> h : reqHeaders.entrySet()) {
        con.setRequestProperty(h.getKey(), h.getValue());
      }
      configureHTTPS(con);
  
      boolean canRetry = true;
      try {
        con.setDoInput(true);
  
        // HttpURLConnection will change method to POST if there is a body associated
        // with a GET request. Only try to write entity if it is not empty.
        entry.withRequestContentLength(entity.length).mark("start");
        if (entity.length > 0) {
          con.setDoOutput(true);
          try (OutputStream out = con.getOutputStream()) {
            out.write(entity);
          }
        }
  
        int status = con.getResponseCode();
        canRetry = (status >= 500 || status == 429);
        entry.mark("complete").withStatusCode(status);
  
        // A null key is used to return the status line, remove it before sending to
        // the log entry or creating the response object
        Map<String, List<String>> headers = new LinkedHashMap<>(con.getHeaderFields());
        headers.remove(null);
        for (Map.Entry<String, List<String>> h : headers.entrySet()) {
          for (String v : h.getValue()) {
            entry.withResponseHeader(h.getKey(), v);
          }
        }
  
        try (InputStream in = (status >= 400) ? con.getErrorStream() : con.getInputStream()) {
          byte[] data = readAll(in);
          entry.withResponseContentLength(data.length);
          return new HttpResponse(status, headers, data);
        }
      } catch (IOException e) {
        entry.mark("complete").withException(e);
        throw e;
      } finally {
        entry.withCanRetry(canRetry);
        HttpLogEntry.logClientRequest(entry);
      }
    }