You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2015/06/03 20:21:33 UTC
svn commit: r1683405 - in /httpcomponents/httpcore/trunk:
httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/
httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/
httpcore-nio/src/main/java/org/apache/http/nio/reactor/ httpcore-nio/src/...
Author: olegk
Date: Wed Jun 3 18:21:33 2015
New Revision: 1683405
URL: http://svn.apache.org/r1683405
Log:
RFC 7230: permit some empty lines before message head
Modified:
httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/AbstractMessageParser.java
httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpRequestParser.java
httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpResponseParser.java
httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java
httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/SessionInputBuffer.java
httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/MessageConstraintException.java
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/config/MessageConstraints.java
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpRequestParser.java
httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpResponseParser.java
httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestRequestParser.java
httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestResponseParser.java
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/AbstractMessageParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/AbstractMessageParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/AbstractMessageParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/AbstractMessageParser.java Wed Jun 3 18:21:33 2015
@@ -34,8 +34,6 @@ import java.util.List;
import org.apache.http.HttpException;
import org.apache.http.HttpMessage;
import org.apache.http.MessageConstraintException;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolException;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.config.MessageConstraints;
import org.apache.http.message.LazyLineParser;
@@ -63,24 +61,25 @@ public abstract class AbstractMessagePar
private T message;
private CharArrayBuffer lineBuf;
private final List<CharArrayBuffer> headerBufs;
+ private int emptyLineCount;
private final LineParser lineParser;
- private final MessageConstraints constraints;
+ private final MessageConstraints messageConstraints;
/**
* Creates an instance of AbstractMessageParser.
*
* @param lineParser the line parser. If {@code null}
* {@link org.apache.http.message.LazyLineParser#INSTANCE} will be used.
- * @param constraints Message constraints. If {@code null}
+ * @param messageConstraints Message constraints. If {@code null}
* {@link MessageConstraints#DEFAULT} will be used.
*
* @since 4.3
*/
- public AbstractMessageParser(final LineParser lineParser, final MessageConstraints constraints) {
+ public AbstractMessageParser(final LineParser lineParser, final MessageConstraints messageConstraints) {
super();
this.lineParser = lineParser != null ? lineParser : LazyLineParser.INSTANCE;
- this.constraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
+ this.messageConstraints = messageConstraints != null ? messageConstraints : MessageConstraints.DEFAULT;
this.headerBufs = new ArrayList<>();
this.state = READ_HEAD_LINE;
}
@@ -93,6 +92,7 @@ public abstract class AbstractMessagePar
public void reset() {
this.state = READ_HEAD_LINE;
this.headerBufs.clear();
+ this.emptyLineCount = 0;
this.message = null;
}
@@ -103,13 +103,19 @@ public abstract class AbstractMessagePar
* @param buffer the line buffer.
* @return HTTP message.
* @throws HttpException in case of HTTP protocol violation
- * @throws ParseException in case of a parse error.
*/
- protected abstract T createMessage(CharArrayBuffer buffer)
- throws HttpException, ParseException;
+ protected abstract T createMessage(CharArrayBuffer buffer) throws HttpException;
- private void parseHeadLine() throws HttpException, ParseException {
- this.message = createMessage(this.lineBuf);
+ private T parseHeadLine() throws IOException, HttpException {
+ if (this.lineBuf.length() == 0) {
+ this.emptyLineCount++;
+ if (this.emptyLineCount >= this.messageConstraints.getMaxEmptyLineCount()) {
+ throw new MessageConstraintException("Maximum empty line limit exceeded");
+ }
+ return null;
+ } else {
+ return createMessage(this.lineBuf);
+ }
}
private void parseHeader() throws IOException {
@@ -126,7 +132,7 @@ public abstract class AbstractMessagePar
}
i++;
}
- final int maxLineLen = this.constraints.getMaxLineLength();
+ final int maxLineLen = this.messageConstraints.getMaxLineLength();
if (maxLineLen > 0 && previous.length() + 1 + current.length() - i > maxLineLen) {
throw new MessageConstraintException("Maximum line length limit exceeded");
}
@@ -149,7 +155,7 @@ public abstract class AbstractMessagePar
this.lineBuf.clear();
}
final boolean lineComplete = sessionBuffer.readLine(this.lineBuf, endOfStream);
- final int maxLineLen = this.constraints.getMaxLineLength();
+ final int maxLineLen = this.messageConstraints.getMaxLineLength();
if (maxLineLen > 0 &&
(this.lineBuf.length() > maxLineLen ||
(!lineComplete && sessionBuffer.length() > maxLineLen))) {
@@ -161,16 +167,14 @@ public abstract class AbstractMessagePar
switch (this.state) {
case READ_HEAD_LINE:
- try {
- parseHeadLine();
- } catch (final ParseException px) {
- throw new ProtocolException(px.getMessage(), px);
+ this.message = parseHeadLine();
+ if (this.message != null) {
+ this.state = READ_HEADERS;
}
- this.state = READ_HEADERS;
break;
case READ_HEADERS:
if (this.lineBuf.length() > 0) {
- final int maxHeaderCount = this.constraints.getMaxHeaderCount();
+ final int maxHeaderCount = this.messageConstraints.getMaxHeaderCount();
if (maxHeaderCount > 0 && headerBufs.size() >= maxHeaderCount) {
throw new MessageConstraintException("Maximum header count exceeded");
}
@@ -187,11 +191,7 @@ public abstract class AbstractMessagePar
}
if (this.state == COMPLETED) {
for (final CharArrayBuffer buffer : this.headerBufs) {
- try {
- this.message.addHeader(lineParser.parseHeader(buffer));
- } catch (final ParseException ex) {
- throw new ProtocolException(ex.getMessage(), ex);
- }
+ this.message.addHeader(this.lineParser.parseHeader(buffer));
}
return this.message;
} else {
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpRequestParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpRequestParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpRequestParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpRequestParser.java Wed Jun 3 18:21:33 2015
@@ -31,7 +31,6 @@ import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestFactory;
import org.apache.http.HttpVersion;
-import org.apache.http.ParseException;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.UnsupportedHttpVersionException;
@@ -87,8 +86,7 @@ public class DefaultHttpRequestParser ex
}
@Override
- protected HttpRequest createMessage(final CharArrayBuffer buffer)
- throws HttpException, ParseException {
+ protected HttpRequest createMessage(final CharArrayBuffer buffer) throws HttpException {
final RequestLine requestLine = getLineParser().parseRequestLine(buffer);
final ProtocolVersion version = requestLine.getProtocolVersion();
if (version.greaterEquals(HttpVersion.HTTP_2)) {
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpResponseParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpResponseParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpResponseParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/codecs/DefaultHttpResponseParser.java Wed Jun 3 18:21:33 2015
@@ -31,7 +31,6 @@ import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseFactory;
import org.apache.http.HttpVersion;
-import org.apache.http.ParseException;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
import org.apache.http.UnsupportedHttpVersionException;
@@ -88,8 +87,7 @@ public class DefaultHttpResponseParser e
}
@Override
- protected HttpResponse createMessage(final CharArrayBuffer buffer)
- throws HttpException, ParseException {
+ protected HttpResponse createMessage(final CharArrayBuffer buffer) throws HttpException {
final StatusLine statusLine = getLineParser().parseStatusLine(buffer);
final ProtocolVersion version = statusLine.getProtocolVersion();
if (version.greaterEquals(HttpVersion.HTTP_2)) {
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/impl/nio/reactor/SessionInputBufferImpl.java Wed Jun 3 18:21:33 2015
@@ -32,7 +32,6 @@ import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
-import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
@@ -226,7 +225,7 @@ public class SessionInputBufferImpl exte
@Override
public boolean readLine(
final CharArrayBuffer linebuffer,
- final boolean endOfStream) throws CharacterCodingException {
+ final boolean endOfStream) throws IOException {
setOutputMode();
// See if there is LF char present in the buffer
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/SessionInputBuffer.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/SessionInputBuffer.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/SessionInputBuffer.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/main/java/org/apache/http/nio/reactor/SessionInputBuffer.java Wed Jun 3 18:21:33 2015
@@ -31,7 +31,6 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
-import java.nio.charset.CharacterCodingException;
import org.apache.http.util.CharArrayBuffer;
@@ -162,10 +161,10 @@ public interface SessionInputBuffer {
* line has been transferred to the destination buffer, {@code false}
* otherwise.
*
- * @throws CharacterCodingException in case a character encoding or decoding
+ * @throws java.nio.charset.CharacterCodingException in case a character encoding or decoding
* error occurs.
+ * @throws org.apache.http.MessageConstraintException in case a message constraint violation.
*/
- boolean readLine(CharArrayBuffer dst, boolean endOfStream)
- throws CharacterCodingException;
+ boolean readLine(CharArrayBuffer dst, boolean endOfStream) throws IOException;
}
Modified: httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore-nio/src/test/java/org/apache/http/impl/nio/codecs/TestHttpMessageParser.java Wed Jun 3 18:21:33 2015
@@ -39,6 +39,7 @@ import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
+import org.apache.http.MessageConstraintException;
import org.apache.http.UnsupportedHttpVersionException;
import org.apache.http.config.MessageConstraints;
import org.apache.http.impl.nio.reactor.SessionInputBufferImpl;
@@ -307,6 +308,30 @@ public class TestHttpMessageParser {
requestParser.parse(inbuf, false);
}
+ @Test
+ public void testParsingEmptyLines() throws Exception {
+ final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
+ final MessageConstraints constraints = MessageConstraints.custom()
+ .setMaxEmptyLineCount(3).build();
+ final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(constraints);
+ inbuf.fill(newChannel("\r\n\r\nGET /whatever HTTP/1.1\r\nSome header: stuff\r\n\r\n"));
+ final HttpRequest request = requestParser.parse(inbuf, false);
+ Assert.assertNotNull(request);
+ Assert.assertEquals("/whatever", request.getRequestLine().getUri());
+ Assert.assertEquals(1, request.getAllHeaders().length);
+ }
+
+ @Test(expected = MessageConstraintException.class)
+ public void testParsingTooManyEmptyLines() throws Exception {
+ final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
+
+ final MessageConstraints constraints = MessageConstraints.custom()
+ .setMaxEmptyLineCount(3).build();
+ final NHttpMessageParser<HttpRequest> requestParser = new DefaultHttpRequestParser(constraints);
+ inbuf.fill(newChannel("\r\n\r\n\r\nGET /whatever HTTP/1.0\r\nHeader: one\r\nHeader: two\r\n\r\n"));
+ requestParser.parse(inbuf, false);
+ }
+
@Test(expected = UnsupportedHttpVersionException.class)
public void testParsingUnsupportedRequestVersion() throws Exception {
final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 128, Consts.ASCII);
Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/MessageConstraintException.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/MessageConstraintException.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/MessageConstraintException.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/MessageConstraintException.java Wed Jun 3 18:21:33 2015
@@ -27,20 +27,21 @@
package org.apache.http;
-import java.nio.charset.CharacterCodingException;
+import java.io.IOException;
/**
* Signals a message constraint violation.
*
* @since 4.3
*/
-public class MessageConstraintException extends CharacterCodingException {
+public class MessageConstraintException extends IOException {
private static final long serialVersionUID = 6077207720446368695L;
private final String message;
+
/**
- * Creates a TruncatedChunkException with the specified detail message.
+ * Creates a MessageConstraintException with the specified detail message.
*
* @param message The exception detail message
*/
Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/config/MessageConstraints.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/config/MessageConstraints.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/config/MessageConstraints.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/config/MessageConstraints.java Wed Jun 3 18:21:33 2015
@@ -45,11 +45,13 @@ public class MessageConstraints {
private final int maxLineLength;
private final int maxHeaderCount;
+ private final int maxEmptyLineCount;
- MessageConstraints(final int maxLineLength, final int maxHeaderCount) {
+ MessageConstraints(final int maxLineLength, final int maxHeaderCount, final int maxEmptyLineCount) {
super();
this.maxLineLength = maxLineLength;
this.maxHeaderCount = maxHeaderCount;
+ this.maxEmptyLineCount = maxEmptyLineCount;
}
public int getMaxLineLength() {
@@ -60,6 +62,13 @@ public class MessageConstraints {
return maxHeaderCount;
}
+ /**
+ * @since 5.0
+ */
+ public int getMaxEmptyLineCount() {
+ return this.maxEmptyLineCount;
+ }
+
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
@@ -69,10 +78,6 @@ public class MessageConstraints {
return builder.toString();
}
- public static MessageConstraints lineLen(final int max) {
- return new MessageConstraints(Args.notNegative(max, "Max line length"), -1);
- }
-
public static MessageConstraints.Builder custom() {
return new Builder();
}
@@ -88,10 +93,12 @@ public class MessageConstraints {
private int maxLineLength;
private int maxHeaderCount;
+ private int maxEmptyLineCount;
Builder() {
this.maxLineLength = -1;
this.maxHeaderCount = -1;
+ this.maxEmptyLineCount = 10;
}
public Builder setMaxLineLength(final int maxLineLength) {
@@ -104,10 +111,19 @@ public class MessageConstraints {
return this;
}
+ public Builder setMaxEmptyLineCount(final int maxEmptyLineCount) {
+ this.maxEmptyLineCount = maxEmptyLineCount;
+ return this;
+ }
+
public MessageConstraints build() {
- return new MessageConstraints(maxLineLength, maxHeaderCount);
+ return new MessageConstraints(maxLineLength, maxHeaderCount, maxEmptyLineCount);
}
}
+ public static MessageConstraints lineLen(final int max) {
+ return custom().setMaxLineLength(Args.notNegative(max, "Max line length")).build();
+ }
+
}
Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java Wed Jun 3 18:21:33 2015
@@ -35,8 +35,6 @@ import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpMessage;
import org.apache.http.MessageConstraintException;
-import org.apache.http.ParseException;
-import org.apache.http.ProtocolException;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.config.MessageConstraints;
import org.apache.http.io.HttpMessageParser;
@@ -60,6 +58,7 @@ public abstract class AbstractMessagePar
private final MessageConstraints messageConstraints;
private final List<CharArrayBuffer> headerLines;
+ private final CharArrayBuffer headLine;
private final LineParser lineParser;
private int state;
@@ -80,6 +79,7 @@ public abstract class AbstractMessagePar
this.lineParser = lineParser != null ? lineParser : LazyLineParser.INSTANCE;
this.messageConstraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
this.headerLines = new ArrayList<>();
+ this.headLine = new CharArrayBuffer(128);
this.state = HEAD_LINE;
}
@@ -195,11 +195,7 @@ public abstract class AbstractMessagePar
final Header[] headers = new Header[headerLines.size()];
for (int i = 0; i < headerLines.size(); i++) {
final CharArrayBuffer buffer = headerLines.get(i);
- try {
- headers[i] = parser.parseHeader(buffer);
- } catch (final ParseException ex) {
- throw new ProtocolException(ex.getMessage());
- }
+ headers[i] = parser.parseHeader(buffer);
}
return headers;
}
@@ -216,10 +212,18 @@ public abstract class AbstractMessagePar
* @return HTTP message based on the input from the session buffer.
* @throws IOException in case of an I/O error.
* @throws HttpException in case of HTTP protocol violation.
- * @throws ParseException in case of a parse error.
+ *
+ * @since 5.0
*/
- protected abstract T parseHead(SessionInputBuffer buffer)
- throws IOException, HttpException, ParseException;
+ protected abstract T createMessage(CharArrayBuffer buffer) throws IOException, HttpException;
+
+ /**
+ * Subclasses must override this method to generate an appropriate exception
+ * in case of unexpected connection termination by the peer endpoint.
+ *
+ * @since 5.0
+ */
+ protected abstract IOException createConnectionClosedException();
@Override
public T parse(final SessionInputBuffer buffer) throws IOException, HttpException {
@@ -227,10 +231,19 @@ public abstract class AbstractMessagePar
final int st = this.state;
switch (st) {
case HEAD_LINE:
- try {
- this.message = parseHead(buffer);
- } catch (final ParseException px) {
- throw new ProtocolException(px.getMessage(), px);
+ for (int n = 0; n < this.messageConstraints.getMaxEmptyLineCount(); n++) {
+ this.headLine.clear();
+ final int i = buffer.readLine(this.headLine);
+ if (i == -1) {
+ throw createConnectionClosedException();
+ }
+ if (this.headLine.length() > 0) {
+ this.message = createMessage(this.headLine);
+ break;
+ }
+ }
+ if (this.message == null) {
+ throw new MessageConstraintException("Maximum empty line limit exceeded");
}
this.state = HEADERS;
//$FALL-THROUGH$
Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpRequestParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpRequestParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpRequestParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpRequestParser.java Wed Jun 3 18:21:33 2015
@@ -34,14 +34,12 @@ import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestFactory;
import org.apache.http.HttpVersion;
-import org.apache.http.ParseException;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.UnsupportedHttpVersionException;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.config.MessageConstraints;
import org.apache.http.impl.DefaultHttpRequestFactory;
-import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.LineParser;
import org.apache.http.util.CharArrayBuffer;
@@ -55,7 +53,6 @@ import org.apache.http.util.CharArrayBuf
public class DefaultHttpRequestParser extends AbstractMessageParser<HttpRequest> {
private final HttpRequestFactory requestFactory;
- private final CharArrayBuffer lineBuf;
/**
* Creates new instance of DefaultHttpRequestParser.
@@ -74,9 +71,7 @@ public class DefaultHttpRequestParser ex
final HttpRequestFactory requestFactory,
final MessageConstraints constraints) {
super(lineParser, constraints);
- this.requestFactory = requestFactory != null ? requestFactory :
- DefaultHttpRequestFactory.INSTANCE;
- this.lineBuf = new CharArrayBuffer(128);
+ this.requestFactory = requestFactory != null ? requestFactory : DefaultHttpRequestFactory.INSTANCE;
}
/**
@@ -94,15 +89,13 @@ public class DefaultHttpRequestParser ex
}
@Override
- protected HttpRequest parseHead(final SessionInputBuffer sessionBuffer)
- throws IOException, HttpException, ParseException {
+ protected IOException createConnectionClosedException() {
+ return new ConnectionClosedException("Client closed connection");
+ }
- this.lineBuf.clear();
- final int i = sessionBuffer.readLine(this.lineBuf);
- if (i == -1) {
- throw new ConnectionClosedException("Client closed connection");
- }
- final RequestLine requestLine = getLineParser().parseRequestLine(this.lineBuf);
+ @Override
+ protected HttpRequest createMessage(final CharArrayBuffer buffer) throws IOException, HttpException {
+ final RequestLine requestLine = getLineParser().parseRequestLine(buffer);
final ProtocolVersion version = requestLine.getProtocolVersion();
if (version.greaterEquals(HttpVersion.HTTP_2)) {
throw new UnsupportedHttpVersionException("Unsupported version: " + version);
Modified: httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpResponseParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpResponseParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpResponseParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/main/java/org/apache/http/impl/io/DefaultHttpResponseParser.java Wed Jun 3 18:21:33 2015
@@ -34,14 +34,12 @@ import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseFactory;
import org.apache.http.HttpVersion;
import org.apache.http.NoHttpResponseException;
-import org.apache.http.ParseException;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
import org.apache.http.UnsupportedHttpVersionException;
import org.apache.http.annotation.NotThreadSafe;
import org.apache.http.config.MessageConstraints;
import org.apache.http.impl.DefaultHttpResponseFactory;
-import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.LineParser;
import org.apache.http.util.CharArrayBuffer;
@@ -55,7 +53,6 @@ import org.apache.http.util.CharArrayBuf
public class DefaultHttpResponseParser extends AbstractMessageParser<HttpResponse> {
private final HttpResponseFactory responseFactory;
- private final CharArrayBuffer lineBuf;
/**
* Creates new instance of DefaultHttpResponseParser.
@@ -75,7 +72,6 @@ public class DefaultHttpResponseParser e
final MessageConstraints constraints) {
super(lineParser, constraints);
this.responseFactory = responseFactory != null ? responseFactory : DefaultHttpResponseFactory.INSTANCE;
- this.lineBuf = new CharArrayBuffer(128);
}
/**
@@ -93,16 +89,13 @@ public class DefaultHttpResponseParser e
}
@Override
- protected HttpResponse parseHead(
- final SessionInputBuffer sessionBuffer) throws IOException, HttpException, ParseException {
+ protected IOException createConnectionClosedException() {
+ return new NoHttpResponseException("The target server failed to respond");
+ }
- this.lineBuf.clear();
- final int i = sessionBuffer.readLine(this.lineBuf);
- if (i == -1) {
- throw new NoHttpResponseException("The target server failed to respond");
- }
- //create the status line from the status string
- final StatusLine statusline = getLineParser().parseStatusLine(this.lineBuf);
+ @Override
+ protected HttpResponse createMessage(final CharArrayBuffer buffer) throws IOException, HttpException {
+ final StatusLine statusline = getLineParser().parseStatusLine(buffer);
final ProtocolVersion version = statusline.getProtocolVersion();
if (version.greaterEquals(HttpVersion.HTTP_2)) {
throw new UnsupportedHttpVersionException("Unsupported version: " + version);
Modified: httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestRequestParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestRequestParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestRequestParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestRequestParser.java Wed Jun 3 18:21:33 2015
@@ -33,8 +33,10 @@ import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpVersion;
+import org.apache.http.MessageConstraintException;
import org.apache.http.RequestLine;
import org.apache.http.UnsupportedHttpVersionException;
+import org.apache.http.config.MessageConstraints;
import org.apache.http.impl.SessionInputBufferMock;
import org.apache.http.io.SessionInputBuffer;
import org.junit.Assert;
@@ -75,6 +77,45 @@ public class TestRequestParser {
parser.parse(inbuffer);
}
+ @Test
+ public void testBasicMessageParsingLeadingEmptyLines() throws Exception {
+ final String s =
+ "\r\n" +
+ "\r\n" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "\r\n";
+ final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII);
+
+ final DefaultHttpRequestParser parser = new DefaultHttpRequestParser(
+ MessageConstraints.custom().setMaxEmptyLineCount(3).build());
+ final HttpRequest httprequest = parser.parse(inbuffer);
+
+ final RequestLine reqline = httprequest.getRequestLine();
+ Assert.assertNotNull(reqline);
+ Assert.assertEquals("GET", reqline.getMethod());
+ Assert.assertEquals("/", reqline.getUri());
+ Assert.assertEquals(HttpVersion.HTTP_1_1, reqline.getProtocolVersion());
+ final Header[] headers = httprequest.getAllHeaders();
+ Assert.assertEquals(1, headers.length);
+ }
+
+ @Test(expected = MessageConstraintException.class)
+ public void testBasicMessageParsingTooManyLeadingEmptyLines() throws Exception {
+ final String s =
+ "\r\n" +
+ "\r\n" +
+ "\r\n" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "\r\n";
+ final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII);
+
+ final DefaultHttpRequestParser parser = new DefaultHttpRequestParser(
+ MessageConstraints.custom().setMaxEmptyLineCount(3).build());
+ parser.parse(inbuffer);
+ }
+
@Test
public void testMessageParsingTimeout() throws Exception {
final String s =
Modified: httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestResponseParser.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestResponseParser.java?rev=1683405&r1=1683404&r2=1683405&view=diff
==============================================================================
--- httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestResponseParser.java (original)
+++ httpcomponents/httpcore/trunk/httpcore/src/test/java/org/apache/http/impl/io/TestResponseParser.java Wed Jun 3 18:21:33 2015
@@ -33,9 +33,11 @@ import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
+import org.apache.http.MessageConstraintException;
import org.apache.http.NoHttpResponseException;
import org.apache.http.StatusLine;
import org.apache.http.UnsupportedHttpVersionException;
+import org.apache.http.config.MessageConstraints;
import org.apache.http.impl.SessionInputBufferMock;
import org.apache.http.io.SessionInputBuffer;
import org.junit.Assert;
@@ -76,6 +78,45 @@ public class TestResponseParser {
parser.parse(inbuffer);
}
+ @Test
+ public void testBasicMessageParsingLeadingEmptyLines() throws Exception {
+ final String s =
+ "\r\n" +
+ "\r\n" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Server: whatever\r\n" +
+ "\r\n";
+ final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII);
+
+ final DefaultHttpResponseParser parser = new DefaultHttpResponseParser(
+ MessageConstraints.custom().setMaxEmptyLineCount(3).build());
+ final HttpResponse httpresponse = parser.parse(inbuffer);
+
+ final StatusLine statusline = httpresponse.getStatusLine();
+ Assert.assertNotNull(statusline);
+ Assert.assertEquals(200, statusline.getStatusCode());
+ Assert.assertEquals("OK", statusline.getReasonPhrase());
+ Assert.assertEquals(HttpVersion.HTTP_1_1, statusline.getProtocolVersion());
+ final Header[] headers = httpresponse.getAllHeaders();
+ Assert.assertEquals(1, headers.length);
+ }
+
+ @Test(expected = MessageConstraintException.class)
+ public void testBasicMessageParsingTooManyLeadingEmptyLines() throws Exception {
+ final String s =
+ "\r\n" +
+ "\r\n" +
+ "\r\n" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Server: whatever\r\n" +
+ "\r\n";
+ final SessionInputBuffer inbuffer = new SessionInputBufferMock(s, Consts.ASCII);
+
+ final DefaultHttpResponseParser parser = new DefaultHttpResponseParser(
+ MessageConstraints.custom().setMaxEmptyLineCount(3).build());
+ parser.parse(inbuffer);
+ }
+
@Test
public void testMessageParsingTimeout() throws Exception {
final String s =