diff options
author | Greg Wilkins | 2014-06-11 13:16:40 +0000 |
---|---|---|
committer | Greg Wilkins | 2014-06-11 13:16:40 +0000 |
commit | bbd61f8e192b0af9cf7c4aae51a65e5cd07c863c (patch) | |
tree | e8ab3e1ef0481b203b43d969c4cfade54b6e5b73 | |
parent | 70223cbda9cb8a5575641050819c080c4b7d5a57 (diff) | |
download | org.eclipse.jetty.project-bbd61f8e192b0af9cf7c4aae51a65e5cd07c863c.tar.gz org.eclipse.jetty.project-bbd61f8e192b0af9cf7c4aae51a65e5cd07c863c.tar.xz org.eclipse.jetty.project-bbd61f8e192b0af9cf7c4aae51a65e5cd07c863c.zip |
Multiple mixed in changes and improvements
Simplified HttpParser as per rfc7230
implemented local/remote hpack max table sizes
18 files changed, 601 insertions, 570 deletions
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java index f98f482894..34e586f5ee 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java @@ -197,14 +197,11 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { HttpExchange exchange = getHttpExchange(); - if (exchange == null) - return false; - - responseHeader(exchange, field); - return false; + if (exchange != null) + responseHeader(exchange, field); } @Override diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index 83a9a79ddb..ef82e32fdf 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -153,7 +153,7 @@ public class ResponseContentParser extends StreamContentParser } @Override - public boolean parsedHeader(HttpField httpField) + public void parsedHeader(HttpField httpField) { try { @@ -188,7 +188,6 @@ public class ResponseContentParser extends StreamContentParser { logger.debug("Exception while invoking listener " + listener, x); } - return false; } private void notifyBegin(int code, String reason) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/BadMessage.java b/jetty-http/src/main/java/org/eclipse/jetty/http/BadMessage.java new file mode 100644 index 0000000000..c21beff3ce --- /dev/null +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/BadMessage.java @@ -0,0 +1,67 @@ +// +// ======================================================================== +// 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; + +/* ------------------------------------------------------------------------------- */ +class BadMessage extends Error +{ + final int _code; + final String _reason; + + BadMessage() + { + this(400,null); + } + + BadMessage(int code) + { + this(code,null); + } + + BadMessage(String reason) + { + this(400,reason); + } + + BadMessage(int code,String reason) + { + _code=code; + _reason=reason; + } + + BadMessage(int code,String reason,Throwable cause) + { + super(cause); + _code=code; + _reason=reason; + } + + public int getCode() + { + return _code; + } + + public String getReason() + { + return _reason; + } + + +}
\ No newline at end of file diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java new file mode 100644 index 0000000000..11c233cd4f --- /dev/null +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java @@ -0,0 +1,102 @@ +// +// ======================================================================== +// 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 org.eclipse.jetty.util.StringUtil; + + + +/* ------------------------------------------------------------ */ +/** + */ +public class HostPortHttpField extends HttpField +{ + public final String _host; + public final int _port; + + public HostPortHttpField(HttpHeader header, String name, String authority) + { + super(header,name,authority); + + try + { + if (authority.charAt(0)=='[') + { + // ipv6reference + int close=authority.lastIndexOf(']'); + if (close<0) + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad ipv6"); + _host=authority.substring(1,close); + + if (authority.length()>close+1) + { + if (authority.charAt(close+1)!=':') + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"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; + } + } + } + catch (BadMessage bm) + { + throw bm; + } + catch(Exception e) + { + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad HostPort",e); + } + } + + /* ------------------------------------------------------------ */ + /** 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-http/src/main/java/org/eclipse/jetty/http/HttpField.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpField.java index f270482f3a..7cece45c30 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpField.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpField.java @@ -18,6 +18,8 @@ package org.eclipse.jetty.http; +import org.eclipse.jetty.util.QuotedStringTokenizer; + /* ------------------------------------------------------------ */ /** A HTTP Field @@ -65,6 +67,17 @@ public class HttpField return _value; } + public String[] getValues() + { + QuotedStringTokenizer tok = new QuotedStringTokenizer(_value, ",", false, false); + tok.setSingle(false); + String[] v = new String[tok.countTokens()]; + int t=0; + while(tok.hasMoreTokens()) + v[t++]=tok.nextToken(); + return v; + } + @Override public String toString() { 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 ac50f342de..e0a7e9552c 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 @@ -33,7 +33,7 @@ import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ -/** A Parser for 1.0 and 1.1 +/** A Parser for 1.0 and 1.1 as defined by RFC7230 * <p> * The is parser parses HTTP client and server messages from buffers * passed in the {@link #parseNext(ByteBuffer)} method. The parsed @@ -71,6 +71,8 @@ import org.eclipse.jetty.util.log.Logger; * fields. Otherwise a fast case insensitive string lookup is used that may alter the * case of the method and/or headers * </p> + * <p> + * @see http://tools.ietf.org/html/rfc7230 */ public class HttpParser { @@ -330,36 +332,6 @@ public class HttpParser } /* ------------------------------------------------------------------------------- */ - private static class BadMessage extends Error - { - private static final long serialVersionUID = 1L; - private final int _code; - private final String _message; - - BadMessage() - { - this(400,null); - } - - BadMessage(int code) - { - this(code,null); - } - - BadMessage(String message) - { - this(400,message); - } - - BadMessage(int code,String message) - { - _code=code; - _message=message; - } - - } - - /* ------------------------------------------------------------------------------- */ private byte next(ByteBuffer buffer) { byte ch = buffer.get(); @@ -781,124 +753,105 @@ public class HttpParser return handle; } - private boolean handleKnownHeaders(ByteBuffer buffer) + private void parsedHeader() { - boolean add_to_connection_trie=false; - switch (_header) + // handler last header if any. Delayed to here just in case there was a continuation line (above) + if (_headerString!=null || _valueString!=null) { - case CONTENT_LENGTH: - if (_endOfContent != EndOfContent.CHUNKED_CONTENT) - { - try - { - _contentLength=Long.parseLong(_valueString); - } - catch(NumberFormatException e) - { - LOG.ignore(e); - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Content-Length"); - } - if (_contentLength <= 0) - _endOfContent=EndOfContent.NO_CONTENT; - else - _endOfContent=EndOfContent.CONTENT_LENGTH; - } - break; - - case TRANSFER_ENCODING: - if (_value==HttpHeaderValue.CHUNKED) - _endOfContent=EndOfContent.CHUNKED_CONTENT; - else - { - if (_valueString.endsWith(HttpHeaderValue.CHUNKED.toString())) - _endOfContent=EndOfContent.CHUNKED_CONTENT; - else if (_valueString.contains(HttpHeaderValue.CHUNKED.toString())) - { - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad chunking"); - } - } - break; - - case HOST: - add_to_connection_trie=_connectionFields!=null && _field==null; - _host=true; - String host=_valueString; - int port=0; - if (host==null || host.length()==0) - { - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header"); - } - - int len=host.length(); - loop: for (int i = len; i-- > 0;) + // Handle known headers + if (_header!=null) + { + boolean add_to_connection_trie=false; + switch (_header) { - char c2 = (char)(0xff & host.charAt(i)); - switch (c2) - { - case ']': - break loop; - - case ':': + case CONTENT_LENGTH: + if (_endOfContent != EndOfContent.CHUNKED_CONTENT) + { try { - len=i; - port = StringUtil.toInt(host,i+1); + _contentLength=Long.parseLong(_valueString); } - catch (NumberFormatException e) + catch(NumberFormatException e) { - if (DEBUG) - LOG.debug(e); - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header"); + LOG.ignore(e); + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Content-Length"); } - break loop; - } - } - if (host.charAt(0)=='[') - { - if (host.charAt(len-1)!=']') - { - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad IPv6 Host header"); - } - host = host.substring(1,len-1); + if (_contentLength <= 0) + _endOfContent=EndOfContent.NO_CONTENT; + else + _endOfContent=EndOfContent.CONTENT_LENGTH; + } + break; + + case TRANSFER_ENCODING: + if (_value==HttpHeaderValue.CHUNKED) + _endOfContent=EndOfContent.CHUNKED_CONTENT; + else + { + if (_valueString.endsWith(HttpHeaderValue.CHUNKED.toString())) + _endOfContent=EndOfContent.CHUNKED_CONTENT; + else if (_valueString.contains(HttpHeaderValue.CHUNKED.toString())) + { + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad chunking"); + } + } + break; + + case HOST: + _host=true; + HostPortHttpField hpfield; + if (_field!=null) + { + hpfield = (HostPortHttpField)_field; + } + else + { + _field=hpfield=new HostPortHttpField(_header,_strict?_headerString:_header.asString(),_valueString); + add_to_connection_trie=_connectionFields!=null; + } + + if (_requestHandler!=null) + _requestHandler.parsedHostHeader(hpfield.getHost(),hpfield.getPort()); + + break; + + case CONNECTION: + // Don't cache if not persistent + if (_valueString!=null && _valueString.contains("close")) + { + _closed=true; + _connectionFields=null; + } + break; + + case AUTHORIZATION: + case ACCEPT: + case ACCEPT_CHARSET: + case ACCEPT_ENCODING: + case ACCEPT_LANGUAGE: + case COOKIE: + case CACHE_CONTROL: + case USER_AGENT: + add_to_connection_trie=_connectionFields!=null && _field==null; + break; + + default: break; } - else if (len!=host.length()) - host = host.substring(0,len); - - if (_requestHandler!=null) - _requestHandler.parsedHostHeader(host,port); - - break; - - case CONNECTION: - // Don't cache if not persistent - if (_valueString!=null && _valueString.contains("close")) + + if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null) { - _closed=true; - _connectionFields=null; + if (_field==null) + _field=new HttpField(_header,_strict?_headerString:_header.asString(),_valueString); + _connectionFields.put(_field); } - break; - - case AUTHORIZATION: - case ACCEPT: - case ACCEPT_CHARSET: - case ACCEPT_ENCODING: - case ACCEPT_LANGUAGE: - case COOKIE: - case CACHE_CONTROL: - case USER_AGENT: - add_to_connection_trie=_connectionFields!=null && _field==null; - break; - - default: break; - } - - if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null) - { - _field=new HttpField(_header,_valueString); - _connectionFields.put(_field); + } + _handler.parsedHeader(_field!=null?_field:new HttpField(_header,_headerString,_valueString)); } - return false; + _headerString=_valueString=null; + _header=null; + _value=null; + _field=null; } @@ -932,194 +885,160 @@ public class HttpParser case HttpTokens.COLON: case HttpTokens.SPACE: case HttpTokens.TAB: + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Continuation"); + + case HttpTokens.LINE_FEED: { - // header value without name - continuation? - if (_valueString==null) + _contentPosition=0; + + // End of headers! + + // Was there a required host header? + if (!_host && _version!=HttpVersion.HTTP_1_0 && _requestHandler!=null) { - _string.setLength(0); - _length=0; + throw new BadMessage(HttpStatus.BAD_REQUEST_400,"No Host"); } - else + + // is it a response that cannot have a body? + if (_responseHandler !=null && // response + (_responseStatus == 304 || // not-modified response + _responseStatus == 204 || // no-content response + _responseStatus < 200)) // 1xx response + _endOfContent=EndOfContent.NO_CONTENT; // ignore any other headers set + + // else if we don't know framing + else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT) { - setString(_valueString); - _string.append(' '); - _length++; - _valueString=null; + if (_responseStatus == 0 // request + || _responseStatus == 304 // not-modified response + || _responseStatus == 204 // no-content response + || _responseStatus < 200) // 1xx response + _endOfContent=EndOfContent.NO_CONTENT; + else + _endOfContent=EndOfContent.EOF_CONTENT; + } + + // How is the message ended? + switch (_endOfContent) + { + case EOF_CONTENT: + setState(State.EOF_CONTENT); + handle=_handler.headerComplete()||handle; + break; + + case CHUNKED_CONTENT: + setState(State.CHUNKED_CONTENT); + handle=_handler.headerComplete()||handle; + break; + + case NO_CONTENT: + handle=_handler.headerComplete()||handle; + setState(State.END); + handle=_handler.messageComplete()||handle; + break; + + default: + setState(State.CONTENT); + handle=_handler.headerComplete()||handle; + break; } - setState(State.HEADER_VALUE); break; } default: { - // handler last header if any. Delayed to here just in case there was a continuation line (above) - if (_headerString!=null || _valueString!=null) - { - // Handle known headers - if (_header!=null && handleKnownHeaders(buffer)) - { - _headerString=_valueString=null; - _header=null; - _value=null; - _field=null; - return true; - } - handle=_handler.parsedHeader(_field!=null?_field:new HttpField(_header,_headerString,_valueString))||handle; - } - _headerString=_valueString=null; - _header=null; - _value=null; - _field=null; - // now handle the ch - if (ch == HttpTokens.LINE_FEED) - { - _contentPosition=0; + if (ch<=HttpTokens.SPACE) + throw new BadMessage(); - // End of headers! + if (buffer.hasRemaining()) + { + // Try a look ahead for the known header name and value. + HttpField field=_connectionFields==null?null:_connectionFields.getBest(buffer,-1,buffer.remaining()); + if (field==null) + field=CACHE.getBest(buffer,-1,buffer.remaining()); - // Was there a required host header? - if (!_host && _version!=HttpVersion.HTTP_1_0 && _requestHandler!=null) + if (field!=null) { - throw new BadMessage(HttpStatus.BAD_REQUEST_400,"No Host"); - } + final String n; + final String v; - // is it a response that cannot have a body? - if (_responseHandler !=null && // response - (_responseStatus == 304 || // not-modified response - _responseStatus == 204 || // no-content response - _responseStatus < 200)) // 1xx response - _endOfContent=EndOfContent.NO_CONTENT; // ignore any other headers set - - // else if we don't know framing - else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT) - { - if (_responseStatus == 0 // request - || _responseStatus == 304 // not-modified response - || _responseStatus == 204 // no-content response - || _responseStatus < 200) // 1xx response - _endOfContent=EndOfContent.NO_CONTENT; + if (_strict) + { + // Have to get the fields exactly from the buffer to match case + String fn=field.getName(); + String fv=field.getValue(); + n=BufferUtil.toString(buffer,buffer.position()-1,fn.length(),StandardCharsets.US_ASCII); + if (fv==null) + v=null; + else + { + v=BufferUtil.toString(buffer,buffer.position()+fn.length()+1,fv.length(),StandardCharsets.ISO_8859_1); + field=new HttpField(field.getHeader(),n,v); + } + } else - _endOfContent=EndOfContent.EOF_CONTENT; - } - - // How is the message ended? - switch (_endOfContent) - { - case EOF_CONTENT: - setState(State.EOF_CONTENT); - handle=_handler.headerComplete()||handle; - break; - - case CHUNKED_CONTENT: - setState(State.CHUNKED_CONTENT); - handle=_handler.headerComplete()||handle; - break; + { + n=field.getName(); + v=field.getValue(); + } - case NO_CONTENT: - handle=_handler.headerComplete()||handle; - setState(State.END); - handle=_handler.messageComplete()||handle; - break; + _header=field.getHeader(); + _headerString=n; - default: - setState(State.CONTENT); - handle=_handler.headerComplete()||handle; + if (v==null) + { + // Header only + setState(State.HEADER_VALUE); + _string.setLength(0); + _length=0; + buffer.position(buffer.position()+n.length()+1); break; - } - } - else if (ch<=HttpTokens.SPACE) - throw new BadMessage(); - else - { - if (buffer.hasRemaining()) - { - // Try a look ahead for the known header name and value. - HttpField field=_connectionFields==null?null:_connectionFields.getBest(buffer,-1,buffer.remaining()); - if (field==null) - field=CACHE.getBest(buffer,-1,buffer.remaining()); - - if (field!=null) + } + else { - final String n; - final String v; + // Header and value + int pos=buffer.position()+n.length()+v.length()+1; + byte b=buffer.get(pos); - if (_strict) - { - // Have to get the fields exactly from the buffer to match case - String fn=field.getName(); - String fv=field.getValue(); - n=BufferUtil.toString(buffer,buffer.position()-1,fn.length(),StandardCharsets.US_ASCII); - if (fv==null) - v=null; - else + if (b==HttpTokens.CARRIAGE_RETURN || b==HttpTokens.LINE_FEED) + { + _field=field; + _valueString=v; + setState(State.HEADER_IN_VALUE); + + if (b==HttpTokens.CARRIAGE_RETURN) { - v=BufferUtil.toString(buffer,buffer.position()+fn.length()+1,fv.length(),StandardCharsets.ISO_8859_1); - field=new HttpField(field.getHeader(),n,v); + _cr=true; + buffer.position(pos+1); } - } - else - { - n=field.getName(); - v=field.getValue(); - } - - _header=field.getHeader(); - _headerString=n; - - if (v==null) - { - // Header only - setState(State.HEADER_VALUE); - _string.setLength(0); - _length=0; - buffer.position(buffer.position()+n.length()+1); + else + buffer.position(pos); break; } else { - // Header and value - int pos=buffer.position()+n.length()+v.length()+1; - byte b=buffer.get(pos); - - if (b==HttpTokens.CARRIAGE_RETURN || b==HttpTokens.LINE_FEED) - { - _field=field; - _valueString=v; - setState(State.HEADER_IN_VALUE); - - if (b==HttpTokens.CARRIAGE_RETURN) - { - _cr=true; - buffer.position(pos+1); - } - else - buffer.position(pos); - break; - } - else - { - setState(State.HEADER_IN_VALUE); - setString(v); - buffer.position(pos); - break; - } + setState(State.HEADER_IN_VALUE); + setString(v); + buffer.position(pos); + break; } } } - - // New header - setState(State.HEADER_IN_NAME); - _string.setLength(0); - _string.append((char)ch); - _length=1; } + + // New header + setState(State.HEADER_IN_NAME); + _string.setLength(0); + _string.append((char)ch); + _length=1; + } } break; case HEADER_IN_NAME: - if (ch==HttpTokens.COLON || ch==HttpTokens.LINE_FEED) + if (ch==HttpTokens.COLON) { if (_headerString==null) { @@ -1128,11 +1047,11 @@ public class HttpParser } _length=-1; - setState(ch==HttpTokens.LINE_FEED?State.HEADER:State.HEADER_VALUE); + setState(State.HEADER_VALUE); break; } - if (ch>=HttpTokens.SPACE || ch==HttpTokens.TAB) + if (ch>HttpTokens.SPACE) { if (_header!=null) { @@ -1160,19 +1079,8 @@ public class HttpParser if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB) break; - - if (ch==HttpTokens.LINE_FEED) - { - if (_length > 0) - { - _value=null; - _valueString=(_valueString==null)?takeString():(_valueString+" "+takeString()); - } - setState(State.HEADER); - break; - } - throw new BadMessage("Illegal character"); + throw new BadMessage(); case HEADER_IN_VALUE: if (ch>=HttpTokens.SPACE || ch<0 || ch==HttpTokens.TAB) @@ -1197,6 +1105,7 @@ public class HttpParser _valueString=takeString(); _length=-1; } + parsedHeader(); setState(State.HEADER); break; } @@ -1332,11 +1241,11 @@ public class HttpParser { BufferUtil.clear(buffer); - LOG.warn("badMessage: "+e._code+(e._message!=null?" "+e._message:"")+" for "+_handler); + LOG.warn("badMessage: "+e._code+(e.getReason()!=null?" "+e.getReason():"")+" for "+_handler); if (DEBUG) LOG.debug(e); setState(State.CLOSED); - _handler.badMessage(e._code, e._message); + _handler.badMessage(e.getCode(), e.getReason()); return false; } catch(Exception e) @@ -1609,10 +1518,9 @@ public class HttpParser /** * This is the method called by parser when a HTTP Header name and value is found * @param field The field parsed - * @return True if the parser should return to its caller */ - public boolean parsedHeader(HttpField field); - + public void parsedHeader(HttpField field); + /* ------------------------------------------------------------ */ /** Called to signal that an EOF was received unexpectedly * during the parsing of a HTTP message @@ -1648,14 +1556,14 @@ public class HttpParser * @param version * @return true if handling parsing should return. */ - public abstract boolean startRequest(String method, HttpURI uri, HttpVersion version); + public boolean startRequest(String method, HttpURI uri, HttpVersion version); /** * This is the method called by the parser after it has parsed the host header (and checked it's format). This is * called after the {@link HttpHandler#parsedHeader(HttpField)} methods and before * HttpHandler#headerComplete(); */ - public abstract boolean parsedHostHeader(String host,int port); + public void parsedHostHeader(String host,int port); } public interface ResponseHandler<T> extends HttpHandler<T> @@ -1663,7 +1571,7 @@ public class HttpParser /** * This is the method called by parser when the HTTP request line is parsed */ - public abstract boolean startResponse(HttpVersion version, int status, String reason); + public boolean startResponse(HttpVersion version, int status, String reason); } public Trie<HttpField> getFieldCache() diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTester.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTester.java index 0385ffcb7e..a7f081e76a 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTester.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpTester.java @@ -132,10 +132,9 @@ public class HttpTester } } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { put(field.getName(),field.getValue()); - return false; } @Override @@ -302,9 +301,8 @@ public class HttpTester } @Override - public boolean parsedHostHeader(String host,int port) + public void parsedHostHeader(String host,int port) { - return false; } } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java index 2925f3e41f..5fc8436bfb 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java @@ -247,9 +247,8 @@ public class HttpGeneratorServerHTTPTest } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { - return false; } @Override diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java index 12b2b38908..8b25973d8c 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java @@ -181,6 +181,73 @@ public class HttpParserTest assertEquals("close", _val[1]); assertEquals(1, _headers); } + + @Test + public void test7230NoContinuations() throws Exception + { + ByteBuffer buffer= BufferUtil.toBuffer( + "GET / HTTP/1.0\015\012" + + "Host: localhost\015\012" + + "Name: value\015\012" + + " extra\015\012" + + "\015\012"); + + HttpParser.RequestHandler<ByteBuffer> handler = new Handler(); + HttpParser parser= new HttpParser(handler); + parseAll(parser,buffer); + + Assert.assertThat(_bad,Matchers.notNullValue()); + Assert.assertThat(_bad,Matchers.containsString("Bad Continuation")); + } + + + @Test + public void test7230NoWhiteSpaceInName() throws Exception + { + ByteBuffer buffer= BufferUtil.toBuffer( + "GET / HTTP/1.0\015\012" + + "Host: localhost\015\012" + + " Name: value\015\012" + + "\015\012"); + + HttpParser.RequestHandler<ByteBuffer> handler = new Handler(); + HttpParser parser= new HttpParser(handler); + parseAll(parser,buffer); + + Assert.assertThat(_bad,Matchers.notNullValue()); + Assert.assertThat(_bad,Matchers.containsString("Bad")); + + init(); + buffer= BufferUtil.toBuffer( + "GET / HTTP/1.0\015\012" + + "Host: localhost\015\012" + + "N ame: value\015\012" + + "\015\012"); + + handler = new Handler(); + parser= new HttpParser(handler); + parseAll(parser,buffer); + + Assert.assertThat(_bad,Matchers.containsString("Illegal character")); + + + init(); + buffer= BufferUtil.toBuffer( + "GET / HTTP/1.0\015\012" + + "Host: localhost\015\012" + + "Name : value\015\012" + + "\015\012"); + + handler = new Handler(); + parser= new HttpParser(handler); + parseAll(parser,buffer); + + Assert.assertThat(_bad,Matchers.containsString("Illegal character")); + + } + + + @Test public void testHeaderParseDirect() throws Exception @@ -189,13 +256,11 @@ public class HttpParserTest "GET / HTTP/1.0\015\012" + "Host: localhost\015\012" + "Header1: value1\015\012" + - "Header 2 : value 2a \015\012" + - " value 2b \015\012" + - "Header3: \015\012" + - "Header4 \015\012" + - " value4\015\012" + - "Server5 : notServer\015\012" + - "Host Header: notHost\015\012" + + "Header2: value 2a \015\012" + + "Header3: 3\015\012" + + "Header4:value4\015\012" + + "Server5: notServer\015\012" + + "HostHeader: notHost\015\012" + "Connection: close\015\012" + "Accept-Encoding: gzip, deflated\015\012" + "Accept: unknown\015\012" + @@ -216,15 +281,15 @@ public class HttpParserTest assertEquals("localhost", _val[0]); assertEquals("Header1", _hdr[1]); assertEquals("value1", _val[1]); - assertEquals("Header 2", _hdr[2]); - assertEquals("value 2a value 2b", _val[2]); + assertEquals("Header2", _hdr[2]); + assertEquals("value 2a", _val[2]); assertEquals("Header3", _hdr[3]); - assertEquals(null, _val[3]); + assertEquals("3", _val[3]); assertEquals("Header4", _hdr[4]); assertEquals("value4", _val[4]); assertEquals("Server5", _hdr[5]); assertEquals("notServer", _val[5]); - assertEquals("Host Header", _hdr[6]); + assertEquals("HostHeader", _hdr[6]); assertEquals("notHost", _val[6]); assertEquals("Connection", _hdr[7]); assertEquals("close", _val[7]); @@ -242,13 +307,11 @@ public class HttpParserTest "GET / HTTP/1.0\015\012" + "Host: localhost\015\012" + "Header1: value1\015\012" + - "Header 2 : value 2a \015\012" + - " value 2b \015\012" + - "Header3: \015\012" + - "Header4 \015\012" + - " value4\015\012" + - "Server5 : notServer\015\012" + - "Host Header: notHost\015\012" + + "Header2: value 2a \015\012" + + "Header3: 3\015\012" + + "Header4:value4\015\012" + + "Server5: notServer\015\012" + + "HostHeader: notHost\015\012" + "Connection: close\015\012" + "Accept-Encoding: gzip, deflated\015\012" + "Accept: unknown\015\012" + @@ -264,15 +327,15 @@ public class HttpParserTest assertEquals("localhost", _val[0]); assertEquals("Header1", _hdr[1]); assertEquals("value1", _val[1]); - assertEquals("Header 2", _hdr[2]); - assertEquals("value 2a value 2b", _val[2]); + assertEquals("Header2", _hdr[2]); + assertEquals("value 2a", _val[2]); assertEquals("Header3", _hdr[3]); - assertEquals(null, _val[3]); + assertEquals("3", _val[3]); assertEquals("Header4", _hdr[4]); assertEquals("value4", _val[4]); assertEquals("Server5", _hdr[5]); assertEquals("notServer", _val[5]); - assertEquals("Host Header", _hdr[6]); + assertEquals("HostHeader", _hdr[6]); assertEquals("notHost", _val[6]); assertEquals("Connection", _hdr[7]); assertEquals("close", _val[7]); @@ -292,13 +355,11 @@ public class HttpParserTest "GET / HTTP/1.0\n" + "Host: localhost\n" + "Header1: value1\n" + - "Header 2 : value 2a \n" + - " value 2b \n" + - "Header3: \n" + - "Header4 \n" + - " value4\n" + - "Server5 : notServer\n" + - "Host Header: notHost\n" + + "Header2: value 2a value 2b \n" + + "Header3: 3\n" + + "Header4:value4\n" + + "Server5: notServer\n" + + "HostHeader: notHost\n" + "Connection: close\n" + "Accept-Encoding: gzip, deflated\n" + "Accept: unknown\n" + @@ -314,15 +375,15 @@ public class HttpParserTest assertEquals("localhost", _val[0]); assertEquals("Header1", _hdr[1]); assertEquals("value1", _val[1]); - assertEquals("Header 2", _hdr[2]); + assertEquals("Header2", _hdr[2]); assertEquals("value 2a value 2b", _val[2]); assertEquals("Header3", _hdr[3]); - assertEquals(null, _val[3]); + assertEquals("3", _val[3]); assertEquals("Header4", _hdr[4]); assertEquals("value4", _val[4]); assertEquals("Server5", _hdr[5]); assertEquals("notServer", _val[5]); - assertEquals("Host Header", _hdr[6]); + assertEquals("HostHeader", _hdr[6]); assertEquals("notHost", _val[6]); assertEquals("Connection", _hdr[7]); assertEquals("close", _val[7]); @@ -496,11 +557,9 @@ public class HttpParserTest "XXXXSPLIT / HTTP/1.0\015\012" + "Host: localhost\015\012" + "Header1: value1\015\012" + - "Header2 : value 2a \015\012" + - " value 2b \015\012" + - "Header3: \015\012" + - "Header4 \015\012" + - " value4\015\012" + + "Header2: value 2a \015\012" + + "Header3: 3\015\012" + + "Header4:value4\015\012" + "Server5: notServer\015\012" + "\015\012ZZZZ"); buffer.position(2); @@ -534,9 +593,9 @@ public class HttpParserTest assertEquals("Header1", _hdr[1]); assertEquals("value1", _val[1]); assertEquals("Header2", _hdr[2]); - assertEquals("value 2a value 2b", _val[2]); + assertEquals("value 2a", _val[2]); assertEquals("Header3", _hdr[3]); - assertEquals(null, _val[3]); + assertEquals("3", _val[3]); assertEquals("Header4", _hdr[4]); assertEquals("value4", _val[4]); assertEquals("Server5", _hdr[5]); @@ -1305,7 +1364,7 @@ public class HttpParserTest HttpParser.RequestHandler<ByteBuffer> handler = new Handler(); HttpParser parser= new HttpParser(handler); parser.parseNext(buffer); - assertEquals("Bad IPv6 Host header",_bad); + Assert.assertThat(_bad,Matchers.containsString("Bad")); } @Test @@ -1336,7 +1395,7 @@ public class HttpParserTest HttpParser.RequestHandler<ByteBuffer> handler = new Handler(); HttpParser parser= new HttpParser(handler); parser.parseNext(buffer); - assertEquals("Bad Host header",_bad); + Assert.assertThat(_bad,Matchers.containsString("Bad Host")); } @Test @@ -1517,21 +1576,19 @@ public class HttpParserTest } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { _fields.add(field); //System.err.println("header "+name+": "+value); _hdr[++_headers]= field.getName(); _val[_headers]= field.getValue(); - return false; } @Override - public boolean parsedHostHeader(String host,int port) + public void parsedHostHeader(String host,int port) { _host=host; _port=port; - return false; } @Override 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 index e845f1426f..121788b66c 100644 --- 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 @@ -19,76 +19,20 @@ package org.eclipse.jetty.http2.hpack; -import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http2.hpack.HpackContext; import org.eclipse.jetty.util.StringUtil; /* ------------------------------------------------------------ */ /** */ -public class AuthorityHttpField extends HttpField +public class AuthorityHttpField extends HostPortHttpField { 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; - } - } + super(null,AUTHORITY,authority); } - - /* ------------------------------------------------------------ */ - /** 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 c1afa1a676..4b2eb4a8e2 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 @@ -187,11 +187,11 @@ public class HpackContext _headerTable=new HeaderTable(guesstimateEntries,guesstimateEntries+10); } - public void resize(int maxHeaderTableSize) + public void resize(int newMaxHeaderTableSize) { - LOG.debug("HdrTbl resized {}",maxHeaderTableSize); - _maxHeaderTableSizeInBytes=maxHeaderTableSize; - int guesstimateEntries = 10+maxHeaderTableSize/(32+10+10); + LOG.debug("HdrTbl resized {}",newMaxHeaderTableSize); + _maxHeaderTableSizeInBytes=newMaxHeaderTableSize; + int guesstimateEntries = 10+newMaxHeaderTableSize/(32+10+10); evict(); _headerTable.resizeUnsafe(guesstimateEntries); } @@ -245,11 +245,30 @@ public class HpackContext return entry; } - public Object size() + /** + * @return Current Header table size in entries + */ + public int size() { return _headerTable.size(); } + /** + * @return Current Header table size in Octets + */ + public int getHeaderTableSize() + { + return _headerTableSizeInBytes; + } + + /** + * @return Max Header table size in Octets + */ + public int getMaxHeaderTableSize() + { + return _maxHeaderTableSizeInBytes; + } + public int index(Entry entry) { if (entry._index<0) @@ -575,4 +594,5 @@ public class HpackContext } } + } 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 2ecb070ff0..a31df90c15 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 @@ -21,6 +21,7 @@ package org.eclipse.jetty.http2.hpack; import java.nio.ByteBuffer; +import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; @@ -41,15 +42,22 @@ public class HpackDecoder private final HpackContext _context; private final MetaDataBuilder _builder = new MetaDataBuilder(); + private int _localMaxHeaderTableSize; public HpackDecoder() { this(4096); } - public HpackDecoder(int maxHeaderTableSize) + public HpackDecoder(int localMaxHeaderTableSize) { - _context=new HpackContext(maxHeaderTableSize); + _context=new HpackContext(localMaxHeaderTableSize); + _localMaxHeaderTableSize=localMaxHeaderTableSize; + } + + public void setLocalMaxHeaderTableSize(int localMaxHeaderTableSize) + { + _localMaxHeaderTableSize=localMaxHeaderTableSize; } public MetaData decode(ByteBuffer buffer) @@ -188,6 +196,8 @@ public class HpackDecoder int size = NBitInteger.decode(buffer,4); if (LOG.isDebugEnabled()) LOG.debug("decode resize="+size); + if (size>_localMaxHeaderTableSize) + throw new IllegalArgumentException(); _context.resize(size); } else if (f==3) 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 ac21d4ce35..42e912d618 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 @@ -75,16 +75,24 @@ public class HpackEncoder } private final HpackContext _context; + private int _remoteMaxHeaderTableSize; + private int _localMaxHeaderTableSize; - public HpackEncoder() { - this(4096); + this(4096,4096); + } + + public HpackEncoder(int localMaxHeaderTableSize) + { + this(localMaxHeaderTableSize,4096); } - public HpackEncoder(int maxHeaderTableSize) + public HpackEncoder(int localMaxHeaderTableSize,int remoteMaxHeaderTableSize) { - _context=new HpackContext(maxHeaderTableSize); + _context=new HpackContext(remoteMaxHeaderTableSize); + _remoteMaxHeaderTableSize=remoteMaxHeaderTableSize; + _localMaxHeaderTableSize=localMaxHeaderTableSize; } public HpackContext getContext() @@ -92,6 +100,16 @@ public class HpackEncoder return _context; } + public void setRemoteMaxHeaderTableSize(int remoteMaxHeaderTableSize) + { + _remoteMaxHeaderTableSize=remoteMaxHeaderTableSize; + } + + public void setLocalMaxHeaderTableSize(int localMaxHeaderTableSize) + { + _localMaxHeaderTableSize=localMaxHeaderTableSize; + } + public void encode(MetaData metadata,Lease lease) { ByteBuffer buffer = lease.acquire(8*1024,false); // TODO make size configurable @@ -102,21 +120,15 @@ public class HpackEncoder BufferUtil.flipToFlush(buffer,0); } - public void encodeMaxHeaderTableSize(ByteBuffer buffer, int maxHeaderTableSize) - { - _context.resize(maxHeaderTableSize); - } - - public void encodeClearReferenceSet(ByteBuffer buffer) - { - // TODO - _context.clearReferenceSet(); - } public void encode(ByteBuffer buffer, MetaData metadata) { - // Add Request/response meta fields + // Check the header table sizes! + int maxHeaderTableSize=Math.min(_remoteMaxHeaderTableSize,_localMaxHeaderTableSize); + if (maxHeaderTableSize!=_context.getMaxHeaderTableSize()) + encodeMaxHeaderTableSize(buffer,maxHeaderTableSize); + // Add Request/response meta fields if (metadata.isRequest()) { MetaData.Request request = (MetaData.Request)metadata; @@ -147,6 +159,21 @@ public class HpackEncoder _context.removedUnusedReferences(buffer); } + public void encodeMaxHeaderTableSize(ByteBuffer buffer, int maxHeaderTableSize) + { + if (maxHeaderTableSize>_remoteMaxHeaderTableSize) + throw new IllegalArgumentException(); + buffer.put((byte)0x20); + NBitInteger.encode(buffer,4,maxHeaderTableSize); + _context.resize(maxHeaderTableSize); + } + + public void encodeClearReferenceSet(ByteBuffer buffer) + { + buffer.put((byte)0x30); + _context.clearReferenceSet(); + } + private void encode(ByteBuffer buffer, HttpField field) { final int p=LOG.isDebugEnabled()?buffer.position():-1; 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 6657c7899e..49066b91b5 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 @@ -22,6 +22,7 @@ package org.eclipse.jetty.http2.hpack; import java.util.ArrayList; import java.util.List; +import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; @@ -83,7 +84,7 @@ public class MetaDataBuilder case ":authority": _authority=field.getValue(); - AuthorityHttpField afield=(field instanceof AuthorityHttpField)?((AuthorityHttpField)field):new AuthorityHttpField(field.getValue()); + HostPortHttpField afield=(field instanceof HostPortHttpField)?((HostPortHttpField)field):new AuthorityHttpField(field.getValue()); _host=afield.getHost(); _port=afield.getPort(); break; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 09e9292358..e1e55e30c7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -499,7 +499,7 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { HttpHeader header=field.getHeader(); String value=field.getValue(); @@ -521,18 +521,16 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable if (field.getName()!=null) _request.getHttpFields().add(field); - return false; } @Override - public boolean parsedHostHeader(String host, int port) + public void parsedHostHeader(String host, int port) { if (_request.getUri().getHost()==null) { _request.setServerName(host); _request.setServerPort(port); } - return false; } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index bede165bcf..a041f52582 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -95,7 +95,7 @@ class HttpChannelOverHttp extends HttpChannel<ByteBuffer> implements HttpParser. @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { HttpHeader header=field.getHeader(); String value=field.getValue(); @@ -113,7 +113,7 @@ class HttpChannelOverHttp extends HttpChannel<ByteBuffer> implements HttpParser. break; default: - String[] values = value.split(","); + String[] values = field.getValues(); for (int i = 0; values != null && i < values.length; i++) { expect = HttpHeaderValue.CACHE.get(values[i].trim()); @@ -136,7 +136,7 @@ class HttpChannelOverHttp extends HttpChannel<ByteBuffer> implements HttpParser. } } } - return super.parsedHeader(field); + super.parsedHeader(field); } /** diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java index 17e1ec9af9..294c5ffc22 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java @@ -129,41 +129,6 @@ public class RequestTest } @Test - public void testEmptyHeaders() throws Exception - { - _handler._checker = new RequestTester() - { - @Override - public boolean check(HttpServletRequest request,HttpServletResponse response) - { - assertNotNull(request.getLocale()); - assertTrue(request.getLocales().hasMoreElements()); - assertNull(request.getContentType()); - assertNull(request.getCharacterEncoding()); - assertEquals(0,request.getQueryString().length()); - assertEquals(-1,request.getContentLength()); - assertNull(request.getCookies()); - assertNull(request.getHeader("Name")); - assertFalse(request.getHeaders("Name").hasMoreElements()); - assertEquals(-1,request.getDateHeader("Name")); - return true; - } - }; - - String request="GET /? HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Connection: close\n"+ - "Content-Type: \n"+ - "Accept-Language: \n"+ - "Cookie: \n"+ - "Name: \n"+ - "\n"; - - String responses=_connector.getResponses(request); - assertTrue(responses.startsWith("HTTP/1.1 200")); - } - - @Test public void testMultiPartNoConfig() throws Exception { _handler._checker = new RequestTester() @@ -1058,78 +1023,6 @@ public class RequestTest } - @Test - public void testCookieLeak() throws Exception - { - final String[] cookie=new String[10]; - - _handler._checker = new RequestTester() - { - @Override - public boolean check(HttpServletRequest request,HttpServletResponse response) - { - for (int i=0;i<cookie.length; i++) - cookie[i]=null; - - Cookie[] cookies = request.getCookies(); - for (int i=0;cookies!=null && i<cookies.length; i++) - { - cookie[i]=cookies[i].getValue(); - } - return true; - } - }; - - String request="POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie: other=cookie\r\n"+ - "\r\n" - + - "POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie: name=value\r\n"+ - "Connection: close\r\n"+ - "\r\n"; - - _connector.getResponses(request); - - assertEquals("value",cookie[0]); - assertEquals(null,cookie[1]); - - request="POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie: name=value\r\n"+ - "\r\n" - + - "POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie:\r\n"+ - "Connection: close\r\n"+ - "\r\n"; - - _connector.getResponses(request); - assertEquals(null,cookie[0]); - assertEquals(null,cookie[1]); - - request="POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie: name=value\r\n"+ - "Cookie: other=cookie\r\n"+ - "\r\n" - + - "POST / HTTP/1.1\r\n"+ - "Host: whatever\r\n"+ - "Cookie: name=value\r\n"+ - "Cookie:\r\n"+ - "Connection: close\r\n"+ - "\r\n"; - - _connector.getResponses(request); - - assertEquals("value",cookie[0]); - assertEquals(null,cookie[1]); - } - @Test public void testHashDOS() throws Exception diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java index 26c5b6b055..6a6ba1fad2 100644 --- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java +++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java @@ -94,19 +94,17 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse } @Override - public boolean parsedHeader(HttpField field) + public void parsedHeader(HttpField field) { if (field.getHeader() == HttpHeader.HOST) headers.put(HTTPSPDYHeader.HOST.name(version), field.getValue()); else headers.put(field.getName(), field.getValue()); - return false; } @Override - public boolean parsedHostHeader(String host, int port) + public void parsedHostHeader(String host, int port) { - return false; } @Override |