changeset 1022:3718afd99988

HttpHeaders uses StringCache
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 01 Nov 2016 01:04:46 -0600
parents e350c11242be
children 27f3dc761452
files src/org/eclipse/jetty/http/HttpFields.java src/org/eclipse/jetty/http/HttpGenerator.java src/org/eclipse/jetty/http/HttpHeaderValues.java src/org/eclipse/jetty/http/HttpHeaders.java src/org/eclipse/jetty/http/HttpParser.java src/org/eclipse/jetty/io/StringCache.java src/org/eclipse/jetty/server/AbstractHttpConnection.java src/org/eclipse/jetty/server/Request.java src/org/eclipse/jetty/server/Response.java src/org/eclipse/jetty/server/handler/DefaultHandler.java src/org/eclipse/jetty/server/handler/ResourceHandler.java
diffstat 11 files changed, 317 insertions(+), 543 deletions(-) [+]
line wrap: on
line diff
--- a/src/org/eclipse/jetty/http/HttpFields.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpFields.java	Tue Nov 01 01:04:46 2016 -0600
@@ -40,8 +40,6 @@
 import java.util.concurrent.ConcurrentMap;
 
 import org.eclipse.jetty.io.Buffer;
-import org.eclipse.jetty.io.BufferCache;
-import org.eclipse.jetty.io.BufferCache.CachedBuffer;
 import org.eclipse.jetty.io.BufferUtil;
 import org.eclipse.jetty.io.ByteArrayBuffer;
 import org.eclipse.jetty.util.LazyList;
@@ -267,7 +265,6 @@
 	};
 
 	private final static String __01Jan1970 = formatDate(0);
-	private final static Buffer __01Jan1970_BUFFER = new ByteArrayBuffer(__01Jan1970);
 	private final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
 
 
@@ -275,21 +272,9 @@
 
 
 
-	private final ArrayList<Field> _fields = new ArrayList<Field>(20);
-	private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32);
-/*
-	private Buffer convertValue(String value)
-	{
-		try
-		{   
-			return new ByteArrayBuffer(value,StringUtil.__ISO_8859_1);
-		}
-		catch (UnsupportedEncodingException e)
-		{
-			throw new RuntimeException(e);
-		}
-	}
-*/
+	private final ArrayList<Field> _fields = new ArrayList<Field>();
+	private final HashMap<String,Field> _names = new HashMap<String,Field>();
+
 	
 	/* -------------------------------------------------------------- */
 	/**
@@ -346,28 +331,14 @@
 		return _fields.get(i);
 	}
 
-	/* ------------------------------------------------------------ */
 	private Field getField(String name)
 	{
-		return _names.get(HttpHeaders.CACHE.lookup(name));
+		return _names.get(name.toLowerCase());
 	}
 
-	/* ------------------------------------------------------------ */
-	private Field getField(Buffer name)
-	{
-		return _names.get(HttpHeaders.CACHE.lookup(name));
-	}
-
-	/* ------------------------------------------------------------ */
-	public boolean containsKey(Buffer name)
-	{
-		return _names.containsKey(HttpHeaders.CACHE.lookup(name));
-	}
-
-	/* ------------------------------------------------------------ */
 	public boolean containsKey(String name)
 	{
-		return _names.containsKey(HttpHeaders.CACHE.lookup(name));
+		return _names.containsKey(name.toLowerCase());
 	}
 
 	/* -------------------------------------------------------------- */
