Merged branch 'jetty-http2' into 'http2_flow_control'

This commit is contained in:
Simone Bordet 2014-08-06 15:43:56 +02:00
commit 55dec378fc
75 changed files with 1004 additions and 380 deletions

View File

@ -77,6 +77,16 @@ public class HttpTransportOverFCGI implements HttpTransport
flusher.shutdown();
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
*/
@Override
public void push(org.eclipse.jetty.http.MetaData.Request request)
{
// LOG.debug("ignore push in {}",this);
}
private void commit(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.http;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import java.util.Arrays;
/* ------------------------------------------------------------ */
/**
*/
public class Http1FieldPreEncoder implements HttpFieldPreEncoder
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.HttpFieldPreEncoder#getHttpVersion()
*/
@Override
public HttpVersion getHttpVersion()
{
return HttpVersion.HTTP_1_0;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.HttpFieldPreEncoder#getEncodedField(org.eclipse.jetty.http.HttpHeader, java.lang.String, java.lang.String)
*/
@Override
public byte[] getEncodedField(HttpHeader header, String headerString, String value)
{
if (header!=null)
{
int cbl=header.getBytesColonSpace().length;
byte[] bytes=Arrays.copyOf(header.getBytesColonSpace(), cbl+value.length()+2);
System.arraycopy(value.getBytes(ISO_8859_1),0,bytes,cbl,value.length());
bytes[bytes.length-2]=(byte)'\r';
bytes[bytes.length-1]=(byte)'\n';
return bytes;
}
byte[] n=headerString.getBytes(ISO_8859_1);
byte[] v=value.getBytes(ISO_8859_1);
byte[] bytes=Arrays.copyOf(n,n.length+2+v.length+2);
bytes[n.length]=(byte)':';
bytes[n.length]=(byte)' ';
bytes[bytes.length-2]=(byte)'\r';
bytes[bytes.length-1]=(byte)'\n';
return bytes;
}
}

View File

@ -69,9 +69,14 @@ public class HttpField
return _value;
}
public int getIntValue()
{
return Integer.valueOf(_value);
}
public long getLongValue()
{
return StringUtil.toLong(_value);
return Long.valueOf(_value);
}
public String[] getValues()
@ -416,21 +421,85 @@ public class HttpField
return true;
}
public static class IntValueHttpField extends HttpField
{
final int _int;
public IntValueHttpField(HttpHeader header, String name, String value, int intValue)
{
super(header,name,value);
_int=intValue;
}
public IntValueHttpField(HttpHeader header, String value, int intValue)
{
this(header,header.asString(),value,Integer.valueOf(value));
}
public IntValueHttpField(HttpHeader header, String name, String value)
{
this(header,name,value,Integer.valueOf(value));
}
public IntValueHttpField(HttpHeader header, String value)
{
this(header,header.asString(),value);
}
public IntValueHttpField(HttpHeader header, int value)
{
this(header,header.asString(),value);
}
@Override
public int getIntValue()
{
return _int;
}
@Override
public long getLongValue()
{
return _int;
}
}
public static class LongValueHttpField extends HttpField
{
final long _long;
public LongValueHttpField(HttpHeader header, long value)
public LongValueHttpField(HttpHeader header, String name, String value, long longValue)
{
super(header,Long.toString(value));
_long=value;
super(header,name,value);
_long=longValue;
}
public LongValueHttpField(HttpHeader header, String name, String value)
{
this(header,name,value,Long.valueOf(value));
}
public LongValueHttpField(HttpHeader header, String name, long value)
{
this(header,name,Long.toString(value),value);
}
public LongValueHttpField(HttpHeader header, String value)
{
super(header,value);
_long=StringUtil.toLong(value);
this(header,header.asString(),value);
}
public LongValueHttpField(HttpHeader header,long value)
{
this(header,header.asString(),value);
}
@Override
public int getIntValue()
{
return (int)_long;
}
@Override

View File

@ -0,0 +1,36 @@
//
// ========================================================================
// 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.http;
/* ------------------------------------------------------------ */
/** Interface to pre-encode HttpFields. Used by {@link PreEncodedHttpField}
*/
public interface HttpFieldPreEncoder
{
/* ------------------------------------------------------------ */
/** The major version this encoder is for. Both HTTP/1.0 and HTTP/1.1
* use the same field encoding, so the {@link HttpVersion#HTTP_1_0} should
* be return for all HTTP/1.x encodings.
* @return The major version this encoder is for.
*/
HttpVersion getHttpVersion();
byte[] getEncodedField(HttpHeader header, String headerString, String value);
}

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.http;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
@ -34,7 +35,6 @@ import java.util.StringTokenizer;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -55,11 +55,12 @@ public class HttpFields implements Iterable<HttpField>
private static final Logger LOG = Log.getLogger(HttpFields.class);
private final List<HttpField> _fields;
private HttpField[] _fields;
private int _size;
public HttpFields()
{
_fields=new ArrayList<>();
_fields=new HttpField[20];
}
/**
@ -67,18 +68,27 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpFields(int capacity)
{
_fields=new ArrayList<>(capacity);
_fields=new HttpField[capacity];
}
/**
* Constructor.
*/
public HttpFields(HttpFields fields)
{
_fields=Arrays.copyOf(fields._fields,_fields.length+10);
_size=fields._size;
}
public int size()
{
return _fields.size();
return _size;
}
@Override
public Iterator<HttpField> iterator()
{
return _fields.iterator();
return new Itr();
}
/**
@ -86,7 +96,7 @@ public class HttpFields implements Iterable<HttpField>
*/
public Collection<String> getFieldNamesCollection()
{
final Set<String> list = new HashSet<>(_fields.size());
final Set<String> list = new HashSet<>(_size);
for (HttpField f : this)
{
if (f!=null)
@ -111,14 +121,16 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField getField(int i)
{
return _fields.get(i);
if (i>=_size)
throw new NoSuchElementException();
return _fields[i];
}
public HttpField getField(HttpHeader header)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<_size;i++)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getHeader()==header)
return f;
}
@ -127,9 +139,9 @@ public class HttpFields implements Iterable<HttpField>
public HttpField getField(String name)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<_size;i++)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getName().equalsIgnoreCase(name))
return f;
}
@ -138,9 +150,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpField field)
{
for (int i=_fields.size();i-->0;)
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.isSameName(field) && f.contains(field.getValue()))
return true;
}
@ -149,9 +161,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpHeader header, String value)
{
for (int i=_fields.size();i-->0;)
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getHeader()==header && f.contains(value))
return true;
}
@ -160,9 +172,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(String name, String value)
{
for (int i=_fields.size();i-->0;)
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getName().equalsIgnoreCase(name) && f.contains(value))
return true;
}
@ -172,39 +184,35 @@ public class HttpFields implements Iterable<HttpField>
public boolean containsKey(String name)
{
for (int i=_fields.size();i-->0;)
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getName().equalsIgnoreCase(name))
return true;
}
return false;
}
public String getStringField(HttpHeader header)
{
return getStringField(header.asString());
}
public String get(HttpHeader header)
{
return getStringField(header.asString());
for (int i=0;i<_size;i++)
{
HttpField f=_fields[i];
if (f.getHeader()==header)
return f.getValue();
}
return null;
}
public String get(String header)
{
return getStringField(header);
}
/**
* @return the value of a field, or null if not found. For multiple fields of the same name,
* only the first is returned.
* @param name the case-insensitive field name
*/
public String getStringField(String name)
{
HttpField field = getField(name);
return field==null?null:field.getValue();
for (int i=0;i<_size;i++)
{
HttpField f=_fields[i];
if (f.getName().equalsIgnoreCase(header))
return f.getValue();
}
return null;
}
/**
@ -230,9 +238,9 @@ public class HttpFields implements Iterable<HttpField>
*/
public Enumeration<String> getValues(final String name)
{
for (int i=0;i<_fields.size();i++)
for (int i=0;i<_size;i++)
{
final HttpField f = _fields.get(i);
final HttpField f = _fields[i];
if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
{
@ -247,9 +255,9 @@ public class HttpFields implements Iterable<HttpField>
{
if (field==null)
{
while (i<_fields.size())
while (i<_size)
{
field=_fields.get(i++);
field=_fields[i++];
if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
return true;
}
@ -270,7 +278,6 @@ public class HttpFields implements Iterable<HttpField>
}
throw new NoSuchElementException();
}
};
}
}
@ -328,22 +335,24 @@ public class HttpFields implements Iterable<HttpField>
public void put(HttpField field)
{
boolean put=false;
for (int i=_fields.size();i-->0;)
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.isSameName(field))
{
if (put)
_fields.remove(i);
{
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
}
else
{
_fields.set(i,field);
_fields[i]=field;
put=true;
}
}
}
if (!put)
_fields.add(field);
add(field);
}
/**
@ -408,7 +417,7 @@ public class HttpFields implements Iterable<HttpField>
return;
HttpField field = new HttpField(name, value);
_fields.add(field);
add(field);
}
public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
@ -429,7 +438,7 @@ public class HttpFields implements Iterable<HttpField>
if (value == null) throw new IllegalArgumentException("null value");
HttpField field = new HttpField(header, value);
_fields.add(field);
add(field);
}
/**
@ -439,13 +448,17 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField remove(HttpHeader name)
{
for (int i=_fields.size();i-->0;)
HttpField removed=null;
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getHeader()==name)
return _fields.remove(i);
{
removed=f;
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
}
}
return null;
return removed;
}
/**
@ -455,13 +468,17 @@ public class HttpFields implements Iterable<HttpField>
*/
public HttpField remove(String name)
{
for (int i=_fields.size();i-->0;)
HttpField removed=null;
for (int i=_size;i-->0;)
{
HttpField f=_fields.get(i);
HttpField f=_fields[i];
if (f.getName().equalsIgnoreCase(name))
return _fields.remove(i);
{
removed=f;
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
}
}
return null;
return removed;
}
/**
@ -584,10 +601,14 @@ public class HttpFields implements Iterable<HttpField>
if (size() != that.size())
return false;
for (HttpField field : this)
loop: for (HttpField fi : this)
{
if (!that.contains(field))
return false;
for (HttpField fa : that)
{
if (fi.equals(fa))
continue loop;
}
return false;
}
return true;
}
@ -622,17 +643,20 @@ public class HttpFields implements Iterable<HttpField>
public void clear()
{
_fields.clear();
_size=0;
}
public void add(HttpField field)
{
_fields.add(field);
if (_size==_fields.length)
_fields=Arrays.copyOf(_fields,_size*2);
_fields[_size++]=field;
}
public void addAll(HttpFields fields)
{
_fields.addAll(fields._fields);
for (int i=0;i<fields._size;i++)
add(fields._fields[i]);
}
/**
@ -808,5 +832,34 @@ public class HttpFields implements Iterable<HttpField>
}
private class Itr implements Iterator<HttpField>
{
int _cursor; // index of next element to return
int _last=-1;
public boolean hasNext()
{
return _cursor != _size;
}
public HttpField next()
{
int i = _cursor;
if (i >= _size)
throw new NoSuchElementException();
_cursor = i + 1;
return _fields[_last=i];
}
public void remove()
{
if (_last<0)
throw new IllegalStateException();
System.arraycopy(_fields,_last+1,_fields,_last,--_size-_last);
_cursor=_last;
_last=-1;
}
}
}

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.http;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.eclipse.jetty.http.HttpTokens.EndOfContent;
@ -1058,9 +1057,9 @@ public class HttpGenerator
public static void putTo(HttpField field, ByteBuffer bufferInFillMode)
{
if (field instanceof CachedHttpField)
if (field instanceof PreEncodedHttpField)
{
((CachedHttpField)field).putTo(bufferInFillMode);
((PreEncodedHttpField)field).putTo(bufferInFillMode,HttpVersion.HTTP_1_0);
}
else
{
@ -1090,23 +1089,4 @@ public class HttpGenerator
}
BufferUtil.putCRLF(bufferInFillMode);
}
public static class CachedHttpField extends HttpField
{
private final byte[] _bytes;
public CachedHttpField(HttpHeader header,String value)
{
super(header,value);
int cbl=header.getBytesColonSpace().length;
_bytes=Arrays.copyOf(header.getBytesColonSpace(), cbl+value.length()+2);
System.arraycopy(value.getBytes(StandardCharsets.ISO_8859_1),0,_bytes,cbl,value.length());
_bytes[_bytes.length-2]=(byte)'\r';
_bytes[_bytes.length-1]=(byte)'\n';
}
public void putTo(ByteBuffer bufferInFillMode)
{
bufferInFillMode.put(_bytes);
}
}
}

View File

@ -183,15 +183,15 @@ public class HttpParser
// Add common Content types as fields
for (String type : new String[]{"text/plain","text/html","text/xml","text/json","application/json","application/x-www-form-urlencoded"})
{
HttpField field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type);
HttpField field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type);
CACHE.put(field);
for (String charset : new String[]{"utf-8","iso-8859-1"})
{
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase()));
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset.toUpperCase()));
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase()));
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset.toUpperCase()));
}
}

View File

@ -90,7 +90,7 @@ public class MimeTypes
_charset=null;
_charsetString=null;
_assumedCharset=false;
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
}
/* ------------------------------------------------------------ */
@ -103,7 +103,7 @@ public class MimeTypes
_charset=Charset.forName(s.substring(i+9));
_charsetString=_charset==null?null:_charset.toString().toLowerCase();
_assumedCharset=false;
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
}
/* ------------------------------------------------------------ */
@ -115,7 +115,7 @@ public class MimeTypes
_charset=cs;
_charsetString=_charset==null?null:_charset.toString().toLowerCase();
_assumedCharset=true;
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
}
/* ------------------------------------------------------------ */

