public void setConf()

in src/plugin/protocol-okhttp/src/java/org/apache/nutch/protocol/okhttp/OkHttp.java [100:268]


  public void setConf(Configuration conf) {
    super.setConf(conf);

    // protocols in order of preference
    List<okhttp3.Protocol> protocols = new ArrayList<>();
    if (this.useHttp2) {
      protocols.add(okhttp3.Protocol.HTTP_2);
    }
    protocols.add(okhttp3.Protocol.HTTP_1_1);

    okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder()
        .protocols(protocols) //
        .retryOnConnectionFailure(true) //
        .followRedirects(false) //
        .connectTimeout(this.timeout, TimeUnit.MILLISECONDS)
        .writeTimeout(this.timeout, TimeUnit.MILLISECONDS)
        .readTimeout(this.timeout, TimeUnit.MILLISECONDS);

    if (!this.tlsCheckCertificate) {
      try {
        SSLContext trustAllSslContext = SSLContext.getInstance("TLS");
        trustAllSslContext.init(null, trustAllCerts, null);
        SSLSocketFactory trustAllSslSocketFactory = trustAllSslContext
            .getSocketFactory();
        builder.sslSocketFactory(trustAllSslSocketFactory,
            (X509TrustManager) trustAllCerts[0]);
      } catch (Exception e) {
        LOG.error(
            "Failed to disable TLS certificate verification (property http.tls.certificates.check)",
            e);
      }
      builder.hostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
          return true;
        }
      });
    }

    if (!this.accept.isEmpty()) {
      getCustomRequestHeaders().add(new String[] { "Accept", this.accept });
    }

    if (!this.acceptLanguage.isEmpty()) {
      getCustomRequestHeaders()
          .add(new String[] { "Accept-Language", this.acceptLanguage });
    }

    if (!this.acceptCharset.isEmpty()) {
      getCustomRequestHeaders()
          .add(new String[] { "Accept-Charset", this.acceptCharset });
    }

    if (this.useProxy) {
      Proxy proxy = new Proxy(this.proxyType,
          new InetSocketAddress(this.proxyHost, this.proxyPort));
      String proxyUsername = conf.get("http.proxy.username");
      if (proxyUsername == null) {
        ProxySelector selector = new ProxySelector() {
          @SuppressWarnings("serial")
          private final List<Proxy> noProxyList = new ArrayList<Proxy>() {
            {
              add(Proxy.NO_PROXY);
            }
          };
          @SuppressWarnings("serial")
          private final List<Proxy> proxyList = new ArrayList<Proxy>() {
            {
              add(proxy);
            }
          };

          @Override
          public List<Proxy> select(URI uri) {
            if (useProxy(uri)) {
              return this.proxyList;
            }
            return this.noProxyList;
          }

          @Override
          public void connectFailed(URI uri, SocketAddress sa,
              IOException ioe) {
            LOG.error("Connection to proxy failed for {}: {}", uri, ioe);
          }
        };
        builder.proxySelector(selector);
      } else {
        /*
         * NOTE: the proxy exceptions list does NOT work with proxy
         * username/password because an okhttp3 bug
         * (https://github.com/square/okhttp/issues/3995) when using the
         * ProxySelector class with proxy auth. If a proxy username is present,
         * the configured proxy will be used for ALL requests.
         */
        if (this.proxyException.size() > 0) {
          LOG.warn(
              "protocol-okhttp does not respect 'http.proxy.exception.list' setting when "
                  + "'http.proxy.username' is set. This is a limitation of the current okhttp3 "
                  + "implementation, see NUTCH-2636");
        }
        builder.proxy(proxy);
        String proxyPassword = conf.get("http.proxy.password");
        Authenticator proxyAuthenticator = new Authenticator() {
          @Override
          public Request authenticate(okhttp3.Route route,
              okhttp3.Response response) throws IOException {
            String credential = okhttp3.Credentials.basic(proxyUsername,
                proxyPassword);
            return response.request().newBuilder()
                .header("Proxy-Authorization", credential).build();
          }
        };
        builder.proxyAuthenticator(proxyAuthenticator);
      }
    }

    IPFilterRules ipFilterRules = new IPFilterRules(conf);
    if (!ipFilterRules.isEmpty()) {
      builder.addNetworkInterceptor(new HTTPFilterIPAddressInterceptor(ipFilterRules));
    }

    if (this.storeIPAddress || this.storeHttpHeaders || this.storeHttpRequest
        || this.storeProtocolVersions) {
      builder.addNetworkInterceptor(new HTTPHeadersInterceptor());
    }

    // enable support for Brotli compression (Content-Encoding)
    builder.addInterceptor(BrotliInterceptor.INSTANCE);

    // instantiate connection pool(s), cf.
    // https://square.github.io/okhttp/3.x/okhttp/okhttp3/ConnectionPool.html
    int numConnectionPools = 1;
    Supplier<ConnectionPool> poolSupplier = null;
    if (conf.get("http.connection.pool.okhttp", "").isEmpty()) {
      // empty pool configuration: use a single pool of default size
    } else {
      int[] poolConfig = {};
      try {
        poolConfig = conf.getInts("http.connection.pool.okhttp");
      } catch (NumberFormatException e) {
        // will show warning below
      }
      if (poolConfig.length == 3 && poolConfig[0] > 0
          && poolConfig[1] > 0 && poolConfig[2] > 0) {
        numConnectionPools = poolConfig[0];
        int size = poolConfig[1];
        int time = poolConfig[2];
        poolSupplier = () -> new ConnectionPool(size, time, TimeUnit.SECONDS);
        LOG.info(
            "Using {} connection pool{} with max. {} idle connections "
                + "and {} sec. connection keep-alive time",
            poolConfig[0], (poolConfig[0] > 1 ? "s" : ""), poolConfig[1],
            poolConfig[2]);
      } else {
        LOG.warn(
            "Ignoring invalid connection pool configuration 'http.connection.pool.okhttp': '{}'",
            conf.get("http.connection.pool.okhttp"));
      }
    }
    if (poolSupplier == null) {
      poolSupplier = ConnectionPool::new;
      LOG.info("Using single connection pool with default settings");
    }
    this.clients = new OkHttpClient[numConnectionPools];
    for (int i = 0; i < numConnectionPools; i++) {
      this.clients[i] = builder.connectionPool(poolSupplier.get()).build();
    }
  }