jetty-9 work in progress on new HttpGenerator
This commit is contained in:
parent
1fa6c998db
commit
a4bee5b12d
|
@ -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)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue