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 package com.jcabi.http.request;
31
32 import com.jcabi.aspects.Immutable;
33 import com.jcabi.aspects.Loggable;
34 import com.jcabi.http.ImmutableHeader;
35 import com.jcabi.http.Request;
36 import com.jcabi.http.RequestBody;
37 import com.jcabi.http.RequestURI;
38 import com.jcabi.http.Response;
39 import com.jcabi.http.Wire;
40 import com.jcabi.immutable.Array;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.net.URI;
44 import java.net.URL;
45 import java.util.Collection;
46 import java.util.LinkedList;
47 import java.util.Map;
48 import lombok.EqualsAndHashCode;
49 import lombok.ToString;
50 import org.apache.http.Header;
51 import org.apache.http.HttpEntity;
52 import org.apache.http.client.config.RequestConfig;
53 import org.apache.http.client.methods.CloseableHttpResponse;
54 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
55 import org.apache.http.entity.BufferedHttpEntity;
56 import org.apache.http.entity.InputStreamEntity;
57 import org.apache.http.impl.client.HttpClients;
58 import org.apache.http.util.EntityUtils;
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @Immutable
73 @EqualsAndHashCode(of = "base")
74 @ToString(of = "base")
75 @Loggable(Loggable.DEBUG)
76 @SuppressWarnings("PMD.TooManyMethods")
77 public final class ApacheRequest implements Request {
78
79
80
81
82
83 private static final Wire WIRE = new Wire() {
84
85 @Override
86 public Response send(final Request req, final String home,
87 final String method,
88 final Collection<Map.Entry<String, String>> headers,
89 final InputStream content,
90 final int connect,
91 final int read) throws IOException {
92 final CloseableHttpResponse response =
93 HttpClients.createSystem().execute(
94 this.httpRequest(
95 home, method, headers, content,
96 connect, read
97 )
98 );
99 try {
100 return new DefaultResponse(
101 req,
102 response.getStatusLine().getStatusCode(),
103 response.getStatusLine().getReasonPhrase(),
104 this.headers(response.getAllHeaders()),
105 this.consume(response.getEntity())
106 );
107 } finally {
108 response.close();
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124 public HttpEntityEnclosingRequestBase httpRequest(final String home,
125 final String method,
126 final Collection<Map.Entry<String, String>> headers,
127 final InputStream content,
128 final int connect,
129 final int read) throws IOException {
130 final HttpEntityEnclosingRequestBase req =
131 new HttpEntityEnclosingRequestBase() {
132 @Override
133 public String getMethod() {
134 return method;
135 }
136 };
137 final URI uri = URI.create(home);
138 req.setConfig(
139 RequestConfig.custom()
140 .setCircularRedirectsAllowed(false)
141 .setRedirectsEnabled(false)
142 .setConnectTimeout(connect)
143 .setSocketTimeout(read)
144 .build()
145 );
146 req.setURI(uri);
147 req.setEntity(
148 new BufferedHttpEntity(new InputStreamEntity(content))
149 );
150 for (final Map.Entry<String, String> header : headers) {
151 req.addHeader(header.getKey(), header.getValue());
152 }
153 return req;
154 }
155
156
157
158
159
160
161
162 private byte[] consume(final HttpEntity entity) throws IOException {
163 final byte[] body;
164 if (entity == null) {
165 body = new byte[0];
166 } else {
167 body = EntityUtils.toByteArray(entity);
168 }
169 return body;
170 }
171
172
173
174
175
176
177 @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
178 private Array<Map.Entry<String, String>> headers(final Header... list) {
179 final Collection<Map.Entry<String, String>> headers =
180 new LinkedList<>();
181 for (final Header header : list) {
182 headers.add(
183 new ImmutableHeader(
184 header.getName(),
185 header.getValue()
186 )
187 );
188 }
189 return new Array<Map.Entry<String, String>>(headers);
190 }
191 };
192
193
194
195
196 private final transient Request base;
197
198
199
200
201
202 public ApacheRequest(final URL url) {
203 this(url.toString());
204 }
205
206
207
208
209
210 public ApacheRequest(final URI uri) {
211 this(uri.toString());
212 }
213
214
215
216
217
218 public ApacheRequest(final String uri) {
219 this.base = new BaseRequest(ApacheRequest.WIRE, uri);
220 }
221
222 @Override
223 public RequestURI uri() {
224 return this.base.uri();
225 }
226
227 @Override
228 public Request header(final String name, final Object value) {
229 return this.base.header(name, value);
230 }
231
232 @Override
233 public Request reset(final String name) {
234 return this.base.reset(name);
235 }
236
237 @Override
238 public RequestBody body() {
239 return this.base.body();
240 }
241
242 @Override
243 public RequestBody multipartBody() {
244 return this.base.multipartBody();
245 }
246
247 @Override
248 public Request method(final String method) {
249 return this.base.method(method);
250 }
251
252 @Override
253 public Request timeout(final int connect, final int read) {
254 return this.base.timeout(connect, read);
255 }
256
257 @Override
258 public Response fetch() throws IOException {
259 return this.base.fetch();
260 }
261
262 @Override
263 public Response fetch(final InputStream stream) throws IOException {
264 return this.base.fetch(stream);
265 }
266
267 @Override
268 public <T extends Wire> Request through(final Class<T> type,
269 final Object... args) {
270 return this.base.through(type, args);
271 }
272
273 @Override
274 public Request through(final Wire wire) {
275 return this.base.through(wire);
276 }
277 }