View File

@ -0,0 +1,80 @@
//
// ========================================================================
// 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.http;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Pre encoded HttpField.
* <p>A HttpField that will be cached and used many times can be created as
* a {@link PreEncodedHttpField}, which will use the {@link HttpFieldPreEncoder}
* instances discovered by the {@link ServiceLoader} to pre-encode the header
* for each version of HTTP in use. This will save garbage
* and CPU each time the field is encoded into a response.
* </p>
*/
public class PreEncodedHttpField extends HttpField
{
private final static Logger LOG = Log.getLogger(PreEncodedHttpField.class);
private final static HttpFieldPreEncoder[] __encoders;
static
{
List<HttpFieldPreEncoder> encoders = new ArrayList<>();
for (HttpFieldPreEncoder enc : ServiceLoader.load(HttpFieldPreEncoder.class,PreEncodedHttpField.class.getClassLoader()))
encoders.add(enc);
LOG.debug("HttpField encoders loaded: {}",encoders);
__encoders = encoders.toArray(new HttpFieldPreEncoder[encoders.size()]);
}
private final byte[][] _encodedField=new byte[2][];
public PreEncodedHttpField(HttpHeader header,String name,String value)
{
super(header,name, value);
for (HttpFieldPreEncoder e:__encoders)
{
_encodedField[e.getHttpVersion()==HttpVersion.HTTP_2?1:0]=e.getEncodedField(header,header.asString(),value);
}
}
public PreEncodedHttpField(HttpHeader header,String value)
{
this(header,header.asString(),value);
}
public PreEncodedHttpField(String name,String value)
{
this(null,name,value);
}
public void putTo(ByteBuffer bufferInFillMode, HttpVersion version)
{
bufferInFillMode.put(_encodedField[version==HttpVersion.HTTP_2?1:0]);
}
}

View File

@ -0,0 +1 @@
org.eclipse.jetty.http.Http1FieldPreEncoder

View File

