|
23 | 23 | import java.io.InputStream; |
24 | 24 | import java.net.CookieManager; |
25 | 25 | import java.net.CookiePolicy; |
26 | | -import java.net.HttpURLConnection; |
| 26 | +import java.net.InetSocketAddress; |
| 27 | +import java.net.ProxySelector; |
| 28 | +import java.net.http.HttpClient; |
27 | 29 | import java.nio.file.Files; |
28 | 30 | import java.nio.file.Path; |
29 | 31 | import java.nio.file.StandardOpenOption; |
30 | 32 | import java.security.KeyStore; |
31 | 33 | import java.security.KeyStoreException; |
32 | 34 | import java.security.NoSuchAlgorithmException; |
33 | 35 | import java.security.cert.CertificateException; |
34 | | -import java.util.Optional; |
35 | | -import java.util.concurrent.TimeUnit; |
36 | 36 | import javax.annotation.Nullable; |
37 | 37 | import nl.altindag.ssl.SSLFactory; |
38 | 38 | import nl.altindag.ssl.exception.GenericKeyStoreException; |
39 | 39 | import nl.altindag.ssl.util.KeyStoreUtils; |
40 | | -import okhttp3.ConnectionSpec; |
41 | | -import okhttp3.Credentials; |
42 | | -import okhttp3.JavaNetCookieJar; |
43 | | -import okhttp3.OkHttpClient; |
44 | | -import okhttp3.logging.HttpLoggingInterceptor; |
45 | 40 | import org.bouncycastle.jce.provider.BouncyCastleProvider; |
46 | 41 | import org.bouncycastle.util.Properties; |
47 | 42 | import org.slf4j.Logger; |
48 | 43 | import org.slf4j.LoggerFactory; |
49 | 44 | import org.sonarsource.scanner.lib.internal.http.ssl.CertificateStore; |
50 | 45 | import org.sonarsource.scanner.lib.internal.http.ssl.SslConfig; |
51 | 46 |
|
52 | | -import static java.nio.charset.StandardCharsets.UTF_8; |
53 | | -import static java.util.Arrays.asList; |
54 | | -import static org.apache.commons.lang3.StringUtils.isNotBlank; |
55 | 47 | import static org.sonarsource.scanner.lib.ScannerProperties.SONAR_SCANNER_SKIP_SYSTEM_TRUSTSTORE; |
56 | 48 |
|
57 | | -public class OkHttpClientFactory { |
| 49 | +public class HttpClientFactory { |
58 | 50 |
|
59 | | - private static final Logger LOG = LoggerFactory.getLogger(OkHttpClientFactory.class); |
| 51 | + private static final Logger LOG = LoggerFactory.getLogger(HttpClientFactory.class); |
60 | 52 |
|
61 | 53 | static final CookieManager COOKIE_MANAGER; |
62 | | - private static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; |
63 | | - // use the same cookie jar for all instances |
64 | | - private static final JavaNetCookieJar COOKIE_JAR; |
65 | | - // This property tells Bouncycastle to not fail on empty keystore passwords |
66 | 54 | public static final String BC_IGNORE_USELESS_PASSWD = "org.bouncycastle.pkcs12.ignore_useless_passwd"; |
67 | 55 |
|
68 | | - private OkHttpClientFactory() { |
69 | | - // only statics |
| 56 | + private HttpClientFactory() { |
70 | 57 | } |
71 | 58 |
|
72 | 59 | static { |
73 | 60 | COOKIE_MANAGER = new CookieManager(); |
74 | 61 | COOKIE_MANAGER.setCookiePolicy(CookiePolicy.ACCEPT_ALL); |
75 | | - COOKIE_JAR = new JavaNetCookieJar(COOKIE_MANAGER); |
76 | 62 | } |
77 | 63 |
|
78 | | - static OkHttpClient create(HttpConfig httpConfig) { |
79 | | - |
| 64 | + static HttpClient create(HttpConfig httpConfig) { |
80 | 65 | var sslContext = configureSsl(httpConfig.getSslConfig(), httpConfig.skipSystemTruststore()); |
81 | 66 |
|
82 | | - OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder() |
83 | | - .connectTimeout(httpConfig.getConnectTimeout().toMillis(), TimeUnit.MILLISECONDS) |
84 | | - .readTimeout(httpConfig.getSocketTimeout().toMillis(), TimeUnit.MILLISECONDS) |
85 | | - .callTimeout(httpConfig.getResponseTimeout().toMillis(), TimeUnit.MILLISECONDS) |
86 | | - .cookieJar(COOKIE_JAR) |
87 | | - .sslSocketFactory(sslContext.getSslSocketFactory(), sslContext.getTrustManager().orElseThrow()); |
88 | | - |
89 | | - ConnectionSpec tls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) |
90 | | - .allEnabledTlsVersions() |
91 | | - .allEnabledCipherSuites() |
92 | | - .build(); |
93 | | - okHttpClientBuilder.connectionSpecs(asList(tls, ConnectionSpec.CLEARTEXT)); |
| 67 | + var httpClientBuilder = HttpClient.newBuilder() |
| 68 | + .connectTimeout(httpConfig.getConnectTimeout()) |
| 69 | + .cookieHandler(COOKIE_MANAGER) |
| 70 | + .sslContext(sslContext.getSslContext()) |
| 71 | + .sslParameters(sslContext.getSslParameters()) |
| 72 | + .followRedirects(HttpClient.Redirect.NEVER); |
94 | 73 |
|
95 | 74 | if (httpConfig.getProxy() != null) { |
96 | | - okHttpClientBuilder.proxy(httpConfig.getProxy()); |
97 | | - } |
98 | | - |
99 | | - if (isNotBlank(httpConfig.getProxyUser())) { |
100 | | - okHttpClientBuilder.proxyAuthenticator((route, response) -> { |
101 | | - if (response.request().header(PROXY_AUTHORIZATION) != null) { |
102 | | - // Give up, we've already attempted to authenticate. |
103 | | - return null; |
104 | | - } |
105 | | - if (HttpURLConnection.HTTP_PROXY_AUTH == response.code()) { |
106 | | - String credential = Credentials.basic(httpConfig.getProxyUser(), Optional.ofNullable(httpConfig.getProxyPassword()).orElse(""), UTF_8); |
107 | | - return response.request().newBuilder().header(PROXY_AUTHORIZATION, credential).build(); |
108 | | - } |
109 | | - return null; |
110 | | - }); |
| 75 | + var proxyAddress = httpConfig.getProxy().address(); |
| 76 | + if (proxyAddress instanceof InetSocketAddress) { |
| 77 | + httpClientBuilder.proxy(ProxySelector.of((InetSocketAddress) proxyAddress)); |
| 78 | + } |
111 | 79 | } |
112 | 80 |
|
113 | | - var logging = new HttpLoggingInterceptor(LOG::debug); |
114 | | - logging.setLevel(HttpLoggingInterceptor.Level.BASIC); |
115 | | - okHttpClientBuilder.addInterceptor(logging); |
116 | | - |
117 | | - return okHttpClientBuilder.build(); |
| 81 | + return httpClientBuilder.build(); |
118 | 82 | } |
119 | 83 |
|
120 | 84 | private static SSLFactory configureSsl(SslConfig sslConfig, boolean skipSystemTrustMaterial) { |
|
0 commit comments