1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.http;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertNotEquals;
24 import static org.junit.Assert.assertTrue;
25
26 import java.nio.charset.CharacterCodingException;
27 import java.nio.charset.Charset;
28 import java.nio.charset.CharsetEncoder;
29
30 import org.apache.mina.core.buffer.IoBuffer;
31 import org.apache.mina.core.filterchain.IoFilter.NextFilter;
32 import org.apache.mina.core.session.DummySession;
33 import org.apache.mina.core.session.IoSession;
34 import org.apache.mina.filter.codec.AbstractProtocolDecoderOutput;
35 import org.apache.mina.filter.codec.ProtocolDecoder;
36 import org.apache.mina.http.api.HttpEndOfContent;
37 import org.apache.mina.http.api.HttpRequest;
38 import org.junit.Test;
39
40 public class HttpServerDecoderTest {
41 private static final String DECODER_STATE_ATT = "http.ds";
42
43 private static final CharsetEncoder encoder = Charset.forName("US-ASCII").newEncoder();
44
45 private static final ProtocolDecoder decoder = new HttpServerDecoder();
46
47
48
49
50 private static IoSession session = new DummySession();
51
52
53
54
55
56
57
58
59
60 protected static IoBuffer getRequestBuffer(String method, String body) throws CharacterCodingException {
61 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
62 buffer.putString(method + " / HTTP/1.1\r\nHost: dummy\r\n", encoder);
63
64 if (body != null) {
65 buffer.putString("Content-Length: " + body.length() + "\r\n\r\n", encoder);
66 buffer.putString(body, encoder);
67 } else {
68 buffer.putString("\r\n", encoder);
69 }
70
71 buffer.rewind();
72
73 return buffer;
74 }
75
76 protected static IoBuffer getRequestBuffer(String method) throws CharacterCodingException {
77 return getRequestBuffer(method, null);
78 }
79
80
81
82
83
84
85
86
87
88 protected static AbstractProtocolDecoderOutput executeRequest(String method, String body) throws Exception {
89 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
90 public void flush(NextFilter nextFilter, IoSession session) {
91 }
92 };
93
94 IoBuffer buffer = getRequestBuffer(method, body);
95
96 while (buffer.hasRemaining()) {
97 decoder.decode(session, buffer, out);
98 }
99
100 return out;
101 }
102
103 @Test
104 public void testGetRequestWithoutBody() throws Exception {
105 AbstractProtocolDecoderOutput out = executeRequest("GET", null);
106 assertEquals(2, out.getMessageQueue().size());
107 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
108 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
109 }
110
111 @Test
112 public void testGetRequestBody() throws Exception {
113 AbstractProtocolDecoderOutput out = executeRequest("GET", "body");
114 assertEquals(3, out.getMessageQueue().size());
115 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
116 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
117 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
118 }
119
120 @Test
121 public void testPutRequestWithoutBody() throws Exception {
122 AbstractProtocolDecoderOutput out = executeRequest("PUT", null);
123 assertEquals(2, out.getMessageQueue().size());
124 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
125 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
126 }
127
128 @Test
129 public void testPutRequestBody() throws Exception {
130 AbstractProtocolDecoderOutput out = executeRequest("PUT", "body");
131 assertEquals(3, out.getMessageQueue().size());
132 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
133 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
134 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
135 }
136
137 @Test
138 public void testPostRequestWithoutBody() throws Exception {
139 AbstractProtocolDecoderOutput out = executeRequest("POST", null);
140 assertEquals(2, out.getMessageQueue().size());
141 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
142 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
143 }
144
145 @Test
146 public void testPostRequestBody() throws Exception {
147 AbstractProtocolDecoderOutput out = executeRequest("POST", "body");
148 assertEquals(3, out.getMessageQueue().size());
149 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
150 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
151 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
152 }
153
154 @Test
155 public void testDeleteRequestWithoutBody() throws Exception {
156 AbstractProtocolDecoderOutput out = executeRequest("DELETE", null);
157 assertEquals(2, out.getMessageQueue().size());
158 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
159 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
160 }
161
162 @Test
163 public void testDeleteRequestBody() throws Exception {
164 AbstractProtocolDecoderOutput out = executeRequest("DELETE", "body");
165 assertEquals(3, out.getMessageQueue().size());
166 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
167 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
168 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
169 }
170
171 @Test
172 public void testDIRMINA965NoContent() throws Exception {
173 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
174 public void flush(NextFilter nextFilter, IoSession session) {
175 }
176 };
177 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
178 buffer.putString("GET / HTTP/1.1\r\nHost: ", encoder);
179 buffer.rewind();
180 while (buffer.hasRemaining()) {
181 decoder.decode(session, buffer, out);
182 }
183 buffer = IoBuffer.allocate(0).setAutoExpand(true);
184 buffer.putString("dummy\r\n\r\n", encoder);
185 buffer.rewind();
186 while (buffer.hasRemaining()) {
187 decoder.decode(session, buffer, out);
188 }
189 assertEquals(2, out.getMessageQueue().size());
190 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
191 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
192 }
193
194 @Test
195 public void testDIRMINA965WithContent() throws Exception {
196 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
197 public void flush(NextFilter nextFilter, IoSession session) {
198 }
199 };
200 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
201 buffer.putString("GET / HTTP/1.1\r\nHost: ", encoder);
202 buffer.rewind();
203 while (buffer.hasRemaining()) {
204 decoder.decode(session, buffer, out);
205 }
206 buffer = IoBuffer.allocate(0).setAutoExpand(true);
207 buffer.putString("dummy\r\nContent-Length: 1\r\n\r\nA", encoder);
208 buffer.rewind();
209 while (buffer.hasRemaining()) {
210 decoder.decode(session, buffer, out);
211 }
212 assertEquals(3, out.getMessageQueue().size());
213 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
214 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
215 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
216 }
217 @Test
218 public void testDIRMINA965WithContentOnTwoChunks() throws Exception {
219 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
220 public void flush(NextFilter nextFilter, IoSession session) {
221 }
222 };
223 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
224 buffer.putString("GET / HTTP/1.1\r\nHost: ", encoder);
225 buffer.rewind();
226 while (buffer.hasRemaining()) {
227 decoder.decode(session, buffer, out);
228 }
229 buffer = IoBuffer.allocate(0).setAutoExpand(true);
230 buffer.putString("dummy\r\nContent-Length: 2\r\n\r\nA", encoder);
231 buffer.rewind();
232 while (buffer.hasRemaining()) {
233 decoder.decode(session, buffer, out);
234 }
235 buffer = IoBuffer.allocate(0).setAutoExpand(true);
236 buffer.putString("B", encoder);
237 buffer.rewind();
238 while (buffer.hasRemaining()) {
239 decoder.decode(session, buffer, out);
240 }
241 assertEquals(4, out.getMessageQueue().size());
242 assertTrue(out.getMessageQueue().poll() instanceof HttpRequest);
243 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
244 assertTrue(out.getMessageQueue().poll() instanceof IoBuffer);
245 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
246 }
247
248 @Test
249 public void testDIRMINA1035HeadersWithColons() throws Exception {
250 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
251 public void flush(NextFilter nextFilter, IoSession session) {
252 }
253 };
254
255 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
256 buffer.putString("GET / HTTP/1.0\r\nHost: localhost\r\n", encoder);
257 buffer.putString("SomeHeaderA: Value-A\r\n", encoder);
258 buffer.putString("SomeHeaderB: Value-B:Has:Some:Colons\r\n", encoder);
259 buffer.putString("SomeHeaderC: Value-C\r\n", encoder);
260 buffer.putString("SomeHeaderD:\r\n\r\n", encoder);
261 buffer.rewind();
262 while (buffer.hasRemaining()) {
263 decoder.decode(session, buffer, out);
264 }
265 assertEquals(2, out.getMessageQueue().size());
266 HttpRequest request = (HttpRequest) out.getMessageQueue().poll();
267 assertEquals("Value-A", request.getHeader("SomeHeaderA".toLowerCase()));
268 assertEquals("Value-B:Has:Some:Colons", request.getHeader("SomeHeaderB".toLowerCase()));
269 assertEquals("Value-C", request.getHeader("SomeHeaderC".toLowerCase()));
270 assertEquals("", request.getHeader("SomeHeaderD".toLowerCase()));
271 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
272 }
273
274 @Test
275 public void verifyThatHeaderWithoutLeadingSpaceIsSupported() throws Exception {
276 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
277 public void flush(NextFilter nextFilter, IoSession session) {
278 }
279 };
280 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
281 buffer.putString("GET / HTTP/1.0\r\nHost:localhost\r\n\r\n", encoder);
282 buffer.rewind();
283 while (buffer.hasRemaining()) {
284 decoder.decode(session, buffer, out);
285 }
286 assertEquals(2, out.getMessageQueue().size());
287 HttpRequest request = (HttpRequest) out.getMessageQueue().poll();
288 assertEquals("localhost", request.getHeader("host"));
289 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
290 }
291
292 @Test
293 public void verifyThatLeadingSpacesAreRemovedFromHeader() throws Exception {
294 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
295 public void flush(NextFilter nextFilter, IoSession session) {
296 }
297 };
298 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
299 buffer.putString("GET / HTTP/1.0\r\nHost: localhost\r\n\r\n", encoder);
300 buffer.rewind();
301 while (buffer.hasRemaining()) {
302 decoder.decode(session, buffer, out);
303 }
304 assertEquals(2, out.getMessageQueue().size());
305 HttpRequest request = (HttpRequest) out.getMessageQueue().poll();
306 assertEquals("localhost", request.getHeader("host"));
307 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
308 }
309
310 @Test
311 public void verifyThatTrailingSpacesAreRemovedFromHeader() throws Exception {
312 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
313 public void flush(NextFilter nextFilter, IoSession session) {
314 }
315 };
316 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
317 buffer.putString("GET / HTTP/1.0\r\nHost:localhost \r\n\r\n", encoder);
318 buffer.rewind();
319 while (buffer.hasRemaining()) {
320 decoder.decode(session, buffer, out);
321 }
322 assertEquals(2, out.getMessageQueue().size());
323 HttpRequest request = (HttpRequest) out.getMessageQueue().poll();
324 assertEquals("localhost", request.getHeader("host"));
325 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
326 }
327
328 @Test
329 public void dosOnRequestWithAdditionalData() throws Exception {
330 AbstractProtocolDecoderOutput out = new AbstractProtocolDecoderOutput() {
331 public void flush(NextFilter nextFilter, IoSession session) {
332 }
333 };
334
335 IoBuffer buffer = IoBuffer.allocate(0).setAutoExpand(true);
336 buffer.putString("GET / HTTP/1.0\r\nHost:localhost \r\n\r\ndummy", encoder);
337 buffer.rewind();
338 int prevBufferPosition = buffer.position();
339
340 while (buffer.hasRemaining()) {
341 decoder.decode(session, buffer, out);
342 assertNotEquals("Buffer at new position", prevBufferPosition, buffer.position());
343 prevBufferPosition = buffer.position();
344 }
345
346 assertEquals(2, out.getMessageQueue().size());
347 HttpRequest request = (HttpRequest) out.getMessageQueue().poll();
348 assertEquals("localhost", request.getHeader("host"));
349 assertTrue(out.getMessageQueue().poll() instanceof HttpEndOfContent);
350 session.removeAttribute(DECODER_STATE_ATT);
351 }
352 }