1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.util.httpaccess;
35
36
37 import org.apache.commons.lang3.StringUtils;
38 import org.apache.hc.client5.http.config.RequestConfig;
39 import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
40 import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
41 import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
42 import org.apache.hc.client5.http.impl.classic.HttpClients;
43 import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
44 import org.apache.hc.core5.http.HttpHost;
45 import org.apache.hc.core5.util.Timeout;
46
47 import fr.paris.lutece.portal.service.util.AppLogService;
48 import fr.paris.lutece.portal.service.util.AppPropertiesService;
49
50
51
52
53
54 public class HttpAccessService implements ResponseStatusValidator
55 {
56
57 private static final String DEFAULT_RESPONSE_CODE_AUTHORIZED = "200,201,202";
58
59
60 private static final String PROPERTY_PROXY_HOST = "httpAccess.proxyHost";
61
62
63 private static final String PROPERTY_PROXY_PORT = "httpAccess.proxyPort";
64
65
66 private static final String PROPERTY_PROXY_USERNAME = "httpAccess.proxyUserName";
67
68
69 private static final String PROPERTY_PROXY_PASSWORD = "httpAccess.proxyPassword";
70
71
72 private static final String PROPERTY_HOST_NAME = "httpAccess.hostName";
73
74
75 private static final String PROPERTY_DOMAIN_NAME = "httpAccess.domainName";
76
77
78 private static final String PROPERTY_REALM = "httpAccess.realm";
79
80
81 private static final String PROPERTY_NO_PROXY_FOR = "httpAccess.noProxyFor";
82
83
84 private static final String PROPERTY_CONTENT_CHARSET = "httpAccess.contentCharset";
85
86
87 private static final String PROPERTY_ELEMENT_CHARSET = "httpAccess.elementCharset";
88
89
90 private static final String PROPERTY_SOCKET_TIMEOUT = "httpAccess.socketTimeout";
91
92
93 private static final String PROPERTY_CONNECTION_TIMEOUT = "httpAccess.connectionTimeout";
94
95
96 private static final String PROPERTY_CONNECTION_POOL_ENABLED = "httpAccess.connectionPoolEnabled";
97
98
99 private static final String PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION = "httpAccess.connectionPoolMaxTotalConnections";
100
101
102 private static final String PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION_PER_HOST = "httpAccess.connectionPoolMaxConnectionsPerHost";
103
104
105 private static final String PROPERTY_HTTP_RESPONSES_CODE_AUTHORIZED = "httpAccess.responsesCodeAuthorized";
106
107
108 private static final String PROPERTY_HTTP_PROTOCOLE_CONTENT_CHARSET = "http.protocol.content-charset";
109
110
111 private static final String PROPERTY_HTTP_PROTOCOLE_ELEMENT_CHARSET = "http.protocol.element-charset";
112
113
114 private static HttpAccessService _singleton;
115
116 private HttpClientConfiguration _httpClientConfiguration;
117
118
119 private PoolingHttpClientConnectionManager _connectionManager;
120
121 private CloseableHttpClient _httpClient;
122
123
124 public HttpClientConfiguration getHttpClientConfiguration() {
125 return _httpClientConfiguration;
126 }
127
128
129
130
131 private static final String SEPARATOR = ",";
132
133 private ResponseStatusValidator _responseValidator;
134
135
136
137
138
139
140 public static HttpAccessService getInstance( )
141 {
142 if ( _singleton == null )
143 {
144 _singleton = new HttpAccessService( );
145
146 _singleton.init( );
147 _singleton._responseValidator = SimpleResponseValidator.loadFromProperty( PROPERTY_HTTP_RESPONSES_CODE_AUTHORIZED, DEFAULT_RESPONSE_CODE_AUTHORIZED );
148 }
149
150 return _singleton;
151 }
152
153
154
155
156 public HttpAccessService(HttpClientConfiguration httpClienConfiguration)
157 {
158 super();
159 _httpClientConfiguration=httpClienConfiguration;
160
161 }
162
163 private HttpAccessService( )
164 {
165
166 }
167
168
169
170
171
172
173
174
175
176 public synchronized CloseableHttpClient getHttpClient( String strTargetHost)
177 {
178
179
180 HttpClientBuilder clientBuilder = HttpClients.custom();
181
182
183
184
185 if ( StringUtils.isNotBlank( _httpClientConfiguration.getProxyHost() ) )
186 {
187 boolean bNoProxy = ( StringUtils.isNotBlank( _httpClientConfiguration.getNoProxyFor() ) && matchesList( _httpClientConfiguration.getNoProxyFor().split( SEPARATOR ), strTargetHost) );
188 if(!bNoProxy && StringUtils.isNotBlank( _httpClientConfiguration.getProxyPort() ) && StringUtils.isNumeric( _httpClientConfiguration.getProxyPort() ))
189 {
190 final HttpHost proxy = new HttpHost("http", _httpClientConfiguration.getProxyHost(),Integer.parseInt( _httpClientConfiguration.getProxyPort()));
191 clientBuilder.setProxy(proxy);
192 }
193
194 }
195
196 if ( _httpClientConfiguration.isConnectionPoolEnabled() )
197 {
198
199 if(_connectionManager==null)
200 {
201 _connectionManager= new PoolingHttpClientConnectionManager();
202
203 if (_httpClientConfiguration.getConnectionPoolMaxConnectionPerHost() !=null )
204 {
205 _connectionManager.setDefaultMaxPerRoute(_httpClientConfiguration.getConnectionPoolMaxConnectionPerHost());
206
207
208 }
209
210 if ( _httpClientConfiguration.getConnectionPoolMaxTotalConnection() !=null )
211 {
212 _connectionManager.setMaxTotal( _httpClientConfiguration.getConnectionPoolMaxTotalConnection() );
213 }
214
215 }
216 clientBuilder.setConnectionManager(_connectionManager);
217 clientBuilder.setConnectionManagerShared(true);
218
219 }
220
221 if ( _httpClientConfiguration.getSocketTimeout() != null || _httpClientConfiguration.getConnectionTimeout() != null )
222 {
223 RequestConfig.Builder requestConfiguilder = RequestConfig.custom();
224 if( _httpClientConfiguration.getConnectionTimeout()!=null)
225 {
226 requestConfiguilder.setConnectTimeout(Timeout.ofMilliseconds( _httpClientConfiguration.getConnectionTimeout() ));
227
228 }
229
230 if( _httpClientConfiguration.getSocketTimeout() != null )
231 {
232
233 requestConfiguilder.setResponseTimeout(Timeout.ofMilliseconds( _httpClientConfiguration.getSocketTimeout() ));
234
235
236 }
237 clientBuilder.setDefaultRequestConfig(requestConfiguilder.build());
238
239 clientBuilder.setRedirectStrategy(DefaultRedirectStrategy.INSTANCE);
240 }
241
242
243
244 _httpClient =clientBuilder.build();
245
246
247 return _httpClient;
248 }
249
250
251
252
253
254
255
256
257
258
259 private boolean matchesList( String [ ] listPatterns, String strText )
260 {
261 if ( listPatterns == null )
262 {
263 return false;
264 }
265
266 for ( String pattern : listPatterns )
267 {
268 if ( matches( pattern, strText ) )
269 {
270 return true;
271 }
272 }
273
274 return false;
275 }
276
277
278
279
280
281
282
283
284
285
286 private static boolean matches( String strPattern, String strText )
287 {
288 String strTextTmp = strText + '\0';
289 String strPatternTmp = strPattern + '\0';
290
291 int nLength = strPatternTmp.length( );
292
293 boolean [ ] states = new boolean [ nLength + 1];
294 boolean [ ] old = new boolean [ nLength + 1];
295 old [0] = true;
296
297 for ( int i = 0; i < strTextTmp.length( ); i++ )
298 {
299 char c = strTextTmp.charAt( i );
300 states = new boolean [ nLength + 1];
301
302 for ( int j = 0; j < nLength; j++ )
303 {
304 char p = strPatternTmp.charAt( j );
305
306 if ( old [j] && ( p == '*' ) )
307 {
308 old [j + 1] = true;
309 }
310
311 if ( old [j] && ( p == c ) )
312 {
313 states [j + 1] = true;
314 }
315
316 if ( old [j] && ( p == '?' ) )
317 {
318 states [j + 1] = true;
319 }
320
321 if ( old [j] && ( p == '*' ) )
322 {
323 states [j] = true;
324 }
325
326 if ( old [j] && ( p == '*' ) )
327 {
328 states [j + 1] = true;
329 }
330 }
331
332 old = states;
333 }
334
335 return states [nLength];
336 }
337
338
339
340
341 private void init( )
342 {
343 _httpClientConfiguration=new HttpClientConfiguration();
344 _httpClientConfiguration.setProxyHost(AppPropertiesService.getProperty( PROPERTY_PROXY_HOST ));
345 _httpClientConfiguration.setProxyPort (AppPropertiesService.getProperty( PROPERTY_PROXY_PORT ));
346 _httpClientConfiguration.setProxyUserName (AppPropertiesService.getProperty( PROPERTY_PROXY_USERNAME ));
347 _httpClientConfiguration.setProxyPassword( AppPropertiesService.getProperty( PROPERTY_PROXY_PASSWORD ));
348 _httpClientConfiguration.setHostName (AppPropertiesService.getProperty( PROPERTY_HOST_NAME ));
349 _httpClientConfiguration.setDomainName ( AppPropertiesService.getProperty( PROPERTY_DOMAIN_NAME ));
350 _httpClientConfiguration.setRealm( AppPropertiesService.getProperty( PROPERTY_REALM ));
351 _httpClientConfiguration.setNoProxyFor (AppPropertiesService.getProperty( PROPERTY_NO_PROXY_FOR ));
352 _httpClientConfiguration.setContentCharset (AppPropertiesService.getProperty( PROPERTY_CONTENT_CHARSET ));
353 _httpClientConfiguration.setElementCharset ( AppPropertiesService.getProperty( PROPERTY_ELEMENT_CHARSET ));
354 _httpClientConfiguration.setConnectionPoolEnabled ( AppPropertiesService.getPropertyBoolean( PROPERTY_CONNECTION_POOL_ENABLED, false ));
355
356 try {
357 _httpClientConfiguration.setSocketTimeout( StringUtils.isNotEmpty( AppPropertiesService.getProperty(PROPERTY_SOCKET_TIMEOUT) ) ? Integer.parseInt(AppPropertiesService.getProperty(PROPERTY_SOCKET_TIMEOUT))
358 : null);
359
360 } catch (NumberFormatException e) {
361 AppLogService.error("Error during initialisation of socket timeout ", e);
362 }
363
364 try {
365 _httpClientConfiguration
366 .setConnectionTimeout( StringUtils.isNotEmpty( AppPropertiesService.getProperty(PROPERTY_CONNECTION_TIMEOUT) )
367 ? Integer.parseInt(AppPropertiesService.getProperty(PROPERTY_CONNECTION_TIMEOUT))
368 : null);
369
370 } catch (NumberFormatException e) {
371 AppLogService.error("Error during initialisation of connection timeout ", e);
372 }
373 try {
374 _httpClientConfiguration.setConnectionPoolMaxTotalConnection(
375 StringUtils.isNotEmpty( AppPropertiesService.getProperty(PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION) )
376 ? Integer.parseInt(
377 AppPropertiesService.getProperty(PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION))
378 : null);
379
380 } catch (NumberFormatException e) {
381 AppLogService.error("Error during initialisation of Connection Pool Maxt Total Connection ", e);
382 }
383 try {
384 _httpClientConfiguration.setConnectionPoolMaxConnectionPerHost(
385 StringUtils.isNotEmpty( AppPropertiesService.getProperty(PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION_PER_HOST) )
386 ? Integer.parseInt(AppPropertiesService
387 .getProperty(PROPERTY_CONNECTION_POOL_MAX_TOTAL_CONNECTION_PER_HOST))
388 : null);
389
390 } catch (NumberFormatException e) {
391 AppLogService.error("Error during initialisation of Connection Pool Maxt Total Connection Per Host ", e);
392 }
393
394
395 }
396
397
398
399
400
401
402
403
404 @Override
405 public boolean validate( int nStatus )
406 {
407 return _responseValidator.validate( nStatus );
408 }
409
410
411 }