split authority field and hold results in header table

This commit is contained in:
Greg Wilkins 2014-06-09 15:34:09 +02:00
parent b2296cc2d4
commit 3c321e9b8f
10 changed files with 157 additions and 53 deletions

View File

@ -842,7 +842,7 @@ public class HttpParser
try
{
len=i;
port = StringUtil.toInt(host.substring(i+1));
port = StringUtil.toInt(host,i+1);
}
catch (NumberFormatException e)
{

View File

@ -0,0 +1,94 @@
//
// ========================================================================
// 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 org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.util.StringUtil;
/* ------------------------------------------------------------ */
/**
*/
public class AuthorityHttpField extends HttpField
{
public final static String AUTHORITY = HpackContext.STATIC_TABLE[1][0];
public final String _host;
public final int _port;
public AuthorityHttpField(String authority)
{
super(AUTHORITY,authority);
if (authority.charAt(0)=='[')
{
// ipv6reference
int close=authority.indexOf(']');
if (close<0)
throw new IllegalArgumentException("Bad ipv6");
_host=authority.substring(1,close-1);
if (authority.length()>close+1)
{
if (authority.charAt(close+1)!=':')
throw new IllegalArgumentException("Bad ipv6 port");
_port=StringUtil.toInt(authority,close+2);
}
else
_port=0;
}
else
{
// ipv4address or hostname
int c = authority.lastIndexOf(':');
if (c>=0)
{
_host=authority.substring(0,c);
_port=StringUtil.toInt(authority,c+1);
}
else
{
_host=authority;
_port=0;
}
}
}
/* ------------------------------------------------------------ */
/** Get the host.
* @return the host
*/
public String getHost()
{
return _host;
}
/* ------------------------------------------------------------ */
/** Get the port.
* @return the port
*/
public int getPort()
{
return _port;
}
}

View File

@ -36,7 +36,7 @@ import org.eclipse.jetty.util.Trie;
public class HpackContext
{
private static final String[][] STATIC_TABLE =
public static final String[][] STATIC_TABLE =
{
{null,null},
/* 1 */ {":authority" ,null},

View File

@ -32,7 +32,6 @@ import org.eclipse.jetty.http2.hpack.HpackContext.Entry;
*/
public class HpackDecoder
{
private final HpackContext _context;
private final MetaDataBuilder _builder = new MetaDataBuilder();
@ -46,7 +45,6 @@ public class HpackDecoder
_context=new HpackContext(maxHeaderTableSize);
}
public MetaData decode(ByteBuffer buffer)
{
@ -120,7 +118,12 @@ public class HpackDecoder
value=toASCIIString(buffer,length);
// Make the new field
HttpField field = new HttpField(header,name,value);
HttpField field;
if (":authority".equals(header))
field = new AuthorityHttpField(value);
else
// Normal Field
field = new HttpField(header,name,value);
// emit the field
_builder.emit(field);

View File

@ -104,7 +104,7 @@ public class HpackEncoder
// TODO optimise these to avoid HttpField creation
encode(buffer,new HttpField(":scheme",request.getScheme().asString()));
encode(buffer,new HttpField(":method",request.getMethodString()));
encode(buffer,new HttpField(":method",request.getMethod()));
encode(buffer,new HttpField(":authority",request.getAuthority())); // TODO look for host header?
encode(buffer,new HttpField(":path",request.getPath()));

View File

@ -19,7 +19,9 @@
package org.eclipse.jetty.http2.hpack;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
@ -55,23 +57,36 @@ public class MetaData implements Iterable<HttpField>
return _fields.iterator();
}
public List<HttpField> getFields()
{
if (_fields instanceof List)
return (List<HttpField>)_fields;
ArrayList<HttpField> list = new ArrayList<>();
for (HttpField field:_fields)
list.add(field);
return list;
}
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
public static class Request extends MetaData
{
private final HttpMethod _method;
private final String _methodString;
private final String _method;
private final HttpScheme _scheme;
private final String _authority;
private final String _host;
private final int _port;
private final String _path;
public Request(HttpScheme scheme, HttpMethod method, String methodString, String authority, String path, Iterable<HttpField> fields)
public Request(HttpScheme scheme, String method, String authority, String host, int port, String path, Iterable<HttpField> fields)
{
super(fields);
_authority=authority;
_host=host;
_port=port;
_method=method;
_methodString=methodString;
_path=path;
_scheme=scheme;
}
@ -88,16 +103,11 @@ public class MetaData implements Iterable<HttpField>
return false;
}
public HttpMethod getMethod()
public String getMethod()
{
return _method;
}
public String getMethodString()
{
return _methodString;
}
public HttpScheme getScheme()
{
return _scheme;
@ -108,6 +118,16 @@ public class MetaData implements Iterable<HttpField>
return _authority;
}
public String getHost()
{
return _host;
}
public int getPort()
{
return _port;
}
public String getPath()
{
return _path;

View File

@ -32,10 +32,11 @@ import org.eclipse.jetty.http.HttpScheme;
public class MetaDataBuilder
{
private int _status;
private HttpMethod _method;
private String _methodString;
private String _method;
private HttpScheme _scheme;
private String _authority;
private String _host;
private int _port;
private String _path;
List<HttpField> _fields = new ArrayList<>();
@ -52,25 +53,15 @@ public class MetaDataBuilder
break;
case ":method":
_method=(HttpMethod)value.getStaticValue();
_methodString=_method.asString();
_method=field.getValue();
break;
case ":scheme":
_scheme = (HttpScheme)value.getStaticValue();
break;
case ":authority":
_authority=field.getValue();
break;
case ":path":
_path=field.getValue();
break;
default:
if (field.getName().charAt(0)!=':')
_fields.add(field);
throw new IllegalArgumentException();
}
}
else
@ -83,8 +74,7 @@ public class MetaDataBuilder
break;
case ":method":
_methodString=field.getValue();
_method=HttpMethod.CACHE.get(_methodString);
_method=field.getValue();
break;
case ":scheme":
@ -93,6 +83,9 @@ public class MetaDataBuilder
case ":authority":
_authority=field.getValue();
AuthorityHttpField afield=(field instanceof AuthorityHttpField)?((AuthorityHttpField)field):new AuthorityHttpField(field.getValue());
_host=afield.getHost();
_port=afield.getPort();
break;
case ":path":
@ -111,7 +104,7 @@ public class MetaDataBuilder
try
{
if (_method!=null)
return new MetaData.Request(_scheme,_method,_methodString,_authority,_path,new ArrayList<>(_fields));
return new MetaData.Request(_scheme,_method,_authority,_host,_port,_path,new ArrayList<>(_fields));
if (_status!=0)
return new MetaData.Response(_status,new ArrayList<>(_fields));
return new MetaData(new ArrayList<>(_fields));
@ -123,6 +116,8 @@ public class MetaDataBuilder
_scheme=null;
_authority=null;
_path=null;
_host=null;
_port=0;
_fields.clear();
}
}

View File

@ -50,8 +50,7 @@ public class HpackDecoderTest
MetaData.Request request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET", request.getMethodString());
assertEquals("GET", request.getMethod());
assertEquals(HttpScheme.HTTP,request.getScheme());
assertEquals("/",request.getPath());
assertEquals("www.example.com",request.getAuthority());
@ -64,8 +63,7 @@ public class HpackDecoderTest
request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET", request.getMethodString());
assertEquals("GET", request.getMethod());
assertEquals(HttpScheme.HTTP,request.getScheme());
assertEquals("/",request.getPath());
assertEquals("www.example.com",request.getAuthority());
@ -81,8 +79,7 @@ public class HpackDecoderTest
request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET",request.getMethodString());
assertEquals("GET",request.getMethod());
assertEquals(HttpScheme.HTTPS,request.getScheme());
assertEquals("/index.html",request.getPath());
assertEquals("www.example.com",request.getAuthority());
@ -95,18 +92,15 @@ public class HpackDecoderTest
@Test
public void testDecodeD_4()
{
HpackDecoder decoder = new HpackDecoder();
// First request
String encoded="828786448ce7cf9bebe89b6fb16fa9b6ff";
ByteBuffer buffer = ByteBuffer.wrap(TypeUtil.fromHexString(encoded));
MetaData.Request request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET", request.getMethodString());
assertEquals("GET", request.getMethod());
assertEquals(HttpScheme.HTTP,request.getScheme());
assertEquals("/",request.getPath());
assertEquals("www.example.com",request.getAuthority());
@ -119,8 +113,7 @@ public class HpackDecoderTest
request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET", request.getMethodString());
assertEquals("GET", request.getMethod());
assertEquals(HttpScheme.HTTP,request.getScheme());
assertEquals("/",request.getPath());
assertEquals("www.example.com",request.getAuthority());
@ -135,8 +128,7 @@ public class HpackDecoderTest
request = (MetaData.Request)decoder.decode(buffer);
assertEquals(HttpMethod.GET,request.getMethod());
assertEquals("GET",request.getMethodString());
assertEquals("GET",request.getMethod());
assertEquals(HttpScheme.HTTPS,request.getScheme());
assertEquals("/index.html",request.getPath());
assertEquals("www.example.com",request.getAuthority());

View File

@ -1225,7 +1225,7 @@ public class Request implements HttpServletRequest
try
{
len=i;
_port = StringUtil.toInt(hostPort.substring(i+1));
_port = StringUtil.toInt(hostPort,i+1);
}
catch (NumberFormatException e)
{

View File

@ -622,17 +622,17 @@ public class StringUtil
/**
* Convert String to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
*
* @param string
* A String containing an integer.
* @param string A String containing an integer.
* @param from The index to start parsing from
* @return an int
*/
public static int toInt(String string)
public static int toInt(String string,int from)
{
int val = 0;
boolean started = false;
boolean minus = false;
for (int i = 0; i < string.length(); i++)
for (int i = from; i < string.length(); i++)
{
char b = string.charAt(i);
if (b <= ' ')