Added HttpChunk message for users who want to receive the content chunk by chunk

This commit is contained in:
Trustin Lee 2009-02-12 06:09:29 +00:00
parent b6c992de8b
commit 44d56d2c1a
5 changed files with 138 additions and 14 deletions

View File

@ -0,0 +1,52 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.netty.handler.codec.http;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
* @version $Rev$, $Date$
*/
public class DefaultHttpChunk implements HttpChunk {
private final ChannelBuffer content;
private final boolean last;
public DefaultHttpChunk(ChannelBuffer content) {
if (content == null) {
throw new NullPointerException("content");
}
last = content.readable();
this.content = content;
}
public ChannelBuffer getContent() {
return content;
}
public boolean isLast() {
return last;
}
}

View File

@ -0,0 +1,35 @@
/*
* JBoss, Home of Professional Open Source
*
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.netty.handler.codec.http;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Trustin Lee (tlee@redhat.com)
* @version $Rev$, $Date$
*/
public interface HttpChunk {
boolean isLast();
ChannelBuffer getContent();
}

View File

@ -21,6 +21,8 @@
*/
package org.jboss.netty.handler.codec.http;
import static org.jboss.netty.buffer.ChannelBuffers.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -46,9 +48,11 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
private static final Pattern HEADER_PATTERN = Pattern.compile(
"^\\s*(\\S+)\\s*:\\s*(.*)\\s*$");
protected HttpMessage message;
private ChannelBuffer content;
private int chunkSize;
private final boolean mergeChunks;
protected volatile HttpMessage message;
private volatile ChannelBuffer content;
private volatile int chunkSize;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
@ -70,7 +74,12 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
}
protected HttpMessageDecoder() {
this(true);
}
protected HttpMessageDecoder(boolean mergeChunks) {
super(State.SKIP_CONTROL_CHARS);
this.mergeChunks = mergeChunks;
}
@Override
@ -91,6 +100,9 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
readHeaders(buffer);
if (message.isChunked()) {
checkpoint(State.READ_CHUNK_SIZE);
if (!mergeChunks) {
return message;
}
} else if (message.getContentLength() == 0) {
content = ChannelBuffers.EMPTY_BUFFER;
return reset();
@ -120,13 +132,29 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
chunkSize = getChunkSize(line);
if (chunkSize == 0) {
checkpoint(State.READ_CHUNK_FOOTER);
return null;
if (mergeChunks) {
return null;
} else {
HttpChunk lastChunk = new DefaultHttpChunk(EMPTY_BUFFER);
return lastChunk;
}
} else {
checkpoint(State.READ_CHUNKED_CONTENT);
}
}
case READ_CHUNKED_CONTENT: {
readChunkedContent(channel, buffer);
if (mergeChunks) {
if (content == null) {
content = ChannelBuffers.dynamicBuffer(
chunkSize, channel.getConfig().getBufferFactory());
}
content.writeBytes(buffer, chunkSize);
checkpoint(State.READ_CHUNK_DELIMITER);
} else {
HttpChunk chunk = new DefaultHttpChunk(buffer.readBytes(chunkSize));
checkpoint(State.READ_CHUNK_DELIMITER);
return chunk;
}
}
case READ_CHUNK_DELIMITER: {
for (;;) {
@ -159,6 +187,7 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
}
private Object reset() {
// TODO: Do we need to set message to null here?
message.setContent(content);
content = null;
checkpoint(State.SKIP_CONTROL_CHARS);
@ -176,15 +205,6 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
}
}
private void readChunkedContent(Channel channel, ChannelBuffer buffer) {
if (content == null) {
content = ChannelBuffers.dynamicBuffer(
chunkSize, channel.getConfig().getBufferFactory());
}
content.writeBytes(buffer, chunkSize);
checkpoint(State.READ_CHUNK_DELIMITER);
}
private void readFixedLengthContent(ChannelBuffer buffer) {
int length = message.getContentLength();
if (content == null) {

View File

@ -33,6 +33,14 @@ import org.jboss.netty.buffer.ChannelBuffer;
*/
public class HttpRequestDecoder extends HttpMessageDecoder {
public HttpRequestDecoder() {
super();
}
public HttpRequestDecoder(boolean mergeChunks) {
super(mergeChunks);
}
@Override
protected void readInitial(ChannelBuffer buffer) throws Exception{
String line = readIntoCurrentLine(buffer);

View File

@ -32,6 +32,15 @@ import org.jboss.netty.buffer.ChannelBuffer;
* @version $Rev$, $Date$
*/
public class HttpResponseDecoder extends HttpMessageDecoder {
public HttpResponseDecoder() {
super();
}
public HttpResponseDecoder(boolean mergeChunks) {
super(mergeChunks);
}
@Override
protected void readInitial(ChannelBuffer buffer) {
String line = readIntoCurrentLine(buffer);