1 package com.griddynamics.jagger.invoker.v2;
3 import org.apache.http.conn.ssl.NoopHostnameVerifier;
4 import org.apache.http.impl.client.CloseableHttpClient;
5 import org.apache.http.impl.client.HttpClientBuilder;
6 import org.apache.http.impl.client.HttpClients;
7 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory;
9 import org.springframework.http.HttpHeaders;
10 import org.springframework.http.HttpMethod;
11 import org.springframework.http.MediaType;
12 import org.springframework.http.RequestEntity;
13 import org.springframework.http.ResponseEntity;
14 import org.springframework.http.client.ClientHttpRequestFactory;
15 import org.springframework.http.client.ClientHttpRequestInterceptor;
16 import org.springframework.http.client.ClientHttpResponse;
17 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
18 import org.springframework.http.converter.HttpMessageConverter;
19 import org.springframework.util.FileCopyUtils;
20 import org.springframework.web.client.ResponseErrorHandler;
21 import org.springframework.web.client.RestTemplate;
22 import org.springframework.web.client.UnknownHttpStatusCodeException;
23 import org.springframework.web.util.UriTemplateHandler;
25 import java.io.IOException;
26 import java.io.InputStream;
28 import java.nio.charset.Charset;
29 import java.util.HashMap;
30 import java.util.List;
33 import static com.google.common.collect.Maps.newHashMap;
34 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.CONNECT_TIMEOUT_IN_MS;
35 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.DEFAULT_URI_VARIABLES;
36 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.ERROR_HANDLER;
37 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.INTERCEPTORS;
38 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.MAX_CONN_PER_ROUTE;
39 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.MAX_CONN_TOTAL;
40 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.MESSAGE_CONVERTERS;
41 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.REQUEST_FACTORY;
42 import static com.griddynamics.jagger.invoker.v2.SpringBasedHttpClient.JSpringBasedHttpClientParameters.URI_TEMPLATE_HANDLER;
54 @SuppressWarnings({
"unused",
"unchecked"})
57 private static final int DEFAULT_MAX_CONN_TOTAL = Integer.MAX_VALUE;
58 private static final int DEFAULT_MAX_CONN_PER_ROUTE = Integer.MAX_VALUE;
59 private static final int DEFAULT_CONNECT_TIMEOUT_IN_MS = 60000;
103 private final Map<String, Object> clientParams;
105 private RestTemplate restTemplate;
108 clientParams =
new HashMap<>();
109 restTemplate =
new RestTemplate();
110 restTemplate.setRequestFactory(getRequestFactory());
116 this.clientParams.putAll(clientParams);
117 setRestTemplateParams(this.clientParams);
122 if (query == JHttpQuery.EMPTY_QUERY)
123 return execute(endpoint);
125 URI endpointURI = endpoint.
getURI(query.getPath(), query.getQueryParams());
126 RequestEntity requestEntity = mapToRequestEntity(query, endpointURI);
127 ResponseEntity responseEntity;
128 if (query.getResponseBodyType() != null) {
129 responseEntity = restTemplate.exchange(endpointURI, query.getMethod(), requestEntity, query.getResponseBodyType());
131 responseEntity = restTemplate.exchange(endpointURI, query.getMethod(), requestEntity, byte[].class);
133 return mapToJHttpResponse(responseEntity);
137 URI endpointURI = endpoint.
getURI();
138 RequestEntity requestEntity = mapToRequestEntity(endpointURI);
139 ResponseEntity responseEntity = restTemplate.exchange(endpointURI, HttpMethod.GET, requestEntity, byte[].class);
140 return mapToJHttpResponse(responseEntity);
143 private void setRestTemplateParams(Map<String, Object> clientParams) {
144 int maxConnPerRoute = DEFAULT_MAX_CONN_PER_ROUTE;
145 int maxConnTotal = DEFAULT_MAX_CONN_TOTAL;
146 int connectTimeoutInMs = DEFAULT_CONNECT_TIMEOUT_IN_MS;
148 if (clientParams.containsKey(DEFAULT_URI_VARIABLES.value)) {
149 restTemplate.setDefaultUriVariables((Map<String, ?>) clientParams.get(DEFAULT_URI_VARIABLES.value));
151 if (clientParams.containsKey(ERROR_HANDLER.value)) {
152 restTemplate.setErrorHandler((ResponseErrorHandler) clientParams.get(ERROR_HANDLER.value));
154 if (clientParams.containsKey(MESSAGE_CONVERTERS.value)) {
155 restTemplate.setMessageConverters((List<HttpMessageConverter<?>>) clientParams.get(MESSAGE_CONVERTERS.value));
157 if (clientParams.containsKey(URI_TEMPLATE_HANDLER.value)) {
158 restTemplate.setUriTemplateHandler((UriTemplateHandler) clientParams.get(URI_TEMPLATE_HANDLER.value));
160 if (clientParams.containsKey(INTERCEPTORS.value)) {
161 restTemplate.setInterceptors((List<ClientHttpRequestInterceptor>) clientParams.get(INTERCEPTORS.value));
163 if (clientParams.containsKey(MAX_CONN_PER_ROUTE.value)) {
164 Object value = clientParams.get(MAX_CONN_PER_ROUTE.value);
165 if (value instanceof String)
166 maxConnPerRoute = Integer.parseInt((String) value);
168 maxConnPerRoute = (int) value;
170 if (clientParams.containsKey(MAX_CONN_TOTAL.value)) {
171 Object value = clientParams.get(MAX_CONN_TOTAL.value);
172 if (value instanceof String)
173 maxConnTotal = Integer.parseInt((String) value);
175 maxConnTotal = (int) value;
177 if (clientParams.containsKey(CONNECT_TIMEOUT_IN_MS.value)) {
178 Object value = clientParams.get(CONNECT_TIMEOUT_IN_MS.value);
179 if (value instanceof String)
180 connectTimeoutInMs = Integer.parseInt((String) value);
182 connectTimeoutInMs = (int) value;
185 if (clientParams.containsKey(REQUEST_FACTORY.value)) {
186 restTemplate.setRequestFactory((ClientHttpRequestFactory) clientParams.get(REQUEST_FACTORY.value));
188 if (!clientParams.containsKey(REQUEST_FACTORY.value) && containsAnyRequestFactoryParam(clientParams)) {
189 restTemplate.setRequestFactory(getRequestFactory(maxConnPerRoute, maxConnTotal, connectTimeoutInMs));
190 }
else if (clientParams.containsKey(REQUEST_FACTORY.value) && containsAnyRequestFactoryParam(clientParams)) {
191 throw new IllegalArgumentException(
"Parameters max_conn_total, max_conn_per_route and connect_timeout cannot be set if " +
192 "request_factory parameter presents. You must configure these parameters in your request_factory entity.");
196 private boolean containsAnyRequestFactoryParam(Map<String, Object> clientParams) {
197 return clientParams.containsKey(MAX_CONN_PER_ROUTE.value) ||
198 clientParams.containsKey(MAX_CONN_TOTAL.value) ||
199 clientParams.containsKey(CONNECT_TIMEOUT_IN_MS.value);
202 private HttpComponentsClientHttpRequestFactory getRequestFactory() {
203 return getRequestFactory(DEFAULT_MAX_CONN_PER_ROUTE, DEFAULT_MAX_CONN_TOTAL, DEFAULT_CONNECT_TIMEOUT_IN_MS);
206 private HttpComponentsClientHttpRequestFactory getRequestFactory(
int maxConnPerRoute,
int maxConnTotal,
int connectTimeoutInMs) {
207 HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
208 CloseableHttpClient httpClient = HttpClients.custom()
209 .setSSLHostnameVerifier(
new NoopHostnameVerifier())
210 .setMaxConnPerRoute(maxConnPerRoute)
211 .setMaxConnTotal(maxConnTotal)
213 requestFactory.setHttpClient(httpClient);
214 requestFactory.setConnectTimeout(connectTimeoutInMs);
215 return requestFactory;
218 private <T> RequestEntity<T> mapToRequestEntity(JHttpQuery<T> query, URI endpointURI) {
219 return new RequestEntity<>(query.getBody(), query.getHeaders(), query.getMethod(), endpointURI);
222 private <T> RequestEntity<T> mapToRequestEntity(URI endpointURI) {
223 return new RequestEntity<>(HttpMethod.GET, endpointURI);
226 private <T> JHttpResponse<T> mapToJHttpResponse(ResponseEntity<T> responseEntity) {
227 return new JHttpResponse<>(responseEntity.getStatusCode(), responseEntity.getBody(), responseEntity.getHeaders());
231 return newHashMap(clientParams);
236 public boolean hasError(ClientHttpResponse response)
throws IOException {
241 public void handleError(ClientHttpResponse response)
throws IOException {
243 response.getStatusCode();
244 }
catch (IllegalArgumentException ex) {
245 throw new UnknownHttpStatusCodeException(response.getRawStatusCode(),
246 response.getStatusText(), response.getHeaders(), getResponseBody(response), getCharset(response));
250 private byte[] getResponseBody(ClientHttpResponse response) {
252 InputStream responseBody = response.getBody();
253 if (responseBody != null) {
254 return FileCopyUtils.copyToByteArray(responseBody);
256 }
catch (IOException ex) {
262 private Charset getCharset(ClientHttpResponse response) {
263 HttpHeaders headers = response.getHeaders();
264 MediaType contentType = headers.getContentType();
265 return contentType != null ? contentType.getCharset() : null;