jetty-9 work in progress on new HttpGenerator

This commit is contained in:
Greg Wilkins 2012-03-02 11:39:42 +11:00
parent 1fa6c998db
commit a4bee5b12d
7 changed files with 936 additions and 786 deletions

View File

@ -24,6 +24,7 @@ import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -49,7 +50,7 @@ import org.eclipse.jetty.util.log.Logger;
*
*
*/
public class HttpFields
public class HttpFields implements Iterable<HttpFields.Field>
{
private static final Logger LOG = Log.getLogger(HttpFields.class);
@ -362,7 +363,13 @@ public class HttpFields
{
return _fields.get(i);
}
/* ------------------------------------------------------------ */
public Iterator<Field> iterator()
{
return _fields.iterator();
}
/* ------------------------------------------------------------ */
public Field getField(HttpHeader header)
{

View File

@ -43,40 +43,82 @@ public class HttpGeneratorTest
{
ByteBuffer header=BufferUtil.allocate(8096);
HttpFields fields = new HttpFields();
HttpGenerator hg = new HttpGenerator();
HttpGenerator gen = new HttpGenerator();
fields.add("Host","something");
fields.add("User-Agent","test");
hg.setRequest(HttpMethod.GET,"/index.html",HttpVersion.HTTP_1_1);
hg.completeHeader(header,fields,true);
hg.complete();
gen.setRequest(HttpMethod.GET,"/index.html",HttpVersion.HTTP_1_1);
HttpGenerator.Result
result=gen.complete(null,null);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
result=gen.commit(fields,header,null,null,true);
String out = BufferUtil.toString(header);
BufferUtil.clear(header);
assertEquals(HttpGenerator.Result.NEED_COMPLETE,result);
result=gen.complete(null,null);
assertEquals(HttpGenerator.Result.OK,result);
assertTrue(out.indexOf("GET /index.html HTTP/1.1")==0);
assertTrue(out.indexOf("Content-Length")==-1);
}
assertEquals(HttpGenerator.State.END,gen.getState());
assertEquals(0,gen.getContentWritten()); }
@Test
public void testRequestWithContent() throws Exception
public void testRequestWithSmallContent() throws Exception
{
ByteBuffer header=BufferUtil.allocate(8096);
ByteBuffer buffer=BufferUtil.allocate(8096);
ByteBuffer content=BufferUtil.toBuffer("Hello World");
HttpFields fields = new HttpFields();
HttpGenerator hg = new HttpGenerator();
HttpGenerator gen = new HttpGenerator();
hg.setRequest("GET","/index.html");
gen.setVersion(HttpVersion.HTTP_1_1);
gen.setRequest("POST","/index.html");
fields.add("Host","something");
fields.add("User-Agent","test");
hg.setVersion(HttpVersion.HTTP_1_1);
hg.completeHeader(header,fields,true);
hg.complete();
HttpGenerator.Result
result=gen.prepareContent(null,null,content);
assertEquals(HttpGenerator.Result.NEED_BUFFER,result);
result=gen.prepareContent(null,buffer,content);
assertEquals(HttpGenerator.Result.OK,result);
assertEquals("Hello World",BufferUtil.toString(buffer));
assertTrue(BufferUtil.isEmpty(content));
result=gen.complete(null,buffer);
assertEquals(HttpGenerator.Result.NEED_COMMIT,result);
result=gen.commit(fields,header,buffer,content,true);
assertEquals(HttpGenerator.Result.FLUSH,result);
String out = BufferUtil.toString(header);
BufferUtil.clear(header);
BufferUtil.clear(buffer);
result=gen.complete(null,buffer);
assertEquals(HttpGenerator.Result.OK,result);
result=gen.commit(fields,header,null,null,true);
assertEquals(HttpGenerator.Result.NEED_COMPLETE,result);
result=gen.complete(null,null);
assertEquals(HttpGenerator.Result.OK,result);
assertTrue(out.indexOf("GET /index.html HTTP/1.1")==0);
assertTrue(out.indexOf("Content-Length")==-1);
assertEquals(HttpGenerator.State.END,gen.getState());
assertEquals(0,gen.getContentWritten());
}
@Test
public void testHTTP() throws Exception
{

View File

@ -291,7 +291,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
boolean progress=process(null,toFlush);
// if we received any data,
if (!BufferUtil.isEmpty(_unwrapBuf))
if (BufferUtil.hasContent(_unwrapBuf))
{
// transfer from temp buffer to fill buffer
BufferUtil.put(_unwrapBuf,toFill);
@ -302,7 +302,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
return progress;
}
// Else if there is some temporary data
else if (!BufferUtil.isEmpty(_unwrapBuf))
else if (BufferUtil.hasContent(_unwrapBuf))
{
// transfer from temp buffer to fill buffer
BufferUtil.put(_unwrapBuf,toFill);
@ -332,7 +332,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
_inbound.compact().flip();
// flush any output data
if (!BufferUtil.isEmpty(_outbound) && (flushed=_endp.flush(_outbound))>0)
if (BufferUtil.hasContent(_outbound) && (flushed=_endp.flush(_outbound))>0)
{
progress = true;
_outbound.compact().flip();
@ -358,11 +358,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
case NOT_HANDSHAKING:
{
// Try unwrapping some application data
if (!BufferUtil.isAtCapacity(toFill) && !BufferUtil.isEmpty(_inbound) && unwrap(toFill))
if (!BufferUtil.isAtCapacity(toFill) && BufferUtil.hasContent(_inbound) && unwrap(toFill))
progress=true;
// Try wrapping some application data
if (!BufferUtil.isEmpty(toFlush) && !BufferUtil.isAtCapacity(_outbound) && wrap(toFlush))
if (BufferUtil.hasContent(toFlush) && !BufferUtil.isAtCapacity(_outbound) && wrap(toFlush))
progress=true;
}
break;
@ -418,7 +418,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
}
// If we are reading into the temp buffer and it has some content, then we should be dispatched.
if (toFill==_unwrapBuf && !BufferUtil.isEmpty(_unwrapBuf))
if (toFill==_unwrapBuf && BufferUtil.hasContent(_unwrapBuf))
_aEndp.asyncDispatch();
}
finally
@ -592,8 +592,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
synchronized (SslConnection.this)
{
return _endp.isInputShutdown() &&
!(_unwrapBuf!=null&&!BufferUtil.isEmpty(_unwrapBuf)) &&
!(_inbound!=null&&!BufferUtil.isEmpty(_inbound));
!(_unwrapBuf!=null&&BufferUtil.hasContent(_unwrapBuf)) &&
!(_inbound!=null&&BufferUtil.hasContent(_inbound));
}
}
@ -624,9 +624,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public int flush(ByteBuffer header, ByteBuffer buffer) throws IOException
{
if (!BufferUtil.isEmpty(header))
if (BufferUtil.hasContent(header))
return flush(header);
if (!BufferUtil.isEmpty(buffer))
if (BufferUtil.hasContent(buffer))
return flush(buffer);
return 0;
}

View File

@ -0,0 +1,169 @@
package org.eclipse.jetty.io.nio;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.Test;
public class BufferUtilTest
{
@Test
public void testPut() throws Exception
{
ByteBuffer to = BufferUtil.allocate(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutUnderMax() throws Exception
{
ByteBuffer to = BufferUtil.allocate(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to,10));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to,10));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutAtMax() throws Exception
{
ByteBuffer to = BufferUtil.allocate(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to,5));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to,5));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutOverMax() throws Exception
{
ByteBuffer to = BufferUtil.allocate(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(4,BufferUtil.put(from,to,4));
assertEquals(1,from.remaining());
assertEquals("1234",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX567890ZZ");
from.position(2);
assertEquals(4,BufferUtil.put(from,to,4));
assertEquals(4,from.remaining());
assertEquals("12345678",BufferUtil.toString(to));
}
@Test
public void testPutDirect() throws Exception
{
ByteBuffer to = BufferUtil.allocateDirect(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutUnderMaxDirect() throws Exception
{
ByteBuffer to = BufferUtil.allocateDirect(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to,10));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to,10));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutAtMaxDirect() throws Exception
{
ByteBuffer to = BufferUtil.allocateDirect(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(5,BufferUtil.put(from,to,5));
assertTrue(BufferUtil.isEmpty(from));
assertEquals("12345",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX67890ZZ");
from.position(2);
assertEquals(5,BufferUtil.put(from,to,5));
assertEquals(2,from.remaining());
assertEquals("1234567890",BufferUtil.toString(to));
}
@Test
public void testPutOverMaxDirect() throws Exception
{
ByteBuffer to = BufferUtil.allocateDirect(10);
ByteBuffer from=BufferUtil.toBuffer("12345");
BufferUtil.clear(to);
assertEquals(4,BufferUtil.put(from,to,4));
assertEquals(1,from.remaining());
assertEquals("1234",BufferUtil.toString(to));
from=BufferUtil.toBuffer("XX567890ZZ");
from.position(2);
assertEquals(4,BufferUtil.put(from,to,4));
assertEquals(4,from.remaining());
assertEquals("12345678",BufferUtil.toString(to));
}
}

View File

@ -138,15 +138,15 @@ public class SelectChannelEndPointTest
progress=true;
}
if (!BufferUtil.isEmpty(_in) && BufferUtil.put(_in,_out)>0)
if (BufferUtil.hasContent(_in) && BufferUtil.put(_in,_out)>0)
progress=true;
if (!BufferUtil.isEmpty(_out) && _endp.flush(_out)>0)
if (BufferUtil.hasContent(_out) && _endp.flush(_out)>0)
progress=true;
_out.compact().flip();
if (!!BufferUtil.isEmpty(_out) && _endp.isInputShutdown())
if (BufferUtil.isEmpty(_out) && _endp.isInputShutdown())
_endp.shutdownOutput();
}
return this;

View File

@ -68,7 +68,24 @@ public class BufferUtil
buf.limit(0);
return buf;
}
/* ------------------------------------------------------------ */
public static void flipToFill(ByteBuffer buffer)
{
buffer.position(buffer.limit());
buffer.limit(buffer.capacity());
}
/* ------------------------------------------------------------ */
public static void flipToFlush(ByteBuffer buffer,int position)
{
buffer.limit(buffer.position());
buffer.position(position);
}
/* ------------------------------------------------------------ */
public static byte[] toArray(ByteBuffer buffer)
{
@ -89,17 +106,93 @@ public class BufferUtil
return buf==null || buf.remaining()==0;
}
/* ------------------------------------------------------------ */
public static boolean hasContent(ByteBuffer buf)
{
return buf!=null && buf.remaining()>0;
}
/* ------------------------------------------------------------ */
public static boolean isAtCapacity(ByteBuffer buf)
{
return buf!=null && buf.limit()==buf.capacity();
}
/* ------------------------------------------------------------ */
public static long remaining(ByteBuffer buffer)
{
return buffer==null?0:buffer.remaining();
}
/* ------------------------------------------------------------ */
/**
* Put data from one buffer into another, avoiding over/under flows
* @param from
* @param to
* @param from Buffer to take bytes from
* @param to Buffer to put bytes to
* @return number of bytes moved
*/
public static int put(ByteBuffer from, ByteBuffer to, long maxBytes)
{
return put(from,to,maxBytes>=Integer.MAX_VALUE?Integer.MAX_VALUE:(int)maxBytes);
}
/* ------------------------------------------------------------ */
/**
* Put data from one buffer into another, avoiding over/under flows
* @param from Buffer to take bytes from
* @param to Buffer to put bytes to
* @return number of bytes moved
*/
public static int put(ByteBuffer from, ByteBuffer to, int maxBytes)
{
int put;
int pos=to.position();
try
{
flipToFill(to);
maxBytes=Math.min(maxBytes,to.remaining());
int remaining=from.remaining();
if (remaining>0)
{
if (remaining<=maxBytes)
{
to.put(from);
put=remaining;
}
else if (from.hasArray())
{
put=maxBytes;
to.put(from.array(),from.arrayOffset()+from.position(),put);
from.position(from.position()+put);
}
else
{
put=maxBytes;
ByteBuffer slice=from.slice();
slice.limit(put);
to.put(slice);
from.position(from.position()+put);
}
}
else
put=0;
}
finally
{
flipToFlush(to,pos);
}
return put;
}
/* ------------------------------------------------------------ */
/**
* Put data from one buffer into another, avoiding over/under flows
* @param from Buffer to take bytes from
* @param to Buffer to put bytes to
* @return number of bytes moved
*/
public static int put(ByteBuffer from, ByteBuffer to)
{
@ -107,8 +200,7 @@ public class BufferUtil
int pos=to.position();
try
{
to.position(to.limit());
to.limit(to.capacity());
flipToFill(to);
int remaining=from.remaining();
if (remaining>0)
@ -139,8 +231,7 @@ public class BufferUtil
}
finally
{
to.limit(to.position());
to.position(pos);
flipToFlush(to,pos);
}
return put;
@ -558,4 +649,6 @@ public class BufferUtil
}
}