diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java index d7c46e2099c..ac50f342de7 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java @@ -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) { diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java new file mode 100644 index 00000000000..e845f1426f6 --- /dev/null +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/AuthorityHttpField.java @@ -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; + } + + +} diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java index b0903cdc532..327033a4d30 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackContext.java @@ -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}, diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java index eb77c4f4c9d..06e22ac83bc 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackDecoder.java @@ -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); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java index 6460d965df8..6996d234ee5 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/HpackEncoder.java @@ -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())); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaData.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaData.java index 4228638f975..f787895f580 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaData.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaData.java @@ -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 return _fields.iterator(); } + public List getFields() + { + if (_fields instanceof List) + return (List)_fields; + ArrayList 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 fields) + public Request(HttpScheme scheme, String method, String authority, String host, int port, String path, Iterable 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 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 return _authority; } + public String getHost() + { + return _host; + } + + public int getPort() + { + return _port; + } + public String getPath() { return _path; diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index 549996fc3d6..ac8361db408 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -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 _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(); } } diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java index ee9bc011e14..23a97ccd22b 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackDecoderTest.java @@ -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()); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index eb790fc8068..8ab8c732626 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -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) { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java index 55868ad5edd..cd0e7da27ed 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/StringUtil.java @@ -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 *