View Javadoc
1   package org.oxerr.okcoin.rest.service.web;
2   
3   import static java.util.Collections.emptyMap;
4   
5   import java.io.IOException;
6   import java.net.URI;
7   import java.net.URISyntaxException;
8   import java.nio.charset.Charset;
9   import java.util.ArrayList;
10  import java.util.Arrays;
11  import java.util.Collection;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Optional;
15  
16  import javax.annotation.Nullable;
17  
18  import org.apache.http.Header;
19  import org.apache.http.NameValuePair;
20  import org.apache.http.client.config.RequestConfig;
21  import org.apache.http.client.entity.UrlEncodedFormEntity;
22  import org.apache.http.client.methods.CloseableHttpResponse;
23  import org.apache.http.client.methods.HttpGet;
24  import org.apache.http.client.methods.HttpPost;
25  import org.apache.http.client.methods.HttpUriRequest;
26  import org.apache.http.client.utils.URIBuilder;
27  import org.apache.http.entity.ContentType;
28  import org.apache.http.entity.StringEntity;
29  import org.apache.http.impl.client.CloseableHttpClient;
30  import org.apache.http.impl.client.HttpClientBuilder;
31  import org.apache.http.impl.client.LaxRedirectStrategy;
32  import org.apache.http.message.BasicHeader;
33  import org.apache.http.message.BasicNameValuePair;
34  import org.oxerr.okcoin.rest.dto.valuereader.JsonValueReader;
35  import org.oxerr.okcoin.rest.dto.valuereader.JsonValueTypeRefReader;
36  import org.oxerr.okcoin.rest.dto.valuereader.ValueReader;
37  import org.slf4j.Logger;
38  import org.slf4j.LoggerFactory;
39  
40  import com.fasterxml.jackson.core.JsonParser.Feature;
41  import com.fasterxml.jackson.core.type.TypeReference;
42  import com.fasterxml.jackson.databind.ObjectMapper;
43  
44  public class HttpClient implements AutoCloseable {
45  
46  	private final Logger log = LoggerFactory.getLogger(HttpClient.class);
47  
48  	private final CloseableHttpClient httpClient;
49  
50  	private final ObjectMapper objectMapper;
51  
52  	public HttpClient(CloseableHttpClient httpClient, ObjectMapper objectMapper) {
53  		this.httpClient = httpClient;
54  		this.objectMapper = objectMapper;
55  	}
56  
57  	public HttpClient(
58  			int socketTimeout,
59  			int connectTimeout,
60  			int connectionRequestTimeout) {
61  		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
62  		httpClientBuilder.setRedirectStrategy(new LaxRedirectStrategy());
63  
64  		String userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.71 (KHTML, like Gecko) Version/6.1 Safari/537.71";
65  		httpClientBuilder.setUserAgent(userAgent);
66  
67  		Collection<Header> defaultHeaders = new ArrayList<>();
68  		defaultHeaders.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
69  		httpClientBuilder.setDefaultHeaders(defaultHeaders);
70  
71  		RequestConfig defaultRequestConfig = RequestConfig.custom()
72  				.setSocketTimeout(socketTimeout)
73  				.setConnectTimeout(connectTimeout)
74  				.setConnectionRequestTimeout(connectionRequestTimeout)
75  				.build();
76  		httpClientBuilder.setDefaultRequestConfig(defaultRequestConfig);
77  
78  		httpClient = httpClientBuilder.build();
79  
80  		objectMapper = new ObjectMapper();
81  		objectMapper.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
82  	}
83  
84  	public <T> T get(URI uri, Class<T> valueType) throws IOException {
85  		return get(uri, new JsonValueReader<>(objectMapper, valueType));
86  	}
87  
88  	public <T> T get(URI uri, TypeReference<T> valueTypeRef) throws IOException {
89  		return get(uri, new JsonValueTypeRefReader<>(objectMapper, valueTypeRef));
90  	}
91  
92  	public <T> T get(
93  		URI uri,
94  		TypeReference<T> valueTypeRef,
95  		@Nullable Map<?, ?> params,
96  		@Nullable Map<?, ?> headers
97  	) throws IOException {
98  		return get(uri, new JsonValueTypeRefReader<>(objectMapper, valueTypeRef), params, headers);
99  	}
100 
101 	public <T> T get(URI uri, ValueReader<T> valueReader) throws IOException {
102 		return get(uri, valueReader, null, null);
103 	}
104 
105 	public <T> T get(
106 		URI uri,
107 		ValueReader<T> valueReader,
108 		@Nullable Map<?, ?> params,
109 		@Nullable Map<?, ?> headers
110 	) throws IOException {
111 		HttpGet httpGet = new HttpGet(buildURI(uri, toNameValuePairs(params)));
112 		httpGet.setHeaders(toHeaders(headers));
113 		return execute(httpGet, valueReader);
114 	}
115 
116 	public <T> T post(
117 		URI uri,
118 		Class<T> valueType,
119 		@Nullable Map<?, ?> params,
120 		@Nullable Map<?, ?> headers,
121 		@Nullable Charset charset
122 	) throws IOException {
123 		return post(uri, new JsonValueReader<>(objectMapper, valueType),
124 			toNameValuePairs(params), toHeaders(headers), charset);
125 	}
126 
127 	public <T> T post(
128 		URI uri,
129 		TypeReference<T> valueTypeRef,
130 		@Nullable Map<?, ?> params,
131 		@Nullable Map<?, ?> headers,
132 		@Nullable Charset charset
133 	) throws IOException {
134 		return post(uri, new JsonValueTypeRefReader<>(objectMapper, valueTypeRef),
135 			toNameValuePairs(params), toHeaders(headers), charset);
136 	}
137 
138 	public <T> T post(URI uri, ValueReader<T> valueReader,
139 			NameValuePair... params) throws IOException {
140 		return post(uri, valueReader, Arrays.asList(params));
141 	}
142 
143 	public <T> T post(URI uri, ValueReader<T> valueReader,
144 			List<NameValuePair> params) throws IOException {
145 		return post(uri, valueReader, params, null, null);
146 	}
147 
148 	public <T> T post(
149 		URI uri,
150 		ValueReader<T> valueReader,
151 		@Nullable Map<?, ?> params,
152 		@Nullable Map<?, ?> headers,
153 		@Nullable Charset charset
154 	) throws IOException {
155 		return post(uri, valueReader, toNameValuePairs(params), toHeaders(headers), charset);
156 	}
157 
158 	public <T> T post(
159 		URI uri,
160 		ValueReader<T> valueReader,
161 		@Nullable Iterable<? extends NameValuePair> parameters,
162 		@Nullable Header[] headers,
163 		@Nullable Charset charset
164 	) throws IOException {
165 		HttpPost httpPost = new HttpPost(uri);
166 		httpPost.setEntity(new UrlEncodedFormEntity(parameters, charset));
167 		httpPost.setHeaders(headers);
168 		return execute(httpPost, valueReader);
169 	}
170 
171 	public <T> T post(URI uri, ValueReader<T> valueReader, String content,
172 			String charset) throws IOException {
173 		HttpPost post = new HttpPost(uri);
174 		post.setEntity(new StringEntity(content, charset));
175 		return execute(post, valueReader);
176 	}
177 
178 	public <T> T post(URI uri, ValueReader<T> valueReader, String content,
179 			ContentType contentType) throws IOException {
180 		HttpPost post = new HttpPost(uri);
181 		post.setEntity(new StringEntity(content, contentType));
182 		return execute(post, valueReader);
183 	}
184 
185 	@Deprecated
186 	public <T> T execute(
187 			final ValueReader<T> valueReader,
188 			final HttpUriRequest request) throws IOException {
189 		return execute(request, valueReader);
190 	}
191 
192 	public <T> T execute(HttpUriRequest request, ValueReader<T> valueReader) throws IOException {
193 		log.debug("Executing: {}", request.getURI());
194 		try (CloseableHttpResponse response = httpClient.execute(request)) {
195 			return valueReader.read(response);
196 		}
197 	}
198 
199 	private URI buildURI(URI uri, @Nullable List<NameValuePair> parameters) throws IllegalArgumentException {
200 		URIBuilder builder = new URIBuilder(uri);
201 		if (parameters != null) {
202 			builder.addParameters(parameters);
203 		}
204 		try {
205 			return builder.build();
206 		} catch (URISyntaxException e) {
207 			throw new IllegalArgumentException(e);
208 		}
209 	}
210 
211 	private List<NameValuePair> toNameValuePairs(@Nullable Map<?, ?> params) {
212 		List<NameValuePair> parameters = new ArrayList<>();
213 		Optional.ofNullable(params).orElse(emptyMap()).entrySet().stream().forEach(param -> {
214 			String name = param.getKey().toString();
215 			if (param.getValue() == null) {
216 				// ignore
217 			} else if (param.getValue().getClass().isArray()) {
218 				Object[] values = (Object[]) param.getValue();
219 				Arrays.stream(values).forEach(value -> {
220 					parameters.add(new BasicNameValuePair(name, value.toString()));
221 				});
222 			} else {
223 				parameters.add(new BasicNameValuePair(name, param.getValue().toString()));
224 			}
225 		});
226 		return parameters;
227 	}
228 
229 	private Header[] toHeaders(@Nullable Map<?, ?> headers) {
230 		return Optional.ofNullable(headers).orElse(emptyMap()).entrySet().stream()
231 			.map(header -> new BasicHeader(header.getKey().toString(), header.getValue().toString()))
232 			.toArray(Header[]::new);
233 	}
234 
235 	/**
236 	 * {@inheritDoc}
237 	 */
238 	@Override
239 	public void close() throws IOException {
240 		httpClient.close();
241 	}
242 
243 }