@ -22,6 +22,9 @@ 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;
/**
@ -135,4 +138,17 @@ public class HttpFieldTest
assertEquals("c",values[2]);
}
@Test
public void testCachedField()
{
PreEncodedHttpField field = new PreEncodedHttpField(HttpHeader.ACCEPT,"something");
ByteBuffer buf = BufferUtil.allocate(256);
BufferUtil.clearToFill(buf);
field.putTo(buf,HttpVersion.HTTP_1_0);
BufferUtil.flipToFlush(buf,0);
String s=BufferUtil.toString(buf);
assertEquals("Accept: something\r\n",s);
}
}

View File

@ -27,9 +27,9 @@ import static org.junit.Assert.assertTrue;
import java.nio.ByteBuffer;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.List;
import java.util.NoSuchElementException;
import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers;
import org.junit.Assert;
@ -48,9 +48,10 @@ public class HttpFieldsTest
header.put("name0", "value:0");
header.put("name1", "value1");
assertEquals("value:0",header.getStringField("name0"));
assertEquals("value1",header.getStringField("name1"));
assertNull(header.getStringField("name2"));
assertEquals(2,header.size());
assertEquals("value:0",header.get("name0"));
assertEquals("value1",header.get("name1"));
assertNull(header.get("name2"));
int matches=0;
Enumeration<String> e = header.getFieldNames();
@ -68,6 +69,7 @@ public class HttpFieldsTest
assertEquals(true, e.hasMoreElements());
assertEquals(e.nextElement(), "value:0");
assertEquals(false, e.hasMoreElements());
}
@Test
@ -99,10 +101,45 @@ public class HttpFieldsTest
header.put("name0", "value0");
header.put("name1", "value1");
assertEquals("value0",header.getStringField("name0"));
assertEquals("value0",header.getStringField("Name0"));
assertEquals("value1",header.getStringField("name1"));
assertEquals("value1",header.getStringField("Name1"));
assertEquals("value0",header.get("name0"));
assertEquals("value0",header.get("Name0"));
assertEquals("value1",header.get("name1"));
assertEquals("value1",header.get("Name1"));
assertEquals(null,header.get("Name2"));
assertEquals("value0",header.getField("name0").getValue());
assertEquals("value0",header.getField("Name0").getValue());
assertEquals("value1",header.getField("name1").getValue());
assertEquals("value1",header.getField("Name1").getValue());
assertEquals(null,header.getField("Name2"));
assertEquals("value0",header.getField(0).getValue());
assertEquals("value1",header.getField(1).getValue());
try
{
header.getField(2);
Assert.fail();
}
catch(NoSuchElementException e)
{}
}
@Test
public void testGetKnown() throws Exception
{
HttpFields header = new HttpFields();
header.put("Connection", "value0");
header.put(HttpHeader.ACCEPT, "value1");
assertEquals("value0",header.get(HttpHeader.CONNECTION));
assertEquals("value1",header.get(HttpHeader.ACCEPT));
assertEquals("value0",header.getField(HttpHeader.CONNECTION).getValue());
assertEquals("value1",header.getField(HttpHeader.ACCEPT).getValue());
assertEquals(null,header.getField(HttpHeader.AGE));
assertEquals(null,header.get(HttpHeader.AGE));
}
@Test
@ -153,16 +190,16 @@ public class HttpFieldsTest
header.put("name1", "xxxxxx");
header.put("name2", "value2");
assertEquals("value0",header.getStringField("name0"));
assertEquals("xxxxxx",header.getStringField("name1"));
assertEquals("value2",header.getStringField("name2"));
assertEquals("value0",header.get("name0"));
assertEquals("xxxxxx",header.get("name1"));
assertEquals("value2",header.get("name2"));
header.put("name1", "value1");
assertEquals("value0",header.getStringField("name0"));
assertEquals("value1",header.getStringField("name1"));
assertEquals("value2",header.getStringField("name2"));
assertNull(header.getStringField("name3"));
assertEquals("value0",header.get("name0"));
assertEquals("value1",header.get("name1"));
assertEquals("value2",header.get("name2"));
assertNull(header.get("name3"));
int matches=0;
Enumeration<String> e = header.getFieldNames();
@ -188,22 +225,22 @@ public class HttpFieldsTest
@Test
public void testRemovePut() throws Exception
{
HttpFields header = new HttpFields();
HttpFields header = new HttpFields(1);
header.put("name0", "value0");
header.put("name1", "value1");
header.put("name2", "value2");
assertEquals("value0",header.getStringField("name0"));
assertEquals("value1",header.getStringField("name1"));
assertEquals("value2",header.getStringField("name2"));
assertEquals("value0",header.get("name0"));
assertEquals("value1",header.get("name1"));
assertEquals("value2",header.get("name2"));
header.remove("name1");
assertEquals("value0",header.getStringField("name0"));
assertNull(header.getStringField("name1"));
assertEquals("value2",header.getStringField("name2"));
assertNull(header.getStringField("name3"));
assertEquals("value0",header.get("name0"));
assertNull(header.get("name1"));
assertEquals("value2",header.get("name2"));
assertNull(header.get("name3"));
int matches=0;
Enumeration<String> e = header.getFieldNames();
@ -232,16 +269,16 @@ public class HttpFieldsTest
fields.add("name1", "valueA");
fields.add("name2", "value2");
assertEquals("value0",fields.getStringField("name0"));
assertEquals("valueA",fields.getStringField("name1"));
assertEquals("value2",fields.getStringField("name2"));
assertEquals("value0",fields.get("name0"));
assertEquals("valueA",fields.get("name1"));
assertEquals("value2",fields.get("name2"));
fields.add("name1", "valueB");
assertEquals("value0",fields.getStringField("name0"));
assertEquals("valueA",fields.getStringField("name1"));
assertEquals("value2",fields.getStringField("name2"));
assertNull(fields.getStringField("name3"));
assertEquals("value0",fields.get("name0"));
assertEquals("valueA",fields.get("name1"));
assertEquals("value2",fields.get("name2"));
assertNull(fields.get("name3"));
int matches=0;
Enumeration<String> e = fields.getFieldNames();
@ -304,9 +341,29 @@ public class HttpFieldsTest
assertEquals(true, e.hasMoreElements());
assertEquals(e.nextElement(), "value1D");
assertEquals(false, e.hasMoreElements());
}
@Test
public void testGetQualityValues() throws Exception
{
HttpFields fields = new HttpFields();
fields.put("some", "value");
fields.add("name", "zero;q=0.9,four;q=0.1");
fields.put("other", "value");
fields.add("name", "nothing;q=0");
fields.add("name", "one;q=0.4");
fields.add("name", "three;x=y;q=0.2;a=b,two;q=0.3");
List<String> list = HttpFields.qualityList(fields.getValues("name",","));
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
assertEquals("two",HttpFields.valueParameters(list.get(2),null));
assertEquals("three",HttpFields.valueParameters(list.get(3),null));
assertEquals("four",HttpFields.valueParameters(list.get(4),null));
}
@Test
public void testDateFields() throws Exception
{
@ -346,7 +403,7 @@ public class HttpFieldsTest
assertEquals(951825600000L,d5);
fields.putDateField("D2",d1);
assertEquals("Fri, 31 Dec 1999 23:59:59 GMT",fields.getStringField("D2"));
assertEquals("Fri, 31 Dec 1999 23:59:59 GMT",fields.get("D2"));
}
@Test
@ -355,16 +412,16 @@ public class HttpFieldsTest
HttpFields fields = new HttpFields();
fields.putDateField("Dzero",0);
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Dzero"));
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.get("Dzero"));
fields.putDateField("Dminus",-1);
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus"));
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.get("Dminus"));
fields.putDateField("Dminus",-1000);
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus"));
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.get("Dminus"));
fields.putDateField("Dancient",Long.MIN_VALUE);
assertEquals("Sun, 02 Dec 55 16:47:04 GMT",fields.getStringField("Dancient"));
assertEquals("Sun, 02 Dec 55 16:47:04 GMT",fields.get("Dancient"));
}
@Test
@ -374,15 +431,33 @@ public class HttpFieldsTest
header.put("I1", "42");
header.put("I2", " 43 99");
header.put("I3", "-44;");
header.put("I3", "-44");
header.put("I4", " - 45abc");
header.put("N1", " - ");
header.put("N2", "xx");
long i1=header.getLongField("I1");
long i2=header.getLongField("I2");
try
{
header.getLongField("I2");
assertTrue(false);
}
catch(NumberFormatException e)
{
assertTrue(true);
}
long i3=header.getLongField("I3");
long i4=header.getLongField("I4");
try
{
header.getLongField("I4");
assertTrue(false);
}
catch(NumberFormatException e)
{
assertTrue(true);
}
try{
header.getLongField("N1");
@ -403,14 +478,12 @@ public class HttpFieldsTest
}
assertEquals(42,i1);
assertEquals(43,i2);
assertEquals(-44,i3);
assertEquals(-45,i4);
header.putLongField("I5", 46);
header.putLongField("I6",-47);
assertEquals("46",header.getStringField("I5"));
assertEquals("-47",header.getStringField("I6"));
assertEquals("46",header.get("I5"));
assertEquals("-47",header.get("I6"));
}
@ -429,12 +502,28 @@ public class HttpFieldsTest
header.add("n6", "def");
header.add("N6", "hig");
header.add("n7", "abc , def;q=0.9 , hig");
header.add("n8", "abc , def;q=0 , hig");
header.add(HttpHeader.ACCEPT, "abc , def;q=0 , hig");
for (int i=0;i<8;i++)
{
assertTrue(header.containsKey("n"+i));
assertTrue(header.containsKey("N"+i));
assertFalse(""+i,header.contains("n"+i,"xyz"));
assertEquals(""+i,i>=4,header.contains("n"+i,"def"));
}
assertTrue(header.contains(new HttpField("N5","def")));
assertTrue(header.contains(new HttpField("accept","abc")));
assertTrue(header.contains(HttpHeader.ACCEPT,"abc"));
assertFalse(header.contains(new HttpField("N5","xyz")));
assertFalse(header.contains(new HttpField("N8","def")));
assertFalse(header.contains(HttpHeader.ACCEPT,"def"));
assertFalse(header.contains(HttpHeader.AGE,"abc"));
assertFalse(header.containsKey("n11"));
}
}

View File

@ -28,7 +28,6 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.StringUtil;
@ -119,20 +118,20 @@ public class HpackContext
switch(i)
{
case 2:
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
entry=new StaticEntry(i,new StaticTableHttpField(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));
entry=new StaticEntry(i,new StaticTableHttpField(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));
entry=new StaticEntry(i,new StaticTableHttpField(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));
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
break;
case 8:
case 11:
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
break;
case 9:
@ -140,7 +139,7 @@ public class HpackContext
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])));
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
break;
default:
@ -231,6 +230,11 @@ public class HpackContext
return get(header.asString());
return e;
}
public static Entry getStatic(HttpHeader header)
{
return __headerEntryTable[header.ordinal()];
}
public Entry add(HttpField field)
{
@ -420,6 +424,11 @@ public class HpackContext
return null;
}
public int getSlot()
{
return _slot;
}
public String toString()
{
return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode());
@ -429,6 +438,7 @@ public class HpackContext
public static class StaticEntry extends Entry
{
private final byte[] _huffmanValue;
private final byte _encodedField;
StaticEntry(int index,HttpField field)
{
@ -450,6 +460,8 @@ public class HpackContext
}
else
_huffmanValue=null;
_encodedField=(byte)(0x80|index);
}
@Override
@ -463,6 +475,11 @@ public class HpackContext
{
return _huffmanValue;
}
public byte getEncodedField()
{
return _encodedField;
}
}

View File

@ -24,8 +24,6 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
@ -41,7 +39,8 @@ import org.eclipse.jetty.util.log.Logger;
public class HpackDecoder
{
public static final Logger LOG = Log.getLogger(HpackDecoder.class);
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 = new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 =
new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
private final HpackContext _context;
private final MetaDataBuilder _builder;
@ -191,46 +190,31 @@ public class HpackDecoder
HttpField field;
if (header==null)
{
// just make a normal field and bypass header name lookup
field = new HttpField(null,name,value);
}
else
{
// might be worthwhile to create a value HttpField if it is indexed
// and/or of a type that may be looked up multiple times.
switch(header)
{
case C_METHOD:
HttpMethod method=HttpMethod.CACHE.get(value);
if (method!=null)
field = new StaticValueHttpField(HttpHeader.C_METHOD,method.asString(),method);
else
field = new AuthorityHttpField(value);
break;
case C_STATUS:
Integer code = Integer.valueOf(value);
field = new StaticValueHttpField(HttpHeader.C_STATUS,value,code);
break;
case C_SCHEME:
HttpScheme scheme=HttpScheme.CACHE.get(value);
if (scheme!=null)
field = new StaticValueHttpField(HttpHeader.C_SCHEME,scheme.asString(),scheme);
if (indexed)
field = new HttpField.IntValueHttpField(header,name,value);
else
field = new AuthorityHttpField(value);
field = new HttpField(header,name,value);
break;
case C_AUTHORITY:
field = new AuthorityHttpField(value);
break;
case C_PATH:
field = new HttpField(HttpHeader.C_PATH,value);
break;
case CONTENT_LENGTH:
if ("0".equals(value))
field = CONTENT_LENGTH_0;
else
field = new HttpField.LongValueHttpField(header,value);
field = new HttpField.LongValueHttpField(header,name,value);
break;
default:

View File

@ -26,8 +26,11 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry;
import org.eclipse.jetty.io.ByteBufferPool.Lease;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil;
@ -78,6 +81,7 @@ public class HpackEncoder
}
private final HpackContext _context;
private final boolean _debug;
private int _remoteMaxHeaderTableSize;
private int _localMaxHeaderTableSize;
@ -96,6 +100,7 @@ public class HpackEncoder
_context=new HpackContext(remoteMaxHeaderTableSize);
_remoteMaxHeaderTableSize=remoteMaxHeaderTableSize;
_localMaxHeaderTableSize=localMaxHeaderTableSize;
_debug=LOG.isDebugEnabled();
}
public HpackContext getContext()
@ -154,15 +159,13 @@ public class HpackEncoder
int code=response.getStatus();
HttpField status = code<__status.length?__status[code]:null;
if (status==null)
status=new HttpField(HttpHeader.C_STATUS,Integer.toString(code));
status=new HttpField.IntValueHttpField(HttpHeader.C_STATUS,code);
encode(buffer,status);
}
// Add all the other fields
for (HttpField field : metadata)
{
encode(buffer,field);
}
if (LOG.isDebugEnabled())
LOG.debug(String.format("CtxTbl[%x] encoded %d octets",_context.hashCode(), buffer.position() - pos));
@ -179,38 +182,45 @@ public class HpackEncoder
private void encode(ByteBuffer buffer, HttpField field)
{
final int p=LOG.isDebugEnabled()?buffer.position():-1;
final int p=_debug?buffer.position():-1;
String encoding=null;
// TODO currently we do not check if there is enough space, so we may fail nastily.
// Is there an entry for the field?
Entry entry = _context.get(field);
if (entry!=null)
{
// Known field entry, so encode it as indexed
int index=_context.index(entry);
if (p>=0)
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,index);
if (entry.isStatic())
{
buffer.put(((StaticEntry)entry).getEncodedField());
if (_debug)
encoding="IdxFieldS1";
}
else
{
int index=_context.index(entry);
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,index);
if (_debug)
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
}
}
else
{
// Unknown field entry, so we will have to send literally.
final Entry name;
final boolean indexed;
final boolean never_index;
final boolean huffman;
final int bits;
// But do we know it's name?
HttpHeader header = field.getHeader();
// Select encoding strategy
if (header==null)
{
name = _context.get(field.getName());
// Select encoding strategy for unknown header names
Entry name = _context.get(field.getName());
// has the custom header name been seen before?
if (name==null)
{
@ -218,95 +228,71 @@ public class HpackEncoder
// the first time we have seen a custom name or a custom field.
// unless the name is changing, this is worthwhile
indexed=true;
never_index=false;
huffman=true;
bits = 6;
buffer.put((byte)0x40);
encodeName(buffer,(byte)0x40,6,field.getName(),null);
encodeValue(buffer,true,field.getValue());
if (_debug)
encoding="LitHuffNHuffVIdx";
}
else
{
// known custom name, but unknown value.
// This is probably a custom field with changing value, so don't index now.
// This is probably a custom field with changing value, so don't index.
indexed=false;
never_index=false;
huffman=true;
bits = 4;
buffer.put((byte)0x00);
encodeName(buffer,(byte)0x00,4,field.getName(),null);
encodeValue(buffer,true,field.getValue());
if (_debug)
encoding="LitHuffNHuffV!Idx";
}
}
else
{
name = _context.get(header);
// Select encoding strategy for known header names
Entry name = _context.get(header);
if (__DO_NOT_INDEX.contains(header))
{
// Non indexed field
indexed=false;
never_index=__NEVER_INDEX.contains(header);
huffman=!__DO_NOT_HUFFMAN.contains(header);
bits = 4;
buffer.put(never_index?(byte)0x10:(byte)0x00);
boolean never_index=__NEVER_INDEX.contains(header);
boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
encodeName(buffer,never_index?(byte)0x10:(byte)0x00,4,header.asString(),name);
encodeValue(buffer,huffman,field.getValue());
if (_debug)
encoding="Lit"+
((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(4,_context.index(name)))))+
(huffman?"HuffV":"LitV")+
(indexed?"Idx":(never_index?"!!Idx":"!Idx"));
}
else if (header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>1)
{
// Non indexed content length for non zero value
indexed=false;
never_index=false;
huffman=true;
bits = 4;
buffer.put((byte)0x00);
encodeName(buffer,(byte)0x00,4,header.asString(),name);
encodeValue(buffer,true,field.getValue());
if (_debug)
encoding="LitIdxNS"+(1+NBitInteger.octectsNeeded(4,_context.index(name)))+"HuffV!Idx";
}
else if (field instanceof PreEncodedHttpField)
{
// Preencoded field
indexed=true;
((PreEncodedHttpField)field).putTo(buffer,HttpVersion.HTTP_2);
if (_debug)
encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
"HuffVIdx";
}
else
{
// indexed
indexed=true;
never_index=false;
huffman=!__DO_NOT_HUFFMAN.contains(header);
bits = 6;
buffer.put((byte)0x40);
}
}
if (p>=0)
{
encoding="Lit"+
((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(bits,_context.index(name)))))+
(huffman?"HuffV":"LitV")+
(indexed?"Idx":(never_index?"!!Idx":"!Idx"));
}
if (name!=null)
NBitInteger.encode(buffer,bits,_context.index(name));
else
{
// leave name index bits as 0
// Encode the name always with lowercase huffman
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(field.getName()));
Huffman.encodeLC(buffer,field.getName());
}
// Add the literal value
String value=field.getValue();
if (huffman)
{
// huffman literal value
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
Huffman.encode(buffer,field.getValue());
}
else
{
// add literal assuming iso_8859_1
buffer.put((byte)0x00);
NBitInteger.encode(buffer,7,value.length());
for (int i=0;i<value.length();i++)
{
char c=value.charAt(i);
if (c<' '|| c>127)
throw new IllegalArgumentException();
buffer.put((byte)c);
boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
encodeName(buffer,(byte)0x40,6,header.asString(),name);
encodeValue(buffer,huffman,field.getValue());
if (_debug)
encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
(huffman?"HuffVIdx":"LitVIdx");
}
}
@ -316,11 +302,52 @@ public class HpackEncoder
_context.add(field);
}
if (p>=0)
if (_debug)
{
int e=buffer.position();
if (LOG.isDebugEnabled())
LOG.debug("encode {}:'{}' to '{}'",encoding,field,TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+p,e-p));
}
}
private void encodeName(ByteBuffer buffer, byte mask, int bits, String name, Entry entry)
{
buffer.put(mask);
if (entry==null)
{
// leave name index bits as 0
// Encode the name always with lowercase huffman
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(name));
Huffman.encodeLC(buffer,name);
}
else
{
NBitInteger.encode(buffer,bits,_context.index(entry));
}
}
private void encodeValue(ByteBuffer buffer, boolean huffman, String value)
{
if (huffman)
{
// huffman literal value
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
Huffman.encode(buffer,value);
}
else
{
// add literal assuming iso_8859_1
buffer.put((byte)0x00);
NBitInteger.encode(buffer,7,value.length());
for (int i=0;i<value.length();i++)
{
char c=value.charAt(i);
if (c<' '|| c>127)
throw new IllegalArgumentException();
buffer.put((byte)c);
}
}
}
}

View File

@ -0,0 +1,74 @@
//
// ========================================================================
// 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.http2.hpack;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpFieldPreEncoder;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.util.BufferUtil;
/* ------------------------------------------------------------ */
/**
*/
public class HpackFieldPreEncoder implements HttpFieldPreEncoder
{
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.HttpFieldPreEncoder#getHttpVersion()
*/
@Override
public HttpVersion getHttpVersion()
{
return HttpVersion.HTTP_2;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.HttpFieldPreEncoder#getEncodedField(org.eclipse.jetty.http.HttpHeader, java.lang.String, java.lang.String)
*/
@Override
public byte[] getEncodedField(HttpHeader header, String name, String value)
{
ByteBuffer buffer = BufferUtil.allocate(name.length()+value.length()+10);
BufferUtil.clearToFill(buffer);
buffer.put((byte)0x40);
Entry entry = header==null?null:HpackContext.getStatic(header);
if (entry==null)
{
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(name));
Huffman.encodeLC(buffer,name);
}
else
{
NBitInteger.encode(buffer,6,entry.getSlot());
}
buffer.put((byte)0x80);
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
Huffman.encode(buffer,value);
BufferUtil.flipToFlush(buffer,0);
return BufferUtil.toArray(buffer);
}
}

