Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2013-10-17 10:35:11 +0000
committerGreg Wilkins2013-10-17 10:35:11 +0000
commitf3b393aa5d3752524d8ff82a67b51b4b4935a44e (patch)
tree36825674415cd3ddb63e1c2e5331c88d2b86b7d0 /jetty-http
parente408bd64c73e25575ff8f1e57c05b52b300f7d67 (diff)
downloadorg.eclipse.jetty.project-f3b393aa5d3752524d8ff82a67b51b4b4935a44e.tar.gz
org.eclipse.jetty.project-f3b393aa5d3752524d8ff82a67b51b4b4935a44e.tar.xz
org.eclipse.jetty.project-f3b393aa5d3752524d8ff82a67b51b4b4935a44e.zip
Refactored complexity out of HttpFields
In preparation of merging Fields class and supporting HTTP/2.0 HPACK
Diffstat (limited to 'jetty-http')
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/DateGenerator.java160
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/DateParser.java105
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpField.java188
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java460
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java97
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java74
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java4
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java123
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java8
9 files changed, 469 insertions, 750 deletions
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/DateGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/DateGenerator.java
new file mode 100644
index 0000000000..b1cac66946
--- /dev/null
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/DateGenerator.java
@@ -0,0 +1,160 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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 java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import org.eclipse.jetty.util.StringUtil;
+
+public class DateGenerator
+{
+ private static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
+ static
+ {
+ __GMT.setID("GMT");
+ }
+
+ static final String[] DAYS =
+ { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ static final String[] MONTHS =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
+
+
+ private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()
+ {
+ @Override
+ protected DateGenerator initialValue()
+ {
+ return new DateGenerator();
+ }
+ };
+
+
+ public final static String __01Jan1970=DateGenerator.formatDate(0);
+
+ /**
+ * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
+ */
+ public static String formatDate(long date)
+ {
+ return __dateGenerator.get().doFormatDate(date);
+ }
+
+ /**
+ * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
+ */
+ public static void formatCookieDate(StringBuilder buf, long date)
+ {
+ __dateGenerator.get().doFormatCookieDate(buf,date);
+ }
+
+ /**
+ * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
+ */
+ public static String formatCookieDate(long date)
+ {
+ StringBuilder buf = new StringBuilder(28);
+ formatCookieDate(buf, date);
+ return buf.toString();
+ }
+
+ private final StringBuilder buf = new StringBuilder(32);
+ private final GregorianCalendar gc = new GregorianCalendar(__GMT);
+
+ /**
+ * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
+ */
+ public String doFormatDate(long date)
+ {
+ buf.setLength(0);
+ gc.setTimeInMillis(date);
+
+ int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
+ int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
+ int month = gc.get(Calendar.MONTH);
+ int year = gc.get(Calendar.YEAR);
+ int century = year / 100;
+ year = year % 100;
+
+ int hours = gc.get(Calendar.HOUR_OF_DAY);
+ int minutes = gc.get(Calendar.MINUTE);
+ int seconds = gc.get(Calendar.SECOND);
+
+ buf.append(DAYS[day_of_week]);
+ buf.append(',');
+ buf.append(' ');
+ StringUtil.append2digits(buf, day_of_month);
+
+ buf.append(' ');
+ buf.append(MONTHS[month]);
+ buf.append(' ');
+ StringUtil.append2digits(buf, century);
+ StringUtil.append2digits(buf, year);
+
+ buf.append(' ');
+ StringUtil.append2digits(buf, hours);
+ buf.append(':');
+ StringUtil.append2digits(buf, minutes);
+ buf.append(':');
+ StringUtil.append2digits(buf, seconds);
+ buf.append(" GMT");
+ return buf.toString();
+ }
+
+ /**
+ * Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies
+ */
+ public void doFormatCookieDate(StringBuilder buf, long date)
+ {
+ gc.setTimeInMillis(date);
+
+ int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
+ int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
+ int month = gc.get(Calendar.MONTH);
+ int year = gc.get(Calendar.YEAR);
+ year = year % 10000;
+
+ int epoch = (int) ((date / 1000) % (60 * 60 * 24));
+ int seconds = epoch % 60;
+ epoch = epoch / 60;
+ int minutes = epoch % 60;
+ int hours = epoch / 60;
+
+ buf.append(DAYS[day_of_week]);
+ buf.append(',');
+ buf.append(' ');
+ StringUtil.append2digits(buf, day_of_month);
+
+ buf.append('-');
+ buf.append(MONTHS[month]);
+ buf.append('-');
+ StringUtil.append2digits(buf, year/100);
+ StringUtil.append2digits(buf, year%100);
+
+ buf.append(' ');
+ StringUtil.append2digits(buf, hours);
+ buf.append(':');
+ StringUtil.append2digits(buf, minutes);
+ buf.append(':');
+ StringUtil.append2digits(buf, seconds);
+ buf.append(" GMT");
+ }
+} \ No newline at end of file
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/DateParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/DateParser.java
new file mode 100644
index 0000000000..103c562bb1
--- /dev/null
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/DateParser.java
@@ -0,0 +1,105 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 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 java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+class DateParser
+{
+ private static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
+ static
+ {
+ __GMT.setID("GMT");
+ }
+
+ final static String __dateReceiveFmt[] =
+ {
+ "EEE, dd MMM yyyy HH:mm:ss zzz",
+ "EEE, dd-MMM-yy HH:mm:ss",
+ "EEE MMM dd HH:mm:ss yyyy",
+
+ "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
+ "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
+ "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
+ "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz",
+ "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
+ "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
+ "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
+ };
+
+ public static long parseDate(String date)
+ {
+ return __dateParser.get().parse(date);
+ }
+
+ private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>()
+ {
+ @Override
+ protected DateParser initialValue()
+ {
+ return new DateParser();
+ }
+ };
+
+ final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
+
+ private long parse(final String dateVal)
+ {
+ for (int i = 0; i < _dateReceive.length; i++)
+ {
+ if (_dateReceive[i] == null)
+ {
+ _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
+ _dateReceive[i].setTimeZone(__GMT);
+ }
+
+ try
+ {
+ Date date = (Date) _dateReceive[i].parseObject(dateVal);
+ return date.getTime();
+ }
+ catch (java.lang.Exception e)
+ {
+ // LOG.ignore(e);
+ }
+ }
+
+ if (dateVal.endsWith(" GMT"))
+ {
+ final String val = dateVal.substring(0, dateVal.length() - 4);
+
+ for (SimpleDateFormat element : _dateReceive)
+ {
+ try
+ {
+ Date date = (Date) element.parseObject(val);
+ return date.getTime();
+ }
+ catch (java.lang.Exception e)
+ {
+ // LOG.ignore(e);
+ }
+ }
+ }
+ return -1;
+ }
+} \ No newline at end of file
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 9e26175652..182848f89d 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,92 +18,13 @@
package org.eclipse.jetty.http;
-import java.nio.ByteBuffer;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import org.eclipse.jetty.util.ArrayTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.Trie;
-
/* ------------------------------------------------------------ */
/** A HTTP Field
*/
public class HttpField
{
- /**
- * Cache of common {@link HttpField}s including: <UL>
- * <LI>Common static combinations such as:<UL>
- * <li>Connection: close
- * <li>Accept-Encoding: gzip
- * <li>Content-Length: 0
- * </ul>
- * <li>Combinations of Content-Type header for common mime types by common charsets
- * <li>Most common headers with null values so that a lookup will at least
- * determine the header name even if the name:value combination is not cached
- * </ul>
- */
- public final static Trie<HttpField> CACHE = new ArrayTrie<>(2048);
- public final static Trie<HttpField> CONTENT_TYPE = new ArrayTrie<>(512);
-
- static
- {
- CACHE.put(new CachedHttpField(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE));
- CACHE.put(new CachedHttpField(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE));
- CACHE.put(new CachedHttpField(HttpHeader.CONNECTION,HttpHeaderValue.UPGRADE));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_ENCODING,"gzip"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_ENCODING,"gzip, deflate"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_ENCODING,"gzip,deflate,sdch"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_LANGUAGE,"en-US,en;q=0.5"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_LANGUAGE,"en-GB,en-US;q=0.8,en;q=0.6"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT_CHARSET,"ISO-8859-1,utf-8;q=0.7,*;q=0.3"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT,"*/*"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT,"image/png,image/*;q=0.8,*/*;q=0.5"));
- CACHE.put(new CachedHttpField(HttpHeader.ACCEPT,"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
- CACHE.put(new CachedHttpField(HttpHeader.PRAGMA,"no-cache"));
- CACHE.put(new CachedHttpField(HttpHeader.CACHE_CONTROL,"private, no-cache, no-cache=Set-Cookie, proxy-revalidate"));
- CACHE.put(new CachedHttpField(HttpHeader.CACHE_CONTROL,"no-cache"));
- CACHE.put(new CachedHttpField(HttpHeader.CONTENT_LENGTH,"0"));
- CACHE.put(new CachedHttpField(HttpHeader.CONTENT_ENCODING,"gzip"));
- CACHE.put(new CachedHttpField(HttpHeader.CONTENT_ENCODING,"deflate"));
- CACHE.put(new CachedHttpField(HttpHeader.TRANSFER_ENCODING,"chunked"));
- CACHE.put(new CachedHttpField(HttpHeader.EXPIRES,"Fri, 01 Jan 1990 00:00:00 GMT"));
-
- // Content types
- for (String type : new String[]{"text/plain","text/html","text/xml","text/json","application/x-www-form-urlencoded"})
- {
- HttpField field=new CachedHttpField(HttpHeader.CONTENT_TYPE,type);
- CACHE.put(field);
- CONTENT_TYPE.put(type,field);
-
- for (String charset : new String[]{"UTF-8","ISO-8859-1"})
- {
- String type_charset=type+"; charset="+charset;
- field=new CachedHttpField(HttpHeader.CONTENT_TYPE,type_charset);
- CACHE.put(field);
- CACHE.put(new CachedHttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
- CONTENT_TYPE.put(type_charset,field);
- CONTENT_TYPE.put(type+";charset="+charset,field);
- }
- }
-
- // Add headers with null values so HttpParser can avoid looking up name again for unknown values
- for (HttpHeader h:HttpHeader.values())
- if (!CACHE.put(new HttpField(h,(String)null)))
- throw new IllegalStateException("CACHE FULL");
- // Add some more common headers
- CACHE.put(new HttpField(HttpHeader.REFERER,(String)null));
- CACHE.put(new HttpField(HttpHeader.IF_MODIFIED_SINCE,(String)null));
- CACHE.put(new HttpField(HttpHeader.IF_NONE_MATCH,(String)null));
- CACHE.put(new HttpField(HttpHeader.AUTHORIZATION,(String)null));
- CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
- }
- private final static Pattern __splitter = Pattern.compile("\\s*,\\s*");
- private final static byte[] __colon_space = new byte[] {':',' '};
private final HttpHeader _header;
private final String _name;
@@ -146,89 +67,7 @@ public class HttpField
{
return _value;
}
-
- public boolean contains(String value)
- {
- if (_value==null)
- return false;
-
- if (value.equalsIgnoreCase(_value))
- return true;
-
- String[] split = __splitter.split(_value);
- for (int i = 0; split!=null && i < split.length; i++)
- {
- if (value.equalsIgnoreCase(split[i]))
- return true;
- }
-
- return false;
- }
-
-
- public int getIntValue()
- {
- return StringUtil.toInt(_value);
- }
-
- public long getLongValue()
- {
- return StringUtil.toLong(_value);
- }
- private static byte[] toSanitisedName(String s)
- {
- byte[] bytes = s.getBytes(StringUtil.__ISO_8859_1_CHARSET);
- for (int i=bytes.length;i-->0;)
- {
- switch(bytes[i])
- {
- case '\r':
- case '\n':
- case ':' :
- bytes[i]=(byte)'?';
- }
- }
- return bytes;
- }
-
- private static byte[] toSanitisedValue(String s)
- {
- byte[] bytes = s.getBytes(StringUtil.__ISO_8859_1_CHARSET);
- for (int i=bytes.length;i-->0;)
- {
- switch(bytes[i])
- {
- case '\r':
- case '\n':
- bytes[i]=(byte)'?';
- }
- }
- return bytes;
- }
-
- public void putTo(ByteBuffer bufferInFillMode)
- {
- if (_header!=null)
- {
- bufferInFillMode.put(_header.getBytesColonSpace());
- bufferInFillMode.put(toSanitisedValue(_value));
- }
- else
- {
- bufferInFillMode.put(toSanitisedName(_name));
- bufferInFillMode.put(__colon_space);
- bufferInFillMode.put(toSanitisedValue(_value));
- }
-
- BufferUtil.putCRLF(bufferInFillMode);
- }
-
- public void putValueTo(ByteBuffer buffer)
- {
- buffer.put(toSanitisedValue(_value));
- }
-
@Override
public String toString()
{
@@ -250,31 +89,4 @@ public class HttpField
}
- /* ------------------------------------------------------------ */
- /** A HTTP Field optimised to be reused.
- */
- public static class CachedHttpField extends HttpField
- {
- final byte[] _bytes;
- public CachedHttpField(HttpHeader header, String value)
- {
- super(header,value);
- _bytes=new byte[header.asString().length()+2+value.length()+2];
- System.arraycopy(header.getBytesColonSpace(),0,_bytes,0,header.asString().length()+2);
- System.arraycopy(toSanitisedValue(value),0,_bytes,header.asString().length()+2,value.length());
- _bytes[_bytes.length-2]='\r';
- _bytes[_bytes.length-1]='\n';
- }
-
- CachedHttpField(HttpHeader header, HttpHeaderValue value)
- {
- this(header,value.asString());
- }
-
- @Override
- public void putTo(ByteBuffer bufferInFillMode)
- {
- bufferInFillMode.put(_bytes);
- }
- }
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
index e990ea5898..2d0da1968c 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
@@ -18,29 +18,21 @@
package org.eclipse.jetty.http;
-import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
-import java.util.Date;
import java.util.Enumeration;
-import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
-import java.util.TimeZone;
+import java.util.regex.Pattern;
import org.eclipse.jetty.util.ArrayTernaryTrie;
-import org.eclipse.jetty.util.BufferUtil;
-import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
@@ -48,13 +40,11 @@ import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-import static org.eclipse.jetty.util.QuotedStringTokenizer.isQuoted;
-
/**
* HTTP Fields. A collection of HTTP header and or Trailer fields.
*
- * <p>This class is not synchronised as it is expected that modifications will only be performed by a
+ * <p>This class is not synchronized as it is expected that modifications will only be performed by a
* single thread.
*
* <p>The cookie handling provided by this class is guided by the Servlet specification and RFC6265.
@@ -63,222 +53,9 @@ import static org.eclipse.jetty.util.QuotedStringTokenizer.isQuoted;
public class HttpFields implements Iterable<HttpField>
{
private static final Logger LOG = Log.getLogger(HttpFields.class);
- public static final TimeZone __GMT = TimeZone.getTimeZone("GMT");
- public static final DateCache __dateCache = new DateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
-
- public static final String __COOKIE_DELIM="\",;\\ \t";
-
- static
- {
- __GMT.setID("GMT");
- __dateCache.setTimeZone(__GMT);
- }
-
+ private final static Pattern __splitter = Pattern.compile("\\s*,\\s*");
public final static String __separators = ", \t";
- private static final String[] DAYS =
- { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- private static final String[] MONTHS =
- { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
-
- public static class DateGenerator
- {
- private final StringBuilder buf = new StringBuilder(32);
- private final GregorianCalendar gc = new GregorianCalendar(__GMT);
-
- /**
- * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
- */
- public String formatDate(long date)
- {
- buf.setLength(0);
- gc.setTimeInMillis(date);
-
- int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
- int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
- int month = gc.get(Calendar.MONTH);
- int year = gc.get(Calendar.YEAR);
- int century = year / 100;
- year = year % 100;
-
- int hours = gc.get(Calendar.HOUR_OF_DAY);
- int minutes = gc.get(Calendar.MINUTE);
- int seconds = gc.get(Calendar.SECOND);
-
- buf.append(DAYS[day_of_week]);
- buf.append(',');
- buf.append(' ');
- StringUtil.append2digits(buf, day_of_month);
-
- buf.append(' ');
- buf.append(MONTHS[month]);
- buf.append(' ');
- StringUtil.append2digits(buf, century);
- StringUtil.append2digits(buf, year);
-
- buf.append(' ');
- StringUtil.append2digits(buf, hours);
- buf.append(':');
- StringUtil.append2digits(buf, minutes);
- buf.append(':');
- StringUtil.append2digits(buf, seconds);
- buf.append(" GMT");
- return buf.toString();
- }
-
- /**
- * Format "EEE, dd-MMM-yy HH:mm:ss 'GMT'" for cookies
- */
- public void formatCookieDate(StringBuilder buf, long date)
- {
- gc.setTimeInMillis(date);
-
- int day_of_week = gc.get(Calendar.DAY_OF_WEEK);
- int day_of_month = gc.get(Calendar.DAY_OF_MONTH);
- int month = gc.get(Calendar.MONTH);
- int year = gc.get(Calendar.YEAR);
- year = year % 10000;
-
- int epoch = (int) ((date / 1000) % (60 * 60 * 24));
- int seconds = epoch % 60;
- epoch = epoch / 60;
- int minutes = epoch % 60;
- int hours = epoch / 60;
-
- buf.append(DAYS[day_of_week]);
- buf.append(',');
- buf.append(' ');
- StringUtil.append2digits(buf, day_of_month);
-
- buf.append('-');
- buf.append(MONTHS[month]);
- buf.append('-');
- StringUtil.append2digits(buf, year/100);
- StringUtil.append2digits(buf, year%100);
-
- buf.append(' ');
- StringUtil.append2digits(buf, hours);
- buf.append(':');
- StringUtil.append2digits(buf, minutes);
- buf.append(':');
- StringUtil.append2digits(buf, seconds);
- buf.append(" GMT");
- }
- }
-
- private static final ThreadLocal<DateGenerator> __dateGenerator =new ThreadLocal<DateGenerator>()
- {
- @Override
- protected DateGenerator initialValue()
- {
- return new DateGenerator();
- }
- };
-
- /**
- * Format HTTP date "EEE, dd MMM yyyy HH:mm:ss 'GMT'"
- */
- public static String formatDate(long date)
- {
- return __dateGenerator.get().formatDate(date);
- }
-
- /**
- * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
- */
- public static void formatCookieDate(StringBuilder buf, long date)
- {
- __dateGenerator.get().formatCookieDate(buf,date);
- }
-
- /**
- * Format "EEE, dd-MMM-yyyy HH:mm:ss 'GMT'" for cookies
- */
- public static String formatCookieDate(long date)
- {
- StringBuilder buf = new StringBuilder(28);
- formatCookieDate(buf, date);
- return buf.toString();
- }
-
- private final static String __dateReceiveFmt[] =
- {
- "EEE, dd MMM yyyy HH:mm:ss zzz",
- "EEE, dd-MMM-yy HH:mm:ss",
- "EEE MMM dd HH:mm:ss yyyy",
-
- "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
- "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
- "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
- "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz",
- "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
- "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
- "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
- };
-
- private static class DateParser
- {
- final SimpleDateFormat _dateReceive[]= new SimpleDateFormat[__dateReceiveFmt.length];
-
- long parse(final String dateVal)
- {
- for (int i = 0; i < _dateReceive.length; i++)
- {
- if (_dateReceive[i] == null)
- {
- _dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
- _dateReceive[i].setTimeZone(__GMT);
- }
-
- try
- {
- Date date = (Date) _dateReceive[i].parseObject(dateVal);
- return date.getTime();
- }
- catch (java.lang.Exception e)
- {
- // LOG.ignore(e);
- }
- }
-
- if (dateVal.endsWith(" GMT"))
- {
- final String val = dateVal.substring(0, dateVal.length() - 4);
-
- for (SimpleDateFormat element : _dateReceive)
- {
- try
- {
- Date date = (Date) element.parseObject(val);
- return date.getTime();
- }
- catch (java.lang.Exception e)
- {
- // LOG.ignore(e);
- }
- }
- }
- return -1;
- }
- }
-
- public static long parseDate(String date)
- {
- return __dateParser.get().parse(date);
- }
-
- private static final ThreadLocal<DateParser> __dateParser =new ThreadLocal<DateParser>()
- {
- @Override
- protected DateParser initialValue()
- {
- return new DateParser();
- }
- };
-
- public final static String __01Jan1970=formatDate(0);
- public final static ByteBuffer __01Jan1970_BUFFER=BufferUtil.toBuffer(__01Jan1970);
- public final static String __01Jan1970_COOKIE = formatCookieDate(0).trim();
private final ArrayList<HttpField> _fields = new ArrayList<>(20);
/**
@@ -355,12 +132,14 @@ public class HttpFields implements Iterable<HttpField>
return null;
}
+
+
public boolean contains(HttpHeader header, String value)
{
for (int i=0;i<_fields.size();i++)
{
HttpField f=_fields.get(i);
- if (f.getHeader()==header && f.contains(value))
+ if (f.getHeader()==header && contains(f,value))
return true;
}
return false;
@@ -371,9 +150,29 @@ public class HttpFields implements Iterable<HttpField>
for (int i=0;i<_fields.size();i++)
{
HttpField f=_fields.get(i);
- if (f.getName().equalsIgnoreCase(name) && f.contains(value))
+ if (f.getName().equalsIgnoreCase(name) && contains(f,value))
+ return true;
+ }
+ return false;
+ }
+
+
+ private boolean contains(HttpField field,String value)
+ {
+ String v = field.getValue();
+ if (v==null)
+ return false;
+
+ if (value.equalsIgnoreCase(v))
+ return true;
+
+ String[] split = __splitter.split(v);
+ for (int i = 0; split!=null && i < split.length; i++)
+ {
+ if (value.equals(split[i]))
return true;
}
+
return false;
}
@@ -683,7 +482,7 @@ public class HttpFields implements Iterable<HttpField>
public long getLongField(String name) throws NumberFormatException
{
HttpField field = getField(name);
- return field==null?-1L:field.getLongValue();
+ return field==null?-1L:StringUtil.toLong(field.getValue());
}
/**
@@ -702,7 +501,7 @@ public class HttpFields implements Iterable<HttpField>
if (val == null)
return -1;
- final long date = __dateParser.get().parse(val);
+ final long date = DateParser.parseDate(val);
if (date==-1)
throw new IllegalArgumentException("Cannot convert date: " + val);
return date;
@@ -742,7 +541,7 @@ public class HttpFields implements Iterable<HttpField>
*/
public void putDateField(HttpHeader name, long date)
{
- String d=formatDate(date);
+ String d=DateGenerator.formatDate(date);
put(name, d);
}
@@ -754,7 +553,7 @@ public class HttpFields implements Iterable<HttpField>
*/
public void putDateField(String name, long date)
{
- String d=formatDate(date);
+ String d=DateGenerator.formatDate(date);
put(name, d);
}
@@ -766,170 +565,10 @@ public class HttpFields implements Iterable<HttpField>
*/
public void addDateField(String name, long date)
{
- String d=formatDate(date);
+ String d=DateGenerator.formatDate(date);
add(name,d);
}
- /**
- * Format a set cookie value
- *
- * @param cookie The cookie.
- */
- public void addSetCookie(HttpCookie cookie)
- {
- addSetCookie(
- cookie.getName(),
- cookie.getValue(),
- cookie.getDomain(),
- cookie.getPath(),
- cookie.getMaxAge(),
- cookie.getComment(),
- cookie.isSecure(),
- cookie.isHttpOnly(),
- cookie.getVersion());
- }
-
- /**
- * Format a set cookie value
- *
- * @param name the name
- * @param value the value
- * @param domain the domain
- * @param path the path
- * @param maxAge the maximum age
- * @param comment the comment (only present on versions > 0)
- * @param isSecure true if secure cookie
- * @param isHttpOnly true if for http only
- * @param version version of cookie logic to use (0 == default behavior)
- */
- public void addSetCookie(
- final String name,
- final String value,
- final String domain,
- final String path,
- final long maxAge,
- final String comment,
- final boolean isSecure,
- final boolean isHttpOnly,
- int version)
- {
- // Check arguments
- if (name == null || name.length() == 0)
- throw new IllegalArgumentException("Bad cookie name");
-
- // Format value and params
- StringBuilder buf = new StringBuilder(128);
-
- // Name is checked for legality by servlet spec, but can also be passed directly so check again for quoting
- boolean quote_name=isQuoteNeededForCookie(name);
- quoteOnlyOrAppend(buf,name,quote_name);
-
- buf.append('=');
-
- // Remember name= part to look for other matching set-cookie
- String name_equals=buf.toString();
-
- // Append the value
- boolean quote_value=isQuoteNeededForCookie(value);
- quoteOnlyOrAppend(buf,value,quote_value);
-
- // Look for domain and path fields and check if they need to be quoted
- boolean has_domain = domain!=null && domain.length()>0;
- boolean quote_domain = has_domain && isQuoteNeededForCookie(domain);
- boolean has_path = path!=null && path.length()>0;
- boolean quote_path = has_path && isQuoteNeededForCookie(path);
-
- // Upgrade the version if we have a comment or we need to quote value/path/domain or if they were already quoted
- if (version==0 && ( comment!=null || quote_name || quote_value || quote_domain || quote_path || isQuoted(name) || isQuoted(value) || isQuoted(path) || isQuoted(domain)))
- version=1;
-
- // Append version
- if (version==1)
- buf.append (";Version=1");
- else if (version>1)
- buf.append (";Version=").append(version);
-
- // Append path
- if (has_path)
- {
- buf.append(";Path=");
- quoteOnlyOrAppend(buf,path,quote_path);
- }
-
- // Append domain
- if (has_domain)
- {
- buf.append(";Domain=");
- quoteOnlyOrAppend(buf,domain,quote_domain);
- }
-
- // Handle max-age and/or expires
- if (maxAge >= 0)
- {
- // Always use expires
- // This is required as some browser (M$ this means you!) don't handle max-age even with v1 cookies
- buf.append(";Expires=");
- if (maxAge == 0)
- buf.append(__01Jan1970_COOKIE);
- else
- formatCookieDate(buf, System.currentTimeMillis() + 1000L * maxAge);
-
- // for v1 cookies, also send max-age
- if (version>=1)
- {
- buf.append(";Max-Age=");
- buf.append(maxAge);
- }
- }
-
- // add the other fields
- if (isSecure)
- buf.append(";Secure");
- if (isHttpOnly)
- buf.append(";HttpOnly");
- if (comment != null)
- {
- buf.append(";Comment=");
- quoteOnlyOrAppend(buf,comment,isQuoteNeededForCookie(comment));
- }
-
- // remove any existing set-cookie fields of same name
- Iterator<HttpField> i=_fields.iterator();
- while (i.hasNext())
- {
- HttpField field=i.next();
- if (field.getHeader()==HttpHeader.SET_COOKIE)
- {
- String val = field.getValue();
- if (val!=null && val.startsWith(name_equals))
- {
- //existing cookie has same name, does it also match domain and path?
- if (((!has_domain && !val.contains("Domain")) || (has_domain && val.contains(domain))) &&
- ((!has_path && !val.contains("Path")) || (has_path && val.contains(path))))
- {
- i.remove();
- }
- }
- }
- }
-
- // add the set cookie
- add(HttpHeader.SET_COOKIE.toString(), buf.toString());
-
- // Expire responses with set-cookie headers so they do not get cached.
- put(HttpHeader.EXPIRES.toString(), __01Jan1970);
- }
-
- public void putTo(ByteBuffer bufferInFillMode)
- {
- for (HttpField field : _fields)
- {
- if (field != null)
- field.putTo(bufferInFillMode);
- }
- BufferUtil.putCRLF(bufferInFillMode);
- }
-
@Override
public String
toString()
@@ -1148,39 +787,4 @@ public class HttpFields implements Iterable<HttpField>
- /* ------------------------------------------------------------ */
- /** Does a cookie value need to be quoted?
- * @param s value string
- * @return true if quoted;
- * @throws IllegalArgumentException If there a control characters in the string
- */
- public static boolean isQuoteNeededForCookie(String s)
- {
- if (s==null || s.length()==0)
- return true;
-
- if (QuotedStringTokenizer.isQuoted(s))
- return false;
-
- for (int i=0;i<s.length();i++)
- {
- char c = s.charAt(i);
- if (__COOKIE_DELIM.indexOf(c)>=0)
- return true;
-
- if (c<0x20 || c>=0x7f)
- throw new IllegalArgumentException("Illegal character in cookie value");
- }
-
- return false;
- }
-
-
- private static void quoteOnlyOrAppend(StringBuilder buf, String s, boolean quote)
- {
- if (quote)
- QuotedStringTokenizer.quoteOnly(buf,s);
- else
- buf.append(s);
- }
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
index af09866863..9cbeedddaf 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java
@@ -37,6 +37,7 @@ public class HttpGenerator
{
private static final Logger LOG = Log.getLogger(HttpGenerator.class);
+ private final static byte[] __colon_space = new byte[] {':',' '};
public static final ResponseInfo CONTINUE_100_INFO = new ResponseInfo(HttpVersion.HTTP_1_1,null,-1,100,null,false);
public static final ResponseInfo PROGRESS_102_INFO = new ResponseInfo(HttpVersion.HTTP_1_1,null,-1,102,null,false);
public final static ResponseInfo RESPONSE_500_INFO =
@@ -495,6 +496,9 @@ public class HttpGenerator
case HTTP_1_1:
header.put((byte)' ');
header.put(request.getHttpVersion().toBytes());
+ break;
+ default:
+ throw new IllegalStateException();
}
header.put(HttpTokens.CRLF);
}
@@ -585,7 +589,7 @@ public class HttpGenerator
// write the field to the header
content_type=true;
- field.putTo(header);
+ putTo(field,header);
break;
}
@@ -600,7 +604,7 @@ public class HttpGenerator
case CONNECTION:
{
if (request!=null)
- field.putTo(header);
+ putTo(field,header);
// Lookup and/or split connection value field
HttpHeaderValue[] values = new HttpHeaderValue[]{HttpHeaderValue.CACHE.get(field.getValue())};
@@ -672,12 +676,12 @@ public class HttpGenerator
case SERVER:
{
send=send&~SEND_SERVER;
- field.putTo(header);
+ putTo(field,header);
break;
}
default:
- field.putTo(header);
+ putTo(field,header);
}
}
}
@@ -776,7 +780,7 @@ public class HttpGenerator
{
String c = transfer_encoding.getValue();
if (c.endsWith(HttpHeaderValue.CHUNKED.toString()))
- transfer_encoding.putTo(header);
+ putTo(transfer_encoding,header);
else
throw new IllegalArgumentException("BAD TE");
}
@@ -1007,5 +1011,88 @@ public class HttpGenerator
{
return String.format("ResponseInfo{%s %s %s,%d,%b}",_httpVersion,_status,_reason,_contentLength,_head);
}
+ }
+
+ private static void putSanitisedName(String s,ByteBuffer buffer)
+ {
+ int l=s.length();
+ for (int i=0;i<l;i++)
+ {
+ char c=s.charAt(i);
+
+ if (c<0 || c>0xff || c=='\r' || c=='\n'|| c==':')
+ buffer.put((byte)'?');
+ else
+ buffer.put((byte)(0xff&c));
+ }
+ }
+
+ private static void putSanitisedValue(String s,ByteBuffer buffer)
+ {
+ int l=s.length();
+ for (int i=0;i<l;i++)
+ {
+ char c=s.charAt(i);
+
+ if (c<0 || c>0xff || c=='\r' || c=='\n')
+ buffer.put((byte)'?');
+ else
+ buffer.put((byte)(0xff&c));
+ }
+ }
+
+ public static void putTo(HttpField field, ByteBuffer bufferInFillMode)
+ {
+ if (field instanceof CachedHttpField)
+ {
+ ((CachedHttpField)field).putTo(bufferInFillMode);
+ }
+ else
+ {
+ HttpHeader header=field.getHeader();
+ if (header!=null)
+ {
+ bufferInFillMode.put(header.getBytesColonSpace());
+ putSanitisedValue(field.getValue(),bufferInFillMode);
+ }
+ else
+ {
+ putSanitisedName(field.getName(),bufferInFillMode);
+ bufferInFillMode.put(__colon_space);
+ putSanitisedValue(field.getValue(),bufferInFillMode);
+ }
+
+ BufferUtil.putCRLF(bufferInFillMode);
+ }
+ }
+
+ public static void putTo(HttpFields fields, ByteBuffer bufferInFillMode)
+ {
+ for (HttpField field : fields)
+ {
+ if (field != null)
+ putTo(field,bufferInFillMode);
+ }
+ BufferUtil.putCRLF(bufferInFillMode);
+ }
+
+ public static class CachedHttpField extends HttpField
+ {
+ private final byte[] _bytes;
+ public CachedHttpField(HttpHeader header,String value)
+ {
+ super(header,value);
+ int cbl=header.getBytesColonSpace().length;
+ _bytes=new byte[cbl+value.length()+2];
+ System.arraycopy(header.getBytesColonSpace(),0,_bytes,0,cbl);
+ System.arraycopy(value.getBytes(StringUtil.__ISO_8859_1_CHARSET),0,_bytes,cbl,value.length());
+ _bytes[_bytes.length-2]=(byte)'\r';
+ _bytes[_bytes.length-1]=(byte)'\n';
+ }
+
+ public void putTo(ByteBuffer bufferInFillMode)
+ {
+ bufferInFillMode.put(_bytes);
+ }
}
}
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 7cef1dcf53..9e73ee5d69 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
@@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.http.HttpTokens.EndOfContent;
import org.eclipse.jetty.util.ArrayTernaryTrie;
+import org.eclipse.jetty.util.ArrayTrie;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Trie;
@@ -76,6 +77,21 @@ public class HttpParser
public final static boolean __STRICT=Boolean.getBoolean("org.eclipse.jetty.http.HttpParser.STRICT");
public final static int INITIAL_URI_LENGTH=256;
+ /**
+ * Cache of common {@link HttpField}s including: <UL>
+ * <LI>Common static combinations such as:<UL>
+ * <li>Connection: close
+ * <li>Accept-Encoding: gzip
+ * <li>Content-Length: 0
+ * </ul>
+ * <li>Combinations of Content-Type header for common mime types by common charsets
+ * <li>Most common headers with null values so that a lookup will at least
+ * determine the header name even if the name:value combination is not cached
+ * </ul>
+ */
+ public final static Trie<HttpField> CACHE = new ArrayTrie<>(2048);
+ public final static Trie<HttpField> CONTENT_TYPE = new ArrayTrie<>(512);
+
// States
public enum State
{
@@ -138,6 +154,59 @@ public class HttpParser
private int _length;
private final StringBuilder _string=new StringBuilder();
+ static
+ {
+ CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE));
+ CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.KEEP_ALIVE));
+ CACHE.put(new HttpField(HttpHeader.CONNECTION,HttpHeaderValue.UPGRADE));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip, deflate"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_ENCODING,"gzip,deflate,sdch"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_LANGUAGE,"en-US,en;q=0.5"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_LANGUAGE,"en-GB,en-US;q=0.8,en;q=0.6"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT_CHARSET,"ISO-8859-1,utf-8;q=0.7,*;q=0.3"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT,"*/*"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT,"image/png,image/*;q=0.8,*/*;q=0.5"));
+ CACHE.put(new HttpField(HttpHeader.ACCEPT,"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
+ CACHE.put(new HttpField(HttpHeader.PRAGMA,"no-cache"));
+ CACHE.put(new HttpField(HttpHeader.CACHE_CONTROL,"private, no-cache, no-cache=Set-Cookie, proxy-revalidate"));
+ CACHE.put(new HttpField(HttpHeader.CACHE_CONTROL,"no-cache"));
+ CACHE.put(new HttpField(HttpHeader.CONTENT_LENGTH,"0"));
+ CACHE.put(new HttpField(HttpHeader.CONTENT_ENCODING,"gzip"));
+ CACHE.put(new HttpField(HttpHeader.CONTENT_ENCODING,"deflate"));
+ CACHE.put(new HttpField(HttpHeader.TRANSFER_ENCODING,"chunked"));
+ CACHE.put(new HttpField(HttpHeader.EXPIRES,"Fri, 01 Jan 1990 00:00:00 GMT"));
+
+ // Content types
+ for (String type : new String[]{"text/plain","text/html","text/xml","text/json","application/x-www-form-urlencoded"})
+ {
+ HttpField field=new HttpField(HttpHeader.CONTENT_TYPE,type);
+ CACHE.put(field);
+ CONTENT_TYPE.put(type,field);
+
+ for (String charset : new String[]{"UTF-8","ISO-8859-1"})
+ {
+ String type_charset=type+"; charset="+charset;
+ field=new HttpField(HttpHeader.CONTENT_TYPE,type_charset);
+ CACHE.put(field);
+ CACHE.put(new HttpField(HttpHeader.CONTENT_TYPE,type+";charset="+charset));
+ CONTENT_TYPE.put(type_charset,field);
+ CONTENT_TYPE.put(type+";charset="+charset,field);
+ }
+ }
+
+ // Add headers with null values so HttpParser can avoid looking up name again for unknown values
+ for (HttpHeader h:HttpHeader.values())
+ if (!CACHE.put(new HttpField(h,(String)null)))
+ throw new IllegalStateException("CACHE FULL");
+ // Add some more common headers
+ CACHE.put(new HttpField(HttpHeader.REFERER,(String)null));
+ CACHE.put(new HttpField(HttpHeader.IF_MODIFIED_SINCE,(String)null));
+ CACHE.put(new HttpField(HttpHeader.IF_NONE_MATCH,(String)null));
+ CACHE.put(new HttpField(HttpHeader.AUTHORIZATION,(String)null));
+ CACHE.put(new HttpField(HttpHeader.COOKIE,(String)null));
+ }
+
/* ------------------------------------------------------------------------------- */
public HttpParser(RequestHandler<ByteBuffer> handler)
{
@@ -801,7 +870,7 @@ public class HttpParser
if (add_to_connection_trie && !_connectionFields.isFull() && _header!=null && _valueString!=null)
{
- _field=new HttpField.CachedHttpField(_header,_valueString);
+ _field=new HttpField(_header,_valueString);
_connectionFields.put(_field);
}
@@ -944,7 +1013,7 @@ public class HttpParser
// 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=HttpField.CACHE.getBest(buffer,-1,buffer.remaining());
+ field=CACHE.getBest(buffer,-1,buffer.remaining());
if (field!=null)
{
@@ -1547,5 +1616,4 @@ public class HttpParser
{
return _connectionFields;
}
-
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java
index 311a68827e..35fcb3230c 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MimeTypes.java
@@ -136,10 +136,10 @@ public class MimeTypes
try
{
ResourceBundle mime = ResourceBundle.getBundle("org/eclipse/jetty/http/mime");
- Enumeration i = mime.getKeys();
+ Enumeration<String> i = mime.getKeys();
while(i.hasMoreElements())
{
- String ext = (String)i.nextElement();
+ String ext = i.nextElement();
String m = mime.getString(ext);
__dftMimeMap.put(StringUtil.asciiToLowerCase(ext),normalizeMimeType(m));
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
index 13dbd77cd2..4333cfc2ce 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
@@ -83,7 +83,7 @@ public class HttpFieldsTest
ByteBuffer buffer=BufferUtil.allocate(1024);
BufferUtil.flipToFill(buffer);
- header.putTo(buffer);
+ HttpGenerator.putTo(header,buffer);
BufferUtil.flipToFlush(buffer,0);
String result=BufferUtil.toString(buffer);
@@ -117,7 +117,7 @@ public class HttpFieldsTest
ByteBuffer buffer = BufferUtil.allocate(1024);
BufferUtil.flipToFill(buffer);
- header.putTo(buffer);
+ HttpGenerator.putTo(header,buffer);
BufferUtil.flipToFlush(buffer,0);
String out = BufferUtil.toString(buffer);
assertThat(out,containsString("name0: value??0"));
@@ -136,7 +136,7 @@ public class HttpFieldsTest
ByteBuffer buffer = BufferUtil.allocate(1024);
BufferUtil.flipToFill(buffer);
- header.putTo(buffer);
+ HttpGenerator.putTo(header,buffer);
BufferUtil.flipToFlush(buffer,0);
String out = BufferUtil.toString(buffer).toLowerCase();
@@ -268,123 +268,6 @@ public class HttpFieldsTest
- @Test
- public void testSetCookie() throws Exception
- {
- HttpFields fields = new HttpFields();
-
- fields.addSetCookie("null",null,null,null,-1,null,false,false,-1);
- assertEquals("null=",fields.getStringField("Set-Cookie"));
-
- fields.clear();
-
- fields.addSetCookie("minimal","value",null,null,-1,null,false,false,-1);
- assertEquals("minimal=value",fields.getStringField("Set-Cookie"));
-
- fields.clear();
- //test cookies with same name, domain and path, only 1 allowed
- fields.addSetCookie("everything","wrong","domain","path",0,"to be replaced",true,true,0);
- fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
- assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",fields.getStringField("Set-Cookie"));
- Enumeration<String> e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
- assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
- assertFalse(e.hasMoreElements());
-
- //test cookies with same name, different domain
- fields.clear();
- fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
- fields.addSetCookie("everything","value","domain2","path",0,"comment",true,true,0);
- e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=other;Version=1;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=blah",e.nextElement());
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Path=path;Domain=domain2;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
-
- //test cookies with same name, same path, one with domain, one without
- fields.clear();
- fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
- fields.addSetCookie("everything","value","","path",0,"comment",true,true,0);
- e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=other;Version=1;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=blah",e.nextElement());
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Path=path;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
-
-
- //test cookies with same name, different path
- fields.clear();
- fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
- fields.addSetCookie("everything","value","domain1","path2",0,"comment",true,true,0);
- e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=other;Version=1;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=blah",e.nextElement());
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Path=path2;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
-
- //test cookies with same name, same domain, one with path, one without
- fields.clear();
- fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
- fields.addSetCookie("everything","value","domain1","",0,"comment",true,true,0);
- e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=other;Version=1;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=blah",e.nextElement());
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
-
- //test cookies same name only, no path, no domain
- fields.clear();
- fields.addSetCookie("everything","other","","",0,"blah",true,true,0);
- fields.addSetCookie("everything","value","","",0,"comment",true,true,0);
- e =fields.getValues("Set-Cookie");
- assertTrue(e.hasMoreElements());
- assertEquals("everything=value;Version=1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Max-Age=0;Secure;HttpOnly;Comment=comment",e.nextElement());
- assertFalse(e.hasMoreElements());
-
- fields.clear();
- fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,1);
- String setCookie=fields.getStringField("Set-Cookie");
- assertThat(setCookie,Matchers.startsWith("\"ev erything\"=\"va lue\";Version=1;Path=\"pa th\";Domain=\"do main\";Expires="));
- assertThat(setCookie,Matchers.endsWith(" GMT;Max-Age=1;Secure;HttpOnly;Comment=\"co mment\""));
-
- fields.clear();
- fields.addSetCookie("name","value",null,null,-1,null,false,false,0);
- setCookie=fields.getStringField("Set-Cookie");
- assertEquals(-1,setCookie.indexOf("Version="));
- fields.clear();
- fields.addSetCookie("name","v a l u e",null,null,-1,null,false,false,0);
- setCookie=fields.getStringField("Set-Cookie");
-
- fields.clear();
- fields.addSetCookie("json","{\"services\":[\"cwa\", \"aa\"]}",null,null,-1,null,false,false,-1);
- assertEquals("json=\"{\\\"services\\\":[\\\"cwa\\\", \\\"aa\\\"]}\"",fields.getStringField("Set-Cookie"));
-
- fields.clear();
- fields.addSetCookie("name","value","domain",null,-1,null,false,false,-1);
- fields.addSetCookie("name","other","domain",null,-1,null,false,false,-1);
- assertEquals("name=other;Domain=domain",fields.getStringField("Set-Cookie"));
- fields.addSetCookie("name","more","domain",null,-1,null,false,false,-1);
- assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
- fields.addSetCookie("foo","bar","domain",null,-1,null,false,false,-1);
- fields.addSetCookie("foo","bob","domain",null,-1,null,false,false,-1);
- assertEquals("name=more;Domain=domain",fields.getStringField("Set-Cookie"));
-
- e=fields.getValues("Set-Cookie");
- assertEquals("name=more;Domain=domain",e.nextElement());
- assertEquals("foo=bob;Domain=domain",e.nextElement());
-
- fields=new HttpFields();
- fields.addSetCookie("name","value%=",null,null,-1,null,false,false,0);
- setCookie=fields.getStringField("Set-Cookie");
- assertEquals("name=value%=",setCookie);
-
- }
private Set<String> enum2set(Enumeration<String> e)
{
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 026fd2c3cb..74122714dc 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
@@ -372,7 +372,7 @@ public class HttpGeneratorServerTest
assertEquals(HttpGenerator.State.START, gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
- info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
+ info.getHttpFields().add("Last-Modified", DateGenerator.__01Jan1970);
result = gen.generateResponse(info, null, null, null, true);
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
@@ -441,7 +441,7 @@ public class HttpGeneratorServerTest
assertEquals(HttpGenerator.State.START, gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), -1, 200, null, false);
- info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
+ info.getHttpFields().add("Last-Modified", DateGenerator.__01Jan1970);
result = gen.generateResponse(info, null, null, content0, false);
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
assertEquals(HttpGenerator.State.START, gen.getState());
@@ -503,7 +503,7 @@ public class HttpGeneratorServerTest
assertEquals(HttpGenerator.State.START, gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
- info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
+ info.getHttpFields().add("Last-Modified", DateGenerator.__01Jan1970);
result = gen.generateResponse(info, null, null, content0, false);
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
assertEquals(HttpGenerator.State.START, gen.getState());
@@ -570,7 +570,7 @@ public class HttpGeneratorServerTest
assertEquals(HttpGenerator.State.START, gen.getState());
ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 59, 200, null, false);
- info.getHttpFields().add("Last-Modified", HttpFields.__01Jan1970);
+ info.getHttpFields().add("Last-Modified", DateGenerator.__01Jan1970);
result = gen.generateResponse(info, null, null, content0, false);
assertEquals(HttpGenerator.Result.NEED_HEADER, result);
assertEquals(HttpGenerator.State.START, gen.getState());

Back to the top