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 package org.apache.hc.core5.http.impl.io;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.ByteArrayOutputStream;
31 import java.io.InputStream;
32 import java.net.Socket;
33 import java.nio.charset.StandardCharsets;
34
35 import org.apache.hc.core5.http.ClassicHttpRequest;
36 import org.apache.hc.core5.http.ClassicHttpResponse;
37 import org.apache.hc.core5.http.ContentType;
38 import org.apache.hc.core5.http.HttpEntity;
39 import org.apache.hc.core5.http.LengthRequiredException;
40 import org.apache.hc.core5.http.Method;
41 import org.apache.hc.core5.http.NotImplementedException;
42 import org.apache.hc.core5.http.config.Http1Config;
43 import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
44 import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
45 import org.apache.hc.core5.http.io.entity.StringEntity;
46 import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
47 import org.junit.Assert;
48 import org.junit.Before;
49 import org.junit.Test;
50 import org.mockito.Mock;
51 import org.mockito.Mockito;
52 import org.mockito.MockitoAnnotations;
53
54 public class TestDefaultBHttpClientConnection {
55
56 @Mock
57 private Socket socket;
58
59 private DefaultBHttpClientConnection conn;
60
61 @Before
62 public void setUp() throws Exception {
63 MockitoAnnotations.initMocks(this);
64 conn = new DefaultBHttpClientConnection(Http1Config.DEFAULT,
65 null, null,
66 DefaultContentLengthStrategy.INSTANCE,
67 DefaultContentLengthStrategy.INSTANCE,
68 DefaultHttpRequestWriterFactory.INSTANCE,
69 DefaultHttpResponseParserFactory.INSTANCE);
70 }
71
72 @Test
73 public void testBasics() throws Exception {
74 Assert.assertFalse(conn.isOpen());
75 Assert.assertEquals("[Not bound]", conn.toString());
76 }
77
78 @Test
79 public void testReadResponseHead() throws Exception {
80 final String s = "HTTP/1.1 200 OK\r\nUser-Agent: test\r\n\r\n";
81 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
82 Mockito.when(socket.getInputStream()).thenReturn(inStream);
83
84 conn.bind(socket);
85
86 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
87
88 final ClassicHttpResponse response = conn.receiveResponseHeader();
89 Assert.assertNotNull(response);
90 Assert.assertEquals(200, response.getCode());
91 Assert.assertTrue(response.containsHeader("User-Agent"));
92 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
93 }
94
95 @Test
96 public void testReadResponseEntityWithoutContentLength() throws Exception {
97 final String s = "HTTP/1.1 200 OK\r\nServer: test\r\n\r\n123";
98 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
99 Mockito.when(socket.getInputStream()).thenReturn(inStream);
100
101 conn.bind(socket);
102
103 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
104
105 final ClassicHttpResponse response = conn.receiveResponseHeader();
106
107 Assert.assertNotNull(response);
108 Assert.assertEquals(200, response.getCode());
109 Assert.assertTrue(response.containsHeader("Server"));
110 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
111
112 conn.receiveResponseEntity(response);
113
114 final HttpEntity entity = response.getEntity();
115 Assert.assertNotNull(entity);
116 Assert.assertEquals(-1, entity.getContentLength());
117 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
118
119 final InputStream content = entity.getContent();
120 Assert.assertNotNull(content);
121 Assert.assertEquals(3, content.available());
122 Assert.assertEquals('1', content.read());
123 Assert.assertEquals('2', content.read());
124 Assert.assertEquals('3', content.read());
125 }
126
127 @Test
128 public void testReadResponseEntityWithContentLength() throws Exception {
129 final String s = "HTTP/1.1 200 OK\r\nServer: test\r\nContent-Length: 3\r\n\r\n123";
130 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
131 Mockito.when(socket.getInputStream()).thenReturn(inStream);
132
133 conn.bind(socket);
134
135 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
136
137 final ClassicHttpResponse response = conn.receiveResponseHeader();
138
139 Assert.assertNotNull(response);
140 Assert.assertEquals(200, response.getCode());
141 Assert.assertTrue(response.containsHeader("Server"));
142 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
143
144 conn.receiveResponseEntity(response);
145
146 final HttpEntity entity = response.getEntity();
147 Assert.assertNotNull(entity);
148 Assert.assertEquals(3, entity.getContentLength());
149 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
150 final InputStream content = entity.getContent();
151 Assert.assertNotNull(content);
152 Assert.assertTrue(content instanceof ContentLengthInputStream);
153 }
154
155 @Test
156 public void testReadResponseEntityChunkCoded() throws Exception {
157 final String s = "HTTP/1.1 200 OK\r\nServer: test\r\nTransfer-Encoding: " +
158 "chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n";
159 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
160 Mockito.when(socket.getInputStream()).thenReturn(inStream);
161
162 conn.bind(socket);
163
164 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
165
166 final ClassicHttpResponse response = conn.receiveResponseHeader();
167
168 Assert.assertNotNull(response);
169 Assert.assertEquals(200, response.getCode());
170 Assert.assertTrue(response.containsHeader("Server"));
171 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
172
173 conn.receiveResponseEntity(response);
174
175 final HttpEntity entity = response.getEntity();
176 Assert.assertNotNull(entity);
177 Assert.assertEquals(-1, entity.getContentLength());
178 Assert.assertEquals(true, entity.isChunked());
179 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
180 final InputStream content = entity.getContent();
181 Assert.assertNotNull(content);
182 Assert.assertTrue(content instanceof ChunkedInputStream);
183 }
184
185 @Test(expected = NotImplementedException.class)
186 public void testReadResponseEntityIdentity() throws Exception {
187 final String s = "HTTP/1.1 200 OK\r\nServer: test\r\nTransfer-Encoding: identity\r\n\r\n123";
188 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
189 Mockito.when(socket.getInputStream()).thenReturn(inStream);
190
191 conn.bind(socket);
192
193 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
194
195 final ClassicHttpResponse response = conn.receiveResponseHeader();
196
197 Assert.assertNotNull(response);
198 Assert.assertEquals(200, response.getCode());
199 Assert.assertTrue(response.containsHeader("Server"));
200 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
201
202 conn.receiveResponseEntity(response);
203 }
204
205 @Test
206 public void testReadResponseNoEntity() throws Exception {
207 final String s = "HTTP/1.1 200 OK\r\nServer: test\r\n\r\n";
208 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
209 Mockito.when(socket.getInputStream()).thenReturn(inStream);
210
211 conn.bind(socket);
212
213 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
214
215 final ClassicHttpResponse response = conn.receiveResponseHeader();
216
217 Assert.assertNotNull(response);
218 Assert.assertEquals(200, response.getCode());
219 Assert.assertTrue(response.containsHeader("Server"));
220 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
221
222 conn.receiveResponseEntity(response);
223
224 final HttpEntity entity = response.getEntity();
225 Assert.assertNotNull(entity);
226 final InputStream content = entity.getContent();
227 Assert.assertNotNull(content);
228 Assert.assertTrue(content instanceof IdentityInputStream);
229 }
230
231 @Test
232 public void testWriteRequestHead() throws Exception {
233 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
234 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
235
236 conn.bind(socket);
237
238 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
239
240 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.GET, "/stuff");
241 request.addHeader("User-Agent", "test");
242
243 conn.sendRequestHeader(request);
244 conn.flush();
245
246 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
247 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
248 Assert.assertEquals("GET /stuff HTTP/1.1\r\nUser-Agent: test\r\n\r\n", s);
249 }
250
251 @Test
252 public void testWriteRequestEntityWithContentLength() throws Exception {
253 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
254 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
255
256 conn.bind(socket);
257
258 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
259
260 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
261 request.addHeader("User-Agent", "test");
262 request.addHeader("Content-Length", "3");
263 request.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
264
265 conn.sendRequestHeader(request);
266 conn.sendRequestEntity(request);
267 conn.flush();
268
269 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
270 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
271 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: 3\r\n\r\n123", s);
272 }
273
274 @Test
275 public void testWriteRequestEntityChunkCoded() throws Exception {
276 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
277 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
278
279 conn.bind(socket);
280
281 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
282
283 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
284 request.addHeader("User-Agent", "test");
285 request.addHeader("Transfer-Encoding", "chunked");
286 request.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
287
288 conn.sendRequestHeader(request);
289 conn.sendRequestEntity(request);
290 conn.flush();
291
292 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
293 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
294 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nTransfer-Encoding: " +
295 "chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n", s);
296 }
297
298 @Test(expected = LengthRequiredException.class)
299 public void testWriteRequestEntityNoContentLength() throws Exception {
300 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
301 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
302
303 conn.bind(socket);
304
305 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
306
307 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
308 request.addHeader("User-Agent", "test");
309 request.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
310
311 conn.sendRequestHeader(request);
312 conn.sendRequestEntity(request);
313 }
314
315 @Test
316 public void testWriteRequestNoEntity() throws Exception {
317 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
318 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
319
320 conn.bind(socket);
321
322 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
323
324 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
325 request.addHeader("User-Agent", "test");
326
327 conn.sendRequestHeader(request);
328 conn.sendRequestEntity(request);
329 conn.flush();
330
331 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
332 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
333 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\n\r\n", s);
334 }
335
336 @Test
337 public void testTerminateRequestChunkedEntity() throws Exception {
338 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
339 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
340
341 conn.bind(socket);
342
343 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
344
345 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
346 request.addHeader("User-Agent", "test");
347 request.addHeader("Transfer-Encoding", "chunked");
348 final StringEntity entity = new StringEntity("123", ContentType.TEXT_PLAIN, true);
349
350 request.setEntity(entity);
351
352 conn.sendRequestHeader(request);
353 conn.terminateRequest(request);
354 conn.flush();
355
356 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
357 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
358 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nTransfer-Encoding: " +
359 "chunked\r\n\r\n0\r\n\r\n", s);
360 Assert.assertTrue(conn.isConsistent());
361 }
362
363 @Test
364 public void testTerminateRequestContentLengthShort() throws Exception {
365 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
366 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
367
368 conn.bind(socket);
369
370 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
371
372 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
373 request.addHeader("User-Agent", "test");
374 request.addHeader("Content-Length", "3");
375 final StringEntity entity = new StringEntity("123", ContentType.TEXT_PLAIN, true);
376 request.setEntity(entity);
377
378 conn.sendRequestHeader(request);
379 conn.terminateRequest(request);
380 conn.flush();
381
382 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
383 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
384 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: " +
385 "3\r\n\r\n123", s);
386 Assert.assertTrue(conn.isConsistent());
387 }
388
389 @Test
390 public void testTerminateRequestContentLengthLong() throws Exception {
391 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
392 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
393
394 conn.bind(socket);
395
396 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
397
398 final ClassicHttpRequest request = new BasicClassicHttpRequest(Method.POST, "/stuff");
399 request.addHeader("User-Agent", "test");
400 request.addHeader("Content-Length", "3000");
401 final ByteArrayEntity entity = new ByteArrayEntity(new byte[3000], ContentType.TEXT_PLAIN, true);
402 request.setEntity(entity);
403
404 conn.sendRequestHeader(request);
405 conn.terminateRequest(request);
406 conn.flush();
407
408 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
409 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
410 Assert.assertEquals("POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: " +
411 "3000\r\n\r\n", s);
412 Assert.assertFalse(conn.isConsistent());
413 }
414
415 }