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();
}
}