reworked for metadata
This commit is contained in:
parent
e81e01719f
commit
36081dbcbf
|
@ -1,94 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.hpack;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class Field extends HttpField
|
||||
{
|
||||
// final ByteBuffer _nameLiteral;
|
||||
// final ByteBuffer _nameHuffman;
|
||||
private final NameKey _nameKey=new NameKey();
|
||||
|
||||
public Field(String name,String value)
|
||||
{
|
||||
super(HttpHeader.CACHE.get(name),name,value);
|
||||
|
||||
// Generate a non huffman literal field
|
||||
/*
|
||||
_nameLiteral=BufferUtil.allocate(1+NBitInteger.octectsNeeded(7,name.length())+name.length());
|
||||
BufferUtil.flipToFill(_nameLiteral);
|
||||
_nameLiteral.put((byte)0x00);
|
||||
NBitInteger.encode(_nameLiteral,7,name.length());
|
||||
for (int i=0;i<name.length();i++)
|
||||
{
|
||||
char c=name.charAt(0);
|
||||
if (c<32||c>126)
|
||||
throw new IllegalArgumentException();
|
||||
_nameLiteral.array()[_nameLiteral.position()+i]=(byte)c;
|
||||
}
|
||||
_nameLiteral.position(_nameLiteral.limit());
|
||||
BufferUtil.flipToFlush(_nameLiteral,0);
|
||||
|
||||
// Generate a huffman literal field
|
||||
int h=Huffman.octetsNeeded(name);
|
||||
_nameHuffman=BufferUtil.allocate(1+NBitInteger.octectsNeeded(7,h)+h);
|
||||
BufferUtil.flipToFill(_nameHuffman);
|
||||
_nameHuffman.put((byte)0x80);
|
||||
NBitInteger.encode(_nameHuffman,7,name.length());
|
||||
for (int i=0;i<name.length();i++)
|
||||
{
|
||||
char c=name.charAt(0);
|
||||
if (c<32||c>126)
|
||||
throw new IllegalArgumentException();
|
||||
_nameHuffman.array()[_nameHuffman.position()+i]=(byte)c;
|
||||
}
|
||||
_nameHuffman.position(_nameHuffman.limit());
|
||||
BufferUtil.flipToFlush(_nameHuffman,0);
|
||||
*/
|
||||
}
|
||||
|
||||
public NameKey getNameKey()
|
||||
{
|
||||
return _nameKey;
|
||||
}
|
||||
|
||||
public class NameKey
|
||||
{
|
||||
|
||||
public Field getField()
|
||||
{
|
||||
return Field.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -26,8 +26,9 @@ import java.util.Map;
|
|||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.hpack.HpackDecoder.Listener;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.util.ArrayQueue;
|
||||
import org.eclipse.jetty.util.ArrayTrie;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -111,7 +112,37 @@ public class HpackContext
|
|||
Set<String> added = new HashSet<>();
|
||||
for (int i=1;i<STATIC_TABLE.length;i++)
|
||||
{
|
||||
Entry entry=__staticTable[i]=new StaticEntry(i,STATIC_TABLE[i][0],STATIC_TABLE[i][1]);
|
||||
Entry entry;
|
||||
switch(i)
|
||||
{
|
||||
case 2:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
|
||||
break;
|
||||
case 3:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.POST));
|
||||
break;
|
||||
case 6:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTP));
|
||||
break;
|
||||
case 7:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
break;
|
||||
|
||||
default:
|
||||
entry=new StaticEntry(i,new HttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1]));
|
||||
}
|
||||
|
||||
__staticTable[i]=entry;
|
||||
|
||||
if (entry._field.getValue()!=null)
|
||||
__staticFieldMap.put(entry._field,entry);
|
||||
if (!added.contains(entry._field.getName()))
|
||||
|
@ -254,7 +285,7 @@ public class HpackContext
|
|||
}
|
||||
}
|
||||
|
||||
public void emitUnusedReferences(Listener listener)
|
||||
public void emitUnusedReferences(MetaDataBuilder builder)
|
||||
{
|
||||
Entry entry = _refSet._refSetNext;
|
||||
while(entry!=_refSet)
|
||||
|
@ -262,7 +293,7 @@ public class HpackContext
|
|||
if (entry.isUsed())
|
||||
entry._used=false;
|
||||
else
|
||||
listener.emit(entry.getHttpField());
|
||||
builder.emit(entry.getHttpField());
|
||||
|
||||
entry=entry._refSetNext;
|
||||
}
|
||||
|
@ -478,17 +509,16 @@ public class HpackContext
|
|||
{
|
||||
return _used;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static class StaticEntry extends Entry
|
||||
{
|
||||
final byte[] _huffmanValue;
|
||||
|
||||
StaticEntry(int index,String name, String value)
|
||||
StaticEntry(int index,HttpField field)
|
||||
{
|
||||
super(index,name,value);
|
||||
super(index,field);
|
||||
String value = field.getValue();
|
||||
if (value!=null && value.length()>0)
|
||||
{
|
||||
int huffmanLen = Huffman.octetsNeeded(value);
|
||||
|
@ -501,8 +531,7 @@ public class HpackContext
|
|||
// Add huffman length
|
||||
NBitInteger.encode(buffer,7,huffmanLen);
|
||||
// Encode value
|
||||
Huffman.encode(buffer,value);
|
||||
|
||||
Huffman.encode(buffer,value);
|
||||
}
|
||||
else
|
||||
_huffmanValue=null;
|
||||
|
@ -521,7 +550,23 @@ public class HpackContext
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
public static class StaticValueHttpField extends HttpField
|
||||
{
|
||||
private final Object _value;
|
||||
|
||||
public StaticValueHttpField(String name, String valueString, Object value)
|
||||
{
|
||||
super(name,valueString);
|
||||
_value=value;
|
||||
}
|
||||
|
||||
public Object getStaticValue()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,30 +32,24 @@ import org.eclipse.jetty.http.HttpHeader;
|
|||
*/
|
||||
public class HpackDecoder
|
||||
{
|
||||
public interface Listener
|
||||
{
|
||||
void emit(HttpField field);
|
||||
void endHeaders();
|
||||
}
|
||||
|
||||
private final HpackContext _context;
|
||||
private final Listener _listener;
|
||||
private final MetaDataBuilder _builder = new MetaDataBuilder();
|
||||
|
||||
public HpackDecoder(Listener listener)
|
||||
public HpackDecoder()
|
||||
{
|
||||
this(listener,4096);
|
||||
this(4096);
|
||||
}
|
||||
|
||||
public HpackDecoder(Listener listener,int maxHeaderTableSize)
|
||||
public HpackDecoder(int maxHeaderTableSize)
|
||||
{
|
||||
_listener=listener;
|
||||
_context=new HpackContext(maxHeaderTableSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void decode(ByteBuffer buffer)
|
||||
public MetaData decode(ByteBuffer buffer)
|
||||
{
|
||||
|
||||
while(buffer.hasRemaining())
|
||||
{
|
||||
byte b = buffer.get();
|
||||
|
@ -69,7 +63,7 @@ public class HpackDecoder
|
|||
else if (entry.isStatic())
|
||||
{
|
||||
// emit field
|
||||
_listener.emit(entry.getHttpField());
|
||||
_builder.emit(entry.getHttpField());
|
||||
|
||||
// copy and add to reference set if there is room
|
||||
Entry new_entry = _context.add(entry.getHttpField());
|
||||
|
@ -79,7 +73,7 @@ public class HpackDecoder
|
|||
else
|
||||
{
|
||||
// emit
|
||||
_listener.emit(entry.getHttpField());
|
||||
_builder.emit(entry.getHttpField());
|
||||
// add to reference set
|
||||
_context.addToRefSet(entry);
|
||||
}
|
||||
|
@ -129,7 +123,7 @@ public class HpackDecoder
|
|||
HttpField field = new HttpField(header,name,value);
|
||||
|
||||
// emit the field
|
||||
_listener.emit(field);
|
||||
_builder.emit(field);
|
||||
|
||||
// if indexed
|
||||
if (indexed)
|
||||
|
@ -155,8 +149,8 @@ public class HpackDecoder
|
|||
}
|
||||
}
|
||||
|
||||
_context.emitUnusedReferences(_listener);
|
||||
_listener.endHeaders();
|
||||
_context.emitUnusedReferences(_builder);
|
||||
return _builder.build();
|
||||
}
|
||||
|
||||
public static String toASCIIString(ByteBuffer buffer,int length)
|
||||
|
|
|
@ -26,11 +26,14 @@ import org.eclipse.jetty.hpack.HpackContext.Entry;
|
|||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.ByteBufferPool.Lease;
|
||||
|
||||
public class HpackEncoder
|
||||
{
|
||||
private final static HttpField[] __status= new HttpField[599];
|
||||
|
||||
private final static EnumSet<HttpHeader> __NEVER_INDEX =
|
||||
EnumSet.of(HttpHeader.SET_COOKIE,
|
||||
HttpHeader.SET_COOKIE2);
|
||||
|
@ -61,18 +64,22 @@ public class HpackEncoder
|
|||
HttpHeader.SERVLET_ENGINE,
|
||||
HttpHeader.USER_AGENT);
|
||||
|
||||
private final ByteBufferPool _byteBufferPool;
|
||||
static
|
||||
{
|
||||
for (HttpStatus.Code code : HttpStatus.Code.values())
|
||||
__status[code.getCode()]=new HttpField(":status",Integer.toString(code.getCode()));
|
||||
}
|
||||
|
||||
private final HpackContext _context;
|
||||
|
||||
|
||||
public HpackEncoder(ByteBufferPool byteBufferPool)
|
||||
public HpackEncoder()
|
||||
{
|
||||
this(byteBufferPool,4096);
|
||||
this(4096);
|
||||
}
|
||||
|
||||
public HpackEncoder(ByteBufferPool byteBufferPool,int maxHeaderTableSize)
|
||||
public HpackEncoder(int maxHeaderTableSize)
|
||||
{
|
||||
this._byteBufferPool = byteBufferPool;
|
||||
_context=new HpackContext(maxHeaderTableSize);
|
||||
}
|
||||
|
||||
|
@ -81,20 +88,41 @@ public class HpackEncoder
|
|||
return _context;
|
||||
}
|
||||
|
||||
public ByteBufferPool.Lease encode(HttpFields fields)
|
||||
public void encode(MetaData metadata,Lease lease)
|
||||
{
|
||||
Lease lease=new ByteBufferPool.Lease(_byteBufferPool);
|
||||
ByteBuffer buffer = _byteBufferPool.acquire(8*1024,false); // TODO make configurable
|
||||
lease.add(buffer,true);
|
||||
ByteBuffer buffer = lease.acquire(8*1024,false); // TODO make size configurable
|
||||
|
||||
// TODO handle multiple buffers if large size configured.
|
||||
encode(buffer,fields);
|
||||
return lease;
|
||||
encode(buffer,metadata);
|
||||
}
|
||||
|
||||
public void encode(ByteBuffer buffer, HttpFields fields)
|
||||
public void encode(ByteBuffer buffer, MetaData metadata)
|
||||
{
|
||||
// Add all the known fields
|
||||
for (HttpField field : fields)
|
||||
// Add Request/response meta fields
|
||||
|
||||
if (metadata.isRequest())
|
||||
{
|
||||
MetaData.Request request = (MetaData.Request)metadata;
|
||||
|
||||
// TODO optimise these to avoid HttpField creation
|
||||
encode(buffer,new HttpField(":scheme",request.getScheme().asString()));
|
||||
encode(buffer,new HttpField(":method",request.getMethodString()));
|
||||
encode(buffer,new HttpField(":authority",request.getAuthority())); // TODO look for host header?
|
||||
encode(buffer,new HttpField(":path",request.getPath()));
|
||||
|
||||
}
|
||||
else if (metadata.isResponse())
|
||||
{
|
||||
MetaData.Response response = (MetaData.Response)metadata;
|
||||
int code=response.getStatus();
|
||||
HttpField status = code<__status.length?__status[code]:null;
|
||||
if (status==null)
|
||||
status=new HttpField(":status",Integer.toString(code));
|
||||
encode(buffer,status);
|
||||
}
|
||||
|
||||
// Add all the other fields
|
||||
for (HttpField field : metadata)
|
||||
{
|
||||
encode(buffer,field);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.hpack;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class MetaData implements Iterable<HttpField>
|
||||
{
|
||||
private final Iterable<HttpField> _fields;
|
||||
|
||||
public MetaData(Iterable<HttpField> fields)
|
||||
{
|
||||
_fields=fields;
|
||||
}
|
||||
|
||||
public boolean isRequest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isResponse()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<HttpField> iterator()
|
||||
{
|
||||
return _fields.iterator();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
public static class Request extends MetaData
|
||||
{
|
||||
private final HttpMethod _method;
|
||||
private final String _methodString;
|
||||
private final HttpScheme _scheme;
|
||||
private final String _authority;
|
||||
private final String _path;
|
||||
|
||||
public Request(HttpScheme scheme, HttpMethod method, String methodString, String authority, String path, Iterable<HttpField> fields)
|
||||
{
|
||||
super(fields);
|
||||
_authority=authority;
|
||||
_method=method;
|
||||
_methodString=methodString;
|
||||
_path=path;
|
||||
_scheme=scheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponse()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public HttpMethod getMethod()
|
||||
{
|
||||
return _method;
|
||||
}
|
||||
|
||||
public String getMethodString()
|
||||
{
|
||||
return _methodString;
|
||||
}
|
||||
|
||||
public HttpScheme getScheme()
|
||||
{
|
||||
return _scheme;
|
||||
}
|
||||
|
||||
public String getAuthority()
|
||||
{
|
||||
return _authority;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
public static class Response extends MetaData
|
||||
{
|
||||
private final int _status;
|
||||
|
||||
public Response(int status, HttpFields fields)
|
||||
{
|
||||
super(fields);
|
||||
_status=status;
|
||||
}
|
||||
|
||||
public Response(int status, Iterable<HttpField> fields)
|
||||
{
|
||||
super(fields);
|
||||
_status=status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponse()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getStatus()
|
||||
{
|
||||
return _status;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.hpack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
/* -------------------------------------------------------- */
|
||||
public class MetaDataBuilder
|
||||
{
|
||||
private int _status;
|
||||
private HttpMethod _method;
|
||||
private String _methodString;
|
||||
private HttpScheme _scheme;
|
||||
private String _authority;
|
||||
private String _path;
|
||||
|
||||
List<HttpField> _fields = new ArrayList<>();
|
||||
|
||||
public void emit(HttpField field)
|
||||
{
|
||||
if (field instanceof HpackContext.StaticValueHttpField)
|
||||
{
|
||||
HpackContext.StaticValueHttpField value = (HpackContext.StaticValueHttpField)field;
|
||||
switch(field.getName())
|
||||
{
|
||||
case ":status":
|
||||
_status=(Integer)value.getStaticValue();
|
||||
break;
|
||||
|
||||
case ":method":
|
||||
_method=(HttpMethod)value.getStaticValue();
|
||||
_methodString=_method.asString();
|
||||
break;
|
||||
|
||||
case ":scheme":
|
||||
_scheme = (HttpScheme)value.getStaticValue();
|
||||
break;
|
||||
|
||||
case ":authority":
|
||||
_authority=field.getValue();
|
||||
break;
|
||||
|
||||
case ":path":
|
||||
_path=field.getValue();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (field.getName().charAt(0)!=':')
|
||||
_fields.add(field);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
switch(field.getName())
|
||||
{
|
||||
case ":status":
|
||||
_status=Integer.parseInt(field.getValue());
|
||||
break;
|
||||
|
||||
case ":method":
|
||||
_methodString=field.getValue();
|
||||
_method=HttpMethod.CACHE.get(_methodString);
|
||||
break;
|
||||
|
||||
case ":scheme":
|
||||
_scheme = HttpScheme.valueOf(field.getValue());
|
||||
break;
|
||||
|
||||
case ":authority":
|
||||
_authority=field.getValue();
|
||||
break;
|
||||
|
||||
case ":path":
|
||||
_path=field.getValue();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (field.getName().charAt(0)!=':')
|
||||
_fields.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MetaData build()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_method!=null)
|
||||
return new MetaData.Request(_scheme,_method,_methodString,_authority,_path,new ArrayList<>(_fields));
|
||||
if (_status!=0)
|
||||
return new MetaData.Response(_status,new ArrayList<>(_fields));
|
||||
return new MetaData(new ArrayList<>(_fields));
|
||||
}
|
||||
finally
|
||||
{
|
||||
_status=0;
|
||||
_method=null;
|
||||
_scheme=null;
|
||||
_authority=null;
|
||||
_path=null;
|
||||
_fields.clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,12 +22,12 @@ package org.eclipse.jetty.hpack;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.eclipse.jetty.hpack.HpackDecoder.Listener;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
@ -39,134 +39,109 @@ public class HpackDecoderTest
|
|||
|
||||
@Test
|
||||
public void testDecodeD_3()
|
||||
{
|
||||
final HttpFields fields = new HttpFields();
|
||||
Listener listener = new Listener()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void endHeaders()
|
||||
{
|
||||
System.err.println("===");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(HttpField field)
|
||||
{
|
||||
System.err.println(field);
|
||||
fields.add(field);
|
||||
}
|
||||
};
|
||||
|
||||
HpackDecoder decoder = new HpackDecoder(listener);
|
||||
|
||||
|
||||
{
|
||||
HpackDecoder decoder = new HpackDecoder();
|
||||
|
||||
// First request
|
||||
String encoded="828786440f7777772e6578616d706c652e636f6d";
|
||||
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
MetaData.Request request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(4,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("http",fields.get(":scheme"));
|
||||
assertEquals("/",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTP,request.getScheme());
|
||||
assertEquals("/",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
assertFalse(request.iterator().hasNext());
|
||||
|
||||
|
||||
// Second request
|
||||
fields.clear();
|
||||
encoded="5c086e6f2d6361636865";
|
||||
buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTP,request.getScheme());
|
||||
assertEquals("/",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
Iterator<HttpField> iterator=request.iterator();
|
||||
assertTrue(iterator.hasNext());
|
||||
assertEquals(new HttpField("cache-control","no-cache"),iterator.next());
|
||||
assertFalse(iterator.hasNext());
|
||||
|
||||
assertEquals(5,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("http",fields.get(":scheme"));
|
||||
assertEquals("/",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals("no-cache",fields.get("cache-control"));
|
||||
|
||||
// Third request
|
||||
fields.clear();
|
||||
encoded="30858c8b84400a637573746f6d2d6b65790c637573746f6d2d76616c7565";
|
||||
buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(5,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("https",fields.get(":scheme"));
|
||||
assertEquals("/index.html",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals("custom-value",fields.get("custom-key"));
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTPS,request.getScheme());
|
||||
assertEquals("/index.html",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
iterator=request.iterator();
|
||||
assertTrue(iterator.hasNext());
|
||||
assertEquals(new HttpField("custom-key","custom-value"),iterator.next());
|
||||
assertFalse(iterator.hasNext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecodeD_4()
|
||||
{
|
||||
final HttpFields fields = new HttpFields();
|
||||
Listener listener = new Listener()
|
||||
{
|
||||
|
||||
@Override
|
||||
public void endHeaders()
|
||||
{
|
||||
System.err.println("===");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void emit(HttpField field)
|
||||
{
|
||||
System.err.println(field);
|
||||
fields.add(field);
|
||||
}
|
||||
};
|
||||
|
||||
HpackDecoder decoder = new HpackDecoder(listener);
|
||||
HpackDecoder decoder = new HpackDecoder();
|
||||
|
||||
|
||||
// First request
|
||||
String encoded="828786448ce7cf9bebe89b6fb16fa9b6ff";
|
||||
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
MetaData.Request request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(4,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("http",fields.get(":scheme"));
|
||||
assertEquals("/",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTP,request.getScheme());
|
||||
assertEquals("/",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
assertFalse(request.iterator().hasNext());
|
||||
|
||||
|
||||
// Second request
|
||||
fields.clear();
|
||||
encoded="5c86b9b9949556bf";
|
||||
buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
|
||||
assertEquals(5,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("http",fields.get(":scheme"));
|
||||
assertEquals("/",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals("no-cache",fields.get("cache-control"));
|
||||
request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTP,request.getScheme());
|
||||
assertEquals("/",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
Iterator<HttpField> iterator=request.iterator();
|
||||
assertTrue(iterator.hasNext());
|
||||
assertEquals(new HttpField("cache-control","no-cache"),iterator.next());
|
||||
assertFalse(iterator.hasNext());
|
||||
|
||||
// Third request
|
||||
fields.clear();
|
||||
encoded="30858c8b844088571c5cdb737b2faf89571c5cdb73724d9c57";
|
||||
buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
|
||||
|
||||
decoder.decode(buffer);
|
||||
request = (MetaData.Request)decoder.decode(buffer);
|
||||
|
||||
assertEquals(5,fields.size());
|
||||
assertEquals("GET",fields.get(":method"));
|
||||
assertEquals("https",fields.get(":scheme"));
|
||||
assertEquals("/index.html",fields.get(":path"));
|
||||
assertEquals("www.example.com",fields.get(":authority"));
|
||||
assertEquals("custom-value",fields.get("custom-key"));
|
||||
assertEquals(HttpMethod.GET,request.getMethod());
|
||||
assertEquals("GET",request.getMethodString());
|
||||
assertEquals(HttpScheme.HTTPS,request.getScheme());
|
||||
assertEquals("/index.html",request.getPath());
|
||||
assertEquals("www.example.com",request.getAuthority());
|
||||
iterator=request.iterator();
|
||||
assertTrue(iterator.hasNext());
|
||||
assertEquals(new HttpField("custom-key","custom-value"),iterator.next());
|
||||
assertFalse(iterator.hasNext());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class HpackEncoderTest
|
|||
@Test
|
||||
public void testUnknownFieldsContextManagement()
|
||||
{
|
||||
HpackEncoder encoder = new HpackEncoder(null,38*5);
|
||||
HpackEncoder encoder = new HpackEncoder(38*5);
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class HpackEncoderTest
|
|||
// encode them
|
||||
ByteBuffer buffer = BufferUtil.allocate(4096);
|
||||
int pos = BufferUtil.flipToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,pos);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -87,7 +87,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode exact same fields again!
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// nothing should be encoded!
|
||||
|
@ -110,7 +110,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -134,7 +134,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -161,7 +161,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -189,7 +189,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -215,7 +215,7 @@ public class HpackEncoderTest
|
|||
@Test
|
||||
public void testDoNotReferenceStatics()
|
||||
{
|
||||
HpackEncoder encoder = new HpackEncoder(null,38*5);
|
||||
HpackEncoder encoder = new HpackEncoder(38*5);
|
||||
ByteBuffer buffer = BufferUtil.allocate(4096);
|
||||
|
||||
HttpFields fields = new HttpFields();
|
||||
|
@ -223,7 +223,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -236,7 +236,7 @@ public class HpackEncoderTest
|
|||
@Test
|
||||
public void testNeverIndexSetCookie()
|
||||
{
|
||||
HpackEncoder encoder = new HpackEncoder(null,38*5);
|
||||
HpackEncoder encoder = new HpackEncoder(38*5);
|
||||
ByteBuffer buffer = BufferUtil.allocate(4096);
|
||||
|
||||
HttpFields fields = new HttpFields();
|
||||
|
@ -244,7 +244,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
@ -256,7 +256,7 @@ public class HpackEncoderTest
|
|||
|
||||
// encode again
|
||||
BufferUtil.clearToFill(buffer);
|
||||
encoder.encode(buffer,fields);
|
||||
encoder.encode(buffer,new MetaData(fields));
|
||||
BufferUtil.flipToFlush(buffer,0);
|
||||
|
||||
// something was encoded!
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.hpack;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
public class HpackTest
|
||||
{
|
||||
@Test
|
||||
public void encodeDecodeTest()
|
||||
{
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -64,6 +64,14 @@ public interface ByteBufferPool
|
|||
this.recycles = new ArrayList<>();
|
||||
}
|
||||
|
||||
public ByteBuffer acquire(int capacity,boolean direct)
|
||||
{
|
||||
ByteBuffer buffer = byteBufferPool.acquire(capacity,direct);
|
||||
buffers.add(buffer);
|
||||
recycles.add(true);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void add(ByteBuffer buffer, boolean recycle)
|
||||
{
|
||||
buffers.add(buffer);
|
||||
|
|
Loading…
Reference in New Issue