View File

@ -72,9 +72,9 @@ public class MetaDataBuilder
if (_size>_maxSize)
throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
if (field instanceof StaticValueHttpField)
if (field instanceof StaticTableHttpField)
{
StaticValueHttpField value = (StaticValueHttpField)field;
StaticTableHttpField value = (StaticTableHttpField)field;
switch(field.getHeader())
{
case C_STATUS:
@ -98,7 +98,7 @@ public class MetaDataBuilder
switch(field.getHeader())
{
case C_STATUS:
_status=Integer.parseInt(field.getValue());
_status=field.getIntValue();
break;
case C_METHOD:
@ -114,6 +114,7 @@ public class MetaDataBuilder
break;
case HOST:
// :authority fields must come first. If we have one, ignore the host header as far as authority goes.
if (_authority==null)
_authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
_fields.add(field);

View File

@ -23,19 +23,11 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
/* ------------------------------------------------------------ */
public class StaticValueHttpField extends HttpField
public class StaticTableHttpField extends HttpField
{
private final Object _value;
public StaticValueHttpField(HttpHeader header,String name, String valueString, Object value)
{
super(header,name,valueString);
if (value==null)
throw new IllegalArgumentException();
_value=value;
}
public StaticValueHttpField(HttpHeader header,String valueString, Object value)
public StaticTableHttpField(HttpHeader header,String valueString, Object value)
{
super(header,header.asString(),valueString);
if (value==null)
@ -43,7 +35,7 @@ public class StaticValueHttpField extends HttpField
_value=value;
}
public StaticValueHttpField(String name, String valueString, Object value)
public StaticTableHttpField(String name, String valueString, Object value)
{
super(name,valueString);
if (value==null)

View File

@ -0,0 +1 @@
org.eclipse.jetty.http2.hpack.HpackFieldPreEncoder

View File

@ -24,12 +24,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;

View File

@ -30,7 +30,6 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.Ignore;
import org.junit.Test;

View File

@ -23,13 +23,11 @@ package org.eclipse.jetty.http2.hpack;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
import java.util.HashSet;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers;
import org.junit.Assert;

View File

@ -24,12 +24,15 @@ import static org.junit.Assert.assertEquals;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.BadMessageException;
import org.eclipse.jetty.http.DateGenerator;
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.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http.MetaData.Response;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.Assert;
import org.junit.Test;
@ -37,6 +40,10 @@ import org.junit.Test;
public class HpackTest
{
final static HttpField ServerJetty = new PreEncodedHttpField(HttpHeader.SERVER,"jetty");
final static HttpField XPowerJetty = new PreEncodedHttpField(HttpHeader.X_POWERED_BY,"jetty");
final static HttpField Date = new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(System.currentTimeMillis()));
@Test
public void encodeDecodeResponseTest()
{
@ -47,7 +54,9 @@ public class HpackTest
HttpFields fields0 = new HttpFields();
fields0.add(HttpHeader.CONTENT_TYPE,"text/html");
fields0.add(HttpHeader.CONTENT_LENGTH,"1024");
fields0.add(HttpHeader.SERVER,"jetty");
fields0.add(ServerJetty);
fields0.add(XPowerJetty);
fields0.add(Date);
fields0.add(HttpHeader.SET_COOKIE,"abcdefghijklmnopqrstuvwxyz");
fields0.add("custom-key","custom-value");
Response original0 = new MetaData.Response(HttpVersion.HTTP_2,200,fields0);
@ -70,7 +79,9 @@ public class HpackTest
HttpFields fields1 = new HttpFields();
fields1.add(HttpHeader.CONTENT_TYPE,"text/plain");
fields1.add(HttpHeader.CONTENT_LENGTH,"1234");
fields1.add(HttpHeader.SERVER,"jetty");
fields1.add(ServerJetty);
fields0.add(XPowerJetty);
fields0.add(Date);
fields1.add("Custom-Key","Other-Value");
Response original1 = new MetaData.Response(HttpVersion.HTTP_2,200,fields1);

View File

@ -100,7 +100,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
HttpChannelOverHTTP2 channel = new HttpChannelOverHTTP2(connector, httpConfiguration, endPoint, transport, input, stream);
stream.setAttribute(CHANNEL_ATTRIBUTE, channel);
channel.requestHeaders(frame);
channel.onHeadersFrame(frame);
return frame.isEndStream() ? null : this;
}

View File

@ -18,11 +18,15 @@
package org.eclipse.jetty.http2.server;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.DataFrame;
@ -42,10 +46,10 @@ import org.eclipse.jetty.util.log.Logger;
public class HttpChannelOverHTTP2 extends HttpChannel
{
private static final Logger LOG = Log.getLogger(HttpChannelOverHTTP2.class);
private static final HttpField ACCEPT_ENCODING_GZIP = new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip");
private static final HttpField SERVER_VERSION=new HttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
private static final HttpField POWERED_BY=new HttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
private static final HttpField SERVER_VERSION=new PreEncodedHttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
private static final HttpField POWERED_BY=new PreEncodedHttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
private final Stream stream; // TODO recycle channel for new Stream?
private boolean _expect100Continue = false;
public HttpChannelOverHTTP2(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput input, Stream stream)
{
@ -53,7 +57,13 @@ public class HttpChannelOverHTTP2 extends HttpChannel
this.stream = stream;
}
public void requestHeaders(HeadersFrame frame)
@Override
public boolean isExpecting100Continue()
{
return _expect100Continue;
}
public void onHeadersFrame(HeadersFrame frame)
{
MetaData metaData = frame.getMetaData();
if (!metaData.isRequest())
@ -63,26 +73,21 @@ public class HttpChannelOverHTTP2 extends HttpChannel
}
MetaData.Request request = (MetaData.Request)metaData;
// The specification says user agents MUST support gzip encoding.
// Based on that, some browser does not send the header, but it's
// important that applications can find it (e.g. GzipFilter).
HttpFields fields = request.getFields();
if (!fields.contains(HttpHeader.ACCEPT_ENCODING, "gzip"))
fields.add(ACCEPT_ENCODING_GZIP);
_expect100Continue = fields.contains(HttpHeader.EXPECT,HttpHeaderValue.CONTINUE.asString());
// TODO make this a better field for h2 hpack generation
HttpFields response=getResponse().getHttpFields();
if (getHttpConfiguration().getSendServerVersion())
getResponse().getHttpFields().add(SERVER_VERSION);
response.add(SERVER_VERSION);
if (getHttpConfiguration().getSendXPoweredBy())
getResponse().getHttpFields().add(POWERED_BY);
response.add(POWERED_BY);
onRequest(request);
if (frame.isEndStream())
{
onRequestComplete();
}
if (LOG.isDebugEnabled())
{
@ -127,4 +132,33 @@ public class HttpChannelOverHTTP2 extends HttpChannel
onRequestComplete();
}
}
/**
* If the associated response has the Expect header set to 100 Continue,
* then accessing the input stream indicates that the handler/servlet
* is ready for the request body and thus a 100 Continue response is sent.
*
* @throws IOException if the InputStream cannot be created
*/
@Override
public void continue100(int available) throws IOException
{
// If the client is expecting 100 CONTINUE, then send it now.
// TODO: consider using an AtomicBoolean ?
if (isExpecting100Continue())
{
_expect100Continue = false;
// is content missing?
if (available == 0)
{
if (getResponse().isCommitted())
throw new IOException("Committed before 100 Continues");
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
if (!committed)
throw new IOException("Concurrent commit while trying to send 100-Continue");
}
}
}
}

View File

@ -86,6 +86,16 @@ public class HttpTransportOverHTTP2 implements HttpTransport
}
}
/**
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
*/
@Override
public void push(org.eclipse.jetty.http.MetaData.Request request)
{
// TODO implement push
LOG.warn("NOT YET IMPLEMENTED push in {}",this);
}
private void commit(HttpGenerator.ResponseInfo info, boolean endStream, Callback callback)
{
if (LOG.isDebugEnabled())

View File

@ -227,7 +227,7 @@ public class RuleContainer extends Rule
if (rule.isHandling())
{
LOG.debug("handling {}",rule);
(request instanceof Request?(Request)request:HttpChannel.getCurrentHttpChannel().getRequest()).setHandled(true);
Request.getBaseRequest(request).setHandled(true);
}
if (rule.isTerminating())

View File

@ -289,8 +289,8 @@ public class FormAuthenticator extends LoginAuthenticator
LOG.debug("authenticated {}->{}",form_auth,nuri);
response.setContentLength(0);
Response base_response = HttpChannel.getCurrentHttpChannel().getResponse();
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest();
Request base_request = Request.getBaseRequest(req);
Response base_response = base_request.getResponse();
int redirectCode = (base_request.getHttpVersion().getVersion() < HttpVersion.HTTP_1_1.getVersion() ? HttpServletResponse.SC_MOVED_TEMPORARILY : HttpServletResponse.SC_SEE_OTHER);
base_response.sendRedirect(redirectCode, response.encodeRedirectURL(nuri));
return form_auth;

View File

@ -31,7 +31,11 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.MultiMap;
@ -46,14 +50,14 @@ public class Dispatcher implements RequestDispatcher
private final ContextHandler _contextHandler;
private final HttpURI _uri;
private final String _pathInfo;
private final String _pathInContext;
private final String _named;
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInfo)
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext)
{
_contextHandler=contextHandler;
_uri=uri;
_pathInfo=pathInfo;
_pathInContext=pathInContext;
_named=null;
}
@ -61,7 +65,7 @@ public class Dispatcher implements RequestDispatcher
{
_contextHandler=contextHandler;
_uri=null;
_pathInfo=null;
_pathInContext=null;
_named=name;
}
@ -79,7 +83,7 @@ public class Dispatcher implements RequestDispatcher
@Override
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
{
Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
Request baseRequest=Request.getBaseRequest(request);
if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request);
@ -104,14 +108,14 @@ public class Dispatcher implements RequestDispatcher
attr._requestURI=_uri.getPath();
attr._contextPath=_contextHandler.getContextPath();
attr._servletPath=null; // set by ServletHandler
attr._pathInfo=_pathInfo;
attr._pathInfo=_pathInContext;
attr._query=_uri.getQuery();
if (attr._query!=null)
baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false);
baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
}
}
finally
@ -126,7 +130,7 @@ public class Dispatcher implements RequestDispatcher
protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
{
Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
Request baseRequest=Request.getBaseRequest(request);
Response base_response=baseRequest.getResponse();
base_response.resetForForward();
@ -187,13 +191,13 @@ public class Dispatcher implements RequestDispatcher
baseRequest.setContextPath(_contextHandler.getContextPath());
baseRequest.setServletPath(null);
baseRequest.setPathInfo(_pathInfo);
baseRequest.setPathInfo(_pathInContext);
if (_uri.getQuery()!=null || old_uri.getQuery()!=null)
baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true);
baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
if (!baseRequest.getHttpChannelState().isAsync())
commitResponse(response,baseRequest);
@ -212,6 +216,26 @@ public class Dispatcher implements RequestDispatcher
baseRequest.setDispatcherType(old_type);
}
}
public void push(ServletRequest request)
{
Request baseRequest = Request.getBaseRequest(request);
HttpFields fields = new HttpFields(baseRequest.getHttpFields());
String query=baseRequest.getQueryString();
if (_uri.hasQuery())
{
if (query==null)
query=_uri.getQuery();
else
query=query+"&"+_uri.getQuery(); // TODO is this correct semantic?
}
HttpURI uri = new HttpURI(request.getProtocol(),request.getServerName(),request.getServerPort(),_uri.getPath(),baseRequest.getHttpURI().getParam(),query,null);
MetaData.Request push = new MetaData.Request(HttpMethod.GET.asString(),uri,baseRequest.getHttpVersion(),fields);
baseRequest.getHttpChannel().getHttpTransport().push(push);
}
private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
{

View File

@ -202,13 +202,13 @@ public class ForwardedRequestCustomizer implements Customizer
// Do SSL first
if (getForwardedCipherSuiteHeader()!=null)
{
String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader());
String cipher_suite=httpFields.get(getForwardedCipherSuiteHeader());
if (cipher_suite!=null)
request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite);
}
if (getForwardedSslSessionIdHeader()!=null)
{
String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader());
String ssl_session_id=httpFields.get(getForwardedSslSessionIdHeader());
if(ssl_session_id!=null)
{
request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id);
@ -260,7 +260,7 @@ public class ForwardedRequestCustomizer implements Customizer
if (header == null)
return null;
String headerValue = fields.getStringField(header);
String headerValue = fields.get(header);
if (headerValue == null)
return null;