@@ -379,19 +350,7 @@
 	public String getStringField(String name)
 	{
 		Field field = getField(name);
-		return field==null?null:field.getValue();
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * @return the value of a field, or null if not found. For multiple fields of the same name,
-	 *         only the first is returned.
-	 * @param name the case-insensitive field name
-	 */
-	public String getStringField(Buffer name)
-	{
-		Field field = getField(name);
-		return field==null?null:field.getValue();
+		return field==null ? null : field.getValue();
 	}
 
 	/* -------------------------------------------------------------- */
@@ -454,41 +413,6 @@
 
 	/* -------------------------------------------------------------- */
 	/**
-	 * Get multi headers
-	 * 
-	 * @return Enumeration of the value Strings
-	 * @param name the case-insensitive field name
-	 */
-	public Enumeration<String> getValues(Buffer name)
-	{
-		final Field field = getField(name);
-		if (field == null) 
-		{
-			List<String> empty=Collections.emptyList();
-			return Collections.enumeration(empty);
-		}
-
-		return new Enumeration<String>()
-		{
-			Field f = field;
-
-			public boolean hasMoreElements()
-			{
-				return f != null;
-			}
-
-			public String nextElement() throws NoSuchElementException
-			{
-				if (f == null) throw new NoSuchElementException();
-				Field n = f;
-				f = f._next;
-				return n.getValue();
-			}
-		};
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
 	 * Get multi field values with separator. The multiple values can be represented as separate
 	 * headers of the same name, or by a single header using the separator(s), or a combination of
 	 * both. Separators may be quoted.
@@ -539,69 +463,15 @@
 	 */
 	public void put(String name, String value)
 	{
-		if (value==null)
-			remove(name);
-		else
-		{
-			Buffer n = HttpHeaders.CACHE.lookup(name);
-			put(n, value);
-		}
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Set a field.
-	 * 
-	 * @param name the name of the field
-	 * @param value the value of the field. If null the field is cleared.
-	 */
-	public void put(Buffer name, String value)
-	{
-/*
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-		Buffer v = convertValue(value);
-		put(n, v);
-*/
-		remove(name);
+		String nameLower = name.toLowerCase();
+		removeLower(nameLower);
 		if (value == null)
 			return;
 
-		if (!(name instanceof BufferCache.CachedBuffer)) 
-			name = HttpHeaders.CACHE.lookup(name);
-		int valueOrdinal = HttpHeaderValues.CACHE.getOrdinal(value);
-		
-		// new value;
-		Field field = new Field(name, value, valueOrdinal);
-		_fields.add(field);
-		_names.put(name, field);
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Set a field.
-	 * 
-	 * @param name the name of the field
-	 * @param value the value of the field. If null the field is cleared.
-	 */
-	public void put(Buffer name, Buffer value)
-	{
-/*
-		remove(name);
-		if (value == null)
-			return;
-
-		if (!(name instanceof BufferCache.CachedBuffer)) 
-			name = HttpHeaders.CACHE.lookup(name);
-		if (!(value instanceof CachedBuffer))
-			value = HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer();
-		
 		// new value;
 		Field field = new Field(name, value);
 		_fields.add(field);
-		_names.put(name, field);
-*/
-		String s = value==null ? null : value.toString();
-		put(name,s);
+		_names.put(nameLower, field);
 	}
 
 	/* -------------------------------------------------------------- */
@@ -616,35 +486,11 @@
 	 */
 	public void add(String name, String value) throws IllegalArgumentException
 	{
-		if (value==null)
-			return;
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-		add(n, value);
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
-	 * headers of the same name.
-	 * 
-	 * @param name the name of the field
-	 * @param value the value of the field.
-	 * @exception IllegalArgumentException If the name is a single valued field and already has a
-	 *                value.
-	 */
-	public void add(Buffer name, String value) throws IllegalArgumentException
-	{   
 		if (value == null) throw new IllegalArgumentException("null value");
 
-		if (!(name instanceof CachedBuffer))
-			name = HttpHeaders.CACHE.lookup(name);
-		name=name.asImmutableBuffer();
-/*
-		if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name)))
-			value= HttpHeaderValues.CACHE.lookup(value);
-		value=value.asImmutableBuffer();
-*/
-		Field field = _names.get(name);
+		String nameLower = name.toLowerCase();
+
+		Field field = _names.get(nameLower);
 		Field last = null;
 		while (field != null)
 		{
@@ -653,15 +499,14 @@
 		}
 
 		// create the field
-		int valueOrdinal = HttpHeaderValues.CACHE.getOrdinal(value);
-		field = new Field(name, value, valueOrdinal);
+		field = new Field(name, value);
 		_fields.add(field);
 
 		// look for chain to add too
 		if (last != null)
 			last._next = field;
 		else
-			_names.put(name, field);
+			_names.put(nameLower, field);
 	}
 
 	/* ------------------------------------------------------------ */
@@ -672,20 +517,11 @@
 	 */
 	public void remove(String name)
 	{
-		remove(HttpHeaders.CACHE.lookup(name));
+		removeLower(name.toLowerCase());
 	}
 
-	/* ------------------------------------------------------------ */
-	/**
-	 * Remove a field.
-	 * 
-	 * @param name
-	 */
-	public void remove(Buffer name)
-	{
-		if (!(name instanceof BufferCache.CachedBuffer)) 
-			name = HttpHeaders.CACHE.lookup(name);
-		Field field = _names.remove(name);
+	private void removeLower(String nameLower) {
+		Field field = _names.remove(nameLower);
 		while (field != null)
 		{
 			_fields.remove(field);
@@ -709,20 +545,6 @@
 
 	/* -------------------------------------------------------------- */
 	/**
-	 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The
-	 * case of the field name is ignored.
-	 * 
-	 * @param name the case-insensitive field name
-	 * @exception NumberFormatException If bad long found
-	 */
-	public long getLongField(Buffer name) throws NumberFormatException
-	{
-		Field field = getField(name);
-		return field==null?-1L:field.getLongValue();
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
 	 * Get a header as a date value. Returns the value of a date field, or -1 if not found. The case
 	 * of the field name is ignored.
 	 * 
@@ -751,9 +573,8 @@
 	 * @param name the field name
 	 * @param value the field long value
 	 */
-	public void putLongField(Buffer name, long value)
+	public void putLongField(String name, long value)
 	{
-//		Buffer v = BufferUtil.toBuffer(value);
 		String v = Long.toString(value);
 		put(name, v);
 	}
@@ -765,39 +586,8 @@
 	 * @param name the field name
 	 * @param value the field long value
 	 */
-	public void putLongField(String name, long value)
-	{
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-//		Buffer v = BufferUtil.toBuffer(value);
-		String v = Long.toString(value);
-		put(n, v);
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Sets the value of an long field.
-	 * 
-	 * @param name the field name
-	 * @param value the field long value
-	 */
 	public void addLongField(String name, long value)
 	{
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-//		Buffer v = BufferUtil.toBuffer(value);
-		String v = Long.toString(value);
-		add(n, v);
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Sets the value of an long field.
-	 * 
-	 * @param name the field name
-	 * @param value the field long value
-	 */
-	public void addLongField(Buffer name, long value)
-	{
-//		Buffer v = BufferUtil.toBuffer(value);
 		String v = Long.toString(value);
 		add(name, v);
 	}
@@ -809,24 +599,10 @@
 	 * @param name the field name
 	 * @param date the field date value
 	 */
-	public void putDateField(Buffer name, long date)
-	{
-		String d=formatDate(date);
-		Buffer v = new ByteArrayBuffer(d);
-		put(name, v);
-	}
-
-	/* -------------------------------------------------------------- */
-	/**
-	 * Sets the value of a date field.
-	 * 
-	 * @param name the field name
-	 * @param date the field date value
-	 */
 	public void putDateField(String name, long date)
 	{
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-		putDateField(n,date);
+		String d = formatDate(date);
+		put(name, d);
 	}
 
 	/* -------------------------------------------------------------- */
@@ -838,10 +614,8 @@
 	 */
 	public void addDateField(String name, long date)
 	{
-		String d=formatDate(date);
-		Buffer n = HttpHeaders.CACHE.lookup(name);
-//		Buffer v = new ByteArrayBuffer(d);
-		add(n, d);
+		String d = formatDate(date);
+		add(name, d);
 	}
 
 	/* ------------------------------------------------------------ */
@@ -965,7 +739,7 @@
 				{
 					_fields.remove(field);
 					if (last==null)
-						_names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next);
+						_names.put(HttpHeaders.SET_COOKIE,field._next);
 					else
 						last._next=field._next;
 					break;
@@ -975,10 +749,10 @@
 			field=field._next;
 		}
 
-		add(HttpHeaders.SET_COOKIE_BUFFER, name_value_params);
+		add(HttpHeaders.SET_COOKIE, name_value_params);
 		
 		// Expire responses with set-cookie headers so they do not get cached.
-		put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
+		put(HttpHeaders.EXPIRES, __01Jan1970);
 	}
 
 	@Override
@@ -1159,36 +933,25 @@
 
 	public static final class Field
 	{
-		private final Buffer _name;
+		private final String _name;
 		private final String _value;
-		private final int _valueOrdinal;
 		private Field _next;
 
-		private Field(Buffer name, String value, int valueOrdinal)
+		private Field(String name, String value)
 		{
 			_name = name;
 			_value = value;
-			_valueOrdinal = valueOrdinal;
 			_next = null;
 		}
-/*
-		private Field(Buffer name, Buffer value)
-		{
-			this(name,value.toString(),HttpHeaderValues.CACHE.getOrdinal(value));
-		}
-*/
+
 		public void putTo(Buffer buffer) throws IOException
 		{
-			int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
-			if (o>=0)
-				buffer.put(_name);
+			byte[] nameBytes = StringUtil.getBytes(_name);
+			if (getNameOrdinal() >=0 )
+				buffer.put(nameBytes);
 			else
 			{
-				int s=_name.getIndex();
-				int e=_name.putIndex();
-				while (s<e)
-				{
-					byte b=_name.peek(s++);
+				for( byte b : nameBytes ) {
 					switch(b)
 					{
 						case '\r':
@@ -1204,9 +967,8 @@
 			buffer.put((byte) ':');
 			buffer.put((byte) ' ');
 			
-			o = _valueOrdinal;
 			byte[] valueBytes = StringUtil.getBytes(_value);
-			if (o>=0)
+			if (getValueOrdinal() >= 0)
 				buffer.put(valueBytes);
 			else
 			{
@@ -1242,7 +1004,7 @@
 
 		public int getValueOrdinal()
 		{
-			return _valueOrdinal;
+			return HttpHeaderValues.CACHE.getOrdinal(_value);
 		}
 
 		public int getIntValue()
--- a/src/org/eclipse/jetty/http/HttpGenerator.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpGenerator.java	Tue Nov 01 01:04:46 2016 -0600
@@ -606,7 +606,7 @@
 						if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent)
 						{
 							// known length but not actually set.
-							_header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
+							_header.put(HttpHeaders.CONTENT_LENGTH_BYTES);
 							_header.put(HttpTokens.COLON);
 							_header.put((byte) ' ');
 							BufferUtil.putDecLong(_header, _contentLength);
--- a/src/org/eclipse/jetty/http/HttpHeaderValues.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpHeaderValues.java	Tue Nov 01 01:04:46 2016 -0600
@@ -70,16 +70,4 @@
 		NO_CACHE_BYTES=CACHE.add(NO_CACHE,NO_CACHE_ORDINAL),
 		UPGRADE_BYTES=CACHE.add(UPGRADE,UPGRADE_ORDINAL);
 		
-
-	public static boolean hasKnownValues(int httpHeaderOrdinal)
-	{
-		switch(httpHeaderOrdinal)
-		{
-			case HttpHeaders.CONNECTION_ORDINAL:
-			case HttpHeaders.TRANSFER_ENCODING_ORDINAL:
-			case HttpHeaders.CONTENT_ENCODING_ORDINAL:
-				return true;
-		}
-		return false;
-	}
 }
--- a/src/org/eclipse/jetty/http/HttpHeaders.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpHeaders.java	Tue Nov 01 01:04:46 2016 -0600
@@ -18,224 +18,220 @@
 
 package org.eclipse.jetty.http;
 
-import org.eclipse.jetty.io.Buffer;
-import org.eclipse.jetty.io.BufferCache;
+import org.eclipse.jetty.io.StringCache;
 
-/* ------------------------------------------------------------------------------- */
-/** 
- */
-public class HttpHeaders extends BufferCache
+
+public final class HttpHeaders
 {
-    /* ------------------------------------------------------------ */
-    /** General Fields.
-     */
-    public final static String 
-        CONNECTION= "Connection",
-        CACHE_CONTROL= "Cache-Control",
-        DATE= "Date",
-        PRAGMA= "Pragma",
-        PROXY_CONNECTION = "Proxy-Connection",
-        TRAILER= "Trailer",
-        TRANSFER_ENCODING= "Transfer-Encoding",
-        UPGRADE= "Upgrade",
-        VIA= "Via",
-        WARNING= "Warning",
-        NEGOTIATE= "Negotiate";
+	/* ------------------------------------------------------------ */
+	/** General Fields.
+	 */
+	public final static String 
+		CONNECTION= "Connection",
+		CACHE_CONTROL= "Cache-Control",
+		DATE= "Date",
+		PRAGMA= "Pragma",
+		PROXY_CONNECTION = "Proxy-Connection",
+		TRAILER= "Trailer",
+		TRANSFER_ENCODING= "Transfer-Encoding",
+		UPGRADE= "Upgrade",
+		VIA= "Via",
+		WARNING= "Warning",
+		NEGOTIATE= "Negotiate";
 
-    /* ------------------------------------------------------------ */
-    /** Entity Fields.
-     */
-    public final static String ALLOW= "Allow",
-        CONTENT_ENCODING= "Content-Encoding",
-        CONTENT_LANGUAGE= "Content-Language",
-        CONTENT_LENGTH= "Content-Length",
-        CONTENT_LOCATION= "Content-Location",
-        CONTENT_MD5= "Content-MD5",
-        CONTENT_RANGE= "Content-Range",
-        CONTENT_TYPE= "Content-Type",
-        EXPIRES= "Expires",
-        LAST_MODIFIED= "Last-Modified";
+	/* ------------------------------------------------------------ */
+	/** Entity Fields.
+	 */
+	public final static String ALLOW= "Allow",
+		CONTENT_ENCODING= "Content-Encoding",
+		CONTENT_LANGUAGE= "Content-Language",
+		CONTENT_LENGTH= "Content-Length",
+		CONTENT_LOCATION= "Content-Location",
+		CONTENT_MD5= "Content-MD5",
+		CONTENT_RANGE= "Content-Range",
+		CONTENT_TYPE= "Content-Type",
+		EXPIRES= "Expires",
+		LAST_MODIFIED= "Last-Modified";
 
-    /* ------------------------------------------------------------ */
-    /** Request Fields.
-     */
-    public final static String ACCEPT= "Accept",
-        ACCEPT_CHARSET= "Accept-Charset",
-        ACCEPT_ENCODING= "Accept-Encoding",
-        ACCEPT_LANGUAGE= "Accept-Language",
-        AUTHORIZATION= "Authorization",
-        EXPECT= "Expect",
-        FORWARDED= "Forwarded",
-        FROM= "From",
-        HOST= "Host",
-        IF_MATCH= "If-Match",
-        IF_MODIFIED_SINCE= "If-Modified-Since",
-        IF_NONE_MATCH= "If-None-Match",
-        IF_RANGE= "If-Range",
-        IF_UNMODIFIED_SINCE= "If-Unmodified-Since",
-        KEEP_ALIVE= "Keep-Alive",
-        MAX_FORWARDS= "Max-Forwards",
-        PROXY_AUTHORIZATION= "Proxy-Authorization",
-        RANGE= "Range",
-        REQUEST_RANGE= "Request-Range",
-        REFERER= "Referer",
-        TE= "TE",
-        USER_AGENT= "User-Agent",
-        X_FORWARDED_FOR= "X-Forwarded-For",
-        X_FORWARDED_PROTO= "X-Forwarded-Proto",
-        X_FORWARDED_SERVER= "X-Forwarded-Server",
-        X_FORWARDED_HOST= "X-Forwarded-Host";
+	/* ------------------------------------------------------------ */
+	/** Request Fields.
+	 */
+	public final static String ACCEPT= "Accept",
+		ACCEPT_CHARSET= "Accept-Charset",
+		ACCEPT_ENCODING= "Accept-Encoding",
+		ACCEPT_LANGUAGE= "Accept-Language",
+		AUTHORIZATION= "Authorization",
+		EXPECT= "Expect",
+		FORWARDED= "Forwarded",
+		FROM= "From",
+		HOST= "Host",
+		IF_MATCH= "If-Match",
+		IF_MODIFIED_SINCE= "If-Modified-Since",
+		IF_NONE_MATCH= "If-None-Match",
+		IF_RANGE= "If-Range",
+		IF_UNMODIFIED_SINCE= "If-Unmodified-Since",
+		KEEP_ALIVE= "Keep-Alive",
+		MAX_FORWARDS= "Max-Forwards",
+		PROXY_AUTHORIZATION= "Proxy-Authorization",
+		RANGE= "Range",
+		REQUEST_RANGE= "Request-Range",
+		REFERER= "Referer",
+		TE= "TE",
+		USER_AGENT= "User-Agent",
+		X_FORWARDED_FOR= "X-Forwarded-For",
+		X_FORWARDED_PROTO= "X-Forwarded-Proto",
+		X_FORWARDED_SERVER= "X-Forwarded-Server",
+		X_FORWARDED_HOST= "X-Forwarded-Host";
 
-    /* ------------------------------------------------------------ */
-    /** Response Fields.
-     */
-    public final static String ACCEPT_RANGES= "Accept-Ranges",
-        AGE= "Age",
-        ETAG= "ETag",
-        LOCATION= "Location",
-        PROXY_AUTHENTICATE= "Proxy-Authenticate",
-        RETRY_AFTER= "Retry-After",
-        SERVER= "Server",
-        SERVLET_ENGINE= "Servlet-Engine",
-        VARY= "Vary",
-        WWW_AUTHENTICATE= "WWW-Authenticate";
+	/* ------------------------------------------------------------ */
+	/** Response Fields.
+	 */
+	public final static String ACCEPT_RANGES= "Accept-Ranges",
+		AGE= "Age",
+		ETAG= "ETag",
+		LOCATION= "Location",
+		PROXY_AUTHENTICATE= "Proxy-Authenticate",
+		RETRY_AFTER= "Retry-After",
+		SERVER= "Server",
+		SERVLET_ENGINE= "Servlet-Engine",
+		VARY= "Vary",
+		WWW_AUTHENTICATE= "WWW-Authenticate";
 
-    /* ------------------------------------------------------------ */
-    /** Other Fields.
-     */
-    public final static String COOKIE= "Cookie",
-        SET_COOKIE= "Set-Cookie",
-        SET_COOKIE2= "Set-Cookie2",
-        MIME_VERSION= "MIME-Version",
-        IDENTITY= "identity";
+	/* ------------------------------------------------------------ */
+	/** Other Fields.
+	 */
+	public final static String COOKIE= "Cookie",
+		SET_COOKIE= "Set-Cookie",
+		SET_COOKIE2= "Set-Cookie2",
+		MIME_VERSION= "MIME-Version",
+		IDENTITY= "identity";
 
-    public final static int CONNECTION_ORDINAL= 1,
-        DATE_ORDINAL= 2,
-        PRAGMA_ORDINAL= 3,
-        TRAILER_ORDINAL= 4,
-        TRANSFER_ENCODING_ORDINAL= 5,
-        UPGRADE_ORDINAL= 6,
-        VIA_ORDINAL= 7,
-        WARNING_ORDINAL= 8,
-        ALLOW_ORDINAL= 9,
-        CONTENT_ENCODING_ORDINAL= 10,
-        CONTENT_LANGUAGE_ORDINAL= 11,
-        CONTENT_LENGTH_ORDINAL= 12,
-        CONTENT_LOCATION_ORDINAL= 13,
-        CONTENT_MD5_ORDINAL= 14,
-        CONTENT_RANGE_ORDINAL= 15,
-        CONTENT_TYPE_ORDINAL= 16,
-        EXPIRES_ORDINAL= 17,
-        LAST_MODIFIED_ORDINAL= 18,
-        ACCEPT_ORDINAL= 19,
-        ACCEPT_CHARSET_ORDINAL= 20,
-        ACCEPT_ENCODING_ORDINAL= 21,
-        ACCEPT_LANGUAGE_ORDINAL= 22,
-        AUTHORIZATION_ORDINAL= 23,
-        EXPECT_ORDINAL= 24,
-        FORWARDED_ORDINAL= 25,
-        FROM_ORDINAL= 26,
-        HOST_ORDINAL= 27,
-        IF_MATCH_ORDINAL= 28,
-        IF_MODIFIED_SINCE_ORDINAL= 29,
-        IF_NONE_MATCH_ORDINAL= 30,
-        IF_RANGE_ORDINAL= 31,
-        IF_UNMODIFIED_SINCE_ORDINAL= 32,
-        KEEP_ALIVE_ORDINAL= 33,
-        MAX_FORWARDS_ORDINAL= 34,
-        PROXY_AUTHORIZATION_ORDINAL= 35,
-        RANGE_ORDINAL= 36,
-        REQUEST_RANGE_ORDINAL= 37,
-        REFERER_ORDINAL= 38,
-        TE_ORDINAL= 39,
-        USER_AGENT_ORDINAL= 40,
-        X_FORWARDED_FOR_ORDINAL= 41,
-        ACCEPT_RANGES_ORDINAL= 42,
-        AGE_ORDINAL= 43,
-        ETAG_ORDINAL= 44,
-        LOCATION_ORDINAL= 45,
-        PROXY_AUTHENTICATE_ORDINAL= 46,
-        RETRY_AFTER_ORDINAL= 47,
-        SERVER_ORDINAL= 48,
-        SERVLET_ENGINE_ORDINAL= 49,
-        VARY_ORDINAL= 50,
-        WWW_AUTHENTICATE_ORDINAL= 51,
-        COOKIE_ORDINAL= 52,
-        SET_COOKIE_ORDINAL= 53,
-        SET_COOKIE2_ORDINAL= 54,
-        MIME_VERSION_ORDINAL= 55,
-        IDENTITY_ORDINAL= 56,
-        CACHE_CONTROL_ORDINAL=57,
-        PROXY_CONNECTION_ORDINAL=58,
-        X_FORWARDED_PROTO_ORDINAL=59,
-        X_FORWARDED_SERVER_ORDINAL=60,
-        X_FORWARDED_HOST_ORDINAL=61;
+	public final static int CONNECTION_ORDINAL= 1,
+		DATE_ORDINAL= 2,
+		PRAGMA_ORDINAL= 3,
+		TRAILER_ORDINAL= 4,
+		TRANSFER_ENCODING_ORDINAL= 5,
+		UPGRADE_ORDINAL= 6,
+		VIA_ORDINAL= 7,
+		WARNING_ORDINAL= 8,
+		ALLOW_ORDINAL= 9,
+		CONTENT_ENCODING_ORDINAL= 10,
+		CONTENT_LANGUAGE_ORDINAL= 11,
+		CONTENT_LENGTH_ORDINAL= 12,
+		CONTENT_LOCATION_ORDINAL= 13,
+		CONTENT_MD5_ORDINAL= 14,
+		CONTENT_RANGE_ORDINAL= 15,
+		CONTENT_TYPE_ORDINAL= 16,
+		EXPIRES_ORDINAL= 17,
+		LAST_MODIFIED_ORDINAL= 18,
+		ACCEPT_ORDINAL= 19,
+		ACCEPT_CHARSET_ORDINAL= 20,
+		ACCEPT_ENCODING_ORDINAL= 21,
+		ACCEPT_LANGUAGE_ORDINAL= 22,
+		AUTHORIZATION_ORDINAL= 23,
+		EXPECT_ORDINAL= 24,
+		FORWARDED_ORDINAL= 25,
+		FROM_ORDINAL= 26,
+		HOST_ORDINAL= 27,
+		IF_MATCH_ORDINAL= 28,
+		IF_MODIFIED_SINCE_ORDINAL= 29,
+		IF_NONE_MATCH_ORDINAL= 30,
+		IF_RANGE_ORDINAL= 31,
+		IF_UNMODIFIED_SINCE_ORDINAL= 32,
+		KEEP_ALIVE_ORDINAL= 33,
+		MAX_FORWARDS_ORDINAL= 34,
+		PROXY_AUTHORIZATION_ORDINAL= 35,
+		RANGE_ORDINAL= 36,
+		REQUEST_RANGE_ORDINAL= 37,
+		REFERER_ORDINAL= 38,
+		TE_ORDINAL= 39,
+		USER_AGENT_ORDINAL= 40,
+		X_FORWARDED_FOR_ORDINAL= 41,
+		ACCEPT_RANGES_ORDINAL= 42,
+		AGE_ORDINAL= 43,
+		ETAG_ORDINAL= 44,
+		LOCATION_ORDINAL= 45,
+		PROXY_AUTHENTICATE_ORDINAL= 46,
+		RETRY_AFTER_ORDINAL= 47,
+		SERVER_ORDINAL= 48,
+		SERVLET_ENGINE_ORDINAL= 49,
+		VARY_ORDINAL= 50,
+		WWW_AUTHENTICATE_ORDINAL= 51,
+		COOKIE_ORDINAL= 52,
+		SET_COOKIE_ORDINAL= 53,
+		SET_COOKIE2_ORDINAL= 54,
+		MIME_VERSION_ORDINAL= 55,
+		IDENTITY_ORDINAL= 56,
+		CACHE_CONTROL_ORDINAL=57,
+		PROXY_CONNECTION_ORDINAL=58,
+		X_FORWARDED_PROTO_ORDINAL=59,
+		X_FORWARDED_SERVER_ORDINAL=60,
+		X_FORWARDED_HOST_ORDINAL=61;
 
-    public final static HttpHeaders CACHE= new HttpHeaders();
-    
-    public final static Buffer
-        HOST_BUFFER=CACHE.add(HOST,HOST_ORDINAL),
-        ACCEPT_BUFFER=CACHE.add(ACCEPT,ACCEPT_ORDINAL),
-        ACCEPT_CHARSET_BUFFER=CACHE.add(ACCEPT_CHARSET,ACCEPT_CHARSET_ORDINAL),
-        ACCEPT_ENCODING_BUFFER=CACHE.add(ACCEPT_ENCODING,ACCEPT_ENCODING_ORDINAL),
-        ACCEPT_LANGUAGE_BUFFER=CACHE.add(ACCEPT_LANGUAGE,ACCEPT_LANGUAGE_ORDINAL),
-        
-        CONTENT_LENGTH_BUFFER=CACHE.add(CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL),
-        CONNECTION_BUFFER=CACHE.add(CONNECTION,CONNECTION_ORDINAL),
-        CACHE_CONTROL_BUFFER=CACHE.add(CACHE_CONTROL,CACHE_CONTROL_ORDINAL),
-        DATE_BUFFER=CACHE.add(DATE,DATE_ORDINAL),
-        PRAGMA_BUFFER=CACHE.add(PRAGMA,PRAGMA_ORDINAL),
-        TRAILER_BUFFER=CACHE.add(TRAILER,TRAILER_ORDINAL),
-        TRANSFER_ENCODING_BUFFER=CACHE.add(TRANSFER_ENCODING,TRANSFER_ENCODING_ORDINAL),
-        UPGRADE_BUFFER=CACHE.add(UPGRADE,UPGRADE_ORDINAL),
-        VIA_BUFFER=CACHE.add(VIA,VIA_ORDINAL),
-        WARNING_BUFFER=CACHE.add(WARNING,WARNING_ORDINAL),
-        ALLOW_BUFFER=CACHE.add(ALLOW,ALLOW_ORDINAL),
-        CONTENT_ENCODING_BUFFER=CACHE.add(CONTENT_ENCODING,CONTENT_ENCODING_ORDINAL),
-        CONTENT_LANGUAGE_BUFFER=CACHE.add(CONTENT_LANGUAGE,CONTENT_LANGUAGE_ORDINAL),
-        CONTENT_LOCATION_BUFFER=CACHE.add(CONTENT_LOCATION,CONTENT_LOCATION_ORDINAL),
-        CONTENT_MD5_BUFFER=CACHE.add(CONTENT_MD5,CONTENT_MD5_ORDINAL),
-        CONTENT_RANGE_BUFFER=CACHE.add(CONTENT_RANGE,CONTENT_RANGE_ORDINAL),
-        CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL),
-        EXPIRES_BUFFER=CACHE.add(EXPIRES,EXPIRES_ORDINAL),
-        LAST_MODIFIED_BUFFER=CACHE.add(LAST_MODIFIED,LAST_MODIFIED_ORDINAL),
-        AUTHORIZATION_BUFFER=CACHE.add(AUTHORIZATION,AUTHORIZATION_ORDINAL),
-        EXPECT_BUFFER=CACHE.add(EXPECT,EXPECT_ORDINAL),
-        FORWARDED_BUFFER=CACHE.add(FORWARDED,FORWARDED_ORDINAL),
-        FROM_BUFFER=CACHE.add(FROM,FROM_ORDINAL),
-        IF_MATCH_BUFFER=CACHE.add(IF_MATCH,IF_MATCH_ORDINAL),
-        IF_MODIFIED_SINCE_BUFFER=CACHE.add(IF_MODIFIED_SINCE,IF_MODIFIED_SINCE_ORDINAL),
-        IF_NONE_MATCH_BUFFER=CACHE.add(IF_NONE_MATCH,IF_NONE_MATCH_ORDINAL),
-        IF_RANGE_BUFFER=CACHE.add(IF_RANGE,IF_RANGE_ORDINAL),
-        IF_UNMODIFIED_SINCE_BUFFER=CACHE.add(IF_UNMODIFIED_SINCE,IF_UNMODIFIED_SINCE_ORDINAL),
-        KEEP_ALIVE_BUFFER=CACHE.add(KEEP_ALIVE,KEEP_ALIVE_ORDINAL),
-        MAX_FORWARDS_BUFFER=CACHE.add(MAX_FORWARDS,MAX_FORWARDS_ORDINAL),
-        PROXY_AUTHORIZATION_BUFFER=CACHE.add(PROXY_AUTHORIZATION,PROXY_AUTHORIZATION_ORDINAL),
-        RANGE_BUFFER=CACHE.add(RANGE,RANGE_ORDINAL),
-        REQUEST_RANGE_BUFFER=CACHE.add(REQUEST_RANGE,REQUEST_RANGE_ORDINAL),
-        REFERER_BUFFER=CACHE.add(REFERER,REFERER_ORDINAL),
-        TE_BUFFER=CACHE.add(TE,TE_ORDINAL),
-        USER_AGENT_BUFFER=CACHE.add(USER_AGENT,USER_AGENT_ORDINAL),
-        X_FORWARDED_FOR_BUFFER=CACHE.add(X_FORWARDED_FOR,X_FORWARDED_FOR_ORDINAL),
-        X_FORWARDED_PROTO_BUFFER=CACHE.add(X_FORWARDED_PROTO,X_FORWARDED_PROTO_ORDINAL),
-        X_FORWARDED_SERVER_BUFFER=CACHE.add(X_FORWARDED_SERVER,X_FORWARDED_SERVER_ORDINAL),
-        X_FORWARDED_HOST_BUFFER=CACHE.add(X_FORWARDED_HOST,X_FORWARDED_HOST_ORDINAL),
-        ACCEPT_RANGES_BUFFER=CACHE.add(ACCEPT_RANGES,ACCEPT_RANGES_ORDINAL),
-        AGE_BUFFER=CACHE.add(AGE,AGE_ORDINAL),
-        ETAG_BUFFER=CACHE.add(ETAG,ETAG_ORDINAL),
-        LOCATION_BUFFER=CACHE.add(LOCATION,LOCATION_ORDINAL),
-        PROXY_AUTHENTICATE_BUFFER=CACHE.add(PROXY_AUTHENTICATE,PROXY_AUTHENTICATE_ORDINAL),
-        RETRY_AFTER_BUFFER=CACHE.add(RETRY_AFTER,RETRY_AFTER_ORDINAL),
-        SERVER_BUFFER=CACHE.add(SERVER,SERVER_ORDINAL),
-        SERVLET_ENGINE_BUFFER=CACHE.add(SERVLET_ENGINE,SERVLET_ENGINE_ORDINAL),
-        VARY_BUFFER=CACHE.add(VARY,VARY_ORDINAL),
-        WWW_AUTHENTICATE_BUFFER=CACHE.add(WWW_AUTHENTICATE,WWW_AUTHENTICATE_ORDINAL),
-        COOKIE_BUFFER=CACHE.add(COOKIE,COOKIE_ORDINAL),
-        SET_COOKIE_BUFFER=CACHE.add(SET_COOKIE,SET_COOKIE_ORDINAL),
-        SET_COOKIE2_BUFFER=CACHE.add(SET_COOKIE2,SET_COOKIE2_ORDINAL),
-        MIME_VERSION_BUFFER=CACHE.add(MIME_VERSION,MIME_VERSION_ORDINAL),
-        IDENTITY_BUFFER=CACHE.add(IDENTITY,IDENTITY_ORDINAL),
-        PROXY_CONNECTION_BUFFER=CACHE.add(PROXY_CONNECTION,PROXY_CONNECTION_ORDINAL);
-    
-    
+	public final static StringCache CACHE= new StringCache();
+	
+	public final static byte[]
+		HOST_BYTES=CACHE.add(HOST,HOST_ORDINAL),
+		ACCEPT_BYTES=CACHE.add(ACCEPT,ACCEPT_ORDINAL),
+		ACCEPT_CHARSET_BYTES=CACHE.add(ACCEPT_CHARSET,ACCEPT_CHARSET_ORDINAL),
+		ACCEPT_ENCODING_BYTES=CACHE.add(ACCEPT_ENCODING,ACCEPT_ENCODING_ORDINAL),
+		ACCEPT_LANGUAGE_BYTES=CACHE.add(ACCEPT_LANGUAGE,ACCEPT_LANGUAGE_ORDINAL),
+		
+		CONTENT_LENGTH_BYTES=CACHE.add(CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL),
+		CONNECTION_BYTES=CACHE.add(CONNECTION,CONNECTION_ORDINAL),
+		CACHE_CONTROL_BYTES=CACHE.add(CACHE_CONTROL,CACHE_CONTROL_ORDINAL),
+		DATE_BYTES=CACHE.add(DATE,DATE_ORDINAL),
+		PRAGMA_BYTES=CACHE.add(PRAGMA,PRAGMA_ORDINAL),
+		TRAILER_BYTES=CACHE.add(TRAILER,TRAILER_ORDINAL),
+		TRANSFER_ENCODING_BYTES=CACHE.add(TRANSFER_ENCODING,TRANSFER_ENCODING_ORDINAL),
+		UPGRADE_BYTES=CACHE.add(UPGRADE,UPGRADE_ORDINAL),
+		VIA_BYTES=CACHE.add(VIA,VIA_ORDINAL),
+		WARNING_BYTES=CACHE.add(WARNING,WARNING_ORDINAL),
+		ALLOW_BYTES=CACHE.add(ALLOW,ALLOW_ORDINAL),
+		CONTENT_ENCODING_BYTES=CACHE.add(CONTENT_ENCODING,CONTENT_ENCODING_ORDINAL),
+		CONTENT_LANGUAGE_BYTES=CACHE.add(CONTENT_LANGUAGE,CONTENT_LANGUAGE_ORDINAL),
+		CONTENT_LOCATION_BYTES=CACHE.add(CONTENT_LOCATION,CONTENT_LOCATION_ORDINAL),
+		CONTENT_MD5_BYTES=CACHE.add(CONTENT_MD5,CONTENT_MD5_ORDINAL),
+		CONTENT_RANGE_BYTES=CACHE.add(CONTENT_RANGE,CONTENT_RANGE_ORDINAL),
+		CONTENT_TYPE_BYTES=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL),
+		EXPIRES_BYTES=CACHE.add(EXPIRES,EXPIRES_ORDINAL),
+		LAST_MODIFIED_BYTES=CACHE.add(LAST_MODIFIED,LAST_MODIFIED_ORDINAL),
+		AUTHORIZATION_BYTES=CACHE.add(AUTHORIZATION,AUTHORIZATION_ORDINAL),
+		EXPECT_BYTES=CACHE.add(EXPECT,EXPECT_ORDINAL),
+		FORWARDED_BYTES=CACHE.add(FORWARDED,FORWARDED_ORDINAL),
+		FROM_BYTES=CACHE.add(FROM,FROM_ORDINAL),
+		IF_MATCH_BYTES=CACHE.add(IF_MATCH,IF_MATCH_ORDINAL),
+		IF_MODIFIED_SINCE_BYTES=CACHE.add(IF_MODIFIED_SINCE,IF_MODIFIED_SINCE_ORDINAL),
+		IF_NONE_MATCH_BYTES=CACHE.add(IF_NONE_MATCH,IF_NONE_MATCH_ORDINAL),
+		IF_RANGE_BYTES=CACHE.add(IF_RANGE,IF_RANGE_ORDINAL),
+		IF_UNMODIFIED_SINCE_BYTES=CACHE.add(IF_UNMODIFIED_SINCE,IF_UNMODIFIED_SINCE_ORDINAL),
+		KEEP_ALIVE_BYTES=CACHE.add(KEEP_ALIVE,KEEP_ALIVE_ORDINAL),
+		MAX_FORWARDS_BYTES=CACHE.add(MAX_FORWARDS,MAX_FORWARDS_ORDINAL),
+		PROXY_AUTHORIZATION_BYTES=CACHE.add(PROXY_AUTHORIZATION,PROXY_AUTHORIZATION_ORDINAL),
+		RANGE_BYTES=CACHE.add(RANGE,RANGE_ORDINAL),
+		REQUEST_RANGE_BYTES=CACHE.add(REQUEST_RANGE,REQUEST_RANGE_ORDINAL),
+		REFERER_BYTES=CACHE.add(REFERER,REFERER_ORDINAL),
+		TE_BYTES=CACHE.add(TE,TE_ORDINAL),
+		USER_AGENT_BYTES=CACHE.add(USER_AGENT,USER_AGENT_ORDINAL),
+		X_FORWARDED_FOR_BYTES=CACHE.add(X_FORWARDED_FOR,X_FORWARDED_FOR_ORDINAL),
+		X_FORWARDED_PROTO_BYTES=CACHE.add(X_FORWARDED_PROTO,X_FORWARDED_PROTO_ORDINAL),
+		X_FORWARDED_SERVER_BYTES=CACHE.add(X_FORWARDED_SERVER,X_FORWARDED_SERVER_ORDINAL),
+		X_FORWARDED_HOST_BYTES=CACHE.add(X_FORWARDED_HOST,X_FORWARDED_HOST_ORDINAL),
+		ACCEPT_RANGES_BYTES=CACHE.add(ACCEPT_RANGES,ACCEPT_RANGES_ORDINAL),
+		AGE_BYTES=CACHE.add(AGE,AGE_ORDINAL),
+		ETAG_BYTES=CACHE.add(ETAG,ETAG_ORDINAL),
+		LOCATION_BYTES=CACHE.add(LOCATION,LOCATION_ORDINAL),
+		PROXY_AUTHENTICATE_BYTES=CACHE.add(PROXY_AUTHENTICATE,PROXY_AUTHENTICATE_ORDINAL),
+		RETRY_AFTER_BYTES=CACHE.add(RETRY_AFTER,RETRY_AFTER_ORDINAL),
+		SERVER_BYTES=CACHE.add(SERVER,SERVER_ORDINAL),
+		SERVLET_ENGINE_BYTES=CACHE.add(SERVLET_ENGINE,SERVLET_ENGINE_ORDINAL),
+		VARY_BYTES=CACHE.add(VARY,VARY_ORDINAL),
+		WWW_AUTHENTICATE_BYTES=CACHE.add(WWW_AUTHENTICATE,WWW_AUTHENTICATE_ORDINAL),
+		COOKIE_BYTES=CACHE.add(COOKIE,COOKIE_ORDINAL),
+		SET_COOKIE_BYTES=CACHE.add(SET_COOKIE,SET_COOKIE_ORDINAL),
+		SET_COOKIE2_BYTES=CACHE.add(SET_COOKIE2,SET_COOKIE2_ORDINAL),
+		MIME_VERSION_BYTES=CACHE.add(MIME_VERSION,MIME_VERSION_ORDINAL),
+		IDENTITY_BYTES=CACHE.add(IDENTITY,IDENTITY_ORDINAL),
+		PROXY_CONNECTION_BYTES=CACHE.add(PROXY_CONNECTION,PROXY_CONNECTION_ORDINAL);
+
 }
--- a/src/org/eclipse/jetty/http/HttpParser.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/http/HttpParser.java	Tue Nov 01 01:04:46 2016 -0600
@@ -21,7 +21,6 @@
 import java.io.IOException;
 
 import org.eclipse.jetty.io.Buffer;
-import org.eclipse.jetty.io.BufferCache.CachedBuffer;
 import org.eclipse.jetty.io.BufferUtil;
 import org.eclipse.jetty.io.Buffers;
 import org.eclipse.jetty.io.ByteArrayBuffer;
@@ -66,7 +65,7 @@
 	private Buffer _header; // Buffer for header data (and small _content)
 	private Buffer _body; // Buffer for large content
 	private Buffer _buffer; // The current buffer in use (either _header or _content)
-	private CachedBuffer _cached;
+	private String _cached;
 	private String _tok0; // Saved token: header name, request method or response version
 	private final View.CaseInsensitive _tok1 = new View.CaseInsensitive(); // Saved token: header value, request URI or response code
 	private String _multiLineValue;
@@ -436,7 +435,7 @@
 								// handler last header if any
 								if (_cached!=null || _tok0.length() > 0 || _tok1.length() > 0 || _multiLineValue != null)
 								{
-									String header = _cached!=null?_cached.toString():_tok0;
+									String header = _cached!=null ? _cached : _tok0;
 									_cached = null;
 									String value = _multiLineValue == null ? _tok1.toString() : _multiLineValue;
 
@@ -582,7 +581,8 @@
 									// try cached name!
 									if (array!=null)
 									{
-										_cached = HttpHeaders.CACHE.getBest(array, _buffer.markIndex(), length+1);
+										String s = new String(array, _buffer.markIndex(), length+1);
+										_cached = HttpHeaders.CACHE.getBest(s);
 
 										if (_cached!=null)
 										{
--- a/src/org/eclipse/jetty/io/StringCache.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/io/StringCache.java	Tue Nov 01 01:04:46 2016 -0600
@@ -2,18 +2,22 @@
 
 package org.eclipse.jetty.io;
 
+import java.util.Map;
 import java.util.HashMap;
-import java.util.Map;
+import java.util.TreeMap;
 import org.eclipse.jetty.util.StringUtil;
 
 
 public final class StringCache {
 	private final Map<String,Integer> stringToOrdinal = new HashMap<String,Integer>();
 //	private final Map<Integer,String> ordinalToString = new HashMap<Integer,String>();
+	private final TreeMap<String,String> stringMap = new TreeMap<String,String>();
 
 	public byte[] add(String value, int ordinal) {
-		stringToOrdinal.put(value.toLowerCase(), ordinal);
+		String valueLower = value.toLowerCase();
+		stringToOrdinal.put(valueLower, ordinal);
 //		ordinalToString.put(ordinal, value);
+		stringMap.put(valueLower,value);
 		return StringUtil.getBytes(value);
 	}
 
@@ -25,4 +29,29 @@
 	public boolean contains(String value) {
 		return stringToOrdinal.containsKey(value.toLowerCase());
 	}
+
+	public String getBest(String key) {
+		key = key.toLowerCase();
+		String rtn = stringMap.get(key);
+		if( rtn != null )
+			return rtn;
+		Map.Entry<String,String> floor = stringMap.floorEntry(key);
+		Map.Entry<String,String> ceiling = stringMap.ceilingEntry(key);
+		if( floor==null ) {
+			if( ceiling==null )
+				return null;
+			String ceilingKey = ceiling.getKey();
+			return key.charAt(0) == ceilingKey.charAt(0) ? ceiling.getValue() : null;
+		} else {
+			String floorKey = (String)floor.getKey();
+			if( ceiling==null )
+				return key.charAt(0) == floorKey.charAt(0) ? floor.getValue() : null;
+			String ceilingKey = ceiling.getKey();
+			int n = Math.min( key.length(), Math.min( floorKey.length(), ceilingKey.length() ) );
+			int i = 0;
+			while( ++i <= n && key.regionMatches(0,floorKey,0,i) && key.regionMatches(0,ceilingKey,0,i) );
+			return key.regionMatches(0,floorKey,0,i) ? floor.getValue() : key.regionMatches(0,ceilingKey,0,i) || i > 1 ? ceiling.getValue() : null;
+		}
+	}
+
 }
--- a/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/server/AbstractHttpConnection.java	Tue Nov 01 01:04:46 2016 -0600
@@ -577,7 +577,7 @@
 				_generator.setHead(_head);
 				if (_parser.isPersistent())
 				{
-					_responseFields.add(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.KEEP_ALIVE);
+					_responseFields.add(HttpHeaders.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
 					_generator.setPersistent(true);
 				}
 				else if (HttpMethods.CONNECT.equals(_request.getMethod()))
@@ -592,7 +592,7 @@
 
 				if (!_parser.isPersistent())
 				{
-					_responseFields.add(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE);
+					_responseFields.add(HttpHeaders.CONNECTION,HttpHeaderValues.CLOSE);
 					_generator.setPersistent(false);
 				}
 
@@ -600,7 +600,7 @@
 				{
 					LOG.debug("!host {}",this);
 					_generator.setResponse(HttpStatus.BAD_REQUEST_400, null);
-					_responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE);
+					_responseFields.put(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);
 					_generator.completeHeader(_responseFields, true);
 					_generator.complete();
 					return;
@@ -610,7 +610,7 @@
 				{
 					LOG.debug("!expectation {}",this);
 					_generator.setResponse(HttpStatus.EXPECTATION_FAILED_417, null);
-					_responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE);
+					_responseFields.put(HttpHeaders.CONNECTION, HttpHeaderValues.CLOSE);
 					_generator.completeHeader(_responseFields, true);
 					_generator.complete();
 					return;
--- a/src/org/eclipse/jetty/server/Request.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/server/Request.java	Tue Nov 01 01:04:46 2016 -0600
@@ -293,13 +293,13 @@
 	@Override
 	public int getContentLength()
 	{
-		return (int)_connection._requestFields.getLongField(HttpHeaders.CONTENT_LENGTH_BUFFER);
+		return (int)_connection._requestFields.getLongField(HttpHeaders.CONTENT_LENGTH);
 	}
 
 	@Override
 	public String getContentType()
 	{
-		return _connection._requestFields.getStringField(HttpHeaders.CONTENT_TYPE_BUFFER);
+		return _connection._requestFields.getStringField(HttpHeaders.CONTENT_TYPE);
 	}
 
 	@Override
@@ -316,7 +316,7 @@
 
 		_cookiesExtracted = true;
 
-		Enumeration enm = _connection._requestFields.getValues(HttpHeaders.COOKIE_BUFFER);
+		Enumeration enm = _connection._requestFields.getValues(HttpHeaders.COOKIE);
 
 		// Handle no cookies
 		if (enm != null)
@@ -676,7 +676,7 @@
 			return _serverName;
 
 		// Return host from header field
-		String hostPort = _connection._requestFields.getStringField(HttpHeaders.HOST_BUFFER);
+		String hostPort = _connection._requestFields.getStringField(HttpHeaders.HOST);
 		if (hostPort != null)
 		{
 			loop: for (int i = hostPort.length(); i-- > 0;)
--- a/src/org/eclipse/jetty/server/Response.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/server/Response.java	Tue Nov 01 01:04:46 2016 -0600
@@ -233,8 +233,8 @@
 		}
 		else if (code!=SC_PARTIAL_CONTENT)
 		{
-			_connection._requestFields.remove(HttpHeaders.CONTENT_TYPE_BUFFER);
-			_connection._requestFields.remove(HttpHeaders.CONTENT_LENGTH_BUFFER);
+			_connection._requestFields.remove(HttpHeaders.CONTENT_TYPE);
+			_connection._requestFields.remove(HttpHeaders.CONTENT_LENGTH);
 			_characterEncoding = null;
 			_mimeType = null;
 			_cachedMimeType = null;
@@ -488,9 +488,9 @@
 						_contentType = null;
 
 					if (_contentType==null)
-						_connection._responseFields.remove(HttpHeaders.CONTENT_TYPE_BUFFER);
+						_connection._responseFields.remove(HttpHeaders.CONTENT_TYPE);
 					else
-						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 				}
 			}
 			else
@@ -509,14 +509,14 @@
 							if (content_type!=null)
 							{
 								_contentType = content_type.toString();
-								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
+								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 							}
 						}
 
 						if (_contentType==null)
 						{
 							_contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 					}
 					else
@@ -535,7 +535,7 @@
 							else
 								_contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
 						}
-						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 					}
 				}
 			}
@@ -590,7 +590,7 @@
 			_mimeType = null;
 			_cachedMimeType = null;
 			_contentType=null;
-			_connection._responseFields.remove(HttpHeaders.CONTENT_TYPE_BUFFER);
+			_connection._responseFields.remove(HttpHeaders.CONTENT_TYPE);
 		}
 		else
 		{
@@ -624,29 +624,29 @@
 								if (content_type!=null)
 								{
 									_contentType=content_type.toString();
-									_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
+									_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 								}
 								else
 								{
 									_contentType = _mimeType+";charset="+_characterEncoding;
-									_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+									_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 								}
 							}
 							else
 							{
 								_contentType = _mimeType+";charset="+_characterEncoding;
-								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 							}
 						}
 						else if (i2<0)
 						{
 							_contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 						else
 						{
 							_contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 					}
 					else if ((i1==i0+1 && i2<0) || (i1==i0+2 && i2<0 && contentType.charAt(i0+1)==' '))
@@ -661,38 +661,38 @@
 							if (content_type!=null)
 							{
 								_contentType=content_type.toString();
-								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
+								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 							}
 							else
 							{
 								_contentType=contentType;
-								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+								_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 							}
 						}
 						else
 						{
 							_contentType=contentType;
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 					}
 					else if (i2>0)
 					{
 						_characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8,i2));
 						_contentType=contentType;
-						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 					}
 					else
 					{
 						_characterEncoding = QuotedStringTokenizer.unquote(contentType.substring(i8));
 						_contentType=contentType;
-						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 					}
 				}
 				else // No encoding in the params.
 				{
 					_cachedMimeType = null;
 					_contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 				}
 			}
 			else // No params at all
@@ -708,29 +708,29 @@
 						if (content_type!=null)
 						{
 							_contentType=content_type.toString();
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,content_type);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 						else
 						{
 							_contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+							_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 						}
 					}
 					else
 					{
 						_contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
-						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+						_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 					}
 				}
 				else if (_cachedMimeType!=null)
 				{
 					_contentType = _cachedMimeType.toString();
-					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_cachedMimeType);
+					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 				}
 				else
 				{
 					_contentType=contentType;
-					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
+					_connection._responseFields.put(HttpHeaders.CONTENT_TYPE,_contentType);
 				}
 			}
 		}
