private CloseableHttpClient getHttpClient()

in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/KyuubiConnection.java [435:606]


  private CloseableHttpClient getHttpClient(Boolean useSsl) throws SQLException {
    boolean isCookieEnabled = isCookieEnabled();
    String cookieName = sessConfMap.getOrDefault(COOKIE_NAME, DEFAULT_COOKIE_NAMES_HS2);
    CookieStore cookieStore = isCookieEnabled ? new BasicCookieStore() : null;
    // Request interceptor for any request pre-processing logic
    Map<String, String> additionalHttpHeaders = new HashMap<>();
    Map<String, String> customCookies = new HashMap<>();

    // Retrieve the additional HttpHeaders
    for (Map.Entry<String, String> entry : sessConfMap.entrySet()) {
      String key = entry.getKey();

      if (key.startsWith(HTTP_HEADER_PREFIX)) {
        additionalHttpHeaders.put(key.substring(HTTP_HEADER_PREFIX.length()), entry.getValue());
      }
      if (key.startsWith(HTTP_COOKIE_PREFIX)) {
        customCookies.put(key.substring(HTTP_COOKIE_PREFIX.length()), entry.getValue());
      }
    }

    HttpRequestInterceptor requestInterceptor;
    if (!isSaslAuthMode()) {
      requestInterceptor = null;
    } else if (isPlainSaslAuthMode()) {
      if (isJwtAuthMode()) {
        final String signedJwt = getJWT();
        Preconditions.checkArgument(
            signedJwt != null && !signedJwt.isEmpty(),
            "For jwt auth mode," + " a signed jwt must be provided");
        /*
         * Add an interceptor to pass jwt token in the header. In https mode, the entire
         * information is encrypted
         */
        requestInterceptor =
            new HttpJwtAuthRequestInterceptor(
                signedJwt, cookieStore, cookieName, useSsl, additionalHttpHeaders, customCookies);
      } else {
        /*
         * Add an interceptor to pass username/password in the header. In https mode, the entire
         * information is encrypted
         */
        requestInterceptor =
            new HttpBasicAuthInterceptor(
                getUserName(),
                getPassword(),
                cookieStore,
                cookieName,
                useSsl,
                additionalHttpHeaders,
                customCookies);
      }
    } else {
      // Configure http client for kerberos-based authentication
      Subject subject = createSubject();
      /*
       * Add an interceptor which sets the appropriate header in the request. It does the kerberos
       * authentication and get the final service ticket, for sending to the server before every
       * request. In https mode, the entire information is encrypted
       */
      requestInterceptor =
          new HttpKerberosRequestInterceptor(
              sessConfMap.get(AUTH_PRINCIPAL),
              host,
              subject,
              cookieStore,
              cookieName,
              useSsl,
              additionalHttpHeaders,
              customCookies);
    }
    HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

    // Set timeout
    RequestConfig config =
        RequestConfig.custom()
            .setConnectTimeout(connectTimeout)
            .setSocketTimeout(socketTimeout)
            .build();
    httpClientBuilder.setDefaultRequestConfig(config);

    // Configure http client for cookie based authentication
    if (isCookieEnabled) {
      // Create a http client with a retry mechanism when the server returns a status code of 401.
      httpClientBuilder.setServiceUnavailableRetryStrategy(
          new ServiceUnavailableRetryStrategy() {
            @Override
            public boolean retryRequest(
                final HttpResponse response, final int executionCount, final HttpContext context) {
              int statusCode = response.getStatusLine().getStatusCode();
              boolean ret = statusCode == 401 && executionCount <= 1;

              // Set the context attribute to true which will be interpreted by the request
              // interceptor
              if (ret) {
                context.setAttribute(HIVE_SERVER2_RETRY_KEY, HIVE_SERVER2_RETRY_TRUE);
              }
              return ret;
            }

            @Override
            public long getRetryInterval() {
              // Immediate retry
              return 0;
            }
          });
    }
    // In case the server's idletimeout is set to a lower value, it might close it's side of
    // connection. However we retry one more time on NoHttpResponseException
    httpClientBuilder.setRetryHandler(
        (exception, executionCount, context) -> {
          if (executionCount > 1) {
            LOG.info("Retry attempts to connect to server exceeded.");
            return false;
          }
          if (exception instanceof NoHttpResponseException) {
            LOG.info("Could not connect to the server. Retrying one more time.");
            return true;
          }
          return false;
        });

    // Add the request interceptor to the client builder
    httpClientBuilder.addInterceptorFirst(requestInterceptor);

    // Add an interceptor to add in an XSRF header
    httpClientBuilder.addInterceptorLast(new HttpXsrfRequestInterceptor());

    // Configure http client for SSL
    if (useSsl) {
      String useTwoWaySSL = sessConfMap.get(USE_TWO_WAY_SSL);
      String sslTrustStorePath = sessConfMap.get(SSL_TRUST_STORE);
      String sslTrustStorePassword =
          Utils.getPassword(sessConfMap, JdbcConnectionParams.SSL_TRUST_STORE_PASSWORD);
      KeyStore sslTrustStore;
      SSLConnectionSocketFactory socketFactory;
      SSLContext sslContext;
      /*
       * The code within the try block throws: SSLInitializationException, KeyStoreException,
       * IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException &
       * UnrecoverableKeyException. We don't want the client to retry on any of these, hence we
       * catch all and throw a SQLException.
       */
      try {
        if (useTwoWaySSL != null && useTwoWaySSL.equalsIgnoreCase(TRUE)) {
          socketFactory = getTwoWaySSLSocketFactory();
        } else if (sslTrustStorePath == null || sslTrustStorePath.isEmpty()) {
          // Create a default socket factory based on standard JSSE trust material
          socketFactory = SSLConnectionSocketFactory.getSocketFactory();
        } else {
          // Pick trust store config from the given path
          sslTrustStore = KeyStore.getInstance(SSL_TRUST_STORE_TYPE);
          try (FileInputStream fis = new FileInputStream(sslTrustStorePath)) {
            sslTrustStore.load(
                fis, sslTrustStorePassword != null ? sslTrustStorePassword.toCharArray() : null);
          }
          sslContext = SSLContexts.custom().loadTrustMaterial(sslTrustStore, null).build();
          socketFactory =
              new SSLConnectionSocketFactory(sslContext, new DefaultHostnameVerifier(null));
        }
        final Registry<ConnectionSocketFactory> registry =
            RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", socketFactory)
                .build();
        httpClientBuilder.setConnectionManager(new BasicHttpClientConnectionManager(registry));
      } catch (Exception e) {
        String msg =
            "Could not create an https connection to " + jdbcUriString + ". " + e.getMessage();
        throw new KyuubiSQLException(msg, "08S01", e);
      }
    }
    return httpClientBuilder.build();
  }