View File

@ -199,7 +199,6 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
if (getResponse().isCommitted())
throw new IOException("Committed before 100 Continues");
// TODO: break this dependency with HttpGenerator
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
if (!committed)
throw new IOException("Concurrent commit while trying to send 100-Continue");

View File

@ -634,4 +634,14 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
// response is bad either with RST or by abnormal completion of chunked response.
getEndPoint().close();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
*/
@Override
public void push(org.eclipse.jetty.http.MetaData.Request request)
{
LOG.debug("ignore push in {}",this);
}
}

View File

@ -21,12 +21,15 @@ package org.eclipse.jetty.server;
import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.Callback;
public interface HttpTransport
{
void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback);
void push (MetaData.Request request);
void completed();
/* ------------------------------------------------------------ */

View File

@ -52,6 +52,7 @@ import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -132,6 +133,28 @@ public class Request implements HttpServletRequest
private static final MultiMap<String> NO_PARAMS = new MultiMap<>();
/* ------------------------------------------------------------ */
/**
* Obtain the base {@link Request} instance of a {@link ServletRequest}, by
* coercion, unwrapping or thread local.
* @param request The request
* @return the base {@link Request} instance of a {@link ServletRequest}.
*/
public static Request getBaseRequest(ServletRequest request)
{
if (request instanceof Request)
return (Request)request;
while (request instanceof ServletRequestWrapper)
request=((ServletRequestWrapper)request).getRequest();
if (request instanceof Request)
return (Request)request;
return HttpChannel.getCurrentHttpChannel().getRequest();
}
private final HttpChannel _channel;
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
private final HttpInput _input;
@ -510,7 +533,7 @@ public class Request implements HttpServletRequest
@Override
public String getContentType()
{
String content_type = _metadata.getFields().getStringField(HttpHeader.CONTENT_TYPE);
String content_type = _metadata.getFields().get(HttpHeader.CONTENT_TYPE);
if (_characterEncoding==null && content_type!=null)
{
MimeTypes.Type mime = MimeTypes.CACHE.get(content_type);
@ -603,7 +626,7 @@ public class Request implements HttpServletRequest
@Override
public String getHeader(String name)
{
return _metadata==null?null:_metadata.getFields().getStringField(name);
return _metadata==null?null:_metadata.getFields().get(name);
}
/* ------------------------------------------------------------ */

View File

@ -830,7 +830,7 @@ public class Response implements HttpServletResponse
@Override
public String getHeader(String name)
{
return _fields.getStringField(name);
return _fields.get(name);
}
@Override

View File

@ -38,6 +38,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.DateGenerator;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpGenerator;
@ -299,7 +300,7 @@ public class Server extends HandlerWrapper implements Attributes
df = _dateField;
if (df==null || df._seconds!=seconds)
{
HttpField field=new HttpGenerator.CachedHttpField(HttpHeader.DATE,DateGenerator.formatDate(now));
HttpField field=new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(now));
_dateField=new DateField(seconds,field);
return field;
}

View File

@ -102,7 +102,7 @@ public class PartialRFC2616Test
assertEquals("3.3.1 RFC 850 ANSI C",d3,d2);
fields.putDateField("Date",d1.getTime());
assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.getStringField("Date"));
assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.get("Date"));
}
catch (Exception e)
{

View File

@ -91,6 +91,11 @@ public class ResponseTest
callback.succeeded();
}
@Override
public void push(org.eclipse.jetty.http.MetaData.Request request)
{
}
@Override
public void completed()
{
@ -607,7 +612,7 @@ public class ResponseTest
response.addCookie(cookie);
String set = response.getHttpFields().getStringField("Set-Cookie");
String set = response.getHttpFields().get("Set-Cookie");
assertEquals("name=value;Version=1;Path=/path;Domain=domain;Secure;HttpOnly;Comment=comment", set);
}
@ -669,23 +674,23 @@ public class ResponseTest
HttpFields fields = response.getHttpFields();
response.addSetCookie("null",null,null,null,-1,null,false,false,-1);
assertEquals("null=",fields.getStringField("Set-Cookie"));
assertEquals("null=",fields.get("Set-Cookie"));
fields.clear();
response.addSetCookie("minimal","value",null,null,-1,null,false,false,-1);
assertEquals("minimal=value",fields.getStringField("Set-Cookie"));
assertEquals("minimal=value",fields.get("Set-Cookie"));
fields.clear();
//test cookies with same name, domain and path, only 1 allowed
response.addSetCookie("everything","wrong","domain","path",0,"to be replaced",true,true,0);
response.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",fields.getStringField("Set-Cookie"));
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",fields.get("Set-Cookie"));
Enumeration<String> e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
assertFalse(e.hasMoreElements());
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.get("Expires"));
assertFalse(e.hasMoreElements());
//test cookies with same name, different domain
@ -744,31 +749,31 @@ public class ResponseTest
fields.clear();
response.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,1);
String setCookie=fields.getStringField("Set-Cookie");
String setCookie=fields.get("Set-Cookie");
assertThat(setCookie,Matchers.startsWith("\"ev erything\"=\"va lue\";Version=1;Path=\"pa th\";Domain=\"do main\";Expires="));
assertThat(setCookie,Matchers.endsWith(" GMT;Max-Age=1;Secure;HttpOnly;Comment=\"co mment\""));
fields.clear();
response.addSetCookie("name","value",null,null,-1,null,false,false,0);
setCookie=fields.getStringField("Set-Cookie");
setCookie=fields.get("Set-Cookie");
assertEquals(-1,setCookie.indexOf("Version="));
fields.clear();
response.addSetCookie("name","v a l u e",null,null,-1,null,false,false,0);
setCookie=fields.getStringField("Set-Cookie");
setCookie=fields.get("Set-Cookie");
fields.clear();
response.addSetCookie("json","{\"services\":[\"cwa\", \"aa\"]}",null,null,-1,null,false,false,-1);
assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.getStringField("Set-Cookie"));
assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.get("Set-Cookie"));
fields.clear();
response.addSetCookie("name","value","domain",null,-1,null,false,false,-1);
response.addSetCookie("name","other","domain",null,-1,null,false,false,-1);
assertEquals("name=other;Domain=domain",fields.getStringField("Set-Cookie"));
assertEquals("name=other;Domain=domain",fields.get("Set-Cookie"));
response.addSetCookie("name","more","domain",null,-1,null,false,false,-1);
assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
assertEquals("name=more;Domain=domain",fields.get("Set-Cookie"));
response.addSetCookie("foo","bar","domain",null,-1,null,false,false,-1);
response.addSetCookie("foo","bob","domain",null,-1,null,false,false,-1);
assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
assertEquals("name=more;Domain=domain",fields.get("Set-Cookie"));
e=fields.getValues("Set-Cookie");
assertEquals("name=more;Domain=domain",e.nextElement());
@ -776,7 +781,7 @@ public class ResponseTest
fields.clear();
response.addSetCookie("name","value%=",null,null,-1,null,false,false,0);
setCookie=fields.getStringField("Set-Cookie");
setCookie=fields.get("Set-Cookie");
assertEquals("name=value%=",setCookie);
}