@@ -765,7 +765,7 @@
 		HttpFields response_fields=_connection._responseFields;
 		
 		response_fields.clear();
-		String connection=_connection._requestFields.getStringField(HttpHeaders.CONNECTION_BUFFER);
+		String connection=_connection._requestFields.getStringField(HttpHeaders.CONNECTION);
 		if (connection!=null)
 		{
 			String[] values = connection.split(",");
@@ -778,15 +778,15 @@
 					switch(cb)
 					{
 						case HttpHeaderValues.CLOSE_ORDINAL:
-							response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.CLOSE);
+							response_fields.put(HttpHeaders.CONNECTION,HttpHeaderValues.CLOSE);
 							break;
 
 						case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
 							if (HttpVersions.HTTP_1_0.equalsIgnoreCase(_connection.getRequest().getProtocol()))
-								response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.KEEP_ALIVE);
+								response_fields.put(HttpHeaders.CONNECTION,HttpHeaderValues.KEEP_ALIVE);
 							break;
 						case HttpHeaderValues.TE_ORDINAL:
-							response_fields.put(HttpHeaders.CONNECTION_BUFFER,HttpHeaderValues.TE);
+							response_fields.put(HttpHeaders.CONNECTION,HttpHeaderValues.TE);
 							break;
 					}
 				}
