1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.caravan.commons.httpclient.impl;
21
22 import java.io.IOException;
23 import java.security.GeneralSecurityException;
24
25 import javax.net.ssl.SSLContext;
26
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.http.HttpHost;
29 import org.apache.http.auth.AuthScope;
30 import org.apache.http.auth.UsernamePasswordCredentials;
31 import org.apache.http.client.CredentialsProvider;
32 import org.apache.http.client.config.RequestConfig;
33 import org.apache.http.config.Registry;
34 import org.apache.http.config.RegistryBuilder;
35 import org.apache.http.conn.socket.ConnectionSocketFactory;
36 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
37 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
38 import org.apache.http.impl.client.BasicCredentialsProvider;
39 import org.apache.http.impl.client.CloseableHttpClient;
40 import org.apache.http.impl.client.HttpClientBuilder;
41 import org.apache.http.impl.client.ProxyAuthenticationStrategy;
42 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import io.wcm.caravan.commons.httpclient.HttpClientConfig;
49 import io.wcm.caravan.commons.httpclient.impl.helpers.CertificateLoader;
50
51
52
53
54 class HttpClientItem {
55
56 private final HttpClientConfig config;
57 private final CloseableHttpClient httpClient;
58 private final RequestConfig defaultRequestConfig;
59
60 private static final Logger log = LoggerFactory.getLogger(HttpClientItem.class);
61
62
63
64
65 HttpClientItem(@NotNull HttpClientConfig config) {
66 this.config = config;
67
68
69 SSLContext sslContext;
70 if (CertificateLoader.isSslKeyManagerEnabled(config) || CertificateLoader.isSslTrustStoreEnbaled(config)) {
71 try {
72 sslContext = CertificateLoader.buildSSLContext(config);
73 }
74 catch (IOException | GeneralSecurityException ex) {
75 throw new IllegalArgumentException("Invalid SSL client certificate configuration.", ex);
76 }
77 }
78 else {
79 sslContext = CertificateLoader.createDefaultSSlContext();
80 }
81
82 CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
83
84 if (StringUtils.isNotEmpty(config.getProxyUser())) {
85 credentialsProvider.setCredentials(new AuthScope(config.getProxyHost(), config.getProxyPort()),
86 new UsernamePasswordCredentials(config.getProxyUser(), config.getProxyPassword()));
87 }
88
89 if (StringUtils.isNotEmpty(config.getHttpUser())) {
90 credentialsProvider.setCredentials(AuthScope.ANY,
91 new UsernamePasswordCredentials(config.getHttpUser(), config.getHttpPassword()));
92 }
93
94
95 defaultRequestConfig = buildDefaultRequestConfig(config);
96
97
98 PoolingHttpClientConnectionManager connectionManager = buildConnectionManager(config, sslContext);
99 httpClient = buildHttpClient(config, connectionManager, credentialsProvider, defaultRequestConfig);
100 }
101
102 private static @NotNull RequestConfig buildDefaultRequestConfig(@NotNull HttpClientConfig config) {
103 return RequestConfig.custom()
104
105 .setConnectionRequestTimeout(config.getConnectionRequestTimeout())
106 .setConnectTimeout(config.getConnectTimeout())
107 .setSocketTimeout(config.getSocketTimeout())
108 .setCookieSpec(config.getCookieSpec())
109 .build();
110 }
111
112 private static @NotNull PoolingHttpClientConnectionManager buildConnectionManager(@NotNull HttpClientConfig config,
113 @NotNull SSLContext sslContext) {
114
115 ConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
116 Registry<ConnectionSocketFactory> schemeRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
117 .register("http", PlainConnectionSocketFactory.getSocketFactory())
118 .register("https", sslSocketFactory)
119 .build();
120
121
122 PoolingHttpClientConnectionManager conmgr = new PoolingHttpClientConnectionManager(schemeRegistry);
123 conmgr.setMaxTotal(config.getMaxTotalConnections());
124 conmgr.setDefaultMaxPerRoute(config.getMaxConnectionsPerHost());
125 return conmgr;
126 }
127
128 private static @NotNull CloseableHttpClient buildHttpClient(@NotNull HttpClientConfig config,
129 @NotNull PoolingHttpClientConnectionManager connectionManager, @NotNull CredentialsProvider credentialsProvider,
130 @NotNull RequestConfig defaultRequestConfig) {
131
132
133 HttpClientBuilder httpClientBuilder = HttpClientBuilder.create()
134 .setConnectionManager(connectionManager);
135
136 httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
137
138 httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
139
140
141 if (StringUtils.isNotEmpty(config.getProxyHost())) {
142 httpClientBuilder.setProxy(new HttpHost(config.getProxyHost(), config.getProxyPort()));
143
144
145 if (StringUtils.isNotEmpty(config.getProxyUser())) {
146 httpClientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
147 }
148 }
149
150 return httpClientBuilder.build();
151 }
152
153
154
155
156 public @NotNull CloseableHttpClient getHttpClient() {
157 return httpClient;
158 }
159
160
161
162
163 public @NotNull RequestConfig getDefaultRequestConfig() {
164 return defaultRequestConfig;
165 }
166
167
168
169
170
171
172
173
174 public boolean matches(@Nullable String hostName, @Nullable String wsAddressingToURI, @Nullable String path, boolean isWsCall) {
175 if (isWsCall) {
176 return config.isEnabled()
177 && config.matchesHost(hostName)
178 && config.matchesPath(path)
179 && config.matchesWsAddressingToUri(wsAddressingToURI);
180 }
181 else {
182 return config.isEnabled()
183 && config.matchesHost(hostName)
184 && config.matchesPath(path);
185 }
186 }
187
188
189
190
191 public void close() {
192 try {
193 httpClient.close();
194 }
195 catch (IOException ex) {
196 log.warn("Error closing HTTP client.", ex);
197 }
198 }
199
200 @Override
201 public @NotNull String toString() {
202 return "HttpClientItem[" + config.toString() + "]";
203 }
204
205 }