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(); 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) 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; return _value;
} }
public int getIntValue()
{
return Integer.valueOf(_value);
}
public long getLongValue() public long getLongValue()
{ {
return StringUtil.toLong(_value); return Long.valueOf(_value);
} }
public String[] getValues() public String[] getValues()
@ -416,21 +421,85 @@ public class HttpField
return true; 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 public static class LongValueHttpField extends HttpField
{ {
final long _long; final long _long;
public LongValueHttpField(HttpHeader header, long value) public LongValueHttpField(HttpHeader header, String name, String value, long longValue)
{ {
super(header,Long.toString(value)); super(header,name,value);
_long=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) public LongValueHttpField(HttpHeader header, String value)
{ {
super(header,value); this(header,header.asString(),value);
_long=StringUtil.toLong(value); }
public LongValueHttpField(HttpHeader header,long value)
{
this(header,header.asString(),value);
}
@Override
public int getIntValue()
{
return (int)_long;
} }
@Override @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; package org.eclipse.jetty.http;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
@ -34,7 +35,6 @@ import java.util.StringTokenizer;
import org.eclipse.jetty.util.ArrayTernaryTrie; import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Trie; import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; 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 static final Logger LOG = Log.getLogger(HttpFields.class);
private final List<HttpField> _fields; private HttpField[] _fields;
private int _size;
public HttpFields() public HttpFields()
{ {
_fields=new ArrayList<>(); _fields=new HttpField[20];
} }
/** /**
@ -67,18 +68,27 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public HttpFields(int capacity) 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() public int size()
{ {
return _fields.size(); return _size;
} }
@Override @Override
public Iterator<HttpField> iterator() public Iterator<HttpField> iterator()
{ {
return _fields.iterator(); return new Itr();
} }
/** /**
@ -86,7 +96,7 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public Collection<String> getFieldNamesCollection() public Collection<String> getFieldNamesCollection()
{ {
final Set<String> list = new HashSet<>(_fields.size()); final Set<String> list = new HashSet<>(_size);
for (HttpField f : this) for (HttpField f : this)
{ {
if (f!=null) if (f!=null)
@ -111,14 +121,16 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public HttpField getField(int i) public HttpField getField(int i)
{ {
return _fields.get(i); if (i>=_size)
throw new NoSuchElementException();
return _fields[i];
} }
public HttpField getField(HttpHeader header) 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) if (f.getHeader()==header)
return f; return f;
} }
@ -127,9 +139,9 @@ public class HttpFields implements Iterable<HttpField>
public HttpField getField(String name) 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)) if (f.getName().equalsIgnoreCase(name))
return f; return f;
} }
@ -138,9 +150,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpField field) 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())) if (f.isSameName(field) && f.contains(field.getValue()))
return true; return true;
} }
@ -149,9 +161,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(HttpHeader header, String value) 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)) if (f.getHeader()==header && f.contains(value))
return true; return true;
} }
@ -160,9 +172,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean contains(String name, String value) 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)) if (f.getName().equalsIgnoreCase(name) && f.contains(value))
return true; return true;
} }
@ -172,39 +184,35 @@ public class HttpFields implements Iterable<HttpField>
public boolean containsKey(String name) 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)) if (f.getName().equalsIgnoreCase(name))
return true; return true;
} }
return false; return false;
} }
public String getStringField(HttpHeader header)
{
return getStringField(header.asString());
}
public String get(HttpHeader header) 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) public String get(String header)
{ {
return getStringField(header); for (int i=0;i<_size;i++)
} {
HttpField f=_fields[i];
/** if (f.getName().equalsIgnoreCase(header))
* @return the value of a field, or null if not found. For multiple fields of the same name, return f.getValue();
* only the first is returned. }
* @param name the case-insensitive field name return null;
*/
public String getStringField(String name)
{
HttpField field = getField(name);
return field==null?null:field.getValue();
} }
/** /**
@ -230,9 +238,9 @@ public class HttpFields implements Iterable<HttpField>
*/ */
public Enumeration<String> getValues(final String name) 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) if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
{ {
@ -247,9 +255,9 @@ public class HttpFields implements Iterable<HttpField>
{ {
if (field==null) 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) if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
return true; return true;
} }
@ -270,7 +278,6 @@ public class HttpFields implements Iterable<HttpField>
} }
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
}; };
} }
} }
@ -328,22 +335,24 @@ public class HttpFields implements Iterable<HttpField>
public void put(HttpField field) public void put(HttpField field)
{ {
boolean put=false; 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 (f.isSameName(field))
{ {
if (put) if (put)
_fields.remove(i); {
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
}
else else
{ {
_fields.set(i,field); _fields[i]=field;
put=true; put=true;
} }
} }
} }
if (!put) if (!put)
_fields.add(field); add(field);
} }
/** /**
@ -408,7 +417,7 @@ public class HttpFields implements Iterable<HttpField>
return; return;
HttpField field = new HttpField(name, value); HttpField field = new HttpField(name, value);
_fields.add(field); add(field);
} }
public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException 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"); if (value == null) throw new IllegalArgumentException("null value");
HttpField field = new HttpField(header, 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) 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) 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) 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)) 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()) if (size() != that.size())
return false; return false;
for (HttpField field : this) loop: for (HttpField fi : this)
{ {
if (!that.contains(field)) for (HttpField fa : that)
return false; {
if (fi.equals(fa))
continue loop;
}
return false;
} }
return true; return true;
} }
@ -622,17 +643,20 @@ public class HttpFields implements Iterable<HttpField>
public void clear() public void clear()
{ {
_fields.clear(); _size=0;
} }
public void add(HttpField field) 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) 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.io.IOException;
import java.nio.BufferOverflowException; import java.nio.BufferOverflowException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import org.eclipse.jetty.http.HttpTokens.EndOfContent; import org.eclipse.jetty.http.HttpTokens.EndOfContent;
@ -1058,9 +1057,9 @@ public class HttpGenerator
public static void putTo(HttpField field, ByteBuffer bufferInFillMode) 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 else
{ {
@ -1090,23 +1089,4 @@ public class HttpGenerator
} }
BufferUtil.putCRLF(bufferInFillMode); 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 // 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"}) 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); CACHE.put(field);
for (String charset : new String[]{"utf-8","iso-8859-1"}) for (String charset : new String[]{"utf-8","iso-8859-1"})
{ {
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset)); CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset)); CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase())); CACHE.put(new PreEncodedHttpField(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.toUpperCase()));
} }
} }

View File

@ -90,7 +90,7 @@ public class MimeTypes
_charset=null; _charset=null;
_charsetString=null; _charsetString=null;
_assumedCharset=false; _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)); _charset=Charset.forName(s.substring(i+9));
_charsetString=_charset==null?null:_charset.toString().toLowerCase(); _charsetString=_charset==null?null:_charset.toString().toLowerCase();
_assumedCharset=false; _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; _charset=cs;
_charsetString=_charset==null?null:_charset.toString().toLowerCase(); _charsetString=_charset==null?null:_charset.toString().toLowerCase();
_assumedCharset=true; _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.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.Test; import org.junit.Test;
/** /**
@ -135,4 +138,17 @@ public class HttpFieldTest
assertEquals("c",values[2]); 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.nio.ByteBuffer;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.List;
import java.util.Locale; import java.util.NoSuchElementException;
import java.util.Set;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.Assert; import org.junit.Assert;
@ -48,9 +48,10 @@ public class HttpFieldsTest
header.put("name0", "value:0"); header.put("name0", "value:0");
header.put("name1", "value1"); header.put("name1", "value1");
assertEquals("value:0",header.getStringField("name0")); assertEquals(2,header.size());
assertEquals("value1",header.getStringField("name1")); assertEquals("value:0",header.get("name0"));
assertNull(header.getStringField("name2")); assertEquals("value1",header.get("name1"));
assertNull(header.get("name2"));
int matches=0; int matches=0;
Enumeration<String> e = header.getFieldNames(); Enumeration<String> e = header.getFieldNames();
@ -68,6 +69,7 @@ public class HttpFieldsTest
assertEquals(true, e.hasMoreElements()); assertEquals(true, e.hasMoreElements());
assertEquals(e.nextElement(), "value:0"); assertEquals(e.nextElement(), "value:0");
assertEquals(false, e.hasMoreElements()); assertEquals(false, e.hasMoreElements());
} }
@Test @Test
@ -99,10 +101,45 @@ public class HttpFieldsTest
header.put("name0", "value0"); header.put("name0", "value0");
header.put("name1", "value1"); header.put("name1", "value1");
assertEquals("value0",header.getStringField("name0")); assertEquals("value0",header.get("name0"));
assertEquals("value0",header.getStringField("Name0")); assertEquals("value0",header.get("Name0"));
assertEquals("value1",header.getStringField("name1")); assertEquals("value1",header.get("name1"));
assertEquals("value1",header.getStringField("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 @Test
@ -153,16 +190,16 @@ public class HttpFieldsTest
header.put("name1", "xxxxxx"); header.put("name1", "xxxxxx");
header.put("name2", "value2"); header.put("name2", "value2");
assertEquals("value0",header.getStringField("name0")); assertEquals("value0",header.get("name0"));
assertEquals("xxxxxx",header.getStringField("name1")); assertEquals("xxxxxx",header.get("name1"));
assertEquals("value2",header.getStringField("name2")); assertEquals("value2",header.get("name2"));
header.put("name1", "value1"); header.put("name1", "value1");
assertEquals("value0",header.getStringField("name0")); assertEquals("value0",header.get("name0"));
assertEquals("value1",header.getStringField("name1")); assertEquals("value1",header.get("name1"));
assertEquals("value2",header.getStringField("name2")); assertEquals("value2",header.get("name2"));
assertNull(header.getStringField("name3")); assertNull(header.get("name3"));
int matches=0; int matches=0;
Enumeration<String> e = header.getFieldNames(); Enumeration<String> e = header.getFieldNames();
@ -188,22 +225,22 @@ public class HttpFieldsTest
@Test @Test
public void testRemovePut() throws Exception public void testRemovePut() throws Exception
{ {
HttpFields header = new HttpFields(); HttpFields header = new HttpFields(1);
header.put("name0", "value0"); header.put("name0", "value0");
header.put("name1", "value1"); header.put("name1", "value1");
header.put("name2", "value2"); header.put("name2", "value2");
assertEquals("value0",header.getStringField("name0")); assertEquals("value0",header.get("name0"));
assertEquals("value1",header.getStringField("name1")); assertEquals("value1",header.get("name1"));
assertEquals("value2",header.getStringField("name2")); assertEquals("value2",header.get("name2"));
header.remove("name1"); header.remove("name1");
assertEquals("value0",header.getStringField("name0")); assertEquals("value0",header.get("name0"));
assertNull(header.getStringField("name1")); assertNull(header.get("name1"));
assertEquals("value2",header.getStringField("name2")); assertEquals("value2",header.get("name2"));
assertNull(header.getStringField("name3")); assertNull(header.get("name3"));
int matches=0; int matches=0;
Enumeration<String> e = header.getFieldNames(); Enumeration<String> e = header.getFieldNames();
@ -232,16 +269,16 @@ public class HttpFieldsTest
fields.add("name1", "valueA"); fields.add("name1", "valueA");
fields.add("name2", "value2"); fields.add("name2", "value2");
assertEquals("value0",fields.getStringField("name0")); assertEquals("value0",fields.get("name0"));
assertEquals("valueA",fields.getStringField("name1")); assertEquals("valueA",fields.get("name1"));
assertEquals("value2",fields.getStringField("name2")); assertEquals("value2",fields.get("name2"));
fields.add("name1", "valueB"); fields.add("name1", "valueB");
assertEquals("value0",fields.getStringField("name0")); assertEquals("value0",fields.get("name0"));
assertEquals("valueA",fields.getStringField("name1")); assertEquals("valueA",fields.get("name1"));
assertEquals("value2",fields.getStringField("name2")); assertEquals("value2",fields.get("name2"));
assertNull(fields.getStringField("name3")); assertNull(fields.get("name3"));
int matches=0; int matches=0;
Enumeration<String> e = fields.getFieldNames(); Enumeration<String> e = fields.getFieldNames();
@ -304,9 +341,29 @@ public class HttpFieldsTest
assertEquals(true, e.hasMoreElements()); assertEquals(true, e.hasMoreElements());
assertEquals(e.nextElement(), "value1D"); assertEquals(e.nextElement(), "value1D");
assertEquals(false, e.hasMoreElements()); 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 @Test
public void testDateFields() throws Exception public void testDateFields() throws Exception
{ {
@ -346,7 +403,7 @@ public class HttpFieldsTest
assertEquals(951825600000L,d5); assertEquals(951825600000L,d5);
fields.putDateField("D2",d1); 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 @Test
@ -355,16 +412,16 @@ public class HttpFieldsTest
HttpFields fields = new HttpFields(); HttpFields fields = new HttpFields();
fields.putDateField("Dzero",0); 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); 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); 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); 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 @Test
@ -374,15 +431,33 @@ public class HttpFieldsTest
header.put("I1", "42"); header.put("I1", "42");
header.put("I2", " 43 99"); header.put("I2", " 43 99");
header.put("I3", "-44;"); header.put("I3", "-44");
header.put("I4", " - 45abc"); header.put("I4", " - 45abc");
header.put("N1", " - "); header.put("N1", " - ");
header.put("N2", "xx"); header.put("N2", "xx");
long i1=header.getLongField("I1"); 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 i3=header.getLongField("I3");
long i4=header.getLongField("I4");
try
{
header.getLongField("I4");
assertTrue(false);
}
catch(NumberFormatException e)
{
assertTrue(true);
}
try{ try{
header.getLongField("N1"); header.getLongField("N1");
@ -403,14 +478,12 @@ public class HttpFieldsTest
} }
assertEquals(42,i1); assertEquals(42,i1);
assertEquals(43,i2);
assertEquals(-44,i3); assertEquals(-44,i3);
assertEquals(-45,i4);
header.putLongField("I5", 46); header.putLongField("I5", 46);
header.putLongField("I6",-47); header.putLongField("I6",-47);
assertEquals("46",header.getStringField("I5")); assertEquals("46",header.get("I5"));
assertEquals("-47",header.getStringField("I6")); assertEquals("-47",header.get("I6"));
} }
@ -429,12 +502,28 @@ public class HttpFieldsTest
header.add("n6", "def"); header.add("n6", "def");
header.add("N6", "hig"); header.add("N6", "hig");
header.add("n7", "abc , def;q=0.9 , 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++) for (int i=0;i<8;i++)
{ {
assertTrue(header.containsKey("n"+i));
assertTrue(header.containsKey("N"+i));
assertFalse(""+i,header.contains("n"+i,"xyz")); assertFalse(""+i,header.contains("n"+i,"xyz"));
assertEquals(""+i,i>=4,header.contains("n"+i,"def")); 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.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme; 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.ArrayQueue;
import org.eclipse.jetty.util.ArrayTernaryTrie; import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
@ -119,20 +118,20 @@ public class HpackContext
switch(i) switch(i)
{ {
case 2: 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; break;
case 3: 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; break;
case 6: 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; break;
case 7: 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; break;
case 8: case 8:
case 11: 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; break;
case 9: case 9:
@ -140,7 +139,7 @@ public class HpackContext
case 12: case 12:
case 13: case 13:
case 14: 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; break;
default: default:
@ -231,6 +230,11 @@ public class HpackContext
return get(header.asString()); return get(header.asString());
return e; return e;
} }
public static Entry getStatic(HttpHeader header)
{
return __headerEntryTable[header.ordinal()];
}
public Entry add(HttpField field) public Entry add(HttpField field)
{ {
@ -420,6 +424,11 @@ public class HpackContext
return null; return null;
} }
public int getSlot()
{
return _slot;
}
public String toString() public String toString()
{ {
return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode()); 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 public static class StaticEntry extends Entry
{ {
private final byte[] _huffmanValue; private final byte[] _huffmanValue;
private final byte _encodedField;
StaticEntry(int index,HttpField field) StaticEntry(int index,HttpField field)
{ {
@ -450,6 +460,8 @@ public class HpackContext
} }
else else
_huffmanValue=null; _huffmanValue=null;
_encodedField=(byte)(0x80|index);
} }
@Override @Override
@ -463,6 +475,11 @@ public class HpackContext
{ {
return _huffmanValue; 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.BadMessageException;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader; 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.HttpStatus;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry; import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
@ -41,7 +39,8 @@ import org.eclipse.jetty.util.log.Logger;
public class HpackDecoder public class HpackDecoder
{ {
public static final Logger LOG = Log.getLogger(HpackDecoder.class); 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 HpackContext _context;
private final MetaDataBuilder _builder; private final MetaDataBuilder _builder;
@ -191,46 +190,31 @@ public class HpackDecoder
HttpField field; HttpField field;
if (header==null) if (header==null)
{ {
// just make a normal field and bypass header name lookup
field = new HttpField(null,name,value); field = new HttpField(null,name,value);
} }
else 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) 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: case C_STATUS:
Integer code = Integer.valueOf(value); if (indexed)
field = new StaticValueHttpField(HttpHeader.C_STATUS,value,code); field = new HttpField.IntValueHttpField(header,name,value);
break;
case C_SCHEME:
HttpScheme scheme=HttpScheme.CACHE.get(value);
if (scheme!=null)
field = new StaticValueHttpField(HttpHeader.C_SCHEME,scheme.asString(),scheme);
else else
field = new AuthorityHttpField(value); field = new HttpField(header,name,value);
break; break;
case C_AUTHORITY: case C_AUTHORITY:
field = new AuthorityHttpField(value); field = new AuthorityHttpField(value);
break; break;
case C_PATH:
field = new HttpField(HttpHeader.C_PATH,value);
break;
case CONTENT_LENGTH: case CONTENT_LENGTH:
if ("0".equals(value)) if ("0".equals(value))
field = CONTENT_LENGTH_0; field = CONTENT_LENGTH_0;
else else
field = new HttpField.LongValueHttpField(header,value); field = new HttpField.LongValueHttpField(header,name,value);
break; break;
default: default:

View File

@ -26,8 +26,11 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData; 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.Entry;
import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry;
import org.eclipse.jetty.io.ByteBufferPool.Lease; import org.eclipse.jetty.io.ByteBufferPool.Lease;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
@ -78,6 +81,7 @@ public class HpackEncoder
} }
private final HpackContext _context; private final HpackContext _context;
private final boolean _debug;
private int _remoteMaxHeaderTableSize; private int _remoteMaxHeaderTableSize;
private int _localMaxHeaderTableSize; private int _localMaxHeaderTableSize;
@ -96,6 +100,7 @@ public class HpackEncoder
_context=new HpackContext(remoteMaxHeaderTableSize); _context=new HpackContext(remoteMaxHeaderTableSize);
_remoteMaxHeaderTableSize=remoteMaxHeaderTableSize; _remoteMaxHeaderTableSize=remoteMaxHeaderTableSize;
_localMaxHeaderTableSize=localMaxHeaderTableSize; _localMaxHeaderTableSize=localMaxHeaderTableSize;
_debug=LOG.isDebugEnabled();
} }
public HpackContext getContext() public HpackContext getContext()
@ -154,15 +159,13 @@ public class HpackEncoder
int code=response.getStatus(); int code=response.getStatus();
HttpField status = code<__status.length?__status[code]:null; HttpField status = code<__status.length?__status[code]:null;
if (status==null) if (status==null)
status=new HttpField(HttpHeader.C_STATUS,Integer.toString(code)); status=new HttpField.IntValueHttpField(HttpHeader.C_STATUS,code);
encode(buffer,status); encode(buffer,status);
} }
// Add all the other fields // Add all the other fields
for (HttpField field : metadata) for (HttpField field : metadata)
{
encode(buffer,field); encode(buffer,field);
}
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug(String.format("CtxTbl[%x] encoded %d octets",_context.hashCode(), buffer.position() - pos)); 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) 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; 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? // Is there an entry for the field?
Entry entry = _context.get(field); Entry entry = _context.get(field);
if (entry!=null) if (entry!=null)
{ {
// Known field entry, so encode it as indexed // Known field entry, so encode it as indexed
int index=_context.index(entry); if (entry.isStatic())
if (p>=0) {
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index)); buffer.put(((StaticEntry)entry).getEncodedField());
buffer.put((byte)0x80); if (_debug)
NBitInteger.encode(buffer,7,index); 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 else
{ {
// Unknown field entry, so we will have to send literally. // Unknown field entry, so we will have to send literally.
final Entry name;
final boolean indexed; final boolean indexed;
final boolean never_index;
final boolean huffman;
final int bits;
// But do we know it's name? // But do we know it's name?
HttpHeader header = field.getHeader(); HttpHeader header = field.getHeader();
// Select encoding strategy
if (header==null) 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? // has the custom header name been seen before?
if (name==null) if (name==null)
{ {
@ -218,95 +228,71 @@ public class HpackEncoder
// the first time we have seen a custom name or a custom field. // the first time we have seen a custom name or a custom field.
// unless the name is changing, this is worthwhile // unless the name is changing, this is worthwhile
indexed=true; indexed=true;
never_index=false; encodeName(buffer,(byte)0x40,6,field.getName(),null);
huffman=true; encodeValue(buffer,true,field.getValue());
bits = 6; if (_debug)
buffer.put((byte)0x40); encoding="LitHuffNHuffVIdx";
} }
else else
{ {
// known custom name, but unknown value. // 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; indexed=false;
never_index=false; encodeName(buffer,(byte)0x00,4,field.getName(),null);
huffman=true; encodeValue(buffer,true,field.getValue());
bits = 4; if (_debug)
buffer.put((byte)0x00); encoding="LitHuffNHuffV!Idx";
} }
} }
else else
{ {
name = _context.get(header); // Select encoding strategy for known header names
Entry name = _context.get(header);
if (__DO_NOT_INDEX.contains(header)) if (__DO_NOT_INDEX.contains(header))
{ {
// Non indexed field // Non indexed field
indexed=false; indexed=false;
never_index=__NEVER_INDEX.contains(header); boolean never_index=__NEVER_INDEX.contains(header);
huffman=!__DO_NOT_HUFFMAN.contains(header); boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
bits = 4; encodeName(buffer,never_index?(byte)0x10:(byte)0x00,4,header.asString(),name);
buffer.put(never_index?(byte)0x10:(byte)0x00); 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) else if (header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>1)
{ {
// Non indexed content length for non zero value // Non indexed content length for non zero value
indexed=false; indexed=false;
never_index=false; encodeName(buffer,(byte)0x00,4,header.asString(),name);
huffman=true; encodeValue(buffer,true,field.getValue());
bits = 4; if (_debug)
buffer.put((byte)0x00); 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 else
{ {
// indexed // indexed
indexed=true; indexed=true;
never_index=false; boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
huffman=!__DO_NOT_HUFFMAN.contains(header); encodeName(buffer,(byte)0x40,6,header.asString(),name);
bits = 6; encodeValue(buffer,huffman,field.getValue());
buffer.put((byte)0x40); if (_debug)
} encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
} (huffman?"HuffVIdx":"LitVIdx");
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);
} }
} }
@ -316,11 +302,52 @@ public class HpackEncoder
_context.add(field); _context.add(field);
} }
if (p>=0) if (_debug)
{ {
int e=buffer.position(); int e=buffer.position();
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
LOG.debug("encode {}:'{}' to '{}'",encoding,field,TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+p,e-p)); 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) if (_size>_maxSize)
throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_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()) switch(field.getHeader())
{ {
case C_STATUS: case C_STATUS:
@ -98,7 +98,7 @@ public class MetaDataBuilder
switch(field.getHeader()) switch(field.getHeader())
{ {
case C_STATUS: case C_STATUS:
_status=Integer.parseInt(field.getValue()); _status=field.getIntValue();
break; break;
case C_METHOD: case C_METHOD:
@ -114,6 +114,7 @@ public class MetaDataBuilder
break; break;
case HOST: case HOST:
// :authority fields must come first. If we have one, ignore the host header as far as authority goes.
if (_authority==null) if (_authority==null)
_authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue()); _authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
_fields.add(field); _fields.add(field);

View File

@ -23,19 +23,11 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public class StaticValueHttpField extends HttpField public class StaticTableHttpField extends HttpField
{ {
private final Object _value; private final Object _value;
public StaticValueHttpField(HttpHeader header,String name, String valueString, Object value) public StaticTableHttpField(HttpHeader header,String valueString, Object value)
{
super(header,name,valueString);
if (value==null)
throw new IllegalArgumentException();
_value=value;
}
public StaticValueHttpField(HttpHeader header,String valueString, Object value)
{ {
super(header,header.asString(),valueString); super(header,header.asString(),valueString);
if (value==null) if (value==null)
@ -43,7 +35,7 @@ public class StaticValueHttpField extends HttpField
_value=value; _value=value;
} }
public StaticValueHttpField(String name, String valueString, Object value) public StaticTableHttpField(String name, String valueString, Object value)
{ {
super(name,valueString); super(name,valueString);
if (value==null) 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.assertFalse;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.nio.ByteBuffer; 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.http.HttpField;
import org.eclipse.jetty.http2.hpack.HpackContext.Entry; 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.HttpScheme;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.TypeUtil;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;

View File

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

View File

@ -24,12 +24,15 @@ import static org.junit.Assert.assertEquals;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http.BadMessageException; 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.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http.MetaData.Response; import org.eclipse.jetty.http.MetaData.Response;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -37,6 +40,10 @@ import org.junit.Test;
public class HpackTest 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 @Test
public void encodeDecodeResponseTest() public void encodeDecodeResponseTest()
{ {
@ -47,7 +54,9 @@ public class HpackTest
HttpFields fields0 = new HttpFields(); HttpFields fields0 = new HttpFields();
fields0.add(HttpHeader.CONTENT_TYPE,"text/html"); fields0.add(HttpHeader.CONTENT_TYPE,"text/html");
fields0.add(HttpHeader.CONTENT_LENGTH,"1024"); 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(HttpHeader.SET_COOKIE,"abcdefghijklmnopqrstuvwxyz");
fields0.add("custom-key","custom-value"); fields0.add("custom-key","custom-value");
Response original0 = new MetaData.Response(HttpVersion.HTTP_2,200,fields0); Response original0 = new MetaData.Response(HttpVersion.HTTP_2,200,fields0);
@ -70,7 +79,9 @@ public class HpackTest
HttpFields fields1 = new HttpFields(); HttpFields fields1 = new HttpFields();
fields1.add(HttpHeader.CONTENT_TYPE,"text/plain"); fields1.add(HttpHeader.CONTENT_TYPE,"text/plain");
fields1.add(HttpHeader.CONTENT_LENGTH,"1234"); 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"); fields1.add("Custom-Key","Other-Value");
Response original1 = new MetaData.Response(HttpVersion.HTTP_2,200,fields1); 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); HttpChannelOverHTTP2 channel = new HttpChannelOverHTTP2(connector, httpConfiguration, endPoint, transport, input, stream);
stream.setAttribute(CHANNEL_ATTRIBUTE, channel); stream.setAttribute(CHANNEL_ATTRIBUTE, channel);
channel.requestHeaders(frame); channel.onHeadersFrame(frame);
return frame.isEndStream() ? null : this; return frame.isEndStream() ? null : this;
} }

View File

@ -18,11 +18,15 @@
package org.eclipse.jetty.http2.server; package org.eclipse.jetty.http2.server;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Stream; import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.frames.DataFrame; import org.eclipse.jetty.http2.frames.DataFrame;
@ -42,10 +46,10 @@ import org.eclipse.jetty.util.log.Logger;
public class HttpChannelOverHTTP2 extends HttpChannel public class HttpChannelOverHTTP2 extends HttpChannel
{ {
private static final Logger LOG = Log.getLogger(HttpChannelOverHTTP2.class); 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 PreEncodedHttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
private static final HttpField SERVER_VERSION=new HttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION); private static final HttpField POWERED_BY=new PreEncodedHttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
private static final HttpField POWERED_BY=new HttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
private final Stream stream; // TODO recycle channel for new Stream? 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) 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; this.stream = stream;
} }
public void requestHeaders(HeadersFrame frame) @Override
public boolean isExpecting100Continue()
{
return _expect100Continue;
}
public void onHeadersFrame(HeadersFrame frame)
{ {
MetaData metaData = frame.getMetaData(); MetaData metaData = frame.getMetaData();
if (!metaData.isRequest()) if (!metaData.isRequest())
@ -63,26 +73,21 @@ public class HttpChannelOverHTTP2 extends HttpChannel
} }
MetaData.Request request = (MetaData.Request)metaData; 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(); 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 // TODO make this a better field for h2 hpack generation
HttpFields response=getResponse().getHttpFields();
if (getHttpConfiguration().getSendServerVersion()) if (getHttpConfiguration().getSendServerVersion())
getResponse().getHttpFields().add(SERVER_VERSION); response.add(SERVER_VERSION);
if (getHttpConfiguration().getSendXPoweredBy()) if (getHttpConfiguration().getSendXPoweredBy())
getResponse().getHttpFields().add(POWERED_BY); response.add(POWERED_BY);
onRequest(request); onRequest(request);
if (frame.isEndStream()) if (frame.isEndStream())
{
onRequestComplete(); onRequestComplete();
}
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())
{ {
@ -127,4 +132,33 @@ public class HttpChannelOverHTTP2 extends HttpChannel
onRequestComplete(); 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) private void commit(HttpGenerator.ResponseInfo info, boolean endStream, Callback callback)
{ {
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())

View File

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

View File

@ -289,8 +289,8 @@ public class FormAuthenticator extends LoginAuthenticator
LOG.debug("authenticated {}->{}",form_auth,nuri); LOG.debug("authenticated {}->{}",form_auth,nuri);
response.setContentLength(0); response.setContentLength(0);
Response base_response = HttpChannel.getCurrentHttpChannel().getResponse(); Request base_request = Request.getBaseRequest(req);
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest(); 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); 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)); base_response.sendRedirect(redirectCode, response.encodeRedirectURL(nuri));
return form_auth; return form_auth;

View File

@ -31,7 +31,11 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Attributes; import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.MultiMap;
@ -46,14 +50,14 @@ public class Dispatcher implements RequestDispatcher
private final ContextHandler _contextHandler; private final ContextHandler _contextHandler;
private final HttpURI _uri; private final HttpURI _uri;
private final String _pathInfo; private final String _pathInContext;
private final String _named; private final String _named;
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInfo) public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext)
{ {
_contextHandler=contextHandler; _contextHandler=contextHandler;
_uri=uri; _uri=uri;
_pathInfo=pathInfo; _pathInContext=pathInContext;
_named=null; _named=null;
} }
@ -61,7 +65,7 @@ public class Dispatcher implements RequestDispatcher
{ {
_contextHandler=contextHandler; _contextHandler=contextHandler;
_uri=null; _uri=null;
_pathInfo=null; _pathInContext=null;
_named=name; _named=name;
} }
@ -79,7 +83,7 @@ public class Dispatcher implements RequestDispatcher
@Override @Override
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException 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)) if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request); request = new ServletRequestHttpWrapper(request);
@ -104,14 +108,14 @@ public class Dispatcher implements RequestDispatcher
attr._requestURI=_uri.getPath(); attr._requestURI=_uri.getPath();
attr._contextPath=_contextHandler.getContextPath(); attr._contextPath=_contextHandler.getContextPath();
attr._servletPath=null; // set by ServletHandler attr._servletPath=null; // set by ServletHandler
attr._pathInfo=_pathInfo; attr._pathInfo=_pathInContext;
attr._query=_uri.getQuery(); attr._query=_uri.getQuery();
if (attr._query!=null) if (attr._query!=null)
baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false); baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false);
baseRequest.setAttributes(attr); baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response); _contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
} }
} }
finally finally
@ -126,7 +130,7 @@ public class Dispatcher implements RequestDispatcher
protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException 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(); Response base_response=baseRequest.getResponse();
base_response.resetForForward(); base_response.resetForForward();
@ -187,13 +191,13 @@ public class Dispatcher implements RequestDispatcher
baseRequest.setContextPath(_contextHandler.getContextPath()); baseRequest.setContextPath(_contextHandler.getContextPath());
baseRequest.setServletPath(null); baseRequest.setServletPath(null);
baseRequest.setPathInfo(_pathInfo); baseRequest.setPathInfo(_pathInContext);
if (_uri.getQuery()!=null || old_uri.getQuery()!=null) if (_uri.getQuery()!=null || old_uri.getQuery()!=null)
baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true); baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true);
baseRequest.setAttributes(attr); baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response); _contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
if (!baseRequest.getHttpChannelState().isAsync()) if (!baseRequest.getHttpChannelState().isAsync())
commitResponse(response,baseRequest); commitResponse(response,baseRequest);
@ -212,6 +216,26 @@ public class Dispatcher implements RequestDispatcher
baseRequest.setDispatcherType(old_type); 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 private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
{ {

View File

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

View File

@ -199,7 +199,6 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
if (getResponse().isCommitted()) if (getResponse().isCommitted())
throw new IOException("Committed before 100 Continues"); throw new IOException("Committed before 100 Continues");
// TODO: break this dependency with HttpGenerator
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false); boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
if (!committed) if (!committed)
throw new IOException("Concurrent commit while trying to send 100-Continue"); 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. // response is bad either with RST or by abnormal completion of chunked response.
getEndPoint().close(); 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 java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
public interface HttpTransport public interface HttpTransport
{ {
void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback); void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback);
void push (MetaData.Request request);
void completed(); void completed();
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -52,6 +52,7 @@ import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent; import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener; import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -132,6 +133,28 @@ public class Request implements HttpServletRequest
private static final MultiMap<String> NO_PARAMS = new MultiMap<>(); 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 HttpChannel _channel;
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>(); private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
private final HttpInput _input; private final HttpInput _input;
@ -510,7 +533,7 @@ public class Request implements HttpServletRequest
@Override @Override
public String getContentType() 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) if (_characterEncoding==null && content_type!=null)
{ {
MimeTypes.Type mime = MimeTypes.CACHE.get(content_type); MimeTypes.Type mime = MimeTypes.CACHE.get(content_type);
@ -603,7 +626,7 @@ public class Request implements HttpServletRequest
@Override @Override
public String getHeader(String name) 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 @Override
public String getHeader(String name) public String getHeader(String name)
{ {
return _fields.getStringField(name); return _fields.get(name);
} }
@Override @Override

View File

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

View File

@ -102,7 +102,7 @@ public class PartialRFC2616Test
assertEquals("3.3.1 RFC 850 ANSI C",d3,d2); assertEquals("3.3.1 RFC 850 ANSI C",d3,d2);
fields.putDateField("Date",d1.getTime()); 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) catch (Exception e)
{ {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@ public class CloseableDoSFilter extends DoSFilter
@Override @Override
protected void closeConnection(HttpServletRequest request, HttpServletResponse response, Thread thread) 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(); 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.CRC32;
import java.util.zip.Deflater; import java.util.zip.Deflater;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.HttpChannel;
@ -41,7 +41,7 @@ import org.eclipse.jetty.util.log.Logger;
public class GzipHttpOutput extends HttpOutput public class GzipHttpOutput extends HttpOutput
{ {
public static Logger LOG = Log.getLogger(GzipHttpOutput.class); 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 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}; 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!"); 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) private void sendReply(HttpGenerator.ResponseInfo info, Callback callback, boolean close)
{ {
Fields headers = new Fields(); Fields headers = new Fields();

View File

@ -146,7 +146,7 @@ public abstract class RFC2616BaseTest
// Test formatting // Test formatting
fields.putDateField("Date",expected.getTime().getTime()); 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 //make a request to set up a session on the server
ContentResponse response = client.GET(url + "?action=init"); ContentResponse response = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -103,7 +103,7 @@ public class MaxInactiveMigrationTest
ContentResponse response = request.send(); ContentResponse response = request.send();
assertEquals(HttpServletResponse.SC_OK, response.getStatus()); assertEquals(HttpServletResponse.SC_OK, response.getStatus());
sessionCookie = response.getHeaders().getStringField("Set-Cookie"); sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue( sessionCookie != null ); assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port1 + contextPath +"/bar?action=set");
assertEquals( HttpServletResponse.SC_OK, response.getStatus()); assertEquals( HttpServletResponse.SC_OK, response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
String sessionId = (String)webApp.getServletContext().getAttribute("foo"); String sessionId = (String)webApp.getServletContext().getAttribute("foo");
assertNotNull(sessionId); assertNotNull(sessionId);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -64,7 +64,7 @@ public abstract class AbstractImmortalSessionTest
int value = 42; int value = 42;
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=set&value=" + value); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=set&value=" + value);
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
assertEquals("test", response1.getContentAsString()); assertEquals("test", response1.getContentAsString());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue( sessionCookie != null ); assertTrue( sessionCookie != null );
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
@ -106,7 +106,7 @@ public abstract class AbstractLastAccessTimeTest
assertEquals(HttpServletResponse.SC_OK , response2.getStatus()); assertEquals(HttpServletResponse.SC_OK , response2.getStatus());
assertEquals("test", response2.getContentAsString()); assertEquals("test", response2.getContentAsString());
String setCookie = response2.getHeaders().getStringField("Set-Cookie"); String setCookie = response2.getHeaders().get("Set-Cookie");
if (setCookie!=null) if (setCookie!=null)
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField( "Set-Cookie" ); String sessionCookie = response1.getHeaders().get( "Set-Cookie" );
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -86,7 +86,7 @@ public abstract class AbstractLocalSessionScavengingTest
// Create the session on node1 // Create the session on node1
ContentResponse response1 = client.GET(urls[0] + "?action=init"); ContentResponse response1 = client.GET(urls[0] + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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 // Connect to server1 to create a session and get its session cookie
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init"); ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
//sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); //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 //make a request to set up a session on the server
ContentResponse response = client.GET(url + "?action=init"); ContentResponse response = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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 //make a request to set up a session on the server
ContentResponse response1 = client.GET(url + "?action=init"); ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");

View File

@ -119,7 +119,7 @@ public abstract class AbstractSessionInvalidateAndCreateTest
// Create the session // Create the session
ContentResponse response1 = client.GET(url + "?action=init"); ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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); Request request1 = client.POST("http://localhost:" + port1 + contextPath + servletMapping + "?action=set&value=" + value);
ContentResponse response1 = request1.send(); ContentResponse response1 = request1.send();
assertEquals(HttpServletResponse.SC_OK,response1.getStatus()); assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc. // Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); 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"); ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().getStringField("Set-Cookie"); String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null); assertTrue(sessionCookie != null);
assertFalse(testListener.isCalled()); assertFalse(testListener.isCalled());
@ -79,7 +79,7 @@ public abstract class AbstractSessionRenewTest
request.header("Cookie", sessionCookie); request.header("Cookie", sessionCookie);
ContentResponse renewResponse = request.send(); ContentResponse renewResponse = request.send();
assertEquals(HttpServletResponse.SC_OK,renewResponse.getStatus()); assertEquals(HttpServletResponse.SC_OK,renewResponse.getStatus());
String renewSessionCookie = renewResponse.getHeaders().getStringField("Set-Cookie"); String renewSessionCookie = renewResponse.getHeaders().get("Set-Cookie");
assertNotNull(renewSessionCookie); assertNotNull(renewSessionCookie);
assertNotSame(sessionCookie, renewSessionCookie); assertNotSame(sessionCookie, renewSessionCookie);
assertTrue(testListener.isCalled()); assertTrue(testListener.isCalled());

View File

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

View File

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

View File

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