From 1179458a52064ae24a56fa1469945fe9658c6838 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Wed, 28 Nov 2012 13:42:08 +0000 Subject: [PATCH] DefaultClientConnectionFactory to use lenient HttpResponseParser implementation git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1414679 13f79535-47bb-0310-9956-ffa450edef68 --- .../conn/DefaultClientConnectionFactory.java | 3 +- .../impl/conn/DefaultHttpResponseParser.java | 54 +++++++-- .../DefaultHttpResponseParserFactory.java | 71 ++++++++++++ .../conn/SessionInputBufferMock.java} | 104 ++++++++---------- .../conn/TestDefaultHttpResponseParser.java | 52 +++------ 5 files changed, 180 insertions(+), 104 deletions(-) create mode 100644 httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java rename httpclient/src/test/java/org/apache/http/{mockup/SessionInputBufferMockup.java => impl/conn/SessionInputBufferMock.java} (50%) diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultClientConnectionFactory.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultClientConnectionFactory.java index d9d92794d..ebf3e70d2 100644 --- a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultClientConnectionFactory.java +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultClientConnectionFactory.java @@ -65,7 +65,8 @@ public class DefaultClientConnectionFactory implements HttpConnectionFactory - * The following parameters can be used to customize the behavior of this - * class: - * + * Lenient HTTP response parser implementation that can skip malformed data until + * a valid HTTP response message head is encountered. * * @since 4.2 */ +@SuppressWarnings("deprecation") @ThreadSafe // no public methods public class DefaultHttpResponseParser extends AbstractMessageParser { @@ -66,6 +64,11 @@ public class DefaultHttpResponseParser extends AbstractMessageParsernull {@link BasicLineParser#INSTANCE} + * will be used. + * @param responseFactory HTTP response factory. If null + * {@link DefaultHttpResponseFactory#INSTANCE} will be used. + * @param constraints the message constraints. If null + * {@link MessageConstraints#DEFAULT} will be used. + * + * @since 4.3 + */ + public DefaultHttpResponseParser( + final SessionInputBuffer buffer, + final LineParser lineParser, + final HttpResponseFactory responseFactory, + final MessageConstraints constraints) { + super(buffer, lineParser, constraints); + this.responseFactory = responseFactory != null ? responseFactory : + DefaultHttpResponseFactory.INSTANCE; + this.lineBuf = new CharArrayBuffer(128); + } + + /** + * Creates new instance of DefaultHttpResponseParser. + * + * @param buffer the session input buffer. + * + * @since 4.3 + */ + public DefaultHttpResponseParser(final SessionInputBuffer buffer) { + this(buffer, null, null, MessageConstraints.DEFAULT); + } @Override protected HttpResponse parseHead( diff --git a/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java new file mode 100644 index 000000000..f6ddd5138 --- /dev/null +++ b/httpclient/src/main/java/org/apache/http/impl/conn/DefaultHttpResponseParserFactory.java @@ -0,0 +1,71 @@ +/* + * ==================================================================== + * 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.conn; + +import org.apache.http.HttpResponse; +import org.apache.http.HttpResponseFactory; +import org.apache.http.annotation.Immutable; +import org.apache.http.config.MessageConstraints; +import org.apache.http.impl.DefaultHttpResponseFactory; +import org.apache.http.io.HttpMessageParser; +import org.apache.http.io.HttpMessageParserFactory; +import org.apache.http.io.SessionInputBuffer; +import org.apache.http.message.BasicLineParser; +import org.apache.http.message.LineParser; + +/** + * Default factory for response message parsers. + * + * @since 4.3 + */ +@Immutable +public class DefaultHttpResponseParserFactory implements HttpMessageParserFactory { + + public static final DefaultHttpResponseParserFactory INSTANCE = new DefaultHttpResponseParserFactory(); + + private final LineParser lineParser; + private final HttpResponseFactory responseFactory; + + public DefaultHttpResponseParserFactory(final LineParser lineParser, + final HttpResponseFactory responseFactory) { + super(); + this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE; + this.responseFactory = responseFactory != null ? responseFactory + : DefaultHttpResponseFactory.INSTANCE; + } + + public DefaultHttpResponseParserFactory() { + this(null, null); + } + + public HttpMessageParser create(final SessionInputBuffer buffer, + final MessageConstraints constraints) { + return new DefaultHttpResponseParser(buffer, lineParser, responseFactory, constraints); + } + +} diff --git a/httpclient/src/test/java/org/apache/http/mockup/SessionInputBufferMockup.java b/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java similarity index 50% rename from httpclient/src/test/java/org/apache/http/mockup/SessionInputBufferMockup.java rename to httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java index 85f65ac3d..9a9630124 100644 --- a/httpclient/src/test/java/org/apache/http/mockup/SessionInputBufferMockup.java +++ b/httpclient/src/test/java/org/apache/http/impl/conn/SessionInputBufferMock.java @@ -25,95 +25,85 @@ * */ -package org.apache.http.mockup; +package org.apache.http.impl.conn; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; -import org.apache.http.impl.io.AbstractSessionInputBuffer; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; +import org.apache.http.config.MessageConstraints; +import org.apache.http.impl.io.HttpTransportMetricsImpl; +import org.apache.http.impl.io.SessionInputBufferImpl; /** * {@link org.apache.http.io.SessionInputBuffer} mockup implementation. */ -public class SessionInputBufferMockup extends AbstractSessionInputBuffer { +public class SessionInputBufferMock extends SessionInputBufferImpl { public static final int BUFFER_SIZE = 16; - public SessionInputBufferMockup( - final InputStream instream, - int buffersize, - final HttpParams params) { - super(); - init(instream, buffersize, params); + public SessionInputBufferMock( + final InputStream instream, + int buffersize, + final MessageConstraints constrains, + final CharsetDecoder decoder) { + super(new HttpTransportMetricsImpl(), buffersize, -1, constrains, decoder); + bind(instream); } - public SessionInputBufferMockup( + public SessionInputBufferMock( final InputStream instream, int buffersize) { - this(instream, buffersize, new BasicHttpParams()); + this(instream, buffersize, null, null); } - public SessionInputBufferMockup( + public SessionInputBufferMock( final byte[] bytes, - final HttpParams params) { - this(bytes, BUFFER_SIZE, params); + int buffersize, + final MessageConstraints constrains, + final CharsetDecoder decoder) { + this(new ByteArrayInputStream(bytes), buffersize, constrains, decoder); } - public SessionInputBufferMockup( + public SessionInputBufferMock( + final byte[] bytes, + int buffersize, + final MessageConstraints constrains) { + this(new ByteArrayInputStream(bytes), buffersize, constrains, null); + } + + public SessionInputBufferMock( + final byte[] bytes, + int buffersize) { + this(new ByteArrayInputStream(bytes), buffersize); + } + + public SessionInputBufferMock( final byte[] bytes) { - this(bytes, BUFFER_SIZE, new BasicHttpParams()); + this(bytes, BUFFER_SIZE); } - public SessionInputBufferMockup( - final byte[] bytes, - int buffersize, - final HttpParams params) { - this(new ByteArrayInputStream(bytes), buffersize, params); + public SessionInputBufferMock( + final byte[] bytes, final Charset charset) { + this(bytes, BUFFER_SIZE, null, charset != null ? charset.newDecoder() : null); } - public SessionInputBufferMockup( - final byte[] bytes, - int buffersize) { - this(new ByteArrayInputStream(bytes), buffersize, new BasicHttpParams()); + public SessionInputBufferMock( + final byte[] bytes, + final CharsetDecoder decoder) { + this(bytes, BUFFER_SIZE, null, decoder); } - public SessionInputBufferMockup( + public SessionInputBufferMock( final String s, - final String charset, - int buffersize, - final HttpParams params) - throws UnsupportedEncodingException { - this(s.getBytes(charset), buffersize, params); - } - - public SessionInputBufferMockup( - final String s, - final String charset, - int buffersize) - throws UnsupportedEncodingException { - this(s.getBytes(charset), buffersize, new BasicHttpParams()); - } - - public SessionInputBufferMockup( - final String s, - final String charset, - final HttpParams params) - throws UnsupportedEncodingException { - this(s.getBytes(charset), params); - } - - public SessionInputBufferMockup( - final String s, - final String charset) - throws UnsupportedEncodingException { - this(s.getBytes(charset), new BasicHttpParams()); - + final Charset charset) throws UnsupportedEncodingException { + this(s.getBytes(charset.name()), charset); } + @Override public boolean isDataAvailable(int timeout) throws IOException { return true; } diff --git a/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java b/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java index 04abd81ae..d08974eee 100644 --- a/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java +++ b/httpclient/src/test/java/org/apache/http/impl/conn/TestDefaultHttpResponseParser.java @@ -27,24 +27,20 @@ package org.apache.http.impl.conn; +import org.apache.http.Consts; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.NoHttpResponseException; import org.apache.http.ProtocolException; -import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.io.HttpMessageParser; import org.apache.http.io.SessionInputBuffer; -import org.apache.http.message.BasicLineParser; -import org.apache.http.mockup.SessionInputBufferMockup; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; import org.apache.http.util.CharArrayBuffer; import org.junit.Assert; import org.junit.Test; /** - * Tests for DefaultResponseParser. + * Tests for {@link DefaultResponseParser}. */ public class TestDefaultHttpResponseParser { @@ -59,13 +55,8 @@ public class TestDefaultHttpResponseParser { "header2: value2\r\n" + "\r\n"; - HttpParams params = new BasicHttpParams(); - SessionInputBuffer inbuffer = new SessionInputBufferMockup(s, "US-ASCII", params); - HttpMessageParser parser = new DefaultHttpResponseParser( - inbuffer, - BasicLineParser.DEFAULT, - new DefaultHttpResponseFactory(), - params); + SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); + HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); HttpResponse response = parser.parse(); Assert.assertNotNull(response); @@ -90,18 +81,13 @@ public class TestDefaultHttpResponseParser { "header2: value2\r\n" + "\r\n"; - HttpParams params = new BasicHttpParams(); - SessionInputBuffer inbuffer = new SessionInputBufferMockup(s, "US-ASCII", params); - HttpMessageParser parser = new DefaultHttpResponseParser( - inbuffer, - BasicLineParser.DEFAULT, - new DefaultHttpResponseFactory(), - params) { + SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); + HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer) { - @Override - protected boolean reject(final CharArrayBuffer line, int count) { - return count >= 2; - } + @Override + protected boolean reject(final CharArrayBuffer line, int count) { + return count >= 2; + } }; parser.parse(); @@ -109,13 +95,8 @@ public class TestDefaultHttpResponseParser { @Test(expected=NoHttpResponseException.class) public void testResponseParsingNoResponse() throws Exception { - HttpParams params = new BasicHttpParams(); - SessionInputBuffer inbuffer = new SessionInputBufferMockup("", "US-ASCII", params); - HttpMessageParser parser = new DefaultHttpResponseParser( - inbuffer, - BasicLineParser.DEFAULT, - new DefaultHttpResponseFactory(), - params); + SessionInputBuffer inbuffer = new SessionInputBufferMock("", Consts.ASCII); + HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); parser.parse(); } @@ -126,13 +107,8 @@ public class TestDefaultHttpResponseParser { "garbage\r\n" + "more garbage\r\n" + "a lot more garbage\r\n"; - HttpParams params = new BasicHttpParams(); - SessionInputBuffer inbuffer = new SessionInputBufferMockup(s, "US-ASCII", params); - HttpMessageParser parser = new DefaultHttpResponseParser( - inbuffer, - BasicLineParser.DEFAULT, - new DefaultHttpResponseFactory(), - params); + SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII); + HttpMessageParser parser = new DefaultHttpResponseParser(inbuffer); parser.parse(); }