diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java index 1af0caf1432..65a75b1e4bb 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java @@ -127,6 +127,14 @@ public class HttpReceiver implements HttpParser.ResponseHandler } } + + @Override + public int getHeaderCacheSize() + { + // TODO get from configuration + return 256; + } + @Override public boolean startResponse(HttpVersion version, int status, String reason) { 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 74efd430f0f..0c85690a981 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 @@ -34,6 +34,7 @@ import org.eclipse.jetty.util.log.Logger; public class HttpParser { public static final Logger LOG = Log.getLogger(HttpParser.class); + private static final int INITIAL_URI_LENGTH=256; // States public enum State @@ -80,7 +81,7 @@ public class HttpParser private HttpMethod _method; private String _methodString; private HttpVersion _version; - private ByteBuffer _uri=ByteBuffer.allocate(256); // Tune? + private ByteBuffer _uri=ByteBuffer.allocate(INITIAL_URI_LENGTH); // Tune? private byte _eol; private EndOfContent _endOfContent; private long _contentLength; @@ -89,7 +90,7 @@ public class HttpParser private int _chunkPosition; private boolean _headResponse; private ByteBuffer _contentChunk; - private final Trie _connectionFields=new ArrayTernaryTrie<>(256); + private Trie _connectionFields; private int _length; private final StringBuilder _string=new StringBuilder(); @@ -512,6 +513,14 @@ public class HttpParser badMessage(buffer,HttpStatus.BAD_REQUEST_400,"Unknown Version"); return true; } + + // Should we try to cache header fields? + if (_version.getVersion()>=HttpVersion.HTTP_1_1.getVersion()) + { + int header_cache = _handler.getHeaderCacheSize(); + if (header_cache>0) + _connectionFields=new ArrayTernaryTrie<>(header_cache); + } _eol=ch; setState(State.HEADER); @@ -592,7 +601,7 @@ public class HttpParser break; case HOST: - add_to_connection_trie=_field==null; + add_to_connection_trie=_connectionFields!=null && _field==null; _host=true; String host=_valueString; int port=0; @@ -629,6 +638,12 @@ public class HttpParser _requestHandler.parsedHostHeader(host,port); break; + + case CONNECTION: + // Don't cache if not persistent + if (_valueString!=null && _valueString.indexOf("close")>=0) + _connectionFields=null; + break; case AUTHORIZATION: case ACCEPT: @@ -638,7 +653,7 @@ public class HttpParser case COOKIE: case CACHE_CONTROL: case USER_AGENT: - add_to_connection_trie=_field==null; + add_to_connection_trie=_connectionFields!=null && _field==null; } if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null) @@ -786,7 +801,7 @@ public class HttpParser if (buffer.remaining()>6) { // Try a look ahead for the known header name and value. - _field=_connectionFields.getBest(buffer,-1,buffer.remaining()); + _field=_connectionFields==null?null:_connectionFields.getBest(buffer,-1,buffer.remaining()); if (_field==null) _field=HttpField.CACHE.getBest(buffer,-1,buffer.remaining()); @@ -1396,6 +1411,11 @@ public class HttpParser public boolean earlyEOF(); public void badMessage(int status, String reason); + + /* ------------------------------------------------------------ */ + /** @return the size in bytes of the per parser header cache + */ + public int getHeaderCacheSize(); } public interface RequestHandler extends HttpHandler 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 676ebbf86bf..24f2e7aad82 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 @@ -229,6 +229,12 @@ public class HttpTester } abstract public HttpGenerator.Info getInfo(); + @Override + public int getHeaderCacheSize() + { + return 0; + } + } public static class Request extends Message implements HttpParser.RequestHandler diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java index d6b2dbe11a4..7ca440f0aab 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java @@ -91,6 +91,12 @@ public class HttpGeneratorServerTest { throw new IllegalStateException(reason); } + + @Override + public int getHeaderCacheSize() + { + return 256; + } } private static class TR 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 ed0a838e9b9..c8ebab01b9c 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 @@ -926,5 +926,11 @@ public class HttpParserTest { return true; } + + @Override + public int getHeaderCacheSize() + { + return 512; + } } } diff --git a/jetty-server/src/main/config/etc/jetty.xml b/jetty-server/src/main/config/etc/jetty.xml index 06dc9e71314..954ba71173f 100644 --- a/jetty-server/src/main/config/etc/jetty.xml +++ b/jetty-server/src/main/config/etc/jetty.xml @@ -82,6 +82,7 @@ 8192 true false + 512