split authority field and hold results in header table
This commit is contained in:
parent
b2296cc2d4
commit
3c321e9b8f
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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},
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
@ -45,7 +44,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);
|
||||
|
|
|
@ -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()));
|
||||
|
||||
|
|
|
@ -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,15 +103,10 @@ public class MetaData implements Iterable<HttpField>
|
|||
return false;
|
||||
}
|
||||
|
||||
public HttpMethod getMethod()
|
||||
public String getMethod()
|
||||
{
|
||||
return _method;
|
||||
}
|
||||
|
||||
public String getMethodString()
|
||||
{
|
||||
return _methodString;
|
||||
}
|
||||
|
||||
public HttpScheme getScheme()
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 <= ' ')
|
||||
|
@ -657,7 +657,7 @@ public class StringUtil
|
|||
return minus?(-val):val;
|
||||
throw new NumberFormatException(string);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert String to an long. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue