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.Method;
40 import org.apache.hc.core5.http.NotImplementedException;
41 import org.apache.hc.core5.http.ProtocolException;
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.StringEntity;
45 import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
46 import org.junit.Assert;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.mockito.Mock;
50 import org.mockito.Mockito;
51 import org.mockito.MockitoAnnotations;
52
53 public class TestDefaultBHttpServerConnection {
54
55 @Mock
56 private Socket socket;
57
58 private DefaultBHttpServerConnection conn;
59
60 @Before
61 public void setUp() throws Exception {
62 MockitoAnnotations.initMocks(this);
63 conn = new DefaultBHttpServerConnection("http", Http1Config.DEFAULT,
64 null, null,
65 DefaultContentLengthStrategy.INSTANCE,
66 DefaultContentLengthStrategy.INSTANCE,
67 DefaultHttpRequestParserFactory.INSTANCE,
68 DefaultHttpResponseWriterFactory.INSTANCE);
69 }
70
71 @Test
72 public void testBasics() throws Exception {
73 Assert.assertFalse(conn.isOpen());
74 Assert.assertEquals("[Not bound]", conn.toString());
75 }
76
77 @Test
78 public void testReadRequestHead() throws Exception {
79 final String s = "GET / HTTP/1.1\r\nUser-Agent: test\r\n\r\n";
80 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
81 Mockito.when(socket.getInputStream()).thenReturn(inStream);
82
83 conn.bind(socket);
84
85 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
86
87 final ClassicHttpRequest request = conn.receiveRequestHeader();
88 Assert.assertNotNull(request);
89 Assert.assertEquals("/", request.getPath());
90 Assert.assertEquals(Method.GET.name(), request.getMethod());
91 Assert.assertTrue(request.containsHeader("User-Agent"));
92 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
93 }
94
95 @Test
96 public void testReadRequestEntityWithContentLength() throws Exception {
97 final String s = "POST / HTTP/1.1\r\nUser-Agent: test\r\nContent-Length: 3\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().getRequestCount());
104
105 final ClassicHttpRequest request = conn.receiveRequestHeader();
106
107 Assert.assertNotNull(request);
108 Assert.assertEquals("/", request.getPath());
109 Assert.assertEquals(Method.POST.name(), request.getMethod());
110 Assert.assertTrue(request.containsHeader("User-Agent"));
111 Assert.assertNull(request.getEntity());
112 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
113
114 conn.receiveRequestEntity(request);
115
116 final HttpEntity entity = request.getEntity();
117 Assert.assertNotNull(entity);
118 Assert.assertEquals(3, entity.getContentLength());
119 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
120 final InputStream content = entity.getContent();
121 Assert.assertNotNull(content);
122 Assert.assertTrue(content instanceof ContentLengthInputStream);
123 }
124
125 @Test
126 public void testReadRequestEntityChunckCoded() throws Exception {
127 final String s = "POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nTransfer-Encoding: " +
128 "chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n";
129 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
130 Mockito.when(socket.getInputStream()).thenReturn(inStream);
131
132 conn.bind(socket);
133
134 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
135
136 final ClassicHttpRequest request = conn.receiveRequestHeader();
137
138 Assert.assertNotNull(request);
139 Assert.assertEquals("/stuff", request.getPath());
140 Assert.assertEquals(Method.POST.name(), request.getMethod());
141 Assert.assertTrue(request.containsHeader("User-Agent"));
142 Assert.assertNull(request.getEntity());
143 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
144
145 conn.receiveRequestEntity(request);
146
147 final HttpEntity entity = request.getEntity();
148 Assert.assertNotNull(entity);
149 Assert.assertEquals(-1, entity.getContentLength());
150 Assert.assertEquals(true, entity.isChunked());
151 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
152 final InputStream content = entity.getContent();
153 Assert.assertNotNull(content);
154 Assert.assertTrue(content instanceof ChunkedInputStream);
155 }
156
157 @Test(expected = ProtocolException.class)
158 public void testReadRequestEntityIdentity() throws Exception {
159 final String s = "POST /stuff HTTP/1.1\r\nUser-Agent: test\r\nTransfer-Encoding: " +
160 "identity\r\n\r\n123";
161 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
162 Mockito.when(socket.getInputStream()).thenReturn(inStream);
163
164 conn.bind(socket);
165
166 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
167
168 final ClassicHttpRequest request = conn.receiveRequestHeader();
169
170 Assert.assertNotNull(request);
171 Assert.assertEquals("/stuff", request.getPath());
172 Assert.assertEquals(Method.POST.name(), request.getMethod());
173 Assert.assertTrue(request.containsHeader("User-Agent"));
174 Assert.assertNull(request.getEntity());
175 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
176
177 conn.receiveRequestEntity(request);
178 }
179
180 @Test
181 public void testReadRequestNoEntity() throws Exception {
182 final String s = "POST /stuff HTTP/1.1\r\nUser-Agent: test\r\n\r\n";
183 final ByteArrayInputStream inStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
184 Mockito.when(socket.getInputStream()).thenReturn(inStream);
185
186 conn.bind(socket);
187
188 Assert.assertEquals(0, conn.getEndpointDetails().getRequestCount());
189
190 final ClassicHttpRequest request = conn.receiveRequestHeader();
191
192 Assert.assertNotNull(request);
193 Assert.assertEquals("/stuff", request.getPath());
194 Assert.assertEquals(Method.POST.name(), request.getMethod());
195 Assert.assertTrue(request.containsHeader("User-Agent"));
196 Assert.assertNull(request.getEntity());
197 Assert.assertEquals(1, conn.getEndpointDetails().getRequestCount());
198
199 conn.receiveRequestEntity(request);
200
201 final HttpEntity entity = request.getEntity();
202 Assert.assertNull(entity);
203 }
204
205 @Test
206 public void testWriteResponseHead() throws Exception {
207 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
208 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
209
210 conn.bind(socket);
211
212 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
213
214 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
215 response.addHeader("User-Agent", "test");
216
217 conn.sendResponseHeader(response);
218 conn.flush();
219
220 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
221 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
222 Assert.assertEquals("HTTP/1.1 200 OK\r\nUser-Agent: test\r\n\r\n", s);
223 }
224
225 @Test
226 public void testWriteResponse100Head() throws Exception {
227 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
228 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
229
230 conn.bind(socket);
231
232 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
233
234 final ClassicHttpResponse response = new BasicClassicHttpResponse(100, "Go on");
235
236 conn.sendResponseHeader(response);
237 conn.flush();
238
239 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
240 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
241 Assert.assertEquals("HTTP/1.1 100 Go on\r\n\r\n", s);
242 }
243
244 @Test
245 public void testWriteResponseEntityWithContentLength() throws Exception {
246 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
247 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
248
249 conn.bind(socket);
250
251 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
252
253 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
254 response.addHeader("Server", "test");
255 response.addHeader("Content-Length", "3");
256 response.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
257
258 conn.sendResponseHeader(response);
259 conn.sendResponseEntity(response);
260 conn.flush();
261
262 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
263 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
264 Assert.assertEquals("HTTP/1.1 200 OK\r\nServer: test\r\nContent-Length: 3\r\n\r\n123", s);
265 }
266
267 @Test
268 public void testWriteResponseEntityChunkCoded() throws Exception {
269 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
270 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
271
272 conn.bind(socket);
273
274 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
275
276 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
277 response.addHeader("Server", "test");
278 response.addHeader("Transfer-Encoding", "chunked");
279 response.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
280
281 conn.sendResponseHeader(response);
282 conn.sendResponseEntity(response);
283 conn.flush();
284
285 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
286 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
287 Assert.assertEquals("HTTP/1.1 200 OK\r\nServer: test\r\nTransfer-Encoding: " +
288 "chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n", s);
289 }
290
291 @Test(expected = NotImplementedException.class)
292 public void testWriteResponseEntityIdentity() throws Exception {
293 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
294 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
295
296 conn.bind(socket);
297
298 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
299
300 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
301 response.addHeader("Server", "test");
302 response.addHeader("Transfer-Encoding", "identity");
303 response.setEntity(new StringEntity("123", ContentType.TEXT_PLAIN));
304
305 conn.sendResponseHeader(response);
306 conn.sendResponseEntity(response);
307 conn.flush();
308 }
309
310 @Test
311 public void testWriteResponseNoEntity() throws Exception {
312 final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
313 Mockito.when(socket.getOutputStream()).thenReturn(outStream);
314
315 conn.bind(socket);
316
317 Assert.assertEquals(0, conn.getEndpointDetails().getResponseCount());
318
319 final ClassicHttpResponse response = new BasicClassicHttpResponse(200, "OK");
320 response.addHeader("Server", "test");
321
322 conn.sendResponseHeader(response);
323 conn.sendResponseEntity(response);
324 conn.flush();
325
326 Assert.assertEquals(1, conn.getEndpointDetails().getResponseCount());
327 final String s = new String(outStream.toByteArray(), StandardCharsets.US_ASCII);
328 Assert.assertEquals("HTTP/1.1 200 OK\r\nServer: test\r\n\r\n", s);
329 }
330
331 }