/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package org.apache.http.impl.nio.codecs; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestFactory; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseFactory; import org.apache.http.HttpVersion; import org.apache.http.impl.DefaultHttpRequestFactory; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.impl.nio.reactor.SessionInputBufferImpl; import org.apache.http.nio.NHttpMessageParser; import org.apache.http.nio.reactor.SessionInputBuffer; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.HttpParams; import org.junit.Assert; import org.junit.Test; /** * Simple tests for {@link AbstractMessageParser}. */ public class TestHttpMessageParser { private static ReadableByteChannel newChannel(final String s, final String charset) throws UnsupportedEncodingException { return Channels.newChannel(new ByteArrayInputStream(s.getBytes(charset))); } private static ReadableByteChannel newChannel(final String s) throws UnsupportedEncodingException { return newChannel(s, "US-ASCII"); } @Test public void testSimpleParsing() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.1\r\nSome header: stuff\r\n\r\n")); HttpRequest request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals("/whatever", request.getRequestLine().getUri()); Assert.assertEquals(1, request.getAllHeaders().length); } @Test public void testParsingChunkedMessages() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatev")); HttpRequest request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("er HTTP/1.1\r")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\nSome header: stuff\r\n\r\n")); request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals("/whatever", request.getRequestLine().getUri()); Assert.assertEquals(1, request.getAllHeaders().length); } @Test public void testParsingFoldedHeaders() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatev")); HttpRequest request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("er HTTP/1.1\r")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\nSome header: stuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel(" more\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\tstuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\r\n")); request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals("/whatever", request.getRequestLine().getUri()); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue()); } @Test public void testParsingBadlyFoldedFirstHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatev")); HttpRequest request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("er HTTP/1.1\r")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\n Some header: stuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel(" more stuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\r\n")); request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals("/whatever", request.getRequestLine().getUri()); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue()); } @Test public void testParsingEmptyFoldedHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatev")); HttpRequest request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("er HTTP/1.1\r")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\n Some header: stuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel(" \r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel(" more stuff\r\n")); request = requestParser.parse(); Assert.assertNull(request); requestParser.fillBuffer(newChannel("\r\n")); request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals("/whatever", request.getRequestLine().getUri()); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("stuff more stuff", request.getFirstHeader("Some header").getValue()); } @Test public void testParsingIncompleteRequestLine() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0"); requestParser.fillBuffer(channel); requestParser.fillBuffer(channel); HttpRequest request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals(HttpVersion.HTTP_1_0, request.getRequestLine().getProtocolVersion()); } @Test public void testParsingIncompleteHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: whatever"); requestParser.fillBuffer(channel); requestParser.fillBuffer(channel); HttpRequest request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("whatever", request.getFirstHeader("Header").getValue()); } @Test public void testParsingInvalidRequestLine() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); ReadableByteChannel channel = newChannel("GET garbage\r\n"); requestParser.fillBuffer(channel); try { requestParser.parse(); Assert.fail("HttpException should have been thrown"); } catch (HttpException ex) { // expected } } @Test public void testParsingInvalidStatusLine() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpResponseFactory responseFactory = new DefaultHttpResponseFactory(); NHttpMessageParser responseParser = new DefaultHttpResponseParser(inbuf, null, responseFactory, params); ReadableByteChannel channel = newChannel("HTTP 200 OK\r\n"); responseParser.fillBuffer(channel); try { responseParser.parse(); Assert.fail("HttpException should have been thrown"); } catch (HttpException ex) { // expected } } @Test public void testParsingInvalidHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpResponseFactory responseFactory = new DefaultHttpResponseFactory(); NHttpMessageParser responseParser = new DefaultHttpResponseParser(inbuf, null, responseFactory, params); ReadableByteChannel channel = newChannel("HTTP/1.0 200 OK\r\nstuff\r\n\r\n"); responseParser.fillBuffer(channel); try { responseParser.parse(); Assert.fail("HttpException should have been thrown"); } catch (HttpException ex) { // expected } } @Test public void testResetParser() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); ReadableByteChannel channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n"); requestParser.fillBuffer(channel); HttpRequest request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("one", request.getFirstHeader("Header").getValue()); requestParser.reset(); channel = newChannel("GET /whatever HTTP/1.0\r\nHeader: two\r\n\r\n"); requestParser.fillBuffer(channel); request = requestParser.parse(); Assert.assertNotNull(request); Assert.assertEquals(1, request.getAllHeaders().length); Assert.assertEquals("two", request.getFirstHeader("Header").getValue()); } @Test public void testInvalidConstructor() { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); try { new DefaultHttpRequestParser(null, null, null, params); Assert.fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // ignore } try { new DefaultHttpRequestParser(inbuf, null, null, params); Assert.fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // ignore } try { new DefaultHttpResponseParser(null, null, null, params); Assert.fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // ignore } try { new DefaultHttpResponseParser(inbuf, null, null, params); Assert.fail("IllegalArgumentException should have been thrown"); } catch (IllegalArgumentException ex) { // ignore } } @Test public void testLineLimitForStatus() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 0); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n")); requestParser.parse(); requestParser.reset(); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 15); requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); try { requestParser.fillBuffer(newChannel("GET /loooooooooooooooong HTTP/1.0\r\nHeader: one\r\n\r\n")); requestParser.parse(); Assert.fail("IOException should have been thrown"); } catch (IOException expected) { } } @Test public void testLineLimitForHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 0); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\n\r\n")); requestParser.parse(); requestParser.reset(); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 15); requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n\r\n")); requestParser.parse(); requestParser.reset(); try { requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 90123456\r\n\r\n")); requestParser.parse(); Assert.fail("IOException should have been thrown"); } catch (IOException expected) { } } @Test public void testLineLimitForFoldedHeader() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); params.setIntParameter(CoreConnectionPNames.MAX_HEADER_COUNT, 2); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 15); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); try { requestParser.fillBuffer(newChannel("GET / HTTP/1.0\r\nHeader: 9012345\r\n 23456789012345\r\n 23456789012345\r\n 23456789012345\r\n\r\n")); requestParser.parse(); Assert.fail("IOException should have been thrown"); } catch (IOException expected) { } } @Test public void testMaxHeaderCount() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); params.setIntParameter(CoreConnectionPNames.MAX_HEADER_COUNT, 2); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\n\r\n")); requestParser.parse(); requestParser.reset(); try { requestParser.fillBuffer(newChannel("GET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\nHeader: three\r\n\r\n")); requestParser.parse(); Assert.fail("IOException should have been thrown"); } catch (IOException expected) { } } @Test public void testDetectLineLimitEarly() throws Exception { HttpParams params = new BasicHttpParams(); SessionInputBuffer inbuf = new SessionInputBufferImpl(2, 128, params); HttpRequestFactory requestFactory = new DefaultHttpRequestFactory(); params.setIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, 2); NHttpMessageParser requestParser = new DefaultHttpRequestParser(inbuf, null, requestFactory, params); ReadableByteChannel channel = newChannel("GET / HTTP/1.0\r\nHeader: one\r\n\r\n"); Assert.assertEquals(2, requestParser.fillBuffer(channel)); Assert.assertNull(requestParser.parse()); Assert.assertEquals(4, requestParser.fillBuffer(channel)); try { requestParser.parse(); Assert.fail("IOException should have been thrown"); } catch (IOException expected) { } } }