Merged branch 'jetty-http2' into 'http2_flow_control'
This commit is contained in:
commit
55dec378fc
|
@ -77,6 +77,16 @@ public class HttpTransportOverFCGI implements HttpTransport
|
|||
flusher.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
|
||||
*/
|
||||
@Override
|
||||
public void push(org.eclipse.jetty.http.MetaData.Request request)
|
||||
{
|
||||
// LOG.debug("ignore push in {}",this);
|
||||
}
|
||||
|
||||
private void commit(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -69,9 +69,14 @@ public class HttpField
|
|||
return _value;
|
||||
}
|
||||
|
||||
public int getIntValue()
|
||||
{
|
||||
return Integer.valueOf(_value);
|
||||
}
|
||||
|
||||
public long getLongValue()
|
||||
{
|
||||
return StringUtil.toLong(_value);
|
||||
return Long.valueOf(_value);
|
||||
}
|
||||
|
||||
public String[] getValues()
|
||||
|
@ -416,21 +421,85 @@ public class HttpField
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static class IntValueHttpField extends HttpField
|
||||
{
|
||||
final int _int;
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String name, String value, int intValue)
|
||||
{
|
||||
super(header,name,value);
|
||||
_int=intValue;
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String value, int intValue)
|
||||
{
|
||||
this(header,header.asString(),value,Integer.valueOf(value));
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String name, String value)
|
||||
{
|
||||
this(header,name,value,Integer.valueOf(value));
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, String value)
|
||||
{
|
||||
this(header,header.asString(),value);
|
||||
}
|
||||
|
||||
public IntValueHttpField(HttpHeader header, int value)
|
||||
{
|
||||
this(header,header.asString(),value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntValue()
|
||||
{
|
||||
return _int;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLongValue()
|
||||
{
|
||||
return _int;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LongValueHttpField extends HttpField
|
||||
{
|
||||
final long _long;
|
||||
|
||||
public LongValueHttpField(HttpHeader header, long value)
|
||||
public LongValueHttpField(HttpHeader header, String name, String value, long longValue)
|
||||
{
|
||||
super(header,Long.toString(value));
|
||||
_long=value;
|
||||
super(header,name,value);
|
||||
_long=longValue;
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header, String name, String value)
|
||||
{
|
||||
this(header,name,value,Long.valueOf(value));
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header, String name, long value)
|
||||
{
|
||||
this(header,name,Long.toString(value),value);
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header, String value)
|
||||
{
|
||||
super(header,value);
|
||||
_long=StringUtil.toLong(value);
|
||||
this(header,header.asString(),value);
|
||||
}
|
||||
|
||||
public LongValueHttpField(HttpHeader header,long value)
|
||||
{
|
||||
this(header,header.asString(),value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getIntValue()
|
||||
{
|
||||
return (int)_long;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.http;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
|
@ -34,7 +35,6 @@ import java.util.StringTokenizer;
|
|||
import org.eclipse.jetty.util.ArrayTernaryTrie;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.Trie;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -55,11 +55,12 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
private static final Logger LOG = Log.getLogger(HttpFields.class);
|
||||
|
||||
private final List<HttpField> _fields;
|
||||
private HttpField[] _fields;
|
||||
private int _size;
|
||||
|
||||
public HttpFields()
|
||||
{
|
||||
_fields=new ArrayList<>();
|
||||
_fields=new HttpField[20];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,18 +68,27 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public HttpFields(int capacity)
|
||||
{
|
||||
_fields=new ArrayList<>(capacity);
|
||||
_fields=new HttpField[capacity];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public HttpFields(HttpFields fields)
|
||||
{
|
||||
_fields=Arrays.copyOf(fields._fields,_fields.length+10);
|
||||
_size=fields._size;
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return _fields.size();
|
||||
return _size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<HttpField> iterator()
|
||||
{
|
||||
return _fields.iterator();
|
||||
return new Itr();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +96,7 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public Collection<String> getFieldNamesCollection()
|
||||
{
|
||||
final Set<String> list = new HashSet<>(_fields.size());
|
||||
final Set<String> list = new HashSet<>(_size);
|
||||
for (HttpField f : this)
|
||||
{
|
||||
if (f!=null)
|
||||
|
@ -111,14 +121,16 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public HttpField getField(int i)
|
||||
{
|
||||
return _fields.get(i);
|
||||
if (i>=_size)
|
||||
throw new NoSuchElementException();
|
||||
return _fields[i];
|
||||
}
|
||||
|
||||
public HttpField getField(HttpHeader header)
|
||||
{
|
||||
for (int i=0;i<_fields.size();i++)
|
||||
for (int i=0;i<_size;i++)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getHeader()==header)
|
||||
return f;
|
||||
}
|
||||
|
@ -127,9 +139,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public HttpField getField(String name)
|
||||
{
|
||||
for (int i=0;i<_fields.size();i++)
|
||||
for (int i=0;i<_size;i++)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
return f;
|
||||
}
|
||||
|
@ -138,9 +150,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public boolean contains(HttpField field)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.isSameName(field) && f.contains(field.getValue()))
|
||||
return true;
|
||||
}
|
||||
|
@ -149,9 +161,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public boolean contains(HttpHeader header, String value)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getHeader()==header && f.contains(value))
|
||||
return true;
|
||||
}
|
||||
|
@ -160,9 +172,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public boolean contains(String name, String value)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getName().equalsIgnoreCase(name) && f.contains(value))
|
||||
return true;
|
||||
}
|
||||
|
@ -172,39 +184,35 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public boolean containsKey(String name)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getStringField(HttpHeader header)
|
||||
{
|
||||
return getStringField(header.asString());
|
||||
}
|
||||
|
||||
public String get(HttpHeader header)
|
||||
{
|
||||
return getStringField(header.asString());
|
||||
for (int i=0;i<_size;i++)
|
||||
{
|
||||
HttpField f=_fields[i];
|
||||
if (f.getHeader()==header)
|
||||
return f.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String get(String header)
|
||||
{
|
||||
return getStringField(header);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value of a field, or null if not found. For multiple fields of the same name,
|
||||
* only the first is returned.
|
||||
* @param name the case-insensitive field name
|
||||
*/
|
||||
public String getStringField(String name)
|
||||
{
|
||||
HttpField field = getField(name);
|
||||
return field==null?null:field.getValue();
|
||||
for (int i=0;i<_size;i++)
|
||||
{
|
||||
HttpField f=_fields[i];
|
||||
if (f.getName().equalsIgnoreCase(header))
|
||||
return f.getValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -230,9 +238,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public Enumeration<String> getValues(final String name)
|
||||
{
|
||||
for (int i=0;i<_fields.size();i++)
|
||||
for (int i=0;i<_size;i++)
|
||||
{
|
||||
final HttpField f = _fields.get(i);
|
||||
final HttpField f = _fields[i];
|
||||
|
||||
if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
|
||||
{
|
||||
|
@ -247,9 +255,9 @@ public class HttpFields implements Iterable<HttpField>
|
|||
{
|
||||
if (field==null)
|
||||
{
|
||||
while (i<_fields.size())
|
||||
while (i<_size)
|
||||
{
|
||||
field=_fields.get(i++);
|
||||
field=_fields[i++];
|
||||
if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
|
||||
return true;
|
||||
}
|
||||
|
@ -270,7 +278,6 @@ public class HttpFields implements Iterable<HttpField>
|
|||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -328,22 +335,24 @@ public class HttpFields implements Iterable<HttpField>
|
|||
public void put(HttpField field)
|
||||
{
|
||||
boolean put=false;
|
||||
for (int i=_fields.size();i-->0;)
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.isSameName(field))
|
||||
{
|
||||
if (put)
|
||||
_fields.remove(i);
|
||||
{
|
||||
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fields.set(i,field);
|
||||
_fields[i]=field;
|
||||
put=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!put)
|
||||
_fields.add(field);
|
||||
add(field);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -408,7 +417,7 @@ public class HttpFields implements Iterable<HttpField>
|
|||
return;
|
||||
|
||||
HttpField field = new HttpField(name, value);
|
||||
_fields.add(field);
|
||||
add(field);
|
||||
}
|
||||
|
||||
public void add(HttpHeader header, HttpHeaderValue value) throws IllegalArgumentException
|
||||
|
@ -429,7 +438,7 @@ public class HttpFields implements Iterable<HttpField>
|
|||
if (value == null) throw new IllegalArgumentException("null value");
|
||||
|
||||
HttpField field = new HttpField(header, value);
|
||||
_fields.add(field);
|
||||
add(field);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -439,13 +448,17 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public HttpField remove(HttpHeader name)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
HttpField removed=null;
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getHeader()==name)
|
||||
return _fields.remove(i);
|
||||
{
|
||||
removed=f;
|
||||
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -455,13 +468,17 @@ public class HttpFields implements Iterable<HttpField>
|
|||
*/
|
||||
public HttpField remove(String name)
|
||||
{
|
||||
for (int i=_fields.size();i-->0;)
|
||||
HttpField removed=null;
|
||||
for (int i=_size;i-->0;)
|
||||
{
|
||||
HttpField f=_fields.get(i);
|
||||
HttpField f=_fields[i];
|
||||
if (f.getName().equalsIgnoreCase(name))
|
||||
return _fields.remove(i);
|
||||
{
|
||||
removed=f;
|
||||
System.arraycopy(_fields,i+1,_fields,i,--_size-i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -584,10 +601,14 @@ public class HttpFields implements Iterable<HttpField>
|
|||
if (size() != that.size())
|
||||
return false;
|
||||
|
||||
for (HttpField field : this)
|
||||
loop: for (HttpField fi : this)
|
||||
{
|
||||
if (!that.contains(field))
|
||||
return false;
|
||||
for (HttpField fa : that)
|
||||
{
|
||||
if (fi.equals(fa))
|
||||
continue loop;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -622,17 +643,20 @@ public class HttpFields implements Iterable<HttpField>
|
|||
|
||||
public void clear()
|
||||
{
|
||||
_fields.clear();
|
||||
_size=0;
|
||||
}
|
||||
|
||||
public void add(HttpField field)
|
||||
{
|
||||
_fields.add(field);
|
||||
if (_size==_fields.length)
|
||||
_fields=Arrays.copyOf(_fields,_size*2);
|
||||
_fields[_size++]=field;
|
||||
}
|
||||
|
||||
public void addAll(HttpFields fields)
|
||||
{
|
||||
_fields.addAll(fields._fields);
|
||||
for (int i=0;i<fields._size;i++)
|
||||
add(fields._fields[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -808,5 +832,34 @@ public class HttpFields implements Iterable<HttpField>
|
|||
}
|
||||
|
||||
|
||||
private class Itr implements Iterator<HttpField>
|
||||
{
|
||||
int _cursor; // index of next element to return
|
||||
int _last=-1;
|
||||
|
||||
public boolean hasNext()
|
||||
{
|
||||
return _cursor != _size;
|
||||
}
|
||||
|
||||
public HttpField next()
|
||||
{
|
||||
int i = _cursor;
|
||||
if (i >= _size)
|
||||
throw new NoSuchElementException();
|
||||
_cursor = i + 1;
|
||||
return _fields[_last=i];
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
if (_last<0)
|
||||
throw new IllegalStateException();
|
||||
|
||||
System.arraycopy(_fields,_last+1,_fields,_last,--_size-_last);
|
||||
_cursor=_last;
|
||||
_last=-1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ package org.eclipse.jetty.http;
|
|||
import java.io.IOException;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jetty.http.HttpTokens.EndOfContent;
|
||||
|
@ -1058,9 +1057,9 @@ public class HttpGenerator
|
|||
|
||||
public static void putTo(HttpField field, ByteBuffer bufferInFillMode)
|
||||
{
|
||||
if (field instanceof CachedHttpField)
|
||||
if (field instanceof PreEncodedHttpField)
|
||||
{
|
||||
((CachedHttpField)field).putTo(bufferInFillMode);
|
||||
((PreEncodedHttpField)field).putTo(bufferInFillMode,HttpVersion.HTTP_1_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1090,23 +1089,4 @@ public class HttpGenerator
|
|||
}
|
||||
BufferUtil.putCRLF(bufferInFillMode);
|
||||
}
|
||||
|
||||
public static class CachedHttpField extends HttpField
|
||||
{
|
||||
private final byte[] _bytes;
|
||||
public CachedHttpField(HttpHeader header,String value)
|
||||
{
|
||||
super(header,value);
|
||||
int cbl=header.getBytesColonSpace().length;
|
||||
_bytes=Arrays.copyOf(header.getBytesColonSpace(), cbl+value.length()+2);
|
||||
System.arraycopy(value.getBytes(StandardCharsets.ISO_8859_1),0,_bytes,cbl,value.length());
|
||||
_bytes[_bytes.length-2]=(byte)'\r';
|
||||
_bytes[_bytes.length-1]=(byte)'\n';
|
||||
}
|
||||
|
||||
public void putTo(ByteBuffer bufferInFillMode)
|
||||
{
|
||||
bufferInFillMode.put(_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,15 +183,15 @@ public class HttpParser
|
|||
// Add common Content types as fields
|
||||
for (String type : new String[]{"text/plain","text/html","text/xml","text/json","application/json","application/x-www-form-urlencoded"})
|
||||
{
|
||||
HttpField field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type);
|
||||
HttpField field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type);
|
||||
CACHE.put(field);
|
||||
|
||||
for (String charset : new String[]{"utf-8","iso-8859-1"})
|
||||
{
|
||||
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
|
||||
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
|
||||
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase()));
|
||||
CACHE.put(new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset.toUpperCase()));
|
||||
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
|
||||
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset));
|
||||
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset.toUpperCase()));
|
||||
CACHE.put(new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,type+"; charset="+charset.toUpperCase()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public class MimeTypes
|
|||
_charset=null;
|
||||
_charsetString=null;
|
||||
_assumedCharset=false;
|
||||
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -103,7 +103,7 @@ public class MimeTypes
|
|||
_charset=Charset.forName(s.substring(i+9));
|
||||
_charsetString=_charset==null?null:_charset.toString().toLowerCase();
|
||||
_assumedCharset=false;
|
||||
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -115,7 +115,7 @@ public class MimeTypes
|
|||
_charset=cs;
|
||||
_charsetString=_charset==null?null:_charset.toString().toLowerCase();
|
||||
_assumedCharset=true;
|
||||
_field=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
_field=new PreEncodedHttpField(HttpHeader.CONTENT_TYPE,_string);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.http.Http1FieldPreEncoder
|
|
@ -22,6 +22,9 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -135,4 +138,17 @@ public class HttpFieldTest
|
|||
assertEquals("c",values[2]);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCachedField()
|
||||
{
|
||||
PreEncodedHttpField field = new PreEncodedHttpField(HttpHeader.ACCEPT,"something");
|
||||
ByteBuffer buf = BufferUtil.allocate(256);
|
||||
BufferUtil.clearToFill(buf);
|
||||
field.putTo(buf,HttpVersion.HTTP_1_0);
|
||||
BufferUtil.flipToFlush(buf,0);
|
||||
String s=BufferUtil.toString(buf);
|
||||
|
||||
assertEquals("Accept: something\r\n",s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
@ -48,9 +48,10 @@ public class HttpFieldsTest
|
|||
header.put("name0", "value:0");
|
||||
header.put("name1", "value1");
|
||||
|
||||
assertEquals("value:0",header.getStringField("name0"));
|
||||
assertEquals("value1",header.getStringField("name1"));
|
||||
assertNull(header.getStringField("name2"));
|
||||
assertEquals(2,header.size());
|
||||
assertEquals("value:0",header.get("name0"));
|
||||
assertEquals("value1",header.get("name1"));
|
||||
assertNull(header.get("name2"));
|
||||
|
||||
int matches=0;
|
||||
Enumeration<String> e = header.getFieldNames();
|
||||
|
@ -68,6 +69,7 @@ public class HttpFieldsTest
|
|||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value:0");
|
||||
assertEquals(false, e.hasMoreElements());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -99,10 +101,45 @@ public class HttpFieldsTest
|
|||
header.put("name0", "value0");
|
||||
header.put("name1", "value1");
|
||||
|
||||
assertEquals("value0",header.getStringField("name0"));
|
||||
assertEquals("value0",header.getStringField("Name0"));
|
||||
assertEquals("value1",header.getStringField("name1"));
|
||||
assertEquals("value1",header.getStringField("Name1"));
|
||||
assertEquals("value0",header.get("name0"));
|
||||
assertEquals("value0",header.get("Name0"));
|
||||
assertEquals("value1",header.get("name1"));
|
||||
assertEquals("value1",header.get("Name1"));
|
||||
assertEquals(null,header.get("Name2"));
|
||||
|
||||
assertEquals("value0",header.getField("name0").getValue());
|
||||
assertEquals("value0",header.getField("Name0").getValue());
|
||||
assertEquals("value1",header.getField("name1").getValue());
|
||||
assertEquals("value1",header.getField("Name1").getValue());
|
||||
assertEquals(null,header.getField("Name2"));
|
||||
|
||||
assertEquals("value0",header.getField(0).getValue());
|
||||
assertEquals("value1",header.getField(1).getValue());
|
||||
try
|
||||
{
|
||||
header.getField(2);
|
||||
Assert.fail();
|
||||
}
|
||||
catch(NoSuchElementException e)
|
||||
{}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKnown() throws Exception
|
||||
{
|
||||
HttpFields header = new HttpFields();
|
||||
|
||||
header.put("Connection", "value0");
|
||||
header.put(HttpHeader.ACCEPT, "value1");
|
||||
|
||||
assertEquals("value0",header.get(HttpHeader.CONNECTION));
|
||||
assertEquals("value1",header.get(HttpHeader.ACCEPT));
|
||||
|
||||
assertEquals("value0",header.getField(HttpHeader.CONNECTION).getValue());
|
||||
assertEquals("value1",header.getField(HttpHeader.ACCEPT).getValue());
|
||||
|
||||
assertEquals(null,header.getField(HttpHeader.AGE));
|
||||
assertEquals(null,header.get(HttpHeader.AGE));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -153,16 +190,16 @@ public class HttpFieldsTest
|
|||
header.put("name1", "xxxxxx");
|
||||
header.put("name2", "value2");
|
||||
|
||||
assertEquals("value0",header.getStringField("name0"));
|
||||
assertEquals("xxxxxx",header.getStringField("name1"));
|
||||
assertEquals("value2",header.getStringField("name2"));
|
||||
assertEquals("value0",header.get("name0"));
|
||||
assertEquals("xxxxxx",header.get("name1"));
|
||||
assertEquals("value2",header.get("name2"));
|
||||
|
||||
header.put("name1", "value1");
|
||||
|
||||
assertEquals("value0",header.getStringField("name0"));
|
||||
assertEquals("value1",header.getStringField("name1"));
|
||||
assertEquals("value2",header.getStringField("name2"));
|
||||
assertNull(header.getStringField("name3"));
|
||||
assertEquals("value0",header.get("name0"));
|
||||
assertEquals("value1",header.get("name1"));
|
||||
assertEquals("value2",header.get("name2"));
|
||||
assertNull(header.get("name3"));
|
||||
|
||||
int matches=0;
|
||||
Enumeration<String> e = header.getFieldNames();
|
||||
|
@ -188,22 +225,22 @@ public class HttpFieldsTest
|
|||
@Test
|
||||
public void testRemovePut() throws Exception
|
||||
{
|
||||
HttpFields header = new HttpFields();
|
||||
HttpFields header = new HttpFields(1);
|
||||
|
||||
header.put("name0", "value0");
|
||||
header.put("name1", "value1");
|
||||
header.put("name2", "value2");
|
||||
|
||||
assertEquals("value0",header.getStringField("name0"));
|
||||
assertEquals("value1",header.getStringField("name1"));
|
||||
assertEquals("value2",header.getStringField("name2"));
|
||||
assertEquals("value0",header.get("name0"));
|
||||
assertEquals("value1",header.get("name1"));
|
||||
assertEquals("value2",header.get("name2"));
|
||||
|
||||
header.remove("name1");
|
||||
|
||||
assertEquals("value0",header.getStringField("name0"));
|
||||
assertNull(header.getStringField("name1"));
|
||||
assertEquals("value2",header.getStringField("name2"));
|
||||
assertNull(header.getStringField("name3"));
|
||||
assertEquals("value0",header.get("name0"));
|
||||
assertNull(header.get("name1"));
|
||||
assertEquals("value2",header.get("name2"));
|
||||
assertNull(header.get("name3"));
|
||||
|
||||
int matches=0;
|
||||
Enumeration<String> e = header.getFieldNames();
|
||||
|
@ -232,16 +269,16 @@ public class HttpFieldsTest
|
|||
fields.add("name1", "valueA");
|
||||
fields.add("name2", "value2");
|
||||
|
||||
assertEquals("value0",fields.getStringField("name0"));
|
||||
assertEquals("valueA",fields.getStringField("name1"));
|
||||
assertEquals("value2",fields.getStringField("name2"));
|
||||
assertEquals("value0",fields.get("name0"));
|
||||
assertEquals("valueA",fields.get("name1"));
|
||||
assertEquals("value2",fields.get("name2"));
|
||||
|
||||
fields.add("name1", "valueB");
|
||||
|
||||
assertEquals("value0",fields.getStringField("name0"));
|
||||
assertEquals("valueA",fields.getStringField("name1"));
|
||||
assertEquals("value2",fields.getStringField("name2"));
|
||||
assertNull(fields.getStringField("name3"));
|
||||
assertEquals("value0",fields.get("name0"));
|
||||
assertEquals("valueA",fields.get("name1"));
|
||||
assertEquals("value2",fields.get("name2"));
|
||||
assertNull(fields.get("name3"));
|
||||
|
||||
int matches=0;
|
||||
Enumeration<String> e = fields.getFieldNames();
|
||||
|
@ -304,9 +341,29 @@ public class HttpFieldsTest
|
|||
assertEquals(true, e.hasMoreElements());
|
||||
assertEquals(e.nextElement(), "value1D");
|
||||
assertEquals(false, e.hasMoreElements());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetQualityValues() throws Exception
|
||||
{
|
||||
HttpFields fields = new HttpFields();
|
||||
|
||||
fields.put("some", "value");
|
||||
fields.add("name", "zero;q=0.9,four;q=0.1");
|
||||
fields.put("other", "value");
|
||||
fields.add("name", "nothing;q=0");
|
||||
fields.add("name", "one;q=0.4");
|
||||
fields.add("name", "three;x=y;q=0.2;a=b,two;q=0.3");
|
||||
|
||||
List<String> list = HttpFields.qualityList(fields.getValues("name",","));
|
||||
assertEquals("zero",HttpFields.valueParameters(list.get(0),null));
|
||||
assertEquals("one",HttpFields.valueParameters(list.get(1),null));
|
||||
assertEquals("two",HttpFields.valueParameters(list.get(2),null));
|
||||
assertEquals("three",HttpFields.valueParameters(list.get(3),null));
|
||||
assertEquals("four",HttpFields.valueParameters(list.get(4),null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateFields() throws Exception
|
||||
{
|
||||
|
@ -346,7 +403,7 @@ public class HttpFieldsTest
|
|||
assertEquals(951825600000L,d5);
|
||||
|
||||
fields.putDateField("D2",d1);
|
||||
assertEquals("Fri, 31 Dec 1999 23:59:59 GMT",fields.getStringField("D2"));
|
||||
assertEquals("Fri, 31 Dec 1999 23:59:59 GMT",fields.get("D2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -355,16 +412,16 @@ public class HttpFieldsTest
|
|||
HttpFields fields = new HttpFields();
|
||||
|
||||
fields.putDateField("Dzero",0);
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Dzero"));
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.get("Dzero"));
|
||||
|
||||
fields.putDateField("Dminus",-1);
|
||||
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus"));
|
||||
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.get("Dminus"));
|
||||
|
||||
fields.putDateField("Dminus",-1000);
|
||||
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.getStringField("Dminus"));
|
||||
assertEquals("Wed, 31 Dec 1969 23:59:59 GMT",fields.get("Dminus"));
|
||||
|
||||
fields.putDateField("Dancient",Long.MIN_VALUE);
|
||||
assertEquals("Sun, 02 Dec 55 16:47:04 GMT",fields.getStringField("Dancient"));
|
||||
assertEquals("Sun, 02 Dec 55 16:47:04 GMT",fields.get("Dancient"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -374,15 +431,33 @@ public class HttpFieldsTest
|
|||
|
||||
header.put("I1", "42");
|
||||
header.put("I2", " 43 99");
|
||||
header.put("I3", "-44;");
|
||||
header.put("I3", "-44");
|
||||
header.put("I4", " - 45abc");
|
||||
header.put("N1", " - ");
|
||||
header.put("N2", "xx");
|
||||
|
||||
long i1=header.getLongField("I1");
|
||||
long i2=header.getLongField("I2");
|
||||
try
|
||||
{
|
||||
header.getLongField("I2");
|
||||
assertTrue(false);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
long i3=header.getLongField("I3");
|
||||
long i4=header.getLongField("I4");
|
||||
|
||||
try
|
||||
{
|
||||
header.getLongField("I4");
|
||||
assertTrue(false);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
try{
|
||||
header.getLongField("N1");
|
||||
|
@ -403,14 +478,12 @@ public class HttpFieldsTest
|
|||
}
|
||||
|
||||
assertEquals(42,i1);
|
||||
assertEquals(43,i2);
|
||||
assertEquals(-44,i3);
|
||||
assertEquals(-45,i4);
|
||||
|
||||
header.putLongField("I5", 46);
|
||||
header.putLongField("I6",-47);
|
||||
assertEquals("46",header.getStringField("I5"));
|
||||
assertEquals("-47",header.getStringField("I6"));
|
||||
assertEquals("46",header.get("I5"));
|
||||
assertEquals("-47",header.get("I6"));
|
||||
|
||||
}
|
||||
|
||||
|
@ -429,12 +502,28 @@ public class HttpFieldsTest
|
|||
header.add("n6", "def");
|
||||
header.add("N6", "hig");
|
||||
header.add("n7", "abc , def;q=0.9 , hig");
|
||||
header.add("n8", "abc , def;q=0 , hig");
|
||||
header.add(HttpHeader.ACCEPT, "abc , def;q=0 , hig");
|
||||
|
||||
for (int i=0;i<8;i++)
|
||||
{
|
||||
assertTrue(header.containsKey("n"+i));
|
||||
assertTrue(header.containsKey("N"+i));
|
||||
assertFalse(""+i,header.contains("n"+i,"xyz"));
|
||||
assertEquals(""+i,i>=4,header.contains("n"+i,"def"));
|
||||
}
|
||||
|
||||
|
||||
assertTrue(header.contains(new HttpField("N5","def")));
|
||||
assertTrue(header.contains(new HttpField("accept","abc")));
|
||||
assertTrue(header.contains(HttpHeader.ACCEPT,"abc"));
|
||||
assertFalse(header.contains(new HttpField("N5","xyz")));
|
||||
assertFalse(header.contains(new HttpField("N8","def")));
|
||||
assertFalse(header.contains(HttpHeader.ACCEPT,"def"));
|
||||
assertFalse(header.contains(HttpHeader.AGE,"abc"));
|
||||
|
||||
assertFalse(header.containsKey("n11"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.util.ArrayQueue;
|
||||
import org.eclipse.jetty.util.ArrayTernaryTrie;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -119,20 +118,20 @@ public class HpackContext
|
|||
switch(i)
|
||||
{
|
||||
case 2:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.GET));
|
||||
break;
|
||||
case 3:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.POST));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpMethod.POST));
|
||||
break;
|
||||
case 6:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTP));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTP));
|
||||
break;
|
||||
case 7:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],HttpScheme.HTTPS));
|
||||
break;
|
||||
case 8:
|
||||
case 11:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
break;
|
||||
|
||||
case 9:
|
||||
|
@ -140,7 +139,7 @@ public class HpackContext
|
|||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
entry=new StaticEntry(i,new StaticValueHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
entry=new StaticEntry(i,new StaticTableHttpField(STATIC_TABLE[i][0],STATIC_TABLE[i][1],Integer.valueOf(STATIC_TABLE[i][1])));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -231,6 +230,11 @@ public class HpackContext
|
|||
return get(header.asString());
|
||||
return e;
|
||||
}
|
||||
|
||||
public static Entry getStatic(HttpHeader header)
|
||||
{
|
||||
return __headerEntryTable[header.ordinal()];
|
||||
}
|
||||
|
||||
public Entry add(HttpField field)
|
||||
{
|
||||
|
@ -420,6 +424,11 @@ public class HpackContext
|
|||
return null;
|
||||
}
|
||||
|
||||
public int getSlot()
|
||||
{
|
||||
return _slot;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("{%s,%d,%s,%x}",isStatic()?"S":"D",_slot,_field,hashCode());
|
||||
|
@ -429,6 +438,7 @@ public class HpackContext
|
|||
public static class StaticEntry extends Entry
|
||||
{
|
||||
private final byte[] _huffmanValue;
|
||||
private final byte _encodedField;
|
||||
|
||||
StaticEntry(int index,HttpField field)
|
||||
{
|
||||
|
@ -450,6 +460,8 @@ public class HpackContext
|
|||
}
|
||||
else
|
||||
_huffmanValue=null;
|
||||
|
||||
_encodedField=(byte)(0x80|index);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -463,6 +475,11 @@ public class HpackContext
|
|||
{
|
||||
return _huffmanValue;
|
||||
}
|
||||
|
||||
public byte getEncodedField()
|
||||
{
|
||||
return _encodedField;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ import java.nio.ByteBuffer;
|
|||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
|
@ -41,7 +39,8 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class HpackDecoder
|
||||
{
|
||||
public static final Logger LOG = Log.getLogger(HpackDecoder.class);
|
||||
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 = new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
|
||||
public final static HttpField.LongValueHttpField CONTENT_LENGTH_0 =
|
||||
new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,0L);
|
||||
|
||||
private final HpackContext _context;
|
||||
private final MetaDataBuilder _builder;
|
||||
|
@ -191,46 +190,31 @@ public class HpackDecoder
|
|||
HttpField field;
|
||||
if (header==null)
|
||||
{
|
||||
// just make a normal field and bypass header name lookup
|
||||
field = new HttpField(null,name,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// might be worthwhile to create a value HttpField if it is indexed
|
||||
// and/or of a type that may be looked up multiple times.
|
||||
switch(header)
|
||||
{
|
||||
case C_METHOD:
|
||||
HttpMethod method=HttpMethod.CACHE.get(value);
|
||||
if (method!=null)
|
||||
field = new StaticValueHttpField(HttpHeader.C_METHOD,method.asString(),method);
|
||||
else
|
||||
field = new AuthorityHttpField(value);
|
||||
break;
|
||||
|
||||
case C_STATUS:
|
||||
Integer code = Integer.valueOf(value);
|
||||
field = new StaticValueHttpField(HttpHeader.C_STATUS,value,code);
|
||||
break;
|
||||
|
||||
case C_SCHEME:
|
||||
HttpScheme scheme=HttpScheme.CACHE.get(value);
|
||||
if (scheme!=null)
|
||||
field = new StaticValueHttpField(HttpHeader.C_SCHEME,scheme.asString(),scheme);
|
||||
if (indexed)
|
||||
field = new HttpField.IntValueHttpField(header,name,value);
|
||||
else
|
||||
field = new AuthorityHttpField(value);
|
||||
field = new HttpField(header,name,value);
|
||||
break;
|
||||
|
||||
case C_AUTHORITY:
|
||||
field = new AuthorityHttpField(value);
|
||||
break;
|
||||
|
||||
case C_PATH:
|
||||
field = new HttpField(HttpHeader.C_PATH,value);
|
||||
break;
|
||||
|
||||
case CONTENT_LENGTH:
|
||||
if ("0".equals(value))
|
||||
field = CONTENT_LENGTH_0;
|
||||
else
|
||||
field = new HttpField.LongValueHttpField(header,value);
|
||||
field = new HttpField.LongValueHttpField(header,name,value);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -26,8 +26,11 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.StaticEntry;
|
||||
import org.eclipse.jetty.io.ByteBufferPool.Lease;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
|
@ -78,6 +81,7 @@ public class HpackEncoder
|
|||
}
|
||||
|
||||
private final HpackContext _context;
|
||||
private final boolean _debug;
|
||||
private int _remoteMaxHeaderTableSize;
|
||||
private int _localMaxHeaderTableSize;
|
||||
|
||||
|
@ -96,6 +100,7 @@ public class HpackEncoder
|
|||
_context=new HpackContext(remoteMaxHeaderTableSize);
|
||||
_remoteMaxHeaderTableSize=remoteMaxHeaderTableSize;
|
||||
_localMaxHeaderTableSize=localMaxHeaderTableSize;
|
||||
_debug=LOG.isDebugEnabled();
|
||||
}
|
||||
|
||||
public HpackContext getContext()
|
||||
|
@ -154,15 +159,13 @@ public class HpackEncoder
|
|||
int code=response.getStatus();
|
||||
HttpField status = code<__status.length?__status[code]:null;
|
||||
if (status==null)
|
||||
status=new HttpField(HttpHeader.C_STATUS,Integer.toString(code));
|
||||
status=new HttpField.IntValueHttpField(HttpHeader.C_STATUS,code);
|
||||
encode(buffer,status);
|
||||
}
|
||||
|
||||
// Add all the other fields
|
||||
for (HttpField field : metadata)
|
||||
{
|
||||
encode(buffer,field);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug(String.format("CtxTbl[%x] encoded %d octets",_context.hashCode(), buffer.position() - pos));
|
||||
|
@ -179,38 +182,45 @@ public class HpackEncoder
|
|||
|
||||
private void encode(ByteBuffer buffer, HttpField field)
|
||||
{
|
||||
final int p=LOG.isDebugEnabled()?buffer.position():-1;
|
||||
final int p=_debug?buffer.position():-1;
|
||||
|
||||
String encoding=null;
|
||||
|
||||
// TODO currently we do not check if there is enough space, so we may fail nastily.
|
||||
|
||||
// Is there an entry for the field?
|
||||
Entry entry = _context.get(field);
|
||||
if (entry!=null)
|
||||
{
|
||||
// Known field entry, so encode it as indexed
|
||||
int index=_context.index(entry);
|
||||
if (p>=0)
|
||||
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,index);
|
||||
if (entry.isStatic())
|
||||
{
|
||||
buffer.put(((StaticEntry)entry).getEncodedField());
|
||||
if (_debug)
|
||||
encoding="IdxFieldS1";
|
||||
}
|
||||
else
|
||||
{
|
||||
int index=_context.index(entry);
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,index);
|
||||
if (_debug)
|
||||
encoding="IdxField"+(entry.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(7,index));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown field entry, so we will have to send literally.
|
||||
|
||||
final Entry name;
|
||||
final boolean indexed;
|
||||
final boolean never_index;
|
||||
final boolean huffman;
|
||||
final int bits;
|
||||
|
||||
|
||||
// But do we know it's name?
|
||||
HttpHeader header = field.getHeader();
|
||||
|
||||
// Select encoding strategy
|
||||
if (header==null)
|
||||
{
|
||||
name = _context.get(field.getName());
|
||||
// Select encoding strategy for unknown header names
|
||||
Entry name = _context.get(field.getName());
|
||||
|
||||
// has the custom header name been seen before?
|
||||
if (name==null)
|
||||
{
|
||||
|
@ -218,95 +228,71 @@ public class HpackEncoder
|
|||
// the first time we have seen a custom name or a custom field.
|
||||
// unless the name is changing, this is worthwhile
|
||||
indexed=true;
|
||||
never_index=false;
|
||||
huffman=true;
|
||||
bits = 6;
|
||||
buffer.put((byte)0x40);
|
||||
encodeName(buffer,(byte)0x40,6,field.getName(),null);
|
||||
encodeValue(buffer,true,field.getValue());
|
||||
if (_debug)
|
||||
encoding="LitHuffNHuffVIdx";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// known custom name, but unknown value.
|
||||
// This is probably a custom field with changing value, so don't index now.
|
||||
// This is probably a custom field with changing value, so don't index.
|
||||
indexed=false;
|
||||
never_index=false;
|
||||
huffman=true;
|
||||
bits = 4;
|
||||
buffer.put((byte)0x00);
|
||||
encodeName(buffer,(byte)0x00,4,field.getName(),null);
|
||||
encodeValue(buffer,true,field.getValue());
|
||||
if (_debug)
|
||||
encoding="LitHuffNHuffV!Idx";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
name = _context.get(header);
|
||||
// Select encoding strategy for known header names
|
||||
Entry name = _context.get(header);
|
||||
|
||||
if (__DO_NOT_INDEX.contains(header))
|
||||
{
|
||||
// Non indexed field
|
||||
indexed=false;
|
||||
never_index=__NEVER_INDEX.contains(header);
|
||||
huffman=!__DO_NOT_HUFFMAN.contains(header);
|
||||
bits = 4;
|
||||
buffer.put(never_index?(byte)0x10:(byte)0x00);
|
||||
boolean never_index=__NEVER_INDEX.contains(header);
|
||||
boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
|
||||
encodeName(buffer,never_index?(byte)0x10:(byte)0x00,4,header.asString(),name);
|
||||
encodeValue(buffer,huffman,field.getValue());
|
||||
|
||||
if (_debug)
|
||||
encoding="Lit"+
|
||||
((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(4,_context.index(name)))))+
|
||||
(huffman?"HuffV":"LitV")+
|
||||
(indexed?"Idx":(never_index?"!!Idx":"!Idx"));
|
||||
}
|
||||
else if (header==HttpHeader.CONTENT_LENGTH && field.getValue().length()>1)
|
||||
{
|
||||
// Non indexed content length for non zero value
|
||||
indexed=false;
|
||||
never_index=false;
|
||||
huffman=true;
|
||||
bits = 4;
|
||||
buffer.put((byte)0x00);
|
||||
encodeName(buffer,(byte)0x00,4,header.asString(),name);
|
||||
encodeValue(buffer,true,field.getValue());
|
||||
if (_debug)
|
||||
encoding="LitIdxNS"+(1+NBitInteger.octectsNeeded(4,_context.index(name)))+"HuffV!Idx";
|
||||
}
|
||||
else if (field instanceof PreEncodedHttpField)
|
||||
{
|
||||
// Preencoded field
|
||||
indexed=true;
|
||||
((PreEncodedHttpField)field).putTo(buffer,HttpVersion.HTTP_2);
|
||||
if (_debug)
|
||||
encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
|
||||
"HuffVIdx";
|
||||
}
|
||||
else
|
||||
{
|
||||
// indexed
|
||||
indexed=true;
|
||||
never_index=false;
|
||||
huffman=!__DO_NOT_HUFFMAN.contains(header);
|
||||
bits = 6;
|
||||
buffer.put((byte)0x40);
|
||||
}
|
||||
}
|
||||
|
||||
if (p>=0)
|
||||
{
|
||||
encoding="Lit"+
|
||||
((name==null)?"HuffN":("IdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(bits,_context.index(name)))))+
|
||||
(huffman?"HuffV":"LitV")+
|
||||
(indexed?"Idx":(never_index?"!!Idx":"!Idx"));
|
||||
}
|
||||
|
||||
if (name!=null)
|
||||
NBitInteger.encode(buffer,bits,_context.index(name));
|
||||
else
|
||||
{
|
||||
// leave name index bits as 0
|
||||
// Encode the name always with lowercase huffman
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(field.getName()));
|
||||
Huffman.encodeLC(buffer,field.getName());
|
||||
}
|
||||
|
||||
// Add the literal value
|
||||
String value=field.getValue();
|
||||
|
||||
if (huffman)
|
||||
{
|
||||
// huffman literal value
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
|
||||
Huffman.encode(buffer,field.getValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
// add literal assuming iso_8859_1
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer,7,value.length());
|
||||
for (int i=0;i<value.length();i++)
|
||||
{
|
||||
char c=value.charAt(i);
|
||||
if (c<' '|| c>127)
|
||||
throw new IllegalArgumentException();
|
||||
buffer.put((byte)c);
|
||||
boolean huffman=!__DO_NOT_HUFFMAN.contains(header);
|
||||
encodeName(buffer,(byte)0x40,6,header.asString(),name);
|
||||
encodeValue(buffer,huffman,field.getValue());
|
||||
if (_debug)
|
||||
encoding=((name==null)?"LitHuffN":("LitIdxN"+(name.isStatic()?"S":"")+(1+NBitInteger.octectsNeeded(6,_context.index(name)))))+
|
||||
(huffman?"HuffVIdx":"LitVIdx");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,11 +302,52 @@ public class HpackEncoder
|
|||
_context.add(field);
|
||||
}
|
||||
|
||||
if (p>=0)
|
||||
if (_debug)
|
||||
{
|
||||
int e=buffer.position();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("encode {}:'{}' to '{}'",encoding,field,TypeUtil.toHexString(buffer.array(),buffer.arrayOffset()+p,e-p));
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeName(ByteBuffer buffer, byte mask, int bits, String name, Entry entry)
|
||||
{
|
||||
buffer.put(mask);
|
||||
if (entry==null)
|
||||
{
|
||||
// leave name index bits as 0
|
||||
// Encode the name always with lowercase huffman
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,Huffman.octetsNeededLC(name));
|
||||
Huffman.encodeLC(buffer,name);
|
||||
}
|
||||
else
|
||||
{
|
||||
NBitInteger.encode(buffer,bits,_context.index(entry));
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeValue(ByteBuffer buffer, boolean huffman, String value)
|
||||
{
|
||||
if (huffman)
|
||||
{
|
||||
// huffman literal value
|
||||
buffer.put((byte)0x80);
|
||||
NBitInteger.encode(buffer,7,Huffman.octetsNeeded(value));
|
||||
Huffman.encode(buffer,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add literal assuming iso_8859_1
|
||||
buffer.put((byte)0x00);
|
||||
NBitInteger.encode(buffer,7,value.length());
|
||||
for (int i=0;i<value.length();i++)
|
||||
{
|
||||
char c=value.charAt(i);
|
||||
if (c<' '|| c>127)
|
||||
throw new IllegalArgumentException();
|
||||
buffer.put((byte)c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -72,9 +72,9 @@ public class MetaDataBuilder
|
|||
if (_size>_maxSize)
|
||||
throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413,"Header size "+_size+">"+_maxSize);
|
||||
|
||||
if (field instanceof StaticValueHttpField)
|
||||
if (field instanceof StaticTableHttpField)
|
||||
{
|
||||
StaticValueHttpField value = (StaticValueHttpField)field;
|
||||
StaticTableHttpField value = (StaticTableHttpField)field;
|
||||
switch(field.getHeader())
|
||||
{
|
||||
case C_STATUS:
|
||||
|
@ -98,7 +98,7 @@ public class MetaDataBuilder
|
|||
switch(field.getHeader())
|
||||
{
|
||||
case C_STATUS:
|
||||
_status=Integer.parseInt(field.getValue());
|
||||
_status=field.getIntValue();
|
||||
break;
|
||||
|
||||
case C_METHOD:
|
||||
|
@ -114,6 +114,7 @@ public class MetaDataBuilder
|
|||
break;
|
||||
|
||||
case HOST:
|
||||
// :authority fields must come first. If we have one, ignore the host header as far as authority goes.
|
||||
if (_authority==null)
|
||||
_authority=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue());
|
||||
_fields.add(field);
|
||||
|
|
|
@ -23,19 +23,11 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpHeader;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public class StaticValueHttpField extends HttpField
|
||||
public class StaticTableHttpField extends HttpField
|
||||
{
|
||||
private final Object _value;
|
||||
|
||||
public StaticValueHttpField(HttpHeader header,String name, String valueString, Object value)
|
||||
{
|
||||
super(header,name,valueString);
|
||||
if (value==null)
|
||||
throw new IllegalArgumentException();
|
||||
_value=value;
|
||||
}
|
||||
|
||||
public StaticValueHttpField(HttpHeader header,String valueString, Object value)
|
||||
public StaticTableHttpField(HttpHeader header,String valueString, Object value)
|
||||
{
|
||||
super(header,header.asString(),valueString);
|
||||
if (value==null)
|
||||
|
@ -43,7 +35,7 @@ public class StaticValueHttpField extends HttpField
|
|||
_value=value;
|
||||
}
|
||||
|
||||
public StaticValueHttpField(String name, String valueString, Object value)
|
||||
public StaticTableHttpField(String name, String valueString, Object value)
|
||||
{
|
||||
super(name,valueString);
|
||||
if (value==null)
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.jetty.http2.hpack.HpackFieldPreEncoder
|
|
@ -24,12 +24,8 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.eclipse.jetty.http.HttpField;
|
|||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
|
|
@ -23,13 +23,11 @@ package org.eclipse.jetty.http2.hpack;
|
|||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
|
|
@ -24,12 +24,15 @@ import static org.junit.Assert.assertEquals;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.DateGenerator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http.MetaData.Response;
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -37,6 +40,10 @@ import org.junit.Test;
|
|||
|
||||
public class HpackTest
|
||||
{
|
||||
final static HttpField ServerJetty = new PreEncodedHttpField(HttpHeader.SERVER,"jetty");
|
||||
final static HttpField XPowerJetty = new PreEncodedHttpField(HttpHeader.X_POWERED_BY,"jetty");
|
||||
final static HttpField Date = new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(System.currentTimeMillis()));
|
||||
|
||||
@Test
|
||||
public void encodeDecodeResponseTest()
|
||||
{
|
||||
|
@ -47,7 +54,9 @@ public class HpackTest
|
|||
HttpFields fields0 = new HttpFields();
|
||||
fields0.add(HttpHeader.CONTENT_TYPE,"text/html");
|
||||
fields0.add(HttpHeader.CONTENT_LENGTH,"1024");
|
||||
fields0.add(HttpHeader.SERVER,"jetty");
|
||||
fields0.add(ServerJetty);
|
||||
fields0.add(XPowerJetty);
|
||||
fields0.add(Date);
|
||||
fields0.add(HttpHeader.SET_COOKIE,"abcdefghijklmnopqrstuvwxyz");
|
||||
fields0.add("custom-key","custom-value");
|
||||
Response original0 = new MetaData.Response(HttpVersion.HTTP_2,200,fields0);
|
||||
|
@ -70,7 +79,9 @@ public class HpackTest
|
|||
HttpFields fields1 = new HttpFields();
|
||||
fields1.add(HttpHeader.CONTENT_TYPE,"text/plain");
|
||||
fields1.add(HttpHeader.CONTENT_LENGTH,"1234");
|
||||
fields1.add(HttpHeader.SERVER,"jetty");
|
||||
fields1.add(ServerJetty);
|
||||
fields0.add(XPowerJetty);
|
||||
fields0.add(Date);
|
||||
fields1.add("Custom-Key","Other-Value");
|
||||
Response original1 = new MetaData.Response(HttpVersion.HTTP_2,200,fields1);
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public class HTTP2ServerConnectionFactory extends AbstractHTTP2ServerConnectionF
|
|||
HttpChannelOverHTTP2 channel = new HttpChannelOverHTTP2(connector, httpConfiguration, endPoint, transport, input, stream);
|
||||
stream.setAttribute(CHANNEL_ATTRIBUTE, channel);
|
||||
|
||||
channel.requestHeaders(frame);
|
||||
channel.onHeadersFrame(frame);
|
||||
|
||||
return frame.isEndStream() ? null : this;
|
||||
}
|
||||
|
|
|
@ -18,11 +18,15 @@
|
|||
|
||||
package org.eclipse.jetty.http2.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpHeaderValue;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
|
@ -42,10 +46,10 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class HttpChannelOverHTTP2 extends HttpChannel
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpChannelOverHTTP2.class);
|
||||
private static final HttpField ACCEPT_ENCODING_GZIP = new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip");
|
||||
private static final HttpField SERVER_VERSION=new HttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
|
||||
private static final HttpField POWERED_BY=new HttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
|
||||
private static final HttpField SERVER_VERSION=new PreEncodedHttpField(HttpHeader.SERVER,HttpConfiguration.SERVER_VERSION);
|
||||
private static final HttpField POWERED_BY=new PreEncodedHttpField(HttpHeader.X_POWERED_BY,HttpConfiguration.SERVER_VERSION);
|
||||
private final Stream stream; // TODO recycle channel for new Stream?
|
||||
private boolean _expect100Continue = false;
|
||||
|
||||
public HttpChannelOverHTTP2(Connector connector, HttpConfiguration configuration, EndPoint endPoint, HttpTransport transport, HttpInput input, Stream stream)
|
||||
{
|
||||
|
@ -53,7 +57,13 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
this.stream = stream;
|
||||
}
|
||||
|
||||
public void requestHeaders(HeadersFrame frame)
|
||||
@Override
|
||||
public boolean isExpecting100Continue()
|
||||
{
|
||||
return _expect100Continue;
|
||||
}
|
||||
|
||||
public void onHeadersFrame(HeadersFrame frame)
|
||||
{
|
||||
MetaData metaData = frame.getMetaData();
|
||||
if (!metaData.isRequest())
|
||||
|
@ -63,26 +73,21 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
}
|
||||
|
||||
MetaData.Request request = (MetaData.Request)metaData;
|
||||
|
||||
// The specification says user agents MUST support gzip encoding.
|
||||
// Based on that, some browser does not send the header, but it's
|
||||
// important that applications can find it (e.g. GzipFilter).
|
||||
HttpFields fields = request.getFields();
|
||||
if (!fields.contains(HttpHeader.ACCEPT_ENCODING, "gzip"))
|
||||
fields.add(ACCEPT_ENCODING_GZIP);
|
||||
|
||||
_expect100Continue = fields.contains(HttpHeader.EXPECT,HttpHeaderValue.CONTINUE.asString());
|
||||
|
||||
// TODO make this a better field for h2 hpack generation
|
||||
HttpFields response=getResponse().getHttpFields();
|
||||
if (getHttpConfiguration().getSendServerVersion())
|
||||
getResponse().getHttpFields().add(SERVER_VERSION);
|
||||
response.add(SERVER_VERSION);
|
||||
if (getHttpConfiguration().getSendXPoweredBy())
|
||||
getResponse().getHttpFields().add(POWERED_BY);
|
||||
response.add(POWERED_BY);
|
||||
|
||||
onRequest(request);
|
||||
|
||||
if (frame.isEndStream())
|
||||
{
|
||||
onRequestComplete();
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
|
@ -127,4 +132,33 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
onRequestComplete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the associated response has the Expect header set to 100 Continue,
|
||||
* then accessing the input stream indicates that the handler/servlet
|
||||
* is ready for the request body and thus a 100 Continue response is sent.
|
||||
*
|
||||
* @throws IOException if the InputStream cannot be created
|
||||
*/
|
||||
@Override
|
||||
public void continue100(int available) throws IOException
|
||||
{
|
||||
// If the client is expecting 100 CONTINUE, then send it now.
|
||||
// TODO: consider using an AtomicBoolean ?
|
||||
if (isExpecting100Continue())
|
||||
{
|
||||
_expect100Continue = false;
|
||||
|
||||
// is content missing?
|
||||
if (available == 0)
|
||||
{
|
||||
if (getResponse().isCommitted())
|
||||
throw new IOException("Committed before 100 Continues");
|
||||
|
||||
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
|
||||
if (!committed)
|
||||
throw new IOException("Concurrent commit while trying to send 100-Continue");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,16 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
|
||||
*/
|
||||
@Override
|
||||
public void push(org.eclipse.jetty.http.MetaData.Request request)
|
||||
{
|
||||
// TODO implement push
|
||||
LOG.warn("NOT YET IMPLEMENTED push in {}",this);
|
||||
}
|
||||
|
||||
private void commit(HttpGenerator.ResponseInfo info, boolean endStream, Callback callback)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -227,7 +227,7 @@ public class RuleContainer extends Rule
|
|||
if (rule.isHandling())
|
||||
{
|
||||
LOG.debug("handling {}",rule);
|
||||
(request instanceof Request?(Request)request:HttpChannel.getCurrentHttpChannel().getRequest()).setHandled(true);
|
||||
Request.getBaseRequest(request).setHandled(true);
|
||||
}
|
||||
|
||||
if (rule.isTerminating())
|
||||
|
|
|
@ -289,8 +289,8 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
LOG.debug("authenticated {}->{}",form_auth,nuri);
|
||||
|
||||
response.setContentLength(0);
|
||||
Response base_response = HttpChannel.getCurrentHttpChannel().getResponse();
|
||||
Request base_request = HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
Request base_request = Request.getBaseRequest(req);
|
||||
Response base_response = base_request.getResponse();
|
||||
int redirectCode = (base_request.getHttpVersion().getVersion() < HttpVersion.HTTP_1_1.getVersion() ? HttpServletResponse.SC_MOVED_TEMPORARILY : HttpServletResponse.SC_SEE_OTHER);
|
||||
base_response.sendRedirect(redirectCode, response.encodeRedirectURL(nuri));
|
||||
return form_auth;
|
||||
|
|
|
@ -31,7 +31,11 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
|
@ -46,14 +50,14 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
private final ContextHandler _contextHandler;
|
||||
private final HttpURI _uri;
|
||||
private final String _pathInfo;
|
||||
private final String _pathInContext;
|
||||
private final String _named;
|
||||
|
||||
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInfo)
|
||||
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext)
|
||||
{
|
||||
_contextHandler=contextHandler;
|
||||
_uri=uri;
|
||||
_pathInfo=pathInfo;
|
||||
_pathInContext=pathInContext;
|
||||
_named=null;
|
||||
}
|
||||
|
||||
|
@ -61,7 +65,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
{
|
||||
_contextHandler=contextHandler;
|
||||
_uri=null;
|
||||
_pathInfo=null;
|
||||
_pathInContext=null;
|
||||
_named=name;
|
||||
}
|
||||
|
||||
|
@ -79,7 +83,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
@Override
|
||||
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
Request baseRequest=Request.getBaseRequest(request);
|
||||
|
||||
if (!(request instanceof HttpServletRequest))
|
||||
request = new ServletRequestHttpWrapper(request);
|
||||
|
@ -104,14 +108,14 @@ public class Dispatcher implements RequestDispatcher
|
|||
attr._requestURI=_uri.getPath();
|
||||
attr._contextPath=_contextHandler.getContextPath();
|
||||
attr._servletPath=null; // set by ServletHandler
|
||||
attr._pathInfo=_pathInfo;
|
||||
attr._pathInfo=_pathInContext;
|
||||
attr._query=_uri.getQuery();
|
||||
|
||||
if (attr._query!=null)
|
||||
baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false);
|
||||
baseRequest.setAttributes(attr);
|
||||
|
||||
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
|
||||
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -126,7 +130,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
|
||||
{
|
||||
Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
Request baseRequest=Request.getBaseRequest(request);
|
||||
Response base_response=baseRequest.getResponse();
|
||||
base_response.resetForForward();
|
||||
|
||||
|
@ -187,13 +191,13 @@ public class Dispatcher implements RequestDispatcher
|
|||
|
||||
baseRequest.setContextPath(_contextHandler.getContextPath());
|
||||
baseRequest.setServletPath(null);
|
||||
baseRequest.setPathInfo(_pathInfo);
|
||||
baseRequest.setPathInfo(_pathInContext);
|
||||
if (_uri.getQuery()!=null || old_uri.getQuery()!=null)
|
||||
baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true);
|
||||
|
||||
baseRequest.setAttributes(attr);
|
||||
|
||||
_contextHandler.handle(_pathInfo, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
|
||||
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
|
||||
|
||||
if (!baseRequest.getHttpChannelState().isAsync())
|
||||
commitResponse(response,baseRequest);
|
||||
|
@ -212,6 +216,26 @@ public class Dispatcher implements RequestDispatcher
|
|||
baseRequest.setDispatcherType(old_type);
|
||||
}
|
||||
}
|
||||
|
||||
public void push(ServletRequest request)
|
||||
{
|
||||
Request baseRequest = Request.getBaseRequest(request);
|
||||
HttpFields fields = new HttpFields(baseRequest.getHttpFields());
|
||||
|
||||
String query=baseRequest.getQueryString();
|
||||
if (_uri.hasQuery())
|
||||
{
|
||||
if (query==null)
|
||||
query=_uri.getQuery();
|
||||
else
|
||||
query=query+"&"+_uri.getQuery(); // TODO is this correct semantic?
|
||||
}
|
||||
HttpURI uri = new HttpURI(request.getProtocol(),request.getServerName(),request.getServerPort(),_uri.getPath(),baseRequest.getHttpURI().getParam(),query,null);
|
||||
|
||||
MetaData.Request push = new MetaData.Request(HttpMethod.GET.asString(),uri,baseRequest.getHttpVersion(),fields);
|
||||
|
||||
baseRequest.getHttpChannel().getHttpTransport().push(push);
|
||||
}
|
||||
|
||||
private void commitResponse(ServletResponse response, Request baseRequest) throws IOException
|
||||
{
|
||||
|
|
|
@ -202,13 +202,13 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
// Do SSL first
|
||||
if (getForwardedCipherSuiteHeader()!=null)
|
||||
{
|
||||
String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader());
|
||||
String cipher_suite=httpFields.get(getForwardedCipherSuiteHeader());
|
||||
if (cipher_suite!=null)
|
||||
request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite);
|
||||
}
|
||||
if (getForwardedSslSessionIdHeader()!=null)
|
||||
{
|
||||
String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader());
|
||||
String ssl_session_id=httpFields.get(getForwardedSslSessionIdHeader());
|
||||
if(ssl_session_id!=null)
|
||||
{
|
||||
request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id);
|
||||
|
@ -260,7 +260,7 @@ public class ForwardedRequestCustomizer implements Customizer
|
|||
if (header == null)
|
||||
return null;
|
||||
|
||||
String headerValue = fields.getStringField(header);
|
||||
String headerValue = fields.get(header);
|
||||
|
||||
if (headerValue == null)
|
||||
return null;
|
||||
|
|
|
@ -199,7 +199,6 @@ class HttpChannelOverHttp extends HttpChannel implements HttpParser.RequestHandl
|
|||
if (getResponse().isCommitted())
|
||||
throw new IOException("Committed before 100 Continues");
|
||||
|
||||
// TODO: break this dependency with HttpGenerator
|
||||
boolean committed = sendResponse(HttpGenerator.CONTINUE_100_INFO, null, false);
|
||||
if (!committed)
|
||||
throw new IOException("Concurrent commit while trying to send 100-Continue");
|
||||
|
|
|
@ -634,4 +634,14 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
|
|||
// response is bad either with RST or by abnormal completion of chunked response.
|
||||
getEndPoint().close();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
|
||||
*/
|
||||
@Override
|
||||
public void push(org.eclipse.jetty.http.MetaData.Request request)
|
||||
{
|
||||
LOG.debug("ignore push in {}",this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,15 @@ package org.eclipse.jetty.server;
|
|||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
||||
public interface HttpTransport
|
||||
{
|
||||
void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback);
|
||||
|
||||
void push (MetaData.Request request);
|
||||
|
||||
void completed();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -52,6 +52,7 @@ import javax.servlet.ServletInputStream;
|
|||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
import javax.servlet.ServletRequestWrapper;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -132,6 +133,28 @@ public class Request implements HttpServletRequest
|
|||
private static final MultiMap<String> NO_PARAMS = new MultiMap<>();
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Obtain the base {@link Request} instance of a {@link ServletRequest}, by
|
||||
* coercion, unwrapping or thread local.
|
||||
* @param request The request
|
||||
* @return the base {@link Request} instance of a {@link ServletRequest}.
|
||||
*/
|
||||
public static Request getBaseRequest(ServletRequest request)
|
||||
{
|
||||
if (request instanceof Request)
|
||||
return (Request)request;
|
||||
|
||||
while (request instanceof ServletRequestWrapper)
|
||||
request=((ServletRequestWrapper)request).getRequest();
|
||||
|
||||
if (request instanceof Request)
|
||||
return (Request)request;
|
||||
|
||||
return HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
}
|
||||
|
||||
|
||||
private final HttpChannel _channel;
|
||||
private final List<ServletRequestAttributeListener> _requestAttributeListeners=new ArrayList<>();
|
||||
private final HttpInput _input;
|
||||
|
@ -510,7 +533,7 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
String content_type = _metadata.getFields().getStringField(HttpHeader.CONTENT_TYPE);
|
||||
String content_type = _metadata.getFields().get(HttpHeader.CONTENT_TYPE);
|
||||
if (_characterEncoding==null && content_type!=null)
|
||||
{
|
||||
MimeTypes.Type mime = MimeTypes.CACHE.get(content_type);
|
||||
|
@ -603,7 +626,7 @@ public class Request implements HttpServletRequest
|
|||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return _metadata==null?null:_metadata.getFields().getStringField(name);
|
||||
return _metadata==null?null:_metadata.getFields().get(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -830,7 +830,7 @@ public class Response implements HttpServletResponse
|
|||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return _fields.getStringField(name);
|
||||
return _fields.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,6 +38,7 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.DateGenerator;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
|
@ -299,7 +300,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
df = _dateField;
|
||||
if (df==null || df._seconds!=seconds)
|
||||
{
|
||||
HttpField field=new HttpGenerator.CachedHttpField(HttpHeader.DATE,DateGenerator.formatDate(now));
|
||||
HttpField field=new PreEncodedHttpField(HttpHeader.DATE,DateGenerator.formatDate(now));
|
||||
_dateField=new DateField(seconds,field);
|
||||
return field;
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ public class PartialRFC2616Test
|
|||
assertEquals("3.3.1 RFC 850 ANSI C",d3,d2);
|
||||
|
||||
fields.putDateField("Date",d1.getTime());
|
||||
assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.getStringField("Date"));
|
||||
assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.get("Date"));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,11 @@ public class ResponseTest
|
|||
callback.succeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(org.eclipse.jetty.http.MetaData.Request request)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void completed()
|
||||
{
|
||||
|
@ -607,7 +612,7 @@ public class ResponseTest
|
|||
|
||||
response.addCookie(cookie);
|
||||
|
||||
String set = response.getHttpFields().getStringField("Set-Cookie");
|
||||
String set = response.getHttpFields().get("Set-Cookie");
|
||||
|
||||
assertEquals("name=value;Version=1;Path=/path;Domain=domain;Secure;HttpOnly;Comment=comment", set);
|
||||
}
|
||||
|
@ -669,23 +674,23 @@ public class ResponseTest
|
|||
HttpFields fields = response.getHttpFields();
|
||||
|
||||
response.addSetCookie("null",null,null,null,-1,null,false,false,-1);
|
||||
assertEquals("null=",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("null=",fields.get("Set-Cookie"));
|
||||
|
||||
fields.clear();
|
||||
|
||||
response.addSetCookie("minimal","value",null,null,-1,null,false,false,-1);
|
||||
assertEquals("minimal=value",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("minimal=value",fields.get("Set-Cookie"));
|
||||
|
||||
fields.clear();
|
||||
//test cookies with same name, domain and path, only 1 allowed
|
||||
response.addSetCookie("everything","wrong","domain","path",0,"to be replaced",true,true,0);
|
||||
response.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
|
||||
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",fields.get("Set-Cookie"));
|
||||
Enumeration<String> e =fields.getValues("Set-Cookie");
|
||||
assertTrue(e.hasMoreElements());
|
||||
assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
|
||||
assertFalse(e.hasMoreElements());
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
|
||||
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.get("Expires"));
|
||||
assertFalse(e.hasMoreElements());
|
||||
|
||||
//test cookies with same name, different domain
|
||||
|
@ -744,31 +749,31 @@ public class ResponseTest
|
|||
|
||||
fields.clear();
|
||||
response.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,1);
|
||||
String setCookie=fields.getStringField("Set-Cookie");
|
||||
String setCookie=fields.get("Set-Cookie");
|
||||
assertThat(setCookie,Matchers.startsWith("\"ev erything\"=\"va lue\";Version=1;Path=\"pa th\";Domain=\"do main\";Expires="));
|
||||
assertThat(setCookie,Matchers.endsWith(" GMT;Max-Age=1;Secure;HttpOnly;Comment=\"co mment\""));
|
||||
|
||||
fields.clear();
|
||||
response.addSetCookie("name","value",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
setCookie=fields.get("Set-Cookie");
|
||||
assertEquals(-1,setCookie.indexOf("Version="));
|
||||
fields.clear();
|
||||
response.addSetCookie("name","v a l u e",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
setCookie=fields.get("Set-Cookie");
|
||||
|
||||
fields.clear();
|
||||
response.addSetCookie("json","{\"services\":[\"cwa\", \"aa\"]}",null,null,-1,null,false,false,-1);
|
||||
assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.get("Set-Cookie"));
|
||||
|
||||
fields.clear();
|
||||
response.addSetCookie("name","value","domain",null,-1,null,false,false,-1);
|
||||
response.addSetCookie("name","other","domain",null,-1,null,false,false,-1);
|
||||
assertEquals("name=other;Domain=domain",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("name=other;Domain=domain",fields.get("Set-Cookie"));
|
||||
response.addSetCookie("name","more","domain",null,-1,null,false,false,-1);
|
||||
assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("name=more;Domain=domain",fields.get("Set-Cookie"));
|
||||
response.addSetCookie("foo","bar","domain",null,-1,null,false,false,-1);
|
||||
response.addSetCookie("foo","bob","domain",null,-1,null,false,false,-1);
|
||||
assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
|
||||
assertEquals("name=more;Domain=domain",fields.get("Set-Cookie"));
|
||||
|
||||
e=fields.getValues("Set-Cookie");
|
||||
assertEquals("name=more;Domain=domain",e.nextElement());
|
||||
|
@ -776,7 +781,7 @@ public class ResponseTest
|
|||
|
||||
fields.clear();
|
||||
response.addSetCookie("name","value%=",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.getStringField("Set-Cookie");
|
||||
setCookie=fields.get("Set-Cookie");
|
||||
assertEquals("name=value%=",setCookie);
|
||||
|
||||
}
|
||||
|
|
|
@ -39,10 +39,10 @@ import javax.servlet.http.HttpServlet;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.HttpContent;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpGenerator.CachedHttpField;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
|
@ -144,7 +144,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
|
||||
private static final long serialVersionUID = 4930458713846881193L;
|
||||
|
||||
private static final CachedHttpField ACCEPT_RANGES = new CachedHttpField(HttpHeader.ACCEPT_RANGES, "bytes");
|
||||
private static final PreEncodedHttpField ACCEPT_RANGES = new PreEncodedHttpField(HttpHeader.ACCEPT_RANGES, "bytes");
|
||||
|
||||
private ServletContext _servletContext;
|
||||
private ContextHandler _contextHandler;
|
||||
|
@ -241,7 +241,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
|
||||
String cc=getInitParameter("cacheControl");
|
||||
if (cc!=null)
|
||||
_cacheControl=new CachedHttpField(HttpHeader.CACHE_CONTROL, cc);
|
||||
_cacheControl=new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, cc);
|
||||
|
||||
String resourceCache = getInitParameter("resourceCache");
|
||||
int max_cache_size=getInitInt("maxCacheSize", -2);
|
||||
|
|
|
@ -227,7 +227,7 @@ public class Invoker extends HttpServlet
|
|||
|
||||
if (holder!=null)
|
||||
{
|
||||
final Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
final Request baseRequest=Request.getBaseRequest(request);
|
||||
holder.handle(baseRequest,
|
||||
new InvokedRequest(request,included,servlet,servlet_path,path_info),
|
||||
response);
|
||||
|
|
|
@ -1630,7 +1630,7 @@ public class ServletHandler extends ScopedHandler
|
|||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
final Request baseRequest=(request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
final Request baseRequest=Request.getBaseRequest(request);
|
||||
|
||||
// pass to next filter
|
||||
if (_filterHolder!=null)
|
||||
|
@ -1732,7 +1732,7 @@ public class ServletHandler extends ScopedHandler
|
|||
// Call servlet
|
||||
HttpServletRequest srequest = (HttpServletRequest)request;
|
||||
if (_servletHolder == null)
|
||||
notFound((request instanceof Request)?((Request)request):HttpChannel.getCurrentHttpChannel().getRequest(), srequest, (HttpServletResponse)response);
|
||||
notFound(Request.getBaseRequest(request), srequest, (HttpServletResponse)response);
|
||||
else
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -37,9 +37,9 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
|
@ -152,7 +152,7 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
|
|||
protected Set<Pattern> _excludedAgentPatterns;
|
||||
protected Set<String> _excludedPaths;
|
||||
protected Set<Pattern> _excludedPathPatterns;
|
||||
protected HttpField _vary=new HttpGenerator.CachedHttpField(HttpHeader.VARY,HttpHeader.ACCEPT_ENCODING+", "+HttpHeader.USER_AGENT);
|
||||
protected HttpField _vary=new PreEncodedHttpField(HttpHeader.VARY,HttpHeader.ACCEPT_ENCODING+", "+HttpHeader.USER_AGENT);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -278,7 +278,7 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory
|
|||
|
||||
tmp=filterConfig.getInitParameter("vary");
|
||||
if (tmp!=null)
|
||||
_vary=new HttpGenerator.CachedHttpField(HttpHeader.VARY,tmp);
|
||||
_vary=new PreEncodedHttpField(HttpHeader.VARY,tmp);
|
||||
LOG.debug("{} vary={}",this,_vary);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public class CloseableDoSFilter extends DoSFilter
|
|||
@Override
|
||||
protected void closeConnection(HttpServletRequest request, HttpServletResponse response, Thread thread)
|
||||
{
|
||||
Request base_request=(request instanceof Request)?(Request)request:HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
Request base_request=Request.getBaseRequest(request);
|
||||
base_request.getHttpChannel().getEndPoint().close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,8 +24,8 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.eclipse.jetty.http.PreEncodedHttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpGenerator;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.HttpChannel;
|
||||
|
@ -41,7 +41,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class GzipHttpOutput extends HttpOutput
|
||||
{
|
||||
public static Logger LOG = Log.getLogger(GzipHttpOutput.class);
|
||||
private final static HttpGenerator.CachedHttpField CONTENT_ENCODING_GZIP=new HttpGenerator.CachedHttpField(HttpHeader.CONTENT_ENCODING,"gzip");
|
||||
private final static PreEncodedHttpField CONTENT_ENCODING_GZIP=new PreEncodedHttpField(HttpHeader.CONTENT_ENCODING,"gzip");
|
||||
private final static byte[] GZIP_HEADER = new byte[] { (byte)0x1f, (byte)0x8b, Deflater.DEFLATED, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
private enum GZState { NOT_COMPRESSING, MIGHT_COMPRESS, COMMITTING, COMPRESSING, FINISHED};
|
||||
|
|
|
@ -159,6 +159,18 @@ public class HttpTransportOverSPDY implements HttpTransport
|
|||
throw new IllegalStateException("not lastContent, no content and no responseInfo!");
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.HttpTransport#push(org.eclipse.jetty.http.MetaData.Request)
|
||||
*/
|
||||
@Override
|
||||
public void push(org.eclipse.jetty.http.MetaData.Request request)
|
||||
{
|
||||
LOG.warn("NOT YET IMPLEMENTED push in {}",this);
|
||||
}
|
||||
|
||||
|
||||
private void sendReply(HttpGenerator.ResponseInfo info, Callback callback, boolean close)
|
||||
{
|
||||
Fields headers = new Fields();
|
||||
|
|
|
@ -146,7 +146,7 @@ public abstract class RFC2616BaseTest
|
|||
|
||||
// Test formatting
|
||||
fields.putDateField("Date",expected.getTime().getTime());
|
||||
Assert.assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.getStringField("Date"));
|
||||
Assert.assertEquals("3.3.1 RFC 822 preferred","Sun, 06 Nov 1994 08:49:37 GMT",fields.get("Date"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -133,7 +133,7 @@ public class IdleSessionTest
|
|||
//make a request to set up a session on the server
|
||||
ContentResponse response = client.GET(url + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -77,7 +77,7 @@ public class DirtyAttributeTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -103,7 +103,7 @@ public class MaxInactiveMigrationTest
|
|||
ContentResponse response = request.send();
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
|
||||
sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue( sessionCookie != null );
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -70,7 +70,7 @@ public class ModifyMaxInactiveIntervalTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -104,7 +104,7 @@ public class ReloadedSessionMissingClassTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port1 + contextPath +"/bar?action=set");
|
||||
|
||||
assertEquals( HttpServletResponse.SC_OK, response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
String sessionId = (String)webApp.getServletContext().getAttribute("foo");
|
||||
assertNotNull(sessionId);
|
||||
|
|
|
@ -77,7 +77,7 @@ public class SaveIntervalTest
|
|||
// Perform a request to create a session
|
||||
ContentResponse response = client.GET("http://localhost:" + port + "/mod/test?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -102,7 +102,7 @@ public class SessionExpiryTest extends AbstractSessionExpiryTest
|
|||
//make a request to set up a session on the server
|
||||
ContentResponse response1 = client.GET(url + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -94,7 +94,7 @@ public class PurgeInvalidSessionTest
|
|||
//Create a session
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -97,7 +97,7 @@ public class PurgeValidSessionTest
|
|||
//Create a session
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -117,7 +117,7 @@ public class SessionSavingValueTest extends AbstractSessionValueSavingTest
|
|||
|
||||
sessionTestValue = sessionTestResponse;
|
||||
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=","$1\\$Path=");
|
||||
|
@ -144,7 +144,7 @@ public class SessionSavingValueTest extends AbstractSessionValueSavingTest
|
|||
|
||||
sessionTestValue = sessionTestResponse;
|
||||
|
||||
String setCookie = response2.getHeaders().getStringField("Set-Cookie");
|
||||
String setCookie = response2.getHeaders().get("Set-Cookie");
|
||||
if (setCookie != null)
|
||||
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=","$1\\$Path=");
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ public class StopSessionManagerDeleteSessionTest
|
|||
//Create a session
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract class AbstractClientCrossContextSessionTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port + contextA + servletMapping);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -64,7 +64,7 @@ public abstract class AbstractImmortalSessionTest
|
|||
int value = 42;
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=set&value=" + value);
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -79,7 +79,7 @@ public abstract class AbstractInvalidationSessionTest
|
|||
ContentResponse response1 = client.GET(urls[0] + "?action=init");
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -87,7 +87,7 @@ public abstract class AbstractLastAccessTimeTest
|
|||
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK, response1.getStatus());
|
||||
assertEquals("test", response1.getContentAsString());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue( sessionCookie != null );
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
@ -106,7 +106,7 @@ public abstract class AbstractLastAccessTimeTest
|
|||
assertEquals(HttpServletResponse.SC_OK , response2.getStatus());
|
||||
assertEquals("test", response2.getContentAsString());
|
||||
|
||||
String setCookie = response2.getHeaders().getStringField("Set-Cookie");
|
||||
String setCookie = response2.getHeaders().get("Set-Cookie");
|
||||
if (setCookie!=null)
|
||||
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public abstract class AbstractLightLoadTest
|
|||
|
||||
ContentResponse response1 = client.GET(urls[0] + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField( "Set-Cookie" );
|
||||
String sessionCookie = response1.getHeaders().get( "Set-Cookie" );
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -86,7 +86,7 @@ public abstract class AbstractLocalSessionScavengingTest
|
|||
// Create the session on node1
|
||||
ContentResponse response1 = client.GET(urls[0] + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract class AbstractNewSessionTest
|
|||
{
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract class AbstractOrphanedSessionTest
|
|||
// Connect to server1 to create a session and get its session cookie
|
||||
ContentResponse response1 = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -101,7 +101,7 @@ public abstract class AbstractProxySerializationTest
|
|||
{
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -66,7 +66,7 @@ public abstract class AbstractRemoveSessionTest
|
|||
{
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -81,7 +81,7 @@ public abstract class AbstractSessionCookieTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
//sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -75,7 +75,7 @@ public abstract class AbstractSessionExpiryTest
|
|||
//make a request to set up a session on the server
|
||||
ContentResponse response = client.GET(url + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
@ -125,7 +125,7 @@ public abstract class AbstractSessionExpiryTest
|
|||
//make a request to set up a session on the server
|
||||
ContentResponse response1 = client.GET(url + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -119,7 +119,7 @@ public abstract class AbstractSessionInvalidateAndCreateTest
|
|||
// Create the session
|
||||
ContentResponse response1 = client.GET(url + "?action=init");
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -72,7 +72,7 @@ public abstract class AbstractSessionMigrationTest
|
|||
Request request1 = client.POST("http://localhost:" + port1 + contextPath + servletMapping + "?action=set&value=" + value);
|
||||
ContentResponse response1 = request1.send();
|
||||
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -70,7 +70,7 @@ public abstract class AbstractSessionRenewTest
|
|||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
assertFalse(testListener.isCalled());
|
||||
|
||||
|
@ -79,7 +79,7 @@ public abstract class AbstractSessionRenewTest
|
|||
request.header("Cookie", sessionCookie);
|
||||
ContentResponse renewResponse = request.send();
|
||||
assertEquals(HttpServletResponse.SC_OK,renewResponse.getStatus());
|
||||
String renewSessionCookie = renewResponse.getHeaders().getStringField("Set-Cookie");
|
||||
String renewSessionCookie = renewResponse.getHeaders().get("Set-Cookie");
|
||||
assertNotNull(renewSessionCookie);
|
||||
assertNotSame(sessionCookie, renewSessionCookie);
|
||||
assertTrue(testListener.isCalled());
|
||||
|
|
|
@ -72,7 +72,7 @@ public abstract class AbstractSessionValueSavingTest
|
|||
|
||||
sessionTestValue = Long.parseLong(response1.getContentAsString());
|
||||
|
||||
String sessionCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response1.getHeaders().get("Set-Cookie");
|
||||
assertTrue( sessionCookie != null );
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
@ -95,7 +95,7 @@ public abstract class AbstractSessionValueSavingTest
|
|||
assertTrue(sessionTestValue < Long.parseLong(response2.getContentAsString()));
|
||||
sessionTestValue = Long.parseLong(response2.getContentAsString());
|
||||
|
||||
String setCookie = response1.getHeaders().getStringField("Set-Cookie");
|
||||
String setCookie = response1.getHeaders().get("Set-Cookie");
|
||||
if (setCookie!=null)
|
||||
sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ public abstract class AbstractStopSessionManagerPreserveSessionTest
|
|||
//Create a session
|
||||
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
|
@ -120,7 +120,7 @@ public abstract class AbstractWebAppObjectInSessionTest
|
|||
|
||||
ContentResponse response = request.send();
|
||||
assertEquals( HttpServletResponse.SC_OK, response.getStatus());
|
||||
String sessionCookie = response.getHeaders().getStringField("Set-Cookie");
|
||||
String sessionCookie = response.getHeaders().get("Set-Cookie");
|
||||
assertTrue(sessionCookie != null);
|
||||
// Mangle the cookie, replacing Path with $Path, etc.
|
||||
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
|
||||
|
|
Loading…
Reference in New Issue