Better white space handling in HTTP

This commit is contained in:
Trustin Lee 2009-02-12 05:02:22 +00:00
parent 0198da7b6c
commit 9cdc4a959e
3 changed files with 29 additions and 7 deletions

View File

@ -58,24 +58,33 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
* @apiviz.exclude * @apiviz.exclude
*/ */
protected enum State { protected enum State {
SKIP_CONTROL_CHARS,
READ_INITIAL, READ_INITIAL,
READ_HEADER, READ_HEADER,
READ_CONTENT, READ_CONTENT,
READ_FIXED_LENGTH_CONTENT, READ_FIXED_LENGTH_CONTENT,
READ_CHUNK_SIZE, READ_CHUNK_SIZE,
READ_CHUNKED_CONTENT, READ_CHUNKED_CONTENT,
READ_CRLF,; READ_CRLF;
} }
private State nextState; private State nextState;
protected HttpMessageDecoder() { protected HttpMessageDecoder() {
super(State.READ_INITIAL); super(State.SKIP_CONTROL_CHARS);
} }
@Override @Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, State state) throws Exception { protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, State state) throws Exception {
switch (state) { switch (state) {
case SKIP_CONTROL_CHARS: {
try {
skipControlCharacters(buffer);
checkpoint(State.READ_INITIAL);
} finally {
checkpoint();
}
}
case READ_INITIAL: { case READ_INITIAL: {
readInitial(buffer); readInitial(buffer);
} }
@ -144,10 +153,21 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
message.setContent(content); message.setContent(content);
content = null; content = null;
nextState = null; nextState = null;
checkpoint(State.READ_INITIAL); checkpoint(State.SKIP_CONTROL_CHARS);
return message; return message;
} }
private void skipControlCharacters(ChannelBuffer buffer) {
for (;;) {
char c = (char) buffer.readUnsignedByte();
if (!Character.isISOControl(c) &&
!Character.isWhitespace(c)) {
buffer.readerIndex(buffer.readerIndex() - 1);
break;
}
}
}
private void readChunkedContent(Channel channel, ChannelBuffer buffer) { private void readChunkedContent(Channel channel, ChannelBuffer buffer) {
if (content == null) { if (content == null) {
content = ChannelBuffers.dynamicBuffer( content = ChannelBuffers.dynamicBuffer(

View File

@ -125,8 +125,9 @@ public class HttpMethod implements Comparable<HttpMethod> {
} }
for (int i = 0; i < name.length(); i ++) { for (int i = 0; i < name.length(); i ++) {
if (Character.isISOControl(name.charAt(i))) { if (Character.isISOControl(name.charAt(i)) ||
throw new IllegalArgumentException("control character in name"); Character.isWhitespace(name.charAt(i))) {
throw new IllegalArgumentException("invalid character in name");
} }
} }

View File

@ -95,8 +95,9 @@ public class HttpVersion implements Comparable<HttpVersion> {
} }
for (int i = 0; i < protocolName.length(); i ++) { for (int i = 0; i < protocolName.length(); i ++) {
if (Character.isISOControl(protocolName.charAt(i))) { if (Character.isISOControl(protocolName.charAt(i)) ||
throw new IllegalArgumentException("control character in protocolName"); Character.isWhitespace(protocolName.charAt(i))) {
throw new IllegalArgumentException("invalid character in protocolName");
} }
} }