| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.http; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.jetty.http.HttpParser.State; |
| import org.eclipse.jetty.util.BufferUtil; |
| import org.eclipse.jetty.util.log.StacklessLogging; |
| import org.hamcrest.Matchers; |
| import org.junit.Assert; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import static org.hamcrest.Matchers.containsString; |
| import static org.junit.Assert.assertThat; |
| |
| public class HttpParserTest |
| { |
| /** |
| * Parse until {@link State#END} state. |
| * If the parser is already in the END state, then it is {@link HttpParser#reset()} and re-parsed. |
| * |
| * @param parser The parser to test |
| * @param buffer the buffer to parse |
| * @throws IllegalStateException If the buffers have already been partially parsed. |
| */ |
| public static void parseAll(HttpParser parser, ByteBuffer buffer) |
| { |
| if (parser.isState(State.END)) |
| parser.reset(); |
| if (!parser.isState(State.START)) |
| throw new IllegalStateException("!START"); |
| |
| // continue parsing |
| int remaining = buffer.remaining(); |
| while (!parser.isState(State.END) && remaining > 0) |
| { |
| int was_remaining = remaining; |
| parser.parseNext(buffer); |
| remaining = buffer.remaining(); |
| if (remaining == was_remaining) |
| break; |
| } |
| } |
| |
| @Test |
| public void HttpMethodTest() |
| { |
| Assert.assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("Wibble "))); |
| Assert.assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("GET"))); |
| Assert.assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("MO"))); |
| |
| Assert.assertEquals(HttpMethod.GET, HttpMethod.lookAheadGet(BufferUtil.toBuffer("GET "))); |
| Assert.assertEquals(HttpMethod.MOVE, HttpMethod.lookAheadGet(BufferUtil.toBuffer("MOVE "))); |
| |
| ByteBuffer b = BufferUtil.allocateDirect(128); |
| BufferUtil.append(b, BufferUtil.toBuffer("GET")); |
| Assert.assertNull(HttpMethod.lookAheadGet(b)); |
| |
| BufferUtil.append(b, BufferUtil.toBuffer(" ")); |
| Assert.assertEquals(HttpMethod.GET, HttpMethod.lookAheadGet(b)); |
| } |
| |
| @Test |
| public void testLineParse_Mock_IP() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /mock/127.0.0.1 HTTP/1.1\r\n" + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/mock/127.0.0.1", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testLineParse0() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /foo HTTP/1.0\r\n" + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/foo", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testLineParse1_RFC2616() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("GET /999\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, HttpCompliance.RFC2616); |
| parseAll(parser, buffer); |
| |
| Assert.assertNull(_bad); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/999", _uriOrStatus); |
| Assert.assertEquals("HTTP/0.9", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| assertThat(_complianceViolation,containsString("0.9")); |
| } |
| |
| @Test |
| public void testLineParse1() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("GET /999\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("HTTP/0.9 not supported", _bad); |
| Assert.assertNull(_complianceViolation); |
| } |
| |
| @Test |
| public void testLineParse2_RFC2616() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /222 \r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, HttpCompliance.RFC2616); |
| parseAll(parser, buffer); |
| |
| Assert.assertNull(_bad); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/222", _uriOrStatus); |
| Assert.assertEquals("HTTP/0.9", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| assertThat(_complianceViolation,containsString("0.9")); |
| } |
| |
| @Test |
| public void testLineParse2() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /222 \r\n"); |
| |
| _versionOrReason = null; |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("HTTP/0.9 not supported", _bad); |
| Assert.assertNull(_complianceViolation); |
| } |
| |
| @Test |
| public void testLineParse3() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /fo\u0690 HTTP/1.0\r\n" + "\r\n", StandardCharsets.UTF_8); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/fo\u0690", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testLineParse4() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /foo?param=\u0690 HTTP/1.0\r\n" + "\r\n", StandardCharsets.UTF_8); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/foo?param=\u0690", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testLongURLParse() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("POST /123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/ HTTP/1.0\r\n" + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/123456789abcdef/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testConnect() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer("CONNECT 192.168.1.2:80 HTTP/1.1\r\n" + "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("CONNECT", _methodOrVersion); |
| Assert.assertEquals("192.168.1.2:80", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| } |
| |
| @Test |
| public void testSimple() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Connection: close\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Connection", _hdr[1]); |
| Assert.assertEquals("close", _val[1]); |
| Assert.assertEquals(1, _headers); |
| } |
| |
| @Test |
| public void testFoldedField2616() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name: value\r\n" + |
| " extra\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, HttpCompliance.RFC2616); |
| parseAll(parser, buffer); |
| |
| Assert.assertThat(_bad, Matchers.nullValue()); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Name", _hdr[1]); |
| Assert.assertEquals("value extra", _val[1]); |
| Assert.assertEquals(1, _headers); |
| assertThat(_complianceViolation,containsString("folding")); |
| } |
| |
| @Test |
| public void testFoldedField7230() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name: value\r\n" + |
| " extra\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, 4096, HttpCompliance.RFC7230); |
| parseAll(parser, buffer); |
| |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| Assert.assertThat(_bad, Matchers.containsString("Header Folding")); |
| Assert.assertNull(_complianceViolation); |
| } |
| |
| @Test |
| public void testWhiteSpaceInName() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "N ame: value\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, 4096, HttpCompliance.RFC7230); |
| parseAll(parser, buffer); |
| |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| Assert.assertThat(_bad, Matchers.containsString("Illegal character")); |
| } |
| |
| @Test |
| public void testWhiteSpaceAfterName() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name : value\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, 4096, HttpCompliance.RFC7230); |
| parseAll(parser, buffer); |
| |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| Assert.assertThat(_bad, Matchers.containsString("Illegal character")); |
| } |
| |
| @Test |
| public void testNoValue() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name0: \r\n" + |
| "Name1:\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Name0", _hdr[1]); |
| Assert.assertEquals("", _val[1]); |
| Assert.assertEquals("Name1", _hdr[2]); |
| Assert.assertEquals("", _val[2]); |
| Assert.assertEquals(2, _headers); |
| } |
| |
| @Test |
| public void testNoColon2616() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name\r\n" + |
| "Other: value\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler,HttpCompliance.RFC2616); |
| parseAll(parser, buffer); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Name", _hdr[1]); |
| Assert.assertEquals("", _val[1]); |
| Assert.assertEquals("Other", _hdr[2]); |
| Assert.assertEquals("value", _val[2]); |
| Assert.assertEquals(2, _headers); |
| assertThat(_complianceViolation,containsString("name only")); |
| } |
| |
| @Test |
| public void testNoColon7230() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Name\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler,HttpCompliance.RFC7230); |
| parseAll(parser, buffer); |
| Assert.assertThat(_bad, Matchers.containsString("Illegal character")); |
| Assert.assertNull(_complianceViolation); |
| } |
| |
| |
| @Test |
| public void testHeaderParseDirect() throws Exception |
| { |
| ByteBuffer b0 = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Header1: value1\r\n" + |
| "Header2: value 2a \r\n" + |
| "Header3: 3\r\n" + |
| "Header4:value4\r\n" + |
| "Server5: notServer\r\n" + |
| "HostHeader: notHost\r\n" + |
| "Connection: close\r\n" + |
| "Accept-Encoding: gzip, deflated\r\n" + |
| "Accept: unknown\r\n" + |
| "\r\n"); |
| ByteBuffer buffer = BufferUtil.allocateDirect(b0.capacity()); |
| int pos = BufferUtil.flipToFill(buffer); |
| BufferUtil.put(b0, buffer); |
| BufferUtil.flipToFlush(buffer, pos); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("Header2", _hdr[2]); |
| Assert.assertEquals("value 2a", _val[2]); |
| Assert.assertEquals("Header3", _hdr[3]); |
| Assert.assertEquals("3", _val[3]); |
| Assert.assertEquals("Header4", _hdr[4]); |
| Assert.assertEquals("value4", _val[4]); |
| Assert.assertEquals("Server5", _hdr[5]); |
| Assert.assertEquals("notServer", _val[5]); |
| Assert.assertEquals("HostHeader", _hdr[6]); |
| Assert.assertEquals("notHost", _val[6]); |
| Assert.assertEquals("Connection", _hdr[7]); |
| Assert.assertEquals("close", _val[7]); |
| Assert.assertEquals("Accept-Encoding", _hdr[8]); |
| Assert.assertEquals("gzip, deflated", _val[8]); |
| Assert.assertEquals("Accept", _hdr[9]); |
| Assert.assertEquals("unknown", _val[9]); |
| Assert.assertEquals(9, _headers); |
| } |
| |
| @Test |
| public void testHeaderParseCRLF() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Header1: value1\r\n" + |
| "Header2: value 2a \r\n" + |
| "Header3: 3\r\n" + |
| "Header4:value4\r\n" + |
| "Server5: notServer\r\n" + |
| "HostHeader: notHost\r\n" + |
| "Connection: close\r\n" + |
| "Accept-Encoding: gzip, deflated\r\n" + |
| "Accept: unknown\r\n" + |
| "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("Header2", _hdr[2]); |
| Assert.assertEquals("value 2a", _val[2]); |
| Assert.assertEquals("Header3", _hdr[3]); |
| Assert.assertEquals("3", _val[3]); |
| Assert.assertEquals("Header4", _hdr[4]); |
| Assert.assertEquals("value4", _val[4]); |
| Assert.assertEquals("Server5", _hdr[5]); |
| Assert.assertEquals("notServer", _val[5]); |
| Assert.assertEquals("HostHeader", _hdr[6]); |
| Assert.assertEquals("notHost", _val[6]); |
| Assert.assertEquals("Connection", _hdr[7]); |
| Assert.assertEquals("close", _val[7]); |
| Assert.assertEquals("Accept-Encoding", _hdr[8]); |
| Assert.assertEquals("gzip, deflated", _val[8]); |
| Assert.assertEquals("Accept", _hdr[9]); |
| Assert.assertEquals("unknown", _val[9]); |
| Assert.assertEquals(9, _headers); |
| } |
| |
| @Test |
| public void testHeaderParseLF() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\n" + |
| "Host: localhost\n" + |
| "Header1: value1\n" + |
| "Header2: value 2a value 2b \n" + |
| "Header3: 3\n" + |
| "Header4:value4\n" + |
| "Server5: notServer\n" + |
| "HostHeader: notHost\n" + |
| "Connection: close\n" + |
| "Accept-Encoding: gzip, deflated\n" + |
| "Accept: unknown\n" + |
| "\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("Header2", _hdr[2]); |
| Assert.assertEquals("value 2a value 2b", _val[2]); |
| Assert.assertEquals("Header3", _hdr[3]); |
| Assert.assertEquals("3", _val[3]); |
| Assert.assertEquals("Header4", _hdr[4]); |
| Assert.assertEquals("value4", _val[4]); |
| Assert.assertEquals("Server5", _hdr[5]); |
| Assert.assertEquals("notServer", _val[5]); |
| Assert.assertEquals("HostHeader", _hdr[6]); |
| Assert.assertEquals("notHost", _val[6]); |
| Assert.assertEquals("Connection", _hdr[7]); |
| Assert.assertEquals("close", _val[7]); |
| Assert.assertEquals("Accept-Encoding", _hdr[8]); |
| Assert.assertEquals("gzip, deflated", _val[8]); |
| Assert.assertEquals("Accept", _hdr[9]); |
| Assert.assertEquals("unknown", _val[9]); |
| Assert.assertEquals(9, _headers); |
| } |
| |
| @Test |
| public void testQuoted() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\n" + |
| "Name0: \"value0\"\t\n" + |
| "Name1: \"value\t1\"\n" + |
| "Name2: \"value\t2A\",\"value,2B\"\t\n" + |
| "\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Name0", _hdr[0]); |
| Assert.assertEquals("\"value0\"", _val[0]); |
| Assert.assertEquals("Name1", _hdr[1]); |
| Assert.assertEquals("\"value\t1\"", _val[1]); |
| Assert.assertEquals("Name2", _hdr[2]); |
| Assert.assertEquals("\"value\t2A\",\"value,2B\"", _val[2]); |
| Assert.assertEquals(2, _headers); |
| } |
| |
| @Test |
| public void testEncodedHeader() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.allocate(4096); |
| BufferUtil.flipToFill(buffer); |
| BufferUtil.put(BufferUtil.toBuffer("GET "), buffer); |
| buffer.put("/foo/\u0690/".getBytes(StandardCharsets.UTF_8)); |
| BufferUtil.put(BufferUtil.toBuffer(" HTTP/1.0\r\n"), buffer); |
| BufferUtil.put(BufferUtil.toBuffer("Header1: "), buffer); |
| buffer.put("\u00e6 \u00e6".getBytes(StandardCharsets.ISO_8859_1)); |
| BufferUtil.put(BufferUtil.toBuffer(" \r\n\r\n"), buffer); |
| BufferUtil.flipToFlush(buffer, 0); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/foo/\u0690/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("\u00e6 \u00e6", _val[0]); |
| Assert.assertEquals(0, _headers); |
| Assert.assertEquals(null, _bad); |
| } |
| |
| @Test |
| public void testBadMethodEncoding() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "G\u00e6T / HTTP/1.0\r\nHeader0: value0\r\n\n\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| } |
| |
| @Test |
| public void testBadVersionEncoding() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / H\u00e6P/1.0\r\nHeader0: value0\r\n\n\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| } |
| |
| @Test |
| public void testBadHeaderEncoding() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\nH\u00e6der0: value0\r\n\n\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertThat(_bad, Matchers.notNullValue()); |
| } |
| |
| @Test |
| public void testHeaderTab() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" + |
| "Host: localhost\r\n" + |
| "Header: value\talternate\r\n" + |
| "\n\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Header", _hdr[1]); |
| Assert.assertEquals("value\talternate", _val[1]); |
| } |
| |
| @Test |
| public void testCaseInsensitive() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "get / http/1.0\r\n" + |
| "HOST: localhost\r\n" + |
| "cOnNeCtIoN: ClOsE\r\n" + |
| "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, -1, HttpCompliance.RFC7230); |
| parseAll(parser, buffer); |
| Assert.assertNull(_bad); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Connection", _hdr[1]); |
| Assert.assertEquals("close", _val[1]); |
| Assert.assertEquals(1, _headers); |
| Assert.assertNull(_complianceViolation); |
| } |
| |
| @Test |
| public void testCaseSensitiveLegacy() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "gEt / http/1.0\r\n" + |
| "HOST: localhost\r\n" + |
| "cOnNeCtIoN: ClOsE\r\n" + |
| "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler, -1, HttpCompliance.LEGACY); |
| parseAll(parser, buffer); |
| Assert.assertNull(_bad); |
| Assert.assertEquals("gEt", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("HOST", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("cOnNeCtIoN", _hdr[1]); |
| Assert.assertEquals("ClOsE", _val[1]); |
| Assert.assertEquals(1, _headers); |
| assertThat(_complianceViolation,containsString("case sensitive")); |
| } |
| |
| @Test |
| public void testSplitHeaderParse() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "XXXXSPLIT / HTTP/1.0\r\n" + |
| "Host: localhost\r\n" + |
| "Header1: value1\r\n" + |
| "Header2: value 2a \r\n" + |
| "Header3: 3\r\n" + |
| "Header4:value4\r\n" + |
| "Server5: notServer\r\n" + |
| "\r\nZZZZ"); |
| buffer.position(2); |
| buffer.limit(buffer.capacity() - 2); |
| buffer = buffer.slice(); |
| |
| for (int i = 0; i < buffer.capacity() - 4; i++) |
| { |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| buffer.position(2); |
| buffer.limit(2 + i); |
| |
| if (!parser.parseNext(buffer)) |
| { |
| // consumed all |
| Assert.assertEquals(0, buffer.remaining()); |
| |
| // parse the rest |
| buffer.limit(buffer.capacity() - 2); |
| parser.parseNext(buffer); |
| } |
| |
| Assert.assertEquals("SPLIT", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("Header2", _hdr[2]); |
| Assert.assertEquals("value 2a", _val[2]); |
| Assert.assertEquals("Header3", _hdr[3]); |
| Assert.assertEquals("3", _val[3]); |
| Assert.assertEquals("Header4", _hdr[4]); |
| Assert.assertEquals("value4", _val[4]); |
| Assert.assertEquals("Server5", _hdr[5]); |
| Assert.assertEquals("notServer", _val[5]); |
| Assert.assertEquals(5, _headers); |
| } |
| } |
| |
| @Test |
| public void testChunkParse() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /chunk HTTP/1.0\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n" |
| + "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(1, _headers); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("value1", _val[0]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testChunkParseTrailer() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /chunk HTTP/1.0\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n" |
| + "Trailer: value\r\n" |
| + "\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(1, _headers); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("value1", _val[0]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testChunkParseBadTrailer() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /chunk HTTP/1.0\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n" |
| + "Trailer: value"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(1, _headers); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("value1", _val[0]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_early); |
| } |
| |
| |
| @Test |
| public void testChunkParseNoTrailer() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /chunk HTTP/1.0\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(1, _headers); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("value1", _val[0]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testStartEOF() throws Exception |
| { |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| |
| Assert.assertTrue(_early); |
| Assert.assertEquals(null, _bad); |
| } |
| |
| @Test |
| public void testEarlyEOF() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /uri HTTP/1.0\r\n" |
| + "Content-Length: 20\r\n" |
| + "\r\n" |
| + "0123456789"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.atEOF(); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/uri", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals("0123456789", _content); |
| |
| Assert.assertTrue(_early); |
| } |
| |
| @Test |
| public void testChunkEarlyEOF() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /chunk HTTP/1.0\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n"); |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.atEOF(); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(1, _headers); |
| Assert.assertEquals("Header1", _hdr[0]); |
| Assert.assertEquals("value1", _val[0]); |
| Assert.assertEquals("0123456789", _content); |
| |
| Assert.assertTrue(_early); |
| } |
| |
| @Test |
| public void testMultiParse() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET /mp HTTP/1.0\r\n" |
| + "Connection: Keep-Alive\r\n" |
| + "Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n" |
| |
| + "\r\n" |
| |
| + "POST /foo HTTP/1.0\r\n" |
| + "Connection: Keep-Alive\r\n" |
| + "Header2: value2\r\n" |
| + "Content-Length: 0\r\n" |
| + "\r\n" |
| |
| + "PUT /doodle HTTP/1.0\r\n" |
| + "Connection: close\r\n" |
| + "Header3: value3\r\n" |
| + "Content-Length: 10\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/mp", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| parser.reset(); |
| init(); |
| parser.parseNext(buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/foo", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header2", _hdr[1]); |
| Assert.assertEquals("value2", _val[1]); |
| Assert.assertEquals(null, _content); |
| |
| parser.reset(); |
| init(); |
| parser.parseNext(buffer); |
| parser.atEOF(); |
| Assert.assertEquals("PUT", _methodOrVersion); |
| Assert.assertEquals("/doodle", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header3", _hdr[1]); |
| Assert.assertEquals("value3", _val[1]); |
| Assert.assertEquals("0123456789", _content); |
| } |
| |
| @Test |
| public void testMultiParseEarlyEOF() throws Exception |
| { |
| ByteBuffer buffer0 = BufferUtil.toBuffer( |
| "GET /mp HTTP/1.0\r\n" |
| + "Connection: Keep-Alive\r\n"); |
| |
| ByteBuffer buffer1 = BufferUtil.toBuffer("Header1: value1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "a;\r\n" |
| + "0123456789\r\n" |
| + "1a\r\n" |
| + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n" |
| + "0\r\n" |
| |
| + "\r\n" |
| |
| + "POST /foo HTTP/1.0\r\n" |
| + "Connection: Keep-Alive\r\n" |
| + "Header2: value2\r\n" |
| + "Content-Length: 0\r\n" |
| + "\r\n" |
| |
| + "PUT /doodle HTTP/1.0\r\n" |
| + "Connection: close\r\n" |
| + "Header3: value3\r\n" |
| + "Content-Length: 10\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer0); |
| parser.atEOF(); |
| parser.parseNext(buffer1); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/mp", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header1", _hdr[1]); |
| Assert.assertEquals("value1", _val[1]); |
| Assert.assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content); |
| |
| parser.reset(); |
| init(); |
| parser.parseNext(buffer1); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/foo", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header2", _hdr[1]); |
| Assert.assertEquals("value2", _val[1]); |
| Assert.assertEquals(null, _content); |
| |
| parser.reset(); |
| init(); |
| parser.parseNext(buffer1); |
| Assert.assertEquals("PUT", _methodOrVersion); |
| Assert.assertEquals("/doodle", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.0", _versionOrReason); |
| Assert.assertEquals(2, _headers); |
| Assert.assertEquals("Header3", _hdr[1]); |
| Assert.assertEquals("value3", _val[1]); |
| Assert.assertEquals("0123456789", _content); |
| } |
| |
| @Test |
| public void testResponseParse0() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 200 Correct\r\n" |
| + "Content-Length: 10\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals("Correct", _versionOrReason); |
| Assert.assertEquals(10, _content.length()); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponseParse1() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 304 Not-Modified\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("304", _uriOrStatus); |
| Assert.assertEquals("Not-Modified", _versionOrReason); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponseParse2() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 204 No-Content\r\n" |
| + "Header: value\r\n" |
| + "\r\n" |
| |
| + "HTTP/1.1 200 Correct\r\n" |
| + "Content-Length: 10\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("204", _uriOrStatus); |
| Assert.assertEquals("No-Content", _versionOrReason); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| |
| parser.reset(); |
| init(); |
| |
| parser.parseNext(buffer); |
| parser.atEOF(); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals("Correct", _versionOrReason); |
| Assert.assertEquals(_content.length(), 10); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponseParse3() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 200\r\n" |
| + "Content-Length: 10\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals(null, _versionOrReason); |
| Assert.assertEquals(_content.length(), 10); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponseParse4() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 200 \r\n" |
| + "Content-Length: 10\r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals(null, _versionOrReason); |
| Assert.assertEquals(_content.length(), 10); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponseEOFContent() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 200 \r\n" |
| + "Content-Type: text/plain\r\n" |
| + "\r\n" |
| + "0123456789\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.atEOF(); |
| parser.parseNext(buffer); |
| |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals(null, _versionOrReason); |
| Assert.assertEquals(12, _content.length()); |
| Assert.assertEquals("0123456789\r\n", _content); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponse304WithContentLength() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 304 found\r\n" |
| + "Content-Length: 10\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("304", _uriOrStatus); |
| Assert.assertEquals("found", _versionOrReason); |
| Assert.assertEquals(null, _content); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testResponse101WithTransferEncoding() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 101 switching protocols\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("101", _uriOrStatus); |
| Assert.assertEquals("switching protocols", _versionOrReason); |
| Assert.assertEquals(null, _content); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testSeekEOF() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 200 OK\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n" |
| + "\r\n" // extra CRLF ignored |
| + "HTTP/1.1 400 OK\r\n"); // extra data causes close ?? |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("HTTP/1.1", _methodOrVersion); |
| Assert.assertEquals("200", _uriOrStatus); |
| Assert.assertEquals("OK", _versionOrReason); |
| Assert.assertEquals(null, _content); |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| |
| parser.close(); |
| parser.reset(); |
| parser.parseNext(buffer); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testNoURI() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("No URI", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testNoURI2() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET \r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("No URI", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testUnknownReponseVersion() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HPPT/7.7 200 OK\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("Unknown Version", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| |
| } |
| |
| @Test |
| public void testNoStatus() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("No Status", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testNoStatus2() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "HTTP/1.1 \r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.ResponseHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("No Status", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testBadRequestVersion() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HPPT/7.7\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("Unknown Version", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| |
| buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.01\r\n" |
| + "Content-Length: 0\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| handler = new Handler(); |
| parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _methodOrVersion); |
| Assert.assertEquals("Unknown Version", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testBadCR() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" |
| + "Content-Length: 0\r" |
| + "Connection: close\r" |
| + "\r"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("Bad EOL", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| |
| buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r" |
| + "Content-Length: 0\r" |
| + "Connection: close\r" |
| + "\r"); |
| |
| handler = new Handler(); |
| parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("Bad EOL", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testBadContentLength0() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" |
| + "Content-Length: abc\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("Invalid Content-Length Value", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testBadContentLength1() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" |
| + "Content-Length: 9999999999999999999999999999999999999999999999\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("Invalid Content-Length Value", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testBadContentLength2() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.0\r\n" |
| + "Content-Length: 1.5\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("Invalid Content-Length Value", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testDuplicateContentLengthWithLargerThenCorrectValue() |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "POST / HTTP/1.1\r\n" |
| + "Content-Length: 2\r\n" |
| + "Content-Length: 1\r\n" |
| + "Connection: close\r\n" |
| + "\r\n" |
| + "X"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("Duplicate Content-Length", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testDuplicateContentLengthWithCorrectThenLargerValue() |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "POST / HTTP/1.1\r\n" |
| + "Content-Length: 1\r\n" |
| + "Content-Length: 2\r\n" |
| + "Connection: close\r\n" |
| + "\r\n" |
| + "X"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| |
| parser.parseNext(buffer); |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("Duplicate Content-Length", _bad); |
| Assert.assertFalse(buffer.hasRemaining()); |
| Assert.assertEquals(HttpParser.State.CLOSE, parser.getState()); |
| parser.atEOF(); |
| parser.parseNext(BufferUtil.EMPTY_BUFFER); |
| Assert.assertEquals(HttpParser.State.CLOSED, parser.getState()); |
| } |
| |
| @Test |
| public void testTransferEncodingChunkedThenContentLength() |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "POST /chunk HTTP/1.1\r\n" |
| + "Host: localhost\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "Content-Length: 1\r\n" |
| + "\r\n" |
| + "1\r\n" |
| + "X\r\n" |
| + "0\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals("X", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testContentLengthThenTransferEncodingChunked() |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "POST /chunk HTTP/1.1\r\n" |
| + "Host: localhost\r\n" |
| + "Content-Length: 1\r\n" |
| + "Transfer-Encoding: chunked\r\n" |
| + "\r\n" |
| + "1\r\n" |
| + "X\r\n" |
| + "0\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertEquals("POST", _methodOrVersion); |
| Assert.assertEquals("/chunk", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals("X", _content); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| } |
| |
| @Test |
| public void testHost() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: host\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("host", _host); |
| Assert.assertEquals(0, _port); |
| } |
| |
| @Test |
| public void testUriHost11() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET http://host/ HTTP/1.1\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("No Host", _bad); |
| Assert.assertEquals("http://host/", _uriOrStatus); |
| Assert.assertEquals(0, _port); |
| } |
| |
| @Test |
| public void testUriHost10() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET http://host/ HTTP/1.0\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertNull(_bad); |
| Assert.assertEquals("http://host/", _uriOrStatus); |
| Assert.assertEquals(0, _port); |
| } |
| |
| @Test |
| public void testNoHost() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("No Host", _bad); |
| } |
| |
| @Test |
| public void testIPHost() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: 192.168.0.1\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("192.168.0.1", _host); |
| Assert.assertEquals(0, _port); |
| } |
| |
| @Test |
| public void testIPv6Host() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: [::1]\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("[::1]", _host); |
| Assert.assertEquals(0, _port); |
| } |
| |
| @Test |
| public void testBadIPv6Host() throws Exception |
| { |
| try(StacklessLogging s = new StacklessLogging(HttpParser.class)) |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: [::1\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertThat(_bad, Matchers.containsString("Bad")); |
| } |
| } |
| |
| @Test |
| public void testHostPort() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: myhost:8888\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("myhost", _host); |
| Assert.assertEquals(8888, _port); |
| } |
| |
| @Test |
| public void testHostBadPort() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: myhost:testBadPort\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertThat(_bad, Matchers.containsString("Bad Host")); |
| } |
| |
| @Test |
| public void testIPHostPort() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: 192.168.0.1:8888\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("192.168.0.1", _host); |
| Assert.assertEquals(8888, _port); |
| } |
| |
| @Test |
| public void testIPv6HostPort() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host: [::1]:8888\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals("[::1]", _host); |
| Assert.assertEquals(8888, _port); |
| } |
| |
| @Test |
| public void testEmptyHostPort() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" |
| + "Host:\r\n" |
| + "Connection: close\r\n" |
| + "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| Assert.assertEquals(null, _host); |
| Assert.assertEquals(null, _bad); |
| } |
| @Test |
| public void testCachedField() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" + |
| "Host: www.smh.com.au\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| Assert.assertEquals("www.smh.com.au", parser.getFieldCache().get("Host: www.smh.com.au").getValue()); |
| HttpField field = _fields.get(0); |
| |
| buffer.position(0); |
| parseAll(parser, buffer); |
| Assert.assertTrue(field == _fields.get(0)); |
| } |
| |
| @Test |
| public void testParseRequest() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "GET / HTTP/1.1\r\n" + |
| "Host: localhost\r\n" + |
| "Header1: value1\r\n" + |
| "Connection: close\r\n" + |
| "Accept-Encoding: gzip, deflated\r\n" + |
| "Accept: unknown\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parser.parseNext(buffer); |
| |
| Assert.assertEquals("GET", _methodOrVersion); |
| Assert.assertEquals("/", _uriOrStatus); |
| Assert.assertEquals("HTTP/1.1", _versionOrReason); |
| Assert.assertEquals("Host", _hdr[0]); |
| Assert.assertEquals("localhost", _val[0]); |
| Assert.assertEquals("Connection", _hdr[2]); |
| Assert.assertEquals("close", _val[2]); |
| Assert.assertEquals("Accept-Encoding", _hdr[3]); |
| Assert.assertEquals("gzip, deflated", _val[3]); |
| Assert.assertEquals("Accept", _hdr[4]); |
| Assert.assertEquals("unknown", _val[4]); |
| } |
| |
| @Test |
| public void testHTTP2Preface() throws Exception |
| { |
| ByteBuffer buffer = BufferUtil.toBuffer( |
| "PRI * HTTP/2.0\r\n" + |
| "\r\n" + |
| "SM\r\n" + |
| "\r\n"); |
| |
| HttpParser.RequestHandler handler = new Handler(); |
| HttpParser parser = new HttpParser(handler); |
| parseAll(parser, buffer); |
| |
| Assert.assertTrue(_headerCompleted); |
| Assert.assertTrue(_messageCompleted); |
| Assert.assertEquals("PRI", _methodOrVersion); |
| Assert.assertEquals("*", _uriOrStatus); |
| Assert.assertEquals("HTTP/2.0", _versionOrReason); |
| Assert.assertEquals(-1, _headers); |
| Assert.assertEquals(null, _bad); |
| } |
| |
| @Before |
| public void init() |
| { |
| _bad = null; |
| _content = null; |
| _methodOrVersion = null; |
| _uriOrStatus = null; |
| _versionOrReason = null; |
| _hdr = null; |
| _val = null; |
| _headers = 0; |
| _headerCompleted = false; |
| _messageCompleted = false; |
| _complianceViolation = null; |
| } |
| |
| private String _host; |
| private int _port; |
| private String _bad; |
| private String _content; |
| private String _methodOrVersion; |
| private String _uriOrStatus; |
| private String _versionOrReason; |
| private List<HttpField> _fields = new ArrayList<>(); |
| private String[] _hdr; |
| private String[] _val; |
| private int _headers; |
| private boolean _early; |
| private boolean _headerCompleted; |
| private boolean _messageCompleted; |
| private String _complianceViolation; |
| |
| private class Handler implements HttpParser.RequestHandler, HttpParser.ResponseHandler, HttpParser.ComplianceHandler |
| { |
| private HttpFields fields; |
| |
| @Override |
| public boolean content(ByteBuffer ref) |
| { |
| if (_content == null) |
| _content = ""; |
| String c = BufferUtil.toString(ref, StandardCharsets.UTF_8); |
| _content = _content + c; |
| ref.position(ref.limit()); |
| return false; |
| } |
| |
| @Override |
| public boolean startRequest(String method, String uri, HttpVersion version) |
| { |
| _fields.clear(); |
| _headers = -1; |
| _hdr = new String[10]; |
| _val = new String[10]; |
| _methodOrVersion = method; |
| _uriOrStatus = uri; |
| _versionOrReason = version == null ? null : version.asString(); |
| |
| fields = new HttpFields(); |
| _messageCompleted = false; |
| _headerCompleted = false; |
| _early = false; |
| return false; |
| } |
| |
| @Override |
| public void parsedHeader(HttpField field) |
| { |
| _fields.add(field); |
| _hdr[++_headers] = field.getName(); |
| _val[_headers] = field.getValue(); |
| |
| if (field instanceof HostPortHttpField) |
| { |
| HostPortHttpField hpfield = (HostPortHttpField)field; |
| _host = hpfield.getHost(); |
| _port = hpfield.getPort(); |
| } |
| } |
| |
| @Override |
| public boolean headerComplete() |
| { |
| _content = null; |
| String s0 = fields.toString(); |
| String s1 = fields.toString(); |
| if (!s0.equals(s1)) |
| { |
| throw new IllegalStateException(); |
| } |
| |
| _headerCompleted = true; |
| return false; |
| } |
| |
| @Override |
| public boolean contentComplete() |
| { |
| return false; |
| } |
| |
| @Override |
| public boolean messageComplete() |
| { |
| _messageCompleted = true; |
| return true; |
| } |
| |
| @Override |
| public void badMessage(int status, String reason) |
| { |
| _bad = reason == null ? ("" + status) : reason; |
| } |
| |
| @Override |
| public boolean startResponse(HttpVersion version, int status, String reason) |
| { |
| _fields.clear(); |
| _methodOrVersion = version.asString(); |
| _uriOrStatus = Integer.toString(status); |
| _versionOrReason = reason; |
| |
| fields = new HttpFields(); |
| _hdr = new String[9]; |
| _val = new String[9]; |
| |
| _messageCompleted = false; |
| _headerCompleted = false; |
| return false; |
| } |
| |
| @Override |
| public void earlyEOF() |
| { |
| _early = true; |
| } |
| |
| @Override |
| public int getHeaderCacheSize() |
| { |
| return 512; |
| } |
| |
| @Override |
| public void onComplianceViolation(HttpCompliance compliance, HttpCompliance required, String reason) |
| { |
| _complianceViolation=reason; |
| } |
| } |
| } |