/**
  * Sets the timeouts of the HTTP client.
  *
  * @param connectionTimeout timeout until connection established in milliseconds. Zero means no
  *     timeout.
  * @param socketTimeout timeout for waiting for data in milliseconds. Zero means no timeout.
  * @param maxRequests maximum number of connections to a particuar host
  */
 public static void setParams(int connectionTimeout, int socketTimeout, int maxRequests) {
   PrudentHttpEntityResolver.maxRequests = maxRequests;
   PoolingHttpClientConnectionManager phcConnMgr;
   Registry<ConnectionSocketFactory> registry = //
       RegistryBuilder.<ConnectionSocketFactory>create() //
           .register("http", PlainConnectionSocketFactory.getSocketFactory()) //
           .register("https", SSLConnectionSocketFactory.getSocketFactory()) //
           .build();
   HttpClientBuilder builder = HttpClients.custom();
   builder.setRedirectStrategy(new LaxRedirectStrategy());
   builder.setMaxConnPerRoute(maxRequests);
   builder.setMaxConnTotal(200);
   if ("true".equals(System.getProperty("nu.validator.xml.promiscuous-ssl", "false"))) { //
     try {
       SSLContext promiscuousSSLContext =
           new SSLContextBuilder() //
               .loadTrustMaterial(
                   null,
                   new TrustStrategy() {
                     @Override
                     public boolean isTrusted(X509Certificate[] arg0, String arg1)
                         throws CertificateException {
                       return true;
                     }
                   })
               .build();
       builder.setSslcontext(promiscuousSSLContext);
       HostnameVerifier verifier = //
           SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
       SSLConnectionSocketFactory promiscuousSSLConnSocketFactory = //
           new SSLConnectionSocketFactory(promiscuousSSLContext, verifier);
       registry =
           RegistryBuilder.<ConnectionSocketFactory>create() //
               .register("https", promiscuousSSLConnSocketFactory) //
               .register("http", PlainConnectionSocketFactory.getSocketFactory()) //
               .build();
     } catch (KeyManagementException
         | KeyStoreException
         | NoSuchAlgorithmException
         | NumberFormatException e) {
       e.printStackTrace();
     }
   }
   phcConnMgr = new PoolingHttpClientConnectionManager(registry);
   phcConnMgr.setDefaultMaxPerRoute(maxRequests);
   phcConnMgr.setMaxTotal(200);
   builder.setConnectionManager(phcConnMgr);
   RequestConfig.Builder config = RequestConfig.custom();
   config.setCircularRedirectsAllowed(true);
   config.setMaxRedirects(20); // Gecko default
   config.setConnectTimeout(connectionTimeout);
   config.setCookieSpec(CookieSpecs.BEST_MATCH);
   config.setSocketTimeout(socketTimeout);
   client = builder.setDefaultRequestConfig(config.build()).build();
 }
  @Override
  public OutgoingRequest createOutgoingRequest(
      DriverRequest originalRequest, String uri, boolean proxy) {
    // Extract the host in the URI. This is the host we have to send the
    // request to physically.
    HttpHost physicalHost = UriUtils.extractHost(uri);

    if (!originalRequest.isExternal()) {
      if (preserveHost) {
        // Preserve host if required
        HttpHost virtualHost = HttpRequestHelper.getHost(originalRequest.getOriginalRequest());
        // Rewrite the uri with the virtualHost
        uri = UriUtils.rewriteURI(uri, virtualHost);
      } else {
        uri = UriUtils.rewriteURI(uri, firstBaseUrlHost);
      }
    }

    RequestConfig.Builder builder = RequestConfig.custom();
    builder.setConnectTimeout(connectTimeout);
    builder.setSocketTimeout(socketTimeout);

    // Use browser compatibility cookie policy. This policy is the closest
    // to the behavior of a real browser.
    builder.setCookieSpec(CustomBrowserCompatSpecFactory.CUSTOM_BROWSER_COMPATIBILITY);

    builder.setRedirectsEnabled(false);
    RequestConfig config = builder.build();

    OutgoingRequestContext context = new OutgoingRequestContext();

    String method = "GET";
    if (proxy) {
      method = originalRequest.getOriginalRequest().getRequestLine().getMethod().toUpperCase();
    }
    OutgoingRequest outgoingRequest =
        new OutgoingRequest(
            method,
            uri,
            originalRequest.getOriginalRequest().getProtocolVersion(),
            originalRequest,
            config,
            context);
    if (ENTITY_METHODS.contains(method)) {
      outgoingRequest.setEntity(originalRequest.getOriginalRequest().getEntity());
    } else if (!SIMPLE_METHODS.contains(method)) {
      throw new UnsupportedHttpMethodException(method + " " + uri);
    }

    context.setPhysicalHost(physicalHost);
    context.setOutgoingRequest(outgoingRequest);
    context.setProxy(proxy);

    return outgoingRequest;
  }