@@ -825,7 +825,7 @@
 			return;
 
 		_locale = locale;
-		_connection._responseFields.put(HttpHeaders.CONTENT_LANGUAGE_BUFFER,locale.toString().replace('_','-'));
+		_connection._responseFields.put(HttpHeaders.CONTENT_LANGUAGE,locale.toString().replace('_','-'));
 	}
 
 	@Override
--- a/src/org/eclipse/jetty/server/handler/DefaultHandler.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/server/handler/DefaultHandler.java	Tue Nov 01 01:04:46 2016 -0600
@@ -25,7 +25,6 @@
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
 
-import org.eclipse.jetty.http.HttpHeaders;
 import org.eclipse.jetty.http.HttpMethods;
 import org.eclipse.jetty.http.MimeTypes;
 import org.eclipse.jetty.server.Handler;
--- a/src/org/eclipse/jetty/server/handler/ResourceHandler.java	Mon Oct 31 22:49:25 2016 -0600
+++ b/src/org/eclipse/jetty/server/handler/ResourceHandler.java	Tue Nov 01 01:04:46 2016 -0600
@@ -447,10 +447,10 @@
 			HttpFields fields = ((Response)response).getHttpFields();
 
 			if (length>0)
-				fields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER,length);
+				fields.putLongField(HttpHeaders.CONTENT_LENGTH,length);
 
 			if (_cacheControl!=null)
-				fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
+				fields.put(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
 		}
 		else
 		{