View File

@ -39,10 +39,10 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator.CachedHttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.MimeTypes;
@ -144,7 +144,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
private static final long serialVersionUID = 4930458713846881193L;
private static final CachedHttpField ACCEPT_RANGES = new CachedHttpField(HttpHeader.ACCEPT_RANGES, "bytes");
private static final PreEncodedHttpField ACCEPT_RANGES = new PreEncodedHttpField(HttpHeader.ACCEPT_RANGES, "bytes");
private ServletContext _servletContext;
private ContextHandler _contextHandler;
@ -241,7 +241,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
String cc=getInitParameter("cacheControl");
if (cc!=null)
_cacheControl=new CachedHttpField(HttpHeader.CACHE_CONTROL, cc);
_cacheControl=new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, cc);
String resourceCache = getInitParameter("resourceCache");
int max_cache_size=getInitInt("maxCacheSize", -2);

View File

@ -227,7 +227,7 @@ public class Invoker extends HttpServlet
if (holder!=null)
{
final Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
final Request baseRequest=Request.getBaseRequest(request);
holder.handle(baseRequest,
new InvokedRequest(request,included,servlet,servlet_path,path_info),
response);

View File

@ -1630,7 +1630,7 @@ public class ServletHandler extends ScopedHandler
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException
{
final Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
final Request baseRequest=Request.getBaseRequest(request);
// pass to next filter
if (_filterHolder!=null)
@ -1732,7 +1732,7 @@ public class ServletHandler extends ScopedHandler
// Call servlet
HttpServletRequest srequest = (HttpServletRequest)request;
if (_servletHolder == null)
notFound((request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest(), srequest, (HttpServletResponse)response);
notFound(Request.getBaseRequest(request), srequest, (HttpServletResponse)response);
else
{
if (LOG.isDebugEnabled())

View File

@ -37,9 +37,9 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
@ -152,7 +152,7 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
protected Set<Pattern> _excludedAgentPatterns;
protected Set<String> _excludedPaths;
protected Set<Pattern> _excludedPathPatterns;
protected HttpField _vary=new HttpGenerator.CachedHttpField(HttpHeader.VARY,HttpHeader.ACCEPT_ENCODING+", "+HttpHeader.USER_AGENT);
protected HttpField _vary=new PreEncodedHttpField(HttpHeader.VARY,HttpHeader.ACCEPT_ENCODING+", "+HttpHeader.USER_AGENT);
/* ------------------------------------------------------------ */
/**
@ -278,7 +278,7 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
tmp=filterConfig.getInitParameter("vary");
if (tmp!=null)
_vary=new HttpGenerator.CachedHttpField(HttpHeader.VARY,tmp);
_vary=new PreEncodedHttpField(HttpHeader.VARY,tmp);
LOG.debug("{} vary={}",this,_vary);
}

View File

@ -35,7 +35,7 @@ public class CloseableDoSFilter extends DoSFilter
@Override
protected void closeConnection(HttpServletRequest request, HttpServletResponse response, Thread thread)
{
Request base_request=(request instanceof Request)?(Request)request:HttpChannel.getCurrentHttpChannel().getRequest();
Request base_request=Request.getBaseRequest(request);
base_request.getHttpChannel().getEndPoint().close();
}
}

View File

@ -24,8 +24,8 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.HttpChannel;
@ -41,7 +41,7 @@ import org.eclipse.jetty.util.log.Logger;
public class GzipHttpOutput extends HttpOutput
{
public static Logger LOG = Log.getLogger(GzipHttpOutput.class);
private final static HttpGenerator.CachedHttpField CONTENT_ENCODING_GZIP=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_ENCODING,"gzip");
private final static PreEncodedHttpField CONTENT_ENCODING_GZIP=new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING,"gzip");
private final static byte[] GZIP_HEADER = new byte[] { (byte)0x1f, (byte)0x8b, Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0 };
private enum GZState { NOT_COMPRESSING, MIGHT_COMPRESS, COMMITTING, COMPRESSING, FINISHED};

View File

@ -159,6 +159,18 @@ public class HttpTransportOverSPDY implements HttpTransport
throw new IllegalStateException("not lastContent, no content and no responseInfo!");
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
*/
@Override
public void push(org.eclipse.jetty.http.MetaData.Request request)
{
LOG.warn("NOT YET IMPLEMENTED push in {}",this);
}
private void sendReply(HttpGenerator.ResponseInfo info, Callback callback, boolean close)
{
Fields headers = new Fields();

View File

@ -146,7 +146,7 @@ public abstract class RFC2616BaseTest
// Test formatting
fields.putDateField("Date",expected.getTime().getTime());
Assert.assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.getStringField("Date"));
Assert.assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.get("Date"));
}
/**

View File

@ -133,7 +133,7 @@ public class IdleSessionTest
//make a request to set up a session on the server
ContentResponse response = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -77,7 +77,7 @@ public class DirtyAttributeTest
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -103,7 +103,7 @@ public class MaxInactiveMigrationTest
ContentResponse response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
sessionCookie = response.getHeaders().getStringField("Set-Cookie");
sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -70,7 +70,7 @@ public class ModifyMaxInactiveIntervalTest
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -104,7 +104,7 @@ public class ReloadedSessionMissingClassTest
ContentResponse response = client.GET("http://localhost:" + port1 + contextPath +"/bar?action=set");
assertEquals( HttpServletResponse.SC_OK, response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
String sessionId = (String)webApp.getServletContext().getAttribute("foo");
assertNotNull(sessionId);

View File

@ -77,7 +77,7 @@ public class SaveIntervalTest
// Perform a request to create a session
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -102,7 +102,7 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
//make a request to set up a session on the server
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -94,7 +94,7 @@ public class PurgeInvalidSessionTest
//Create a session
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -97,7 +97,7 @@ public class PurgeValidSessionTest
//Create a session
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -117,7 +117,7 @@ public class SessionSavingValueTest extends AbstractSessionValueSavingTest
sessionTestValue = sessionTestResponse;
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=","$1\\$Path=");
@ -144,7 +144,7 @@ public class SessionSavingValueTest extends AbstractSessionValueSavingTest
sessionTestValue = sessionTestResponse;
String setCookie = response2.getHeaders().getStringField("Set-Cookie");
String setCookie = response2.getHeaders().get("Set-Cookie");
if (setCookie != null)
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=","$1\\$Path=");

View File

@ -86,7 +86,7 @@ public class StopSessionManagerDeleteSessionTest
//Create a session
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -74,7 +74,7 @@ public abstract class AbstractClientCrossContextSessionTest
ContentResponse response = client.GET("http://localhost:" + port + contextA + servletMapping);
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -64,7 +64,7 @@ public abstract class AbstractImmortalSessionTest
int value = 42;
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=set&value=" + value);
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -79,7 +79,7 @@ public abstract class AbstractInvalidationSessionTest
ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -87,7 +87,7 @@ public abstract class AbstractLastAccessTimeTest
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
assertEquals("test", response1.getContentAsString());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
@ -106,7 +106,7 @@ public abstract class AbstractLastAccessTimeTest
assertEquals(HttpServletResponse.SC_OK , response2.getStatus());
assertEquals("test", response2.getContentAsString());
String setCookie = response2.getHeaders().getStringField("Set-Cookie");
String setCookie = response2.getHeaders().get("Set-Cookie");
if (setCookie!=null)
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -82,7 +82,7 @@ public abstract class AbstractLightLoadTest
ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField( "Set-Cookie" );
String sessionCookie = response1.getHeaders().get( "Set-Cookie" );
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -86,7 +86,7 @@ public abstract class AbstractLocalSessionScavengingTest
// Create the session on node1
ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -74,7 +74,7 @@ public abstract class AbstractNewSessionTest
{
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -74,7 +74,7 @@ public abstract class AbstractOrphanedSessionTest
// Connect to server1 to create a session and get its session cookie
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -101,7 +101,7 @@ public abstract class AbstractProxySerializationTest
{
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -66,7 +66,7 @@ public abstract class AbstractRemoveSessionTest
{
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -81,7 +81,7 @@ public abstract class AbstractSessionCookieTest
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
//sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -75,7 +75,7 @@ public abstract class AbstractSessionExpiryTest
//make a request to set up a session on the server
ContentResponse response = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
@ -125,7 +125,7 @@ public abstract class AbstractSessionExpiryTest
//make a request to set up a session on the server
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -119,7 +119,7 @@ public abstract class AbstractSessionInvalidateAndCreateTest
// Create the session
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -72,7 +72,7 @@ public abstract class AbstractSessionMigrationTest
Request request1 = client.POST("http://localhost:" + port1 + contextPath + servletMapping + "?action=set&value=" + value);
ContentResponse response1 = request1.send();
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -70,7 +70,7 @@ public abstract class AbstractSessionRenewTest
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
assertFalse(testListener.isCalled());
@ -79,7 +79,7 @@ public abstract class AbstractSessionRenewTest
request.header("Cookie", sessionCookie);
ContentResponse renewResponse = request.send();
assertEquals(HttpServletResponse.SC_OK,renewResponse.getStatus());
String renewSessionCookie = renewResponse.getHeaders().getStringField("Set-Cookie");
String renewSessionCookie = renewResponse.getHeaders().get("Set-Cookie");
assertNotNull(renewSessionCookie);
assertNotSame(sessionCookie, renewSessionCookie);
assertTrue(testListener.isCalled());

View File

@ -72,7 +72,7 @@ public abstract class AbstractSessionValueSavingTest
sessionTestValue = Long.parseLong(response1.getContentAsString());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
@ -95,7 +95,7 @@ public abstract class AbstractSessionValueSavingTest
assertTrue(sessionTestValue < Long.parseLong(response2.getContentAsString()));
sessionTestValue = Long.parseLong(response2.getContentAsString());
String setCookie = response1.getHeaders().getStringField("Set-Cookie");
String setCookie = response1.getHeaders().get("Set-Cookie");
if (setCookie!=null)
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -74,7 +74,7 @@ public abstract class AbstractStopSessionManagerPreserveSessionTest
//Create a session
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -120,7 +120,7 @@ public abstract class AbstractWebAppObjectInSessionTest
ContentResponse response = request.send();
assertEquals( HttpServletResponse.SC_OK, response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");