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