From e37a34c9b831d41f82fdf31c221299b2635e18c4 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Apr 2020 10:58:23 +0200 Subject: [PATCH 01/38] Immutable version of HttpFields Preserve API and usage of HttpFields class while providing a read only interface and immutable implementation. Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpField.java | 50 +- .../org/eclipse/jetty/http/HttpFieldList.java | 437 +++++++++ .../org/eclipse/jetty/http/HttpFields.java | 904 ++++++------------ .../eclipse/jetty/http/HttpFieldsTest.java | 41 +- 4 files changed, 795 insertions(+), 637 deletions(-) create mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java 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 4dc702e42115..3cea85380d82 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,8 +18,11 @@ package org.eclipse.jetty.http; +import java.util.Map; import java.util.Objects; +import java.util.StringTokenizer; +import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.StringUtil; /** @@ -289,9 +292,7 @@ public boolean isSameName(HttpField field) return true; if (_header != null && _header == field.getHeader()) return true; - if (_name.equalsIgnoreCase(field.getName())) - return true; - return false; + return _name.equalsIgnoreCase(field.getName()); } private int nameHashCode() @@ -413,4 +414,47 @@ public long getLongValue() return _long; } } + + /** + * Get field value parameters. Some field values can have parameters. This method separates the + * value from the parameters and optionally populates a map with the parameters. For example: + * + *
+     *
+     * FieldName : Value ; param1=val1 ; param2=val2
+     *
+     * 
+ * + * @param value The Field value, possibly with parameters. + * @param parameters A map to populate with the parameters, or null + * @return The value. + */ + public static String getValueParameters(String value, Map parameters) + { + if (value == null) + return null; + + int i = value.indexOf(';'); + if (i < 0) + return value; + if (parameters == null) + return value.substring(0, i).trim(); + + StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); + while (tok1.hasMoreTokens()) + { + String token = tok1.nextToken(); + StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); + if (tok2.hasMoreTokens()) + { + String paramName = tok2.nextToken(); + String paramVal = null; + if (tok2.hasMoreTokens()) + paramVal = tok2.nextToken(); + parameters.put(paramName, paramVal); + } + } + + return value.substring(0, i).trim(); + } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java new file mode 100644 index 000000000000..08ab53b09508 --- /dev/null +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java @@ -0,0 +1,437 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.http; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Interface that represents readonly list of {@link HttpField}s. + */ +public interface HttpFieldList extends Iterable +{ + default int asHashCode() + { + int hash = 0; + for (HttpField f : this) + hash ^= f.hashCode(); + return hash; + } + + default String asString() + { + StringBuilder buffer = new StringBuilder(); + for (HttpField field : this) + { + if (field != null) + { + String tmp = field.getName(); + if (tmp != null) + buffer.append(tmp); + buffer.append(": "); + tmp = field.getValue(); + if (tmp != null) + buffer.append(tmp); + buffer.append("\r\n"); + } + } + buffer.append("\r\n"); + return buffer.toString(); + } + + default boolean contains(HttpField field) + { + for (HttpField f : this) + { + if (f.isSameName(field) && (f.equals(field) || f.contains(field.getValue()))) + return true; + } + return false; + } + + default boolean contains(HttpHeader header, String value) + { + for (HttpField f : this) + { + if (f.getHeader() == header && f.contains(value)) + return true; + } + return false; + } + + default boolean contains(String name, String value) + { + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name) && f.contains(value)) + return true; + } + return false; + } + + default boolean contains(HttpHeader header) + { + for (HttpField f : this) + { + if (f.getHeader() == header) + return true; + } + return false; + } + + default boolean containsKey(String name) + { + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + return true; + } + return false; + } + + default String get(HttpHeader header) + { + for (HttpField f : this) + { + if (f.getHeader() == header) + return f.getValue(); + } + return null; + } + + default String get(String header) + { + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(header)) + return f.getValue(); + } + return null; + } + + /** + * Get multiple field values of the same name, split + * as a {@link QuotedCSV} + * + * @param header The header + * @param keepQuotes True if the fields are kept quoted + * @return List the values with OWS stripped + */ + default List getCSV(HttpHeader header, boolean keepQuotes) + { + QuotedCSV values = null; + for (HttpField f : this) + { + if (f.getHeader() == header) + { + if (values == null) + values = new QuotedCSV(keepQuotes); + values.addValue(f.getValue()); + } + } + return values == null ? Collections.emptyList() : values.getValues(); + } + + /** + * Get multiple field values of the same name + * as a {@link QuotedCSV} + * + * @param name the case-insensitive field name + * @param keepQuotes True if the fields are kept quoted + * @return List the values with OWS stripped + */ + default List getCSV(String name, boolean keepQuotes) + { + QuotedCSV values = null; + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + { + if (values == null) + values = new QuotedCSV(keepQuotes); + values.addValue(f.getValue()); + } + } + return values == null ? Collections.emptyList() : values.getValues(); + } + + /** + * 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. + * + * @param name the case-insensitive field name + * @return the value of the field as a number of milliseconds since unix epoch + */ + default long getDateField(String name) + { + HttpField field = getField(name); + if (field == null) + return -1; + + String val = HttpField.getValueParameters(field.getValue(), null); + if (val == null) + return -1; + + final long date = DateParser.parseDate(val); + if (date == -1) + throw new IllegalArgumentException("Cannot convert date: " + val); + return date; + } + + /** + * Get a Field by index. + * + * @param index the field index + * @return A Field value or null if the Field value has not been set + */ + HttpField getField(int index); + + default HttpField getField(HttpHeader header) + { + for (HttpField f : this) + { + if (f.getHeader() == header) + return f; + } + return null; + } + + default HttpField getField(String name) + { + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + return f; + } + return null; + } + + /** + * Get enumeration of header _names. Returns an enumeration of strings representing the header + * _names for this request. + * + * @return an enumeration of field names + */ + default Enumeration getFieldNames() + { + return Collections.enumeration(getFieldNamesCollection()); + } + + /** + * Get Set of header names. + * + * @return the unique set of field names. + */ + default Set getFieldNamesCollection() + { + return stream().map(HttpField::getName).collect(Collectors.toSet()); + } + + /** + * Get multiple fields of the same header + * + * @param header the header + * @return List the fields + */ + default List getFields(HttpHeader header) + { + return stream().filter(f -> f.getHeader().equals(header)).collect(Collectors.toList()); + } + + /** + * 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 + * @return the value of the field as a long + * @throws NumberFormatException If bad long found + */ + default long getLongField(String name) throws NumberFormatException + { + HttpField field = getField(name); + return field == null ? -1L : field.getLongValue(); + } + + /** + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} + * + * @param header The header + * @return List the values in quality order with the q param and OWS stripped + */ + default List getQualityCSV(HttpHeader header) + { + return getQualityCSV(header, null); + } + + /** + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} + * + * @param header The header + * @param secondaryOrdering Function to apply an ordering other than specified by quality + * @return List the values in quality order with the q param and OWS stripped + */ + default List getQualityCSV(HttpHeader header, ToIntFunction secondaryOrdering) + { + QuotedQualityCSV values = null; + for (HttpField f : this) + { + if (f.getHeader() == header) + { + if (values == null) + values = new QuotedQualityCSV(secondaryOrdering); + values.addValue(f.getValue()); + } + } + + return values == null ? Collections.emptyList() : values.getValues(); + } + + /** + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} + * + * @param name the case-insensitive field name + * @return List the values in quality order with the q param and OWS stripped + */ + default List getQualityCSV(String name) + { + QuotedQualityCSV values = null; + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + { + if (values == null) + values = new QuotedQualityCSV(); + values.addValue(f.getValue()); + } + } + return values == null ? Collections.emptyList() : values.getValues(); + } + + /** + * Get multi headers + * + * @param name the case-insensitive field name + * @return Enumeration of the values + */ + default Enumeration getValues(String name) + { + Iterator i = iterator(); + return new Enumeration<>() + { + HttpField _field; + + @Override + public boolean hasMoreElements() + { + if (_field != null) + return true; + while (i.hasNext()) + { + HttpField f = i.next(); + if (f.getName().equalsIgnoreCase(name) && f.getValue() != null) + { + _field = f; + return true; + } + } + return false; + } + + @Override + public String nextElement() + { + if (hasMoreElements()) + { + String value = _field.getValue(); + _field = null; + return value; + } + throw new NoSuchElementException(); + } + }; + } + + /** + * Get multiple field values of the same name + * + * @param header the header + * @return List the values + */ + default List getValuesList(HttpHeader header) + { + final List list = new ArrayList<>(); + for (HttpField f : this) + { + if (f.getHeader() == header) + list.add(f.getValue()); + } + return list; + } + + /** + * Get multiple header of the same name + * + * @param name the case-insensitive field name + * @return List the header values + */ + default List getValuesList(String name) + { + final List list = new ArrayList<>(); + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + list.add(f.getValue()); + } + return list; + } + + default boolean isEqualTo(HttpFieldList that) + { + if (size() != that.size()) + return false; + + // Order is not important, so we cannot rely on List.equals(). // TODO is this true? + loop: + for (HttpField fi : this) + { + for (HttpField fa : that) + { + if (fi.equals(fa)) + continue loop; + } + return false; + } + return true; + } + + int size(); + + Stream stream(); +} 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 7def4fdcfc46..571b58ee0957 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,25 +18,15 @@ package org.eclipse.jetty.http; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Enumeration; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.function.ToIntFunction; import java.util.stream.Stream; -import org.eclipse.jetty.util.QuotedStringTokenizer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * HTTP Fields. A collection of HTTP header and or Trailer fields. * @@ -45,12 +35,10 @@ * *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. */ -public class HttpFields implements Iterable +public class HttpFields implements Iterable, HttpFieldList { - private static final Logger LOG = LoggerFactory.getLogger(HttpFields.class); - - private HttpField[] _fields; - private int _size; + HttpField[] _fields; + int _size; /** * Initialize an empty HttpFields. @@ -81,218 +69,111 @@ public HttpFields(HttpFields fields) _size = fields._size; } - public int size() - { - return _size; - } - - @Override - public Iterator iterator() - { - return listIterator(); - } - - public ListIterator listIterator() - { - return new ListItr(); - } - - public Stream stream() - { - return Arrays.stream(_fields).limit(_size); - } - /** - * Get Collection of header names. + * Get field value without parameters. Some field values can have parameters. This method separates the + * value from the parameters and optionally populates a map with the parameters. For example: * - * @return the unique set of field names. - */ - public Set getFieldNamesCollection() - { - Set set = null; - for (int i = 0; i < _size; i++) - { - HttpField f = _fields[i]; - if (set == null) - set = new HashSet<>(); - set.add(f.getName()); - } - return set == null ? Collections.emptySet() : set; - } - - /** - * Get enumeration of header _names. Returns an enumeration of strings representing the header - * _names for this request. + *

      *
-     * @return an enumeration of field names
-     */
-    public Enumeration getFieldNames()
-    {
-        return Collections.enumeration(getFieldNamesCollection());
-    }
-
-    /**
-     * Get a Field by index.
+     * FieldName : Value ; param1=val1 ; param2=val2
      *
-     * @param index the field index
-     * @return A Field value or null if the Field value has not been set
+     * 
+ * + * @param value The Field value, possibly with parameters. + * @return The value. */ - public HttpField getField(int index) - { - if (index >= _size) - throw new NoSuchElementException(); - return _fields[index]; - } - - public HttpField getField(HttpHeader header) - { - for (int i = 0; i < _size; i++) - { - HttpField f = _fields[i]; - if (f.getHeader() == header) - return f; - } - return null; - } - - public HttpField getField(String name) + public static String stripParameters(String value) { - for (int i = 0; i < _size; i++) - { - HttpField f = _fields[i]; - if (f.getName().equalsIgnoreCase(name)) - return f; - } - return null; - } + if (value == null) + return null; - public List getFields(HttpHeader header) - { - List fields = null; - for (int i = 0; i < _size; i++) - { - HttpField f = _fields[i]; - if (f.getHeader() == header) - { - if (fields == null) - fields = new ArrayList<>(); - fields.add(f); - } - } - return fields == null ? Collections.emptyList() : fields; + int i = value.indexOf(';'); + if (i < 0) + return value; + return value.substring(0, i).trim(); } - public boolean contains(HttpField field) + public static String valueParameters(String value, Map parameters) { - for (int i = _size; i-- > 0; ) - { - HttpField f = _fields[i]; - if (f.isSameName(field) && (f.equals(field) || f.contains(field.getValue()))) - return true; - } - return false; + return HttpField.getValueParameters(value, parameters); } - public boolean contains(HttpHeader header, String 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. + */ + public void add(String name, String value) { - for (int i = _size; i-- > 0; ) - { - HttpField f = _fields[i]; - if (f.getHeader() == header && f.contains(value)) - return true; - } - return false; - } + if (value == null) + return; - public boolean contains(String name, String value) - { - for (int i = _size; i-- > 0; ) - { - HttpField f = _fields[i]; - if (f.getName().equalsIgnoreCase(name) && f.contains(value)) - return true; - } - return false; + HttpField field = new HttpField(name, value); + add(field); } - public boolean contains(HttpHeader header) + public void add(HttpHeader header, HttpHeaderValue value) { - for (int i = _size; i-- > 0; ) - { - HttpField f = _fields[i]; - if (f.getHeader() == header) - return true; - } - return false; + add(header, value.toString()); } - public boolean containsKey(String name) + /** + * 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 header the header + * @param value the value of the field. + */ + public void add(HttpHeader header, String value) { - for (int i = _size; i-- > 0; ) - { - HttpField f = _fields[i]; - if (f.getName().equalsIgnoreCase(name)) - return true; - } - return false; - } + if (value == null) + throw new IllegalArgumentException("null value"); - public String get(HttpHeader header) - { - for (int i = 0; i < _size; i++) - { - HttpField f = _fields[i]; - if (f.getHeader() == header) - return f.getValue(); - } - return null; + HttpField field = new HttpField(header, value); + add(field); } - public String get(String header) + public void add(HttpField field) { - for (int i = 0; i < _size; i++) + if (field != null) { - HttpField f = _fields[i]; - if (f.getName().equalsIgnoreCase(header)) - return f.getValue(); + if (_size == _fields.length) + _fields = Arrays.copyOf(_fields, _size * 2); + _fields[_size++] = field; } - return null; } /** - * Get multiple header of the same name + * Add fields from another HttpFields instance. Single valued fields are replaced, while all + * others are added. * - * @param header the header - * @return List the values + * @param fields the fields to add */ - public List getValuesList(HttpHeader header) + public void add(HttpFields fields) { - final List list = new ArrayList<>(); - for (int i = 0; i < _size; i++) + if (fields == null) + return; + + Enumeration e = fields.getFieldNames(); + while (e.hasMoreElements()) { - HttpField f = _fields[i]; - if (f.getHeader() == header) - list.add(f.getValue()); + String name = e.nextElement(); + Enumeration values = fields.getValues(name); + while (values.hasMoreElements()) + { + add(name, values.nextElement()); + } } - return list; } - /** - * Get multiple header of the same name - * - * @param name the case-insensitive field name - * @return List the header values - */ - public List getValuesList(String name) + public void addAll(HttpFields fields) { - final List list = new ArrayList<>(); - for (int i = 0; i < _size; i++) + for (int i = 0; i < fields._size; i++) { - HttpField f = _fields[i]; - if (f.getName().equalsIgnoreCase(name)) - list.add(f.getValue()); + add(fields._fields[i]); } - return list; } /** @@ -356,200 +237,84 @@ public boolean addCSV(String name, String... values) return false; } - protected String addCSV(QuotedCSV existing, String... values) - { - // remove any existing values from the new values - boolean add = true; - if (existing != null && !existing.isEmpty()) - { - add = false; - - for (int i = values.length; i-- > 0; ) - { - String unquoted = QuotedCSV.unquote(values[i]); - if (existing.getValues().contains(unquoted)) - values[i] = null; - else - add = true; - } - } - - if (add) - { - StringBuilder value = new StringBuilder(); - for (String v : values) - { - if (v == null) - continue; - if (value.length() > 0) - value.append(", "); - value.append(v); - } - if (value.length() > 0) - return value.toString(); - } - - return null; - } - /** - * Get multiple field values of the same name, split - * as a {@link QuotedCSV} + * Sets the value of a date field. * - * @param header The header - * @param keepQuotes True if the fields are kept quoted - * @return List the values with OWS stripped + * @param name the field name + * @param date the field date value */ - public List getCSV(HttpHeader header, boolean keepQuotes) + public void addDateField(String name, long date) { - QuotedCSV values = null; - for (HttpField f : this) - { - if (f.getHeader() == header) - { - if (values == null) - values = new QuotedCSV(keepQuotes); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); + String d = DateGenerator.formatDate(date); + add(name, d); } - /** - * Get multiple field values of the same name - * as a {@link QuotedCSV} - * - * @param name the case-insensitive field name - * @param keepQuotes True if the fields are kept quoted - * @return List the values with OWS stripped - */ - public List getCSV(String name, boolean keepQuotes) + public HttpFieldList asImmutable() { - QuotedCSV values = null; - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - { - if (values == null) - values = new QuotedCSV(keepQuotes); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); + return new HttpFields.Immutable(Arrays.copyOf(_fields, _size)); } - /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} - * - * @param header The header - * @return List the values in quality order with the q param and OWS stripped - */ - public List getQualityCSV(HttpHeader header) + public void clear() { - return getQualityCSV(header, null); + _size = 0; } - /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} - * - * @param header The header - * @param secondaryOrdering Function to apply an ordering other than specified by quality - * @return List the values in quality order with the q param and OWS stripped - */ - public List getQualityCSV(HttpHeader header, ToIntFunction secondaryOrdering) + @Override + public boolean equals(Object o) { - QuotedQualityCSV values = null; - for (HttpField f : this) - { - if (f.getHeader() == header) - { - if (values == null) - values = new QuotedQualityCSV(secondaryOrdering); - values.addValue(f.getValue()); - } - } + if (this == o) + return true; + if (!(o instanceof HttpFields)) + return false; - return values == null ? Collections.emptyList() : values.getValues(); + return isEqualTo((HttpFieldList)o); } /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} + * Get a Field by index. * - * @param name the case-insensitive field name - * @return List the values in quality order with the q param and OWS stripped + * @param index the field index + * @return A Field value or null if the Field value has not been set */ - public List getQualityCSV(String name) + @Override + public HttpField getField(int index) { - QuotedQualityCSV values = null; - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - { - if (values == null) - values = new QuotedQualityCSV(); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); + if (index >= _size) + throw new NoSuchElementException(); + return _fields[index]; } - /** - * Get multi headers - * - * @param name the case-insensitive field name - * @return Enumeration of the values - */ - public Enumeration getValues(final String name) + @Override + public int hashCode() { - for (int i = 0; i < _size; i++) + return asHashCode(); + } + + @Override + public Iterator iterator() + { + return new Iterator<>() { - final HttpField f = _fields[i]; + int _index = 0; + @Override + public boolean hasNext() + { + return _index < _size; + } - if (f.getName().equalsIgnoreCase(name) && f.getValue() != null) + @Override + public HttpField next() { - final int first = i; - return new Enumeration() - { - HttpField field = f; - int i = first + 1; - - @Override - public boolean hasMoreElements() - { - if (field == null) - { - while (i < _size) - { - field = _fields[i++]; - if (field.getName().equalsIgnoreCase(name) && field.getValue() != null) - return true; - } - field = null; - return false; - } - return true; - } - - @Override - public String nextElement() throws NoSuchElementException - { - if (hasMoreElements()) - { - String value = field.getValue(); - field = null; - return value; - } - throw new NoSuchElementException(); - } - }; + if (hasNext()) + return _fields[_index++]; + throw new NoSuchElementException(); } - } + }; + } - List empty = Collections.emptyList(); - return Collections.enumeration(empty); + public ListIterator listIterator() + { + return new ListItr(); } public void put(HttpField field) @@ -625,73 +390,51 @@ public void put(String name, List list) } /** - * Add to or set a field. If the field is allowed to have multiple values, add will add multiple - * headers of the same name. + * Sets the value of a date field. * - * @param name the name of the field - * @param value the value of the field. + * @param name the field name + * @param date the field date value */ - public void add(String name, String value) - { - if (value == null) - return; - - HttpField field = new HttpField(name, value); - add(field); - } - - public void add(HttpHeader header, HttpHeaderValue value) + public void putDateField(HttpHeader name, long date) { - add(header, value.toString()); + String d = DateGenerator.formatDate(date); + put(name, d); } /** - * Add to or set a field. If the field is allowed to have multiple values, add will add multiple - * headers of the same name. + * Sets the value of a date field. * - * @param header the header - * @param value the value of the field. + * @param name the field name + * @param date the field date value */ - public void add(HttpHeader header, String value) + public void putDateField(String name, long date) { - if (value == null) - throw new IllegalArgumentException("null value"); - - HttpField field = new HttpField(header, value); - add(field); + String d = DateGenerator.formatDate(date); + put(name, d); } - public void add(HttpField field) + /** + * Sets the value of an long field. + * + * @param name the field name + * @param value the field long value + */ + public void putLongField(HttpHeader name, long value) { - if (field != null) - { - if (_size == _fields.length) - _fields = Arrays.copyOf(_fields, _size * 2); - _fields[_size++] = field; - } + String v = Long.toString(value); + put(name, v); } /** - * Add fields from another HttpFields instance. Single valued fields are replaced, while all - * others are added. + * Sets the value of an long field. * - * @param fields the fields to add + * @param name the field name + * @param value the field long value */ - public void add(HttpFields fields) + public void putLongField(String name, long value) { - if (fields == null) - return; - - Enumeration e = fields.getFieldNames(); - while (e.hasMoreElements()) - { - String name = e.nextElement(); - Enumeration values = fields.getValues(name); - while (values.hasMoreElements()) - { - add(name, values.nextElement()); - } - } + String v = Long.toString(value); + put(name, v); } /** @@ -736,249 +479,146 @@ public HttpField remove(String name) return removed; } - /** - * 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 - * @return the value of the field as a long - * @throws NumberFormatException If bad long found - */ - public long getLongField(String name) throws NumberFormatException + public int size() { - HttpField field = getField(name); - return field == null ? -1L : field.getLongValue(); + return _size; } - /** - * 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. - * - * @param name the case-insensitive field name - * @return the value of the field as a number of milliseconds since unix epoch - */ - public long getDateField(String name) + @Override + public Stream stream() { - HttpField field = getField(name); - if (field == null) - return -1; - - String val = valueParameters(field.getValue(), null); - if (val == null) - return -1; - - final long date = DateParser.parseDate(val); - if (date == -1) - throw new IllegalArgumentException("Cannot convert date: " + val); - return date; + return Arrays.stream(_fields).limit(_size); } - /** - * Sets the value of an long field. - * - * @param name the field name - * @param value the field long value - */ - public void putLongField(HttpHeader name, long value) + @Override + public String toString() { - String v = Long.toString(value); - put(name, v); + return asString(); } - /** - * Sets the value of an long field. - * - * @param name the field name - * @param value the field long value - */ - public void putLongField(String name, long value) + protected String addCSV(QuotedCSV existing, String... values) { - String v = Long.toString(value); - put(name, v); - } + // remove any existing values from the new values + boolean add = true; + if (existing != null && !existing.isEmpty()) + { + add = false; - /** - * Sets the value of a date field. - * - * @param name the field name - * @param date the field date value - */ - public void putDateField(HttpHeader name, long date) - { - String d = DateGenerator.formatDate(date); - put(name, d); - } + for (int i = values.length; i-- > 0; ) + { + String unquoted = QuotedCSV.unquote(values[i]); + if (existing.getValues().contains(unquoted)) + values[i] = null; + else + add = true; + } + } - /** - * 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) - { - String d = DateGenerator.formatDate(date); - put(name, d); + if (add) + { + StringBuilder value = new StringBuilder(); + for (String v : values) + { + if (v == null) + continue; + if (value.length() > 0) + value.append(", "); + value.append(v); + } + if (value.length() > 0) + return value.toString(); + } + + return null; } /** - * Sets the value of a date field. + * HTTP Fields. A collection of HTTP header and or Trailer fields. * - * @param name the field name - * @param date the field date value + *

This class is not synchronized as it is expected that modifications will only be performed by a + * single thread. + * + *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. */ - public void addDateField(String name, long date) + private static class Immutable implements HttpFieldList { - String d = DateGenerator.formatDate(date); - add(name, d); - } + private final HttpField[] _fields; - @Override - public int hashCode() - { - int hash = 0; - for (HttpField field : _fields) + /** + * Initialize HttpFields from copy. + * + * @param fields the fields to copy data from + */ + Immutable(HttpField[] fields) { - hash += field.hashCode(); + _fields = fields; } - return hash; - } - @Override - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof HttpFields)) - return false; + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof Immutable)) + return false; - HttpFields that = (HttpFields)o; + return isEqualTo((HttpFieldList)o); + } - // Order is not important, so we cannot rely on List.equals(). - if (size() != that.size()) - return false; + @Override + public HttpField getField(int index) + { + if (index >= _fields.length) + throw new NoSuchElementException(); + return _fields[index]; + } - loop: - for (HttpField fi : this) + @Override + public int hashCode() { - for (HttpField fa : that) - { - if (fi.equals(fa)) - continue loop; - } - return false; + return asHashCode(); } - return true; - } - @Override - public String toString() - { - try + @Override + public Iterator iterator() { - StringBuilder buffer = new StringBuilder(); - for (HttpField field : this) + return new Iterator<>() { - if (field != null) + int _index = 0; + + @Override + public boolean hasNext() { - String tmp = field.getName(); - if (tmp != null) - buffer.append(tmp); - buffer.append(": "); - tmp = field.getValue(); - if (tmp != null) - buffer.append(tmp); - buffer.append("\r\n"); + return _index < _fields.length; } - } - buffer.append("\r\n"); - return buffer.toString(); + + @Override + public HttpField next() + { + if (_index < _fields.length) + return _fields[_index++]; + throw new NoSuchElementException(); + } + }; } - catch (Exception e) + + @Override + public int size() { - LOG.warn("Unable to get fields as String", e); - return e.toString(); + return _fields.length; } - } - public void clear() - { - _size = 0; - } - - public void addAll(HttpFields fields) - { - for (int i = 0; i < fields._size; i++) + @Override + public Stream stream() { - add(fields._fields[i]); + return Arrays.stream(_fields); } - } - - /** - * Get field value without parameters. Some field values can have parameters. This method separates the - * value from the parameters and optionally populates a map with the parameters. For example: - * - *

-     *
-     * FieldName : Value ; param1=val1 ; param2=val2
-     *
-     * 
- * - * @param value The Field value, possibly with parameters. - * @return The value. - */ - public static String stripParameters(String value) - { - if (value == null) - return null; - - int i = value.indexOf(';'); - if (i < 0) - return value; - return value.substring(0, i).trim(); - } - /** - * Get field value parameters. Some field values can have parameters. This method separates the - * value from the parameters and optionally populates a map with the parameters. For example: - * - *
-     *
-     * FieldName : Value ; param1=val1 ; param2=val2
-     *
-     * 
- * - * @param value The Field value, possibly with parameters. - * @param parameters A map to populate with the parameters, or null - * @return The value. - */ - public static String valueParameters(String value, Map parameters) - { - if (value == null) - return null; - - int i = value.indexOf(';'); - if (i < 0) - return value; - if (parameters == null) - return value.substring(0, i).trim(); - - StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); - while (tok1.hasMoreTokens()) + @Override + public String toString() { - String token = tok1.nextToken(); - StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); - if (tok2.hasMoreTokens()) - { - String paramName = tok2.nextToken(); - String paramVal = null; - if (tok2.hasMoreTokens()) - paramVal = tok2.nextToken(); - parameters.put(paramName, paramVal); - } + return asString(); } - - return value.substring(0, i).trim(); } private class ListItr implements ListIterator @@ -986,12 +626,27 @@ private class ListItr implements ListIterator int _cursor; // index of next element to return int _current = -1; + @Override + public void add(HttpField field) + { + _fields = Arrays.copyOf(_fields, _fields.length + 1); + System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); + _fields[_cursor++] = field; + _current = -1; + } + @Override public boolean hasNext() { return _cursor != _size; } + @Override + public boolean hasPrevious() + { + return _cursor > 0; + } + @Override public HttpField next() { @@ -1002,21 +657,9 @@ public HttpField next() } @Override - public void remove() - { - if (_current < 0) - throw new IllegalStateException(); - _size--; - System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); - _fields[_size] = null; - _cursor = _current; - _current = -1; - } - - @Override - public boolean hasPrevious() + public int nextIndex() { - return _cursor > 0; + return _cursor + 1; } @Override @@ -1028,12 +671,6 @@ public HttpField previous() return _fields[_current]; } - @Override - public int nextIndex() - { - return _cursor + 1; - } - @Override public int previousIndex() { @@ -1041,20 +678,23 @@ public int previousIndex() } @Override - public void set(HttpField field) + public void remove() { if (_current < 0) throw new IllegalStateException(); - _fields[_current] = field; + _size--; + System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); + _fields[_size] = null; + _cursor = _current; + _current = -1; } @Override - public void add(HttpField field) + public void set(HttpField field) { - _fields = Arrays.copyOf(_fields, _fields.length + 1); - System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); - _fields[_cursor++] = field; - _current = -1; + if (_current < 0) + throw new IllegalStateException(); + _fields[_current] = field; } } } 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 d6ba63ad0075..4a7a3f922d8d 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 @@ -96,6 +96,36 @@ public void testPutTo() throws Exception assertThat(result, Matchers.containsString("name1: value:B")); } + @Test + public void testImmutable() throws Exception + { + HttpFields builder = new HttpFields(); + + builder.put("name0", "value0"); + builder.put("name1", "value1"); + + HttpFieldList header = builder.asImmutable(); + + assertEquals("value0", header.get("name0")); + assertEquals("value0", header.get("Name0")); + assertEquals("value1", header.get("name1")); + assertEquals("value1", header.get("Name1")); + assertEquals(null, header.get("Name2")); + + assertEquals("value0", header.getField("name0").getValue()); + assertEquals("value0", header.getField("Name0").getValue()); + assertEquals("value1", header.getField("name1").getValue()); + assertEquals("value1", header.getField("Name1").getValue()); + assertEquals(null, header.getField("Name2")); + + assertEquals("value0", header.getField(0).getValue()); + assertEquals("value1", header.getField(1).getValue()); + assertThrows(NoSuchElementException.class, () -> + { + header.getField(2); + }); + } + @Test public void testGet() throws Exception { @@ -441,7 +471,7 @@ public void testAddQuotedCSV() throws Exception assertEquals(HttpFields.valueParameters(list.get(4), null), "four"); assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); - fields.addCSV("name", "six"); + assertTrue(fields.addCSV("name", "six")); list = fields.getCSV("name", false); assertEquals(HttpFields.valueParameters(list.get(0), null), "zero"); assertEquals(HttpFields.valueParameters(list.get(1), null), "one"); @@ -451,7 +481,7 @@ public void testAddQuotedCSV() throws Exception assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); assertEquals(HttpFields.valueParameters(list.get(6), null), "six"); - fields.addCSV("name", "1 + 1", "7", "zero"); + assertTrue(fields.addCSV("name", "1 + 1", "7", "zero")); list = fields.getCSV("name", false); assertEquals(HttpFields.valueParameters(list.get(0), null), "zero"); assertEquals(HttpFields.valueParameters(list.get(1), null), "one"); @@ -461,6 +491,13 @@ public void testAddQuotedCSV() throws Exception assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); assertEquals(HttpFields.valueParameters(list.get(6), null), "six"); assertEquals(HttpFields.valueParameters(list.get(7), null), "7"); + assertFalse(fields.addCSV("name", "1 + 1", "7", "zero")); + + assertTrue(fields.addCSV(HttpHeader.ACCEPT, "en", "it")); + list = fields.getCSV(HttpHeader.ACCEPT, false); + assertEquals(HttpFields.valueParameters(list.get(0), null), "en"); + assertEquals(HttpFields.valueParameters(list.get(1), null), "it"); + assertFalse(fields.addCSV(HttpHeader.ACCEPT, "en", "it")); } @Test From 75df043c3f976a1cef73aafc609c5b5169a40487 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Apr 2020 11:20:52 +0200 Subject: [PATCH 02/38] Immutable version of HttpFields Use an ArrayList in HttpFields. While slightly slower than the array, it will mostly be used as a builder pattern for an Immutable Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpFields.java | 189 +++++------------- 1 file changed, 54 insertions(+), 135 deletions(-) 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 571b58ee0957..fbc301e5c85c 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,6 +18,7 @@ package org.eclipse.jetty.http; +import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.Iterator; @@ -37,8 +38,7 @@ */ public class HttpFields implements Iterable, HttpFieldList { - HttpField[] _fields; - int _size; + ArrayList _fields; /** * Initialize an empty HttpFields. @@ -55,18 +55,36 @@ public HttpFields() */ public HttpFields(int capacity) { - _fields = new HttpField[capacity]; + _fields = new ArrayList<>(capacity); } /** - * Initialize HttpFields from copy. + * Initialize HttpFields from another. * * @param fields the fields to copy data from */ public HttpFields(HttpFields fields) { - _fields = Arrays.copyOf(fields._fields, fields._fields.length); - _size = fields._size; + _fields = new ArrayList<>(fields._fields); + } + + /** + * Initialize HttpFields from another. + * + * @param fields the fields to copy data from + */ + public HttpFields(HttpFieldList fields) + { + if (fields instanceof Immutable) + _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); + else if (fields instanceof HttpFields) + _fields = new ArrayList<>(((HttpFields)fields)._fields); + else + { + _fields = new ArrayList<>(fields.size() + 4); + for (HttpField f : fields) + _fields.add(f); + } } /** @@ -138,11 +156,7 @@ public void add(HttpHeader header, String value) public void add(HttpField field) { if (field != null) - { - if (_size == _fields.length) - _fields = Arrays.copyOf(_fields, _size * 2); - _fields[_size++] = field; - } + _fields.add(field); } /** @@ -151,11 +165,14 @@ public void add(HttpField field) * * @param fields the fields to add */ - public void add(HttpFields fields) + public void add(HttpFieldList fields) { + // TODO is this any different to addAll? + if (fields == null) return; + _fields.ensureCapacity(size() + fields.size() + 4); Enumeration e = fields.getFieldNames(); while (e.hasMoreElements()) { @@ -168,12 +185,11 @@ public void add(HttpFields fields) } } - public void addAll(HttpFields fields) + public void addAll(HttpFieldList fields) { - for (int i = 0; i < fields._size; i++) - { - add(fields._fields[i]); - } + _fields.ensureCapacity(size() + fields.size() + 4); + for (HttpField f : fields) + _fields.add(f); } /** @@ -186,10 +202,10 @@ public void addAll(HttpFields fields) */ public boolean addCSV(HttpHeader header, String... values) { + // TODO is the javadoc right ? QuotedCSV existing = null; - for (int i = 0; i < _size; i++) + for (HttpField f : this) { - HttpField f = _fields[i]; if (f.getHeader() == header) { if (existing == null) @@ -217,10 +233,10 @@ public boolean addCSV(HttpHeader header, String... values) */ public boolean addCSV(String name, String... values) { + // TODO is the javadoc right ? QuotedCSV existing = null; - for (int i = 0; i < _size; i++) + for (HttpField f : this) { - HttpField f = _fields[i]; if (f.getName().equalsIgnoreCase(name)) { if (existing == null) @@ -251,12 +267,12 @@ public void addDateField(String name, long date) public HttpFieldList asImmutable() { - return new HttpFields.Immutable(Arrays.copyOf(_fields, _size)); + return new HttpFields.Immutable(_fields.toArray(new HttpField[0])); } public void clear() { - _size = 0; + _fields.clear(); } @Override @@ -279,9 +295,7 @@ public boolean equals(Object o) @Override public HttpField getField(int index) { - if (index >= _size) - throw new NoSuchElementException(); - return _fields[index]; + return _fields.get(index); } @Override @@ -293,45 +307,27 @@ public int hashCode() @Override public Iterator iterator() { - return new Iterator<>() - { - int _index = 0; - @Override - public boolean hasNext() - { - return _index < _size; - } - - @Override - public HttpField next() - { - if (hasNext()) - return _fields[_index++]; - throw new NoSuchElementException(); - } - }; + return _fields.iterator(); } public ListIterator listIterator() { - return new ListItr(); + return _fields.listIterator(); } public void put(HttpField field) { boolean put = false; - for (int i = _size; i-- > 0; ) + for (ListIterator i = listIterator(); i.hasNext();) { - HttpField f = _fields[i]; + HttpField f = i.next(); if (f.isSameName(field)) { if (put) - { - System.arraycopy(_fields, i + 1, _fields, i, --_size - i); - } + i.remove(); else { - _fields[i] = field; + i.set(field); put = true; } } @@ -446,13 +442,13 @@ public void putLongField(String name, long value) public HttpField remove(HttpHeader name) { HttpField removed = null; - for (int i = _size; i-- > 0; ) + for (ListIterator i = listIterator(); i.hasNext();) { - HttpField f = _fields[i]; + HttpField f = i.next(); if (f.getHeader() == name) { removed = f; - System.arraycopy(_fields, i + 1, _fields, i, --_size - i); + i.remove(); } } return removed; @@ -467,13 +463,13 @@ public HttpField remove(HttpHeader name) public HttpField remove(String name) { HttpField removed = null; - for (int i = _size; i-- > 0; ) + for (ListIterator i = listIterator(); i.hasNext();) { - HttpField f = _fields[i]; + HttpField f = i.next(); if (f.getName().equalsIgnoreCase(name)) { removed = f; - System.arraycopy(_fields, i + 1, _fields, i, --_size - i); + i.remove(); } } return removed; @@ -481,13 +477,13 @@ public HttpField remove(String name) public int size() { - return _size; + return _fields.size(); } @Override public Stream stream() { - return Arrays.stream(_fields).limit(_size); + return _fields.stream(); } @Override @@ -620,81 +616,4 @@ public String toString() return asString(); } } - - private class ListItr implements ListIterator - { - int _cursor; // index of next element to return - int _current = -1; - - @Override - public void add(HttpField field) - { - _fields = Arrays.copyOf(_fields, _fields.length + 1); - System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); - _fields[_cursor++] = field; - _current = -1; - } - - @Override - public boolean hasNext() - { - return _cursor != _size; - } - - @Override - public boolean hasPrevious() - { - return _cursor > 0; - } - - @Override - public HttpField next() - { - if (_cursor == _size) - throw new NoSuchElementException(); - _current = _cursor++; - return _fields[_current]; - } - - @Override - public int nextIndex() - { - return _cursor + 1; - } - - @Override - public HttpField previous() - { - if (_cursor == 0) - throw new NoSuchElementException(); - _current = --_cursor; - return _fields[_current]; - } - - @Override - public int previousIndex() - { - return _cursor - 1; - } - - @Override - public void remove() - { - if (_current < 0) - throw new IllegalStateException(); - _size--; - System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); - _fields[_size] = null; - _cursor = _current; - _current = -1; - } - - @Override - public void set(HttpField field) - { - if (_current < 0) - throw new IllegalStateException(); - _fields[_current] = field; - } - } } From 753e02cf6be03572eb242b826998431993056a79 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Apr 2020 13:40:22 +0200 Subject: [PATCH 03/38] Immutable version of HttpFields Fixed exception type. Signed-off-by: Greg Wilkins --- jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java | 2 ++ 1 file changed, 2 insertions(+) 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 fbc301e5c85c..e6dd5584a217 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 @@ -295,6 +295,8 @@ public boolean equals(Object o) @Override public HttpField getField(int index) { + if (index >= size()) + throw new NoSuchElementException(); return _fields.get(index); } From 53bf5a5ca6847702db162c04dcd52b93fbffcecb Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 15 Apr 2020 23:25:05 +0200 Subject: [PATCH 04/38] Immutable version of HttpFields asImmutable method Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpFieldList.java | 16 ++++++++++++++++ .../java/org/eclipse/jetty/http/HttpFields.java | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java index 08ab53b09508..9bea960b5ef5 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java @@ -42,6 +42,8 @@ default int asHashCode() return hash; } + HttpFieldList asImmutable(); + default String asString() { StringBuilder buffer = new StringBuilder(); @@ -276,6 +278,20 @@ default long getLongField(String name) throws NumberFormatException return field == null ? -1L : field.getLongValue(); } + /** + * 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 header the header type + * @return the value of the field as a long + * @throws NumberFormatException If bad long found + */ + default long getLongField(HttpHeader header) throws NumberFormatException + { + HttpField field = getField(header); + return field == null ? -1L : field.getLongValue(); + } + /** * Get multiple field values of the same name, split and * sorted as a {@link QuotedQualityCSV} 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 e6dd5584a217..7b161f615751 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 @@ -265,6 +265,7 @@ public void addDateField(String name, long date) add(name, d); } + @Override public HttpFieldList asImmutable() { return new HttpFields.Immutable(_fields.toArray(new HttpField[0])); @@ -552,6 +553,12 @@ private static class Immutable implements HttpFieldList _fields = fields; } + @Override + public HttpFieldList asImmutable() + { + return this; + } + @Override public boolean equals(Object o) { From d9837d93b8ab5103a259250a7052d12a56af44d6 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 16 Apr 2020 11:25:30 +0200 Subject: [PATCH 05/38] Immutable MetaData Made HttpURIU immutable with a builder pattern. MetaData immutable and working within http module. Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpGenerator.java | 41 +- .../java/org/eclipse/jetty/http/HttpURI.java | 1437 ++++++++++------- .../java/org/eclipse/jetty/http/MetaData.java | 190 +-- .../jetty/http/HttpGeneratorClientTest.java | 74 +- .../jetty/http/HttpGeneratorServerTest.java | 152 +- .../org/eclipse/jetty/http/HttpURITest.java | 56 +- 6 files changed, 1066 insertions(+), 884 deletions(-) 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 c488b990403f..378f1209ce97 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 @@ -87,11 +87,11 @@ public enum Result private State _state = State.START; private EndOfContent _endOfContent = EndOfContent.UNKNOWN_CONTENT; + private MetaData _info; private long _contentPrepared = 0; private boolean _noContentResponse = false; private Boolean _persistent = null; - private Supplier _trailers = null; private final int _send; private static final int SEND_SERVER = 0x01; @@ -127,12 +127,12 @@ public HttpGenerator(boolean sendServerVersion, boolean sendXPoweredBy) public void reset() { _state = State.START; + _info = null; _endOfContent = EndOfContent.UNKNOWN_CONTENT; _noContentResponse = false; _persistent = null; _contentPrepared = 0; _needCRLF = false; - _trailers = null; } public State getState() @@ -208,6 +208,7 @@ public Result generateRequest(MetaData.Request info, ByteBuffer header, ByteBuff { if (info == null) return Result.NEED_INFO; + _info = info; if (header == null) return Result.NEED_HEADER; @@ -222,7 +223,7 @@ public Result generateRequest(MetaData.Request info, ByteBuffer header, ByteBuff if (info.getHttpVersion() == HttpVersion.HTTP_0_9) throw new BadMessageException(INTERNAL_SERVER_ERROR_500, "HTTP/0.9 not supported"); - generateHeaders(info, header, content, last); + generateHeaders(header, content, last); boolean expect100 = info.getFields().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); @@ -325,13 +326,14 @@ private Result completing(ByteBuffer chunk, ByteBuffer content) if (isChunking()) { - if (_trailers != null) + Supplier trailerSupplier = _info.getTrailerSupplier(); + if (_info.mayHaveTrailers()) { // Do we need a chunk buffer? if (chunk == null || chunk.capacity() <= CHUNK_SIZE) return Result.NEED_CHUNK_TRAILER; - HttpFields trailers = _trailers.get(); + HttpFieldList trailers = trailerSupplier.get(); if (trailers != null) { @@ -368,6 +370,8 @@ public Result generateResponse(MetaData.Response info, boolean head, ByteBuffer { if (info == null) return Result.NEED_INFO; + _info = info; + HttpVersion version = info.getHttpVersion(); if (version == null) throw new BadMessageException(INTERNAL_SERVER_ERROR_500, "No version"); @@ -411,7 +415,7 @@ else if (status == HttpStatus.NO_CONTENT_204 || status == HttpStatus.NOT_MODIFIE _noContentResponse = true; } - generateHeaders(info, header, content, last); + generateHeaders(header, content, last); // handle the content. int len = BufferUtil.length(content); @@ -494,7 +498,7 @@ private void prepareChunk(ByteBuffer chunk, int remaining) } } - private void generateTrailers(ByteBuffer buffer, HttpFields trailer) + private void generateTrailers(ByteBuffer buffer, HttpFieldList trailer) { // if we need CRLF add this to header if (_needCRLF) @@ -573,30 +577,29 @@ private byte[] getReasonBytes(String reason) return bytes; } - private void generateHeaders(MetaData info, ByteBuffer header, ByteBuffer content, boolean last) + private void generateHeaders(ByteBuffer header, ByteBuffer content, boolean last) { - final MetaData.Request request = (info instanceof MetaData.Request) ? (MetaData.Request)info : null; - final MetaData.Response response = (info instanceof MetaData.Response) ? (MetaData.Response)info : null; + final MetaData.Request request = (_info instanceof MetaData.Request) ? (MetaData.Request)_info : null; + final MetaData.Response response = (_info instanceof MetaData.Response) ? (MetaData.Response)_info : null; if (LOG.isDebugEnabled()) { - LOG.debug("generateHeaders {} last={} content={}", info, last, BufferUtil.toDetailString(content)); - LOG.debug(info.getFields().toString()); + LOG.debug("generateHeaders {} last={} content={}", _info, last, BufferUtil.toDetailString(content)); + LOG.debug(_info.getFields().toString()); } // default field values int send = _send; HttpField transferEncoding = null; - boolean http11 = info.getHttpVersion() == HttpVersion.HTTP_1_1; + boolean http11 = _info.getHttpVersion() == HttpVersion.HTTP_1_1; boolean close = false; - _trailers = http11 ? info.getTrailerSupplier() : null; - boolean chunkedHint = _trailers != null; + boolean chunkedHint = _info.hasTrailerSupplier(); boolean contentType = false; - long contentLength = info.getContentLength(); + long contentLength = _info.getContentLength(); boolean contentLengthField = false; // Generate fields - HttpFields fields = info.getFields(); + HttpFieldList fields = _info.getFields(); if (fields != null) { int n = fields.size(); @@ -647,7 +650,7 @@ else if (contentLength != field.getLongValue()) _persistent = false; } - if (info.getHttpVersion() == HttpVersion.HTTP_1_0 && _persistent == null && field.contains(HttpHeaderValue.KEEP_ALIVE.asString())) + if (_info.getHttpVersion() == HttpVersion.HTTP_1_0 && _persistent == null && field.contains(HttpHeaderValue.KEEP_ALIVE.asString())) { _persistent = true; } @@ -669,7 +672,7 @@ else if (contentLength != field.getLongValue()) } // Can we work out the content length? - if (last && contentLength < 0 && _trailers == null) + if (last && contentLength < 0 && !_info.mayHaveTrailers()) contentLength = _contentPrepared + BufferUtil.length(content); // Calculate how to end _content and connection, _content length and transfer encoding diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 2c112940f8bb..cf51446c499e 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -18,7 +18,6 @@ package org.eclipse.jetty.http; -import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; @@ -50,527 +49,126 @@ */ public class HttpURI { - private enum State + private final String _scheme; + private final String _user; + private final String _host; + private final int _port; + private final String _path; + private final String _param; + private final String _query; + private final String _fragment; + private String _uri; + private String _decodedPath; + + public HttpURI(String uri) { - START, - HOST_OR_PATH, - SCHEME_OR_PATH, - HOST, - IPV6, - PORT, - PATH, - PARAM, - QUERY, - FRAGMENT, - ASTERISK + Builder builder = new Builder(uri); + _uri = builder._uri; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; } - ; - - private String _scheme; - private String _user; - private String _host; - private int _port; - private String _path; - private String _param; - private String _query; - private String _fragment; - - String _uri; - String _decodedPath; - - /** - * Construct a normalized URI. - * Port is not set if it is the default port. - * - * @param scheme the URI scheme - * @param host the URI hose - * @param port the URI port - * @param path the URI path - * @param param the URI param - * @param query the URI query - * @param fragment the URI fragment - * @return the normalized URI - */ - public static HttpURI createHttpURI(String scheme, String host, int port, String path, String param, String query, String fragment) + public HttpURI(URI uri) { - if (port == 80 && HttpScheme.HTTP.is(scheme)) - port = 0; - if (port == 443 && HttpScheme.HTTPS.is(scheme)) - port = 0; - return new HttpURI(scheme, host, port, path, param, query, fragment); + Builder builder = new Builder(uri); + _uri = builder._uri; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; } - public HttpURI() + public HttpURI(HttpURI baseUri, String pathQuery) { + Builder builder = new Builder(baseUri, pathQuery); + _uri = builder._uri; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; } - public HttpURI(String scheme, String host, int port, String path, String param, String query, String fragment) + HttpURI(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) { + _uri = uri; _scheme = scheme; + _user = user; _host = host; _port = port; _path = path; + _decodedPath = decodedPath; _param = param; _query = query; _fragment = fragment; } - public HttpURI(HttpURI uri) - { - this(uri._scheme, uri._host, uri._port, uri._path, uri._param, uri._query, uri._fragment); - _uri = uri._uri; - } - - public HttpURI(String uri) + public void decodeQueryTo(MultiMap parameters) { - _port = -1; - parse(State.START, uri); + if (_query == null) + return; + UrlEncoded.decodeUtf8To(_query, parameters); } - public HttpURI(URI uri) + public void decodeQueryTo(MultiMap parameters, String encoding) { - _uri = null; - - _scheme = uri.getScheme(); - _host = uri.getHost(); - if (_host == null && uri.getRawSchemeSpecificPart().startsWith("//")) - _host = ""; - _port = uri.getPort(); - _user = uri.getUserInfo(); - _path = uri.getRawPath(); - - _decodedPath = uri.getPath(); - if (_decodedPath != null) - { - int p = _decodedPath.lastIndexOf(';'); - if (p >= 0) - _param = _decodedPath.substring(p + 1); - } - _query = uri.getRawQuery(); - _fragment = uri.getFragment(); - - _decodedPath = null; + decodeQueryTo(parameters, Charset.forName(encoding)); } - public HttpURI(String scheme, String host, int port, String pathQuery) + public void decodeQueryTo(MultiMap parameters, Charset encoding) { - _uri = null; - - _scheme = scheme; - _host = host; - _port = port; - - if (pathQuery != null) - parse(State.PATH, pathQuery); - } + if (_query == null) + return; - public void parse(String uri) - { - clear(); - _uri = uri; - parse(State.START, uri); + if (encoding == null || StandardCharsets.UTF_8.equals(encoding)) + UrlEncoded.decodeUtf8To(_query, parameters); + else + UrlEncoded.decodeTo(_query, parameters, encoding); } - public void parse(String uri, int offset, int length) + @Override + public boolean equals(Object o) { - clear(); - int end = offset + length; - _uri = uri.substring(offset, end); - parse(State.START, uri); + if (o == this) + return true; + if (!(o instanceof HttpURI)) + return false; + return toString().equals(o.toString()); } - private void parse(State state, final String uri) + public String getAuthority() { - boolean encoded = false; - int end = uri.length(); - int mark = 0; - int pathMark = 0; - char last = '/'; - for (int i = 0; i < end; i++) - { - char c = uri.charAt(i); - - switch (state) - { - case START: - { - switch (c) - { - case '/': - mark = i; - state = State.HOST_OR_PATH; - break; - case ';': - mark = i + 1; - state = State.PARAM; - break; - case '?': - // assume empty path (if seen at start) - _path = ""; - mark = i + 1; - state = State.QUERY; - break; - case '#': - mark = i + 1; - state = State.FRAGMENT; - break; - case '*': - _path = "*"; - state = State.ASTERISK; - break; - - case '.': - pathMark = i; - state = State.PATH; - encoded = true; - break; - - default: - mark = i; - if (_scheme == null) - state = State.SCHEME_OR_PATH; - else - { - pathMark = i; - state = State.PATH; - } - break; - } - - continue; - } - - case SCHEME_OR_PATH: - { - switch (c) - { - case ':': - // must have been a scheme - _scheme = uri.substring(mark, i); - // Start again with scheme set - state = State.START; - break; - - case '/': - // must have been in a path and still are - state = State.PATH; - break; - - case ';': - // must have been in a path - mark = i + 1; - state = State.PARAM; - break; - - case '?': - // must have been in a path - _path = uri.substring(mark, i); - mark = i + 1; - state = State.QUERY; - break; - - case '%': - // must have be in an encoded path - encoded = true; - state = State.PATH; - break; - - case '#': - // must have been in a path - _path = uri.substring(mark, i); - state = State.FRAGMENT; - break; - - default: - break; - } - continue; - } - - case HOST_OR_PATH: - { - switch (c) - { - case '/': - _host = ""; - mark = i + 1; - state = State.HOST; - break; - - case '@': - case ';': - case '?': - case '#': - // was a path, look again - i--; - pathMark = mark; - state = State.PATH; - break; - - case '.': - // it is a path - encoded = true; - pathMark = mark; - state = State.PATH; - break; - - default: - // it is a path - pathMark = mark; - state = State.PATH; - } - continue; - } - - case HOST: - { - switch (c) - { - case '/': - _host = uri.substring(mark, i); - pathMark = mark = i; - state = State.PATH; - break; - case ':': - if (i > mark) - _host = uri.substring(mark, i); - mark = i + 1; - state = State.PORT; - break; - case '@': - if (_user != null) - throw new IllegalArgumentException("Bad authority"); - _user = uri.substring(mark, i); - mark = i + 1; - break; - - case '[': - state = State.IPV6; - break; - - default: - break; - } - break; - } - - case IPV6: - { - switch (c) - { - case '/': - throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri); - case ']': - c = uri.charAt(++i); - _host = uri.substring(mark, i); - if (c == ':') - { - mark = i + 1; - state = State.PORT; - } - else - { - pathMark = mark = i; - state = State.PATH; - } - break; - - default: - break; - } - - break; - } - - case PORT: - { - if (c == '@') - { - if (_user != null) - throw new IllegalArgumentException("Bad authority"); - // It wasn't a port, but a password! - _user = _host + ":" + uri.substring(mark, i); - mark = i + 1; - state = State.HOST; - } - else if (c == '/') - { - _port = TypeUtil.parseInt(uri, mark, i - mark, 10); - pathMark = mark = i; - state = State.PATH; - } - break; - } - - case PATH: - { - switch (c) - { - case ';': - mark = i + 1; - state = State.PARAM; - break; - case '?': - _path = uri.substring(pathMark, i); - mark = i + 1; - state = State.QUERY; - break; - case '#': - _path = uri.substring(pathMark, i); - mark = i + 1; - state = State.FRAGMENT; - break; - case '%': - encoded = true; - break; - case '.': - if ('/' == last) - encoded = true; - break; - default: - break; - } - break; - } - - case PARAM: - { - switch (c) - { - case '?': - _path = uri.substring(pathMark, i); - _param = uri.substring(mark, i); - mark = i + 1; - state = State.QUERY; - break; - case '#': - _path = uri.substring(pathMark, i); - _param = uri.substring(mark, i); - mark = i + 1; - state = State.FRAGMENT; - break; - case '/': - encoded = true; - // ignore internal params - state = State.PATH; - break; - case ';': - // multiple parameters - mark = i + 1; - break; - default: - break; - } - break; - } - - case QUERY: - { - if (c == '#') - { - _query = uri.substring(mark, i); - mark = i + 1; - state = State.FRAGMENT; - } - break; - } - - case ASTERISK: - { - throw new IllegalArgumentException("Bad character '*'"); - } - - case FRAGMENT: - { - _fragment = uri.substring(mark, end); - i = end; - break; - } - - default: - throw new IllegalStateException(state.toString()); - } - last = c; - } - - switch (state) - { - case START: - break; - case SCHEME_OR_PATH: - _path = uri.substring(mark, end); - break; - - case HOST_OR_PATH: - _path = uri.substring(mark, end); - break; - - case HOST: - if (end > mark) - _host = uri.substring(mark, end); - break; - - case IPV6: - throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri); - - case PORT: - _port = TypeUtil.parseInt(uri, mark, end - mark, 10); - break; - - case ASTERISK: - break; - - case FRAGMENT: - _fragment = uri.substring(mark, end); - break; - - case PARAM: - _path = uri.substring(pathMark, end); - _param = uri.substring(mark, end); - break; - - case PATH: - _path = uri.substring(pathMark, end); - break; - - case QUERY: - _query = uri.substring(mark, end); - break; - - default: - throw new IllegalStateException(state.toString()); - } - - if (!encoded) - { - if (_param == null) - _decodedPath = _path; - else - _decodedPath = _path.substring(0, _path.length() - _param.length() - 1); - } + if (_port > 0) + return _host + ":" + _port; + return _host; } - /** - * Parse according to https://tools.ietf.org/html/rfc7230#section-5.3 - * - * @param method the request method - * @param uri the request uri - */ - public void parseRequestTarget(String method, String uri) + public String getDecodedPath() { - clear(); - _uri = uri; - - if (HttpMethod.CONNECT.is(method)) - _path = uri; - else - parse(uri.startsWith("/") ? State.PATH : State.START, uri); + if (_decodedPath == null && _path != null) + _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); + return _decodedPath; } - public String getScheme() + public String getFragment() { - return _scheme; + return _fragment; } public String getHost() @@ -581,9 +179,9 @@ public String getHost() return _host; } - public int getPort() + public String getParam() { - return _port; + return _param; } /** @@ -596,25 +194,16 @@ public String getPath() return _path; } - public String getDecodedPath() - { - if (_decodedPath == null && _path != null) - _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); - return _decodedPath; - } - - public String getParam() + public String getPathQuery() { - return _param; + if (_query == null) + return _path; + return _path + "?" + _query; } - public void setParam(String param) + public int getPort() { - _param = param; - if (_path != null && !_path.contains(_param)) - { - _path += ";" + _param; - } + return _port; } public String getQuery() @@ -622,58 +211,30 @@ public String getQuery() return _query; } - public boolean hasQuery() + public String getScheme() { - return _query != null && !_query.isEmpty(); + return _scheme; } - public String getFragment() + public String getUser() { - return _fragment; + return _user; } - public void decodeQueryTo(MultiMap parameters) + public boolean hasAuthority() { - if (_query == null) - return; - UrlEncoded.decodeUtf8To(_query, parameters); + return _host != null; } - public void decodeQueryTo(MultiMap parameters, String encoding) throws UnsupportedEncodingException + public boolean hasQuery() { - decodeQueryTo(parameters, Charset.forName(encoding)); + return _query != null && !_query.isEmpty(); } - public void decodeQueryTo(MultiMap parameters, Charset encoding) throws UnsupportedEncodingException + public boolean isAbsolute() { - if (_query == null) - return; - - if (encoding == null || StandardCharsets.UTF_8.equals(encoding)) - UrlEncoded.decodeUtf8To(_query, parameters); - else - UrlEncoded.decodeTo(_query, parameters, encoding); - } - - public void clear() - { - _uri = null; - - _scheme = null; - _host = null; - _port = -1; - _path = null; - _param = null; - _query = null; - _fragment = null; - - _decodedPath = null; - } - - public boolean isAbsolute() - { - return _scheme != null && !_scheme.isEmpty(); - } + return _scheme != null && !_scheme.isEmpty(); + } @Override public String toString() @@ -713,103 +274,743 @@ public String toString() return _uri; } - @Override - public boolean equals(Object o) + public URI toURI() { - if (o == this) - return true; - if (!(o instanceof HttpURI)) - return false; - return toString().equals(o.toString()); + try + { + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + } + catch (URISyntaxException x) + { + throw new RuntimeException(x); + } } - public void setScheme(String scheme) + public static class Builder { - _scheme = scheme; - _uri = null; - } + private enum State + { + START, + HOST_OR_PATH, + SCHEME_OR_PATH, + HOST, + IPV6, + PORT, + PATH, + PARAM, + QUERY, + FRAGMENT, + ASTERISK + } - /** - * @param host the host - * @param port the port - */ - public void setAuthority(String host, int port) - { - _host = host; - _port = port; - _uri = null; - } + String _uri; + String _decodedPath; + private String _scheme; + private String _user; + private String _host; + private int _port; + private String _path; + private String _param; + private String _query; + private String _fragment; + + public Builder() + { + } - /** - * @param path the path - */ - public void setPath(String path) - { - _uri = null; - _path = path; - _decodedPath = null; - } + public Builder(String scheme, String host, int port, String path, String param, String query, String fragment) + { + _scheme = scheme; + _host = host; + _port = port; + _path = path; + _param = param; + _query = query; + _fragment = fragment; + } - /** - * @param path the decoded path - */ - public void setDecodedPath(String path) - { - _uri = null; - _path = URIUtil.encodePath(path); - _decodedPath = path; - } + public Builder(HttpURI uri) + { + _uri = uri._uri; + _scheme = uri._scheme; + _user = uri._user; + _host = uri._host; + _port = uri._port; + _path = uri._path; + _decodedPath = uri._decodedPath; + _param = uri._param; + _query = uri._query; + _fragment = uri._fragment; + } - public void setPathQuery(String pathQuery) - { - _uri = null; - _path = null; - _decodedPath = null; - _param = null; - _fragment = null; - if (pathQuery != null) - parse(State.PATH, pathQuery); - } + public Builder(HttpURI uri, String pathQuery) + { + _uri = null; + _scheme = uri._scheme; + _user = uri._user; + _host = uri._host; + _port = uri._port; + if (pathQuery != null) + parse(State.PATH, pathQuery); + } - public void setQuery(String query) - { - _query = query; - _uri = null; - } + public Builder(String uri) + { + _port = -1; + parse(State.START, uri); + } - public URI toURI() - { - try + public Builder(URI uri) { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + _uri = null; + + _scheme = uri.getScheme(); + _host = uri.getHost(); + if (_host == null && uri.getRawSchemeSpecificPart().startsWith("//")) + _host = ""; + _port = uri.getPort(); + _user = uri.getUserInfo(); + _path = uri.getRawPath(); + + _decodedPath = uri.getPath(); + if (_decodedPath != null) + { + int p = _decodedPath.lastIndexOf(';'); + if (p >= 0) + _param = _decodedPath.substring(p + 1); + } + _query = uri.getRawQuery(); + _fragment = uri.getFragment(); + + _decodedPath = null; } - catch (URISyntaxException x) + + public Builder(String scheme, String host, int port, String pathQuery) { - throw new RuntimeException(x); + _uri = null; + + _scheme = scheme; + _host = host; + _port = port; + + if (pathQuery != null) + parse(State.PATH, pathQuery); } - } - public String getPathQuery() - { - if (_query == null) + public Builder(String method, String uri) + { + _uri = uri; + if (HttpMethod.CONNECT.is(method)) + _path = uri; + else + parse(uri.startsWith("/") ? State.PATH : State.START, uri); + } + + public String authority() + { + if (_port > 0) + return _host + ":" + _port; + return _host; + } + + /** + * @param host the host + * @param port the port + */ + public Builder authority(String host, int port) + { + _user = null; + _host = host; + _port = port; + _uri = null; + return this; + } + + public HttpURI build() + { + return new HttpURI(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); + } + + public void clear() + { + _uri = null; + _scheme = null; + _host = null; + _port = -1; + _path = null; + _param = null; + _query = null; + _fragment = null; + _decodedPath = null; + _user = null; + } + + public String decodedPath() + { + if (_decodedPath == null && _path != null) + _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); + return _decodedPath; + } + + public Builder decodedPath(String path) + { + _uri = null; + _path = URIUtil.encodePath(path); + _decodedPath = path; + return this; + } + + public String fragment() + { + return _fragment; + } + + public Builder fragment(String fragment) + { + _fragment = fragment; + return this; + } + + public boolean hasAuthority() + { + return _host != null; + } + + public boolean hasQuery() + { + return _query != null && !_query.isEmpty(); + } + + public String host() + { + return _host; + } + + public Builder host(String host) + { + _host = host; + return this; + } + + public boolean isAbsolute() + { + return _scheme != null && !_scheme.isEmpty(); + } + + public Builder normalize() + { + if (_port == 80 && HttpScheme.HTTP.is(_scheme)) + _port = 0; + if (_port == 443 && HttpScheme.HTTPS.is(_scheme)) + _port = 0; + return this; + } + + public String param() + { + return _param; + } + + public Builder param(String param) + { + _param = param; + if (_path != null && !_path.contains(_param)) + { + _path += ";" + _param; + } + return this; + } + + /** + * The parsed Path. + * + * @return the path as parsed on valid URI. null for invalid URI. + */ + public String path() + { return _path; - return _path + "?" + _query; - } + } - public boolean hasAuthority() - { - return _host != null; - } + /** + * @param path the path + */ + public Builder path(String path) + { + _uri = null; + _path = path; + _decodedPath = null; + return this; + } - public String getAuthority() - { - if (_port > 0) - return _host + ":" + _port; - return _host; - } + public String pathQuery() + { + if (_query == null) + return _path; + return _path + "?" + _query; + } - public String getUser() - { - return _user; + public Builder pathQuery(String pathQuery) + { + _uri = null; + _path = null; + _decodedPath = null; + _param = null; + _fragment = null; + if (pathQuery != null) + parse(State.PATH, pathQuery); + return this; + } + + public int port() + { + return _port; + } + + public Builder port(int port) + { + _port = port; + return this; + } + + public String query() + { + return _query; + } + + public Builder query(String query) + { + _query = query; + _uri = null; + return this; + } + + public String scheme() + { + return _scheme; + } + + public Builder scheme(String scheme) + { + _scheme = scheme; + _uri = null; + return this; + } + + @Override + public String toString() + { + return build().toString(); + } + + public URI toURI() + { + try + { + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + } + catch (URISyntaxException x) + { + throw new RuntimeException(x); + } + } + + public Builder uri(String uri) + { + clear(); + _uri = uri; + parse(State.START, uri); + return this; + } + + public Builder uri(String uri, int offset, int length) + { + clear(); + int end = offset + length; + _uri = uri.substring(offset, end); + parse(State.START, uri); + return this; + } + + public String user() + { + return _user; + } + + public Builder user(String user) + { + _user = user; + return this; + } + + private void parse(State state, final String uri) + { + boolean encoded = false; + int end = uri.length(); + int mark = 0; + int pathMark = 0; + char last = '/'; + for (int i = 0; i < end; i++) + { + char c = uri.charAt(i); + + switch (state) + { + case START: + { + switch (c) + { + case '/': + mark = i; + state = State.HOST_OR_PATH; + break; + case ';': + mark = i + 1; + state = State.PARAM; + break; + case '?': + // assume empty path (if seen at start) + _path = ""; + mark = i + 1; + state = State.QUERY; + break; + case '#': + mark = i + 1; + state = State.FRAGMENT; + break; + case '*': + _path = "*"; + state = State.ASTERISK; + break; + + case '.': + pathMark = i; + state = State.PATH; + encoded = true; + break; + + default: + mark = i; + if (_scheme == null) + state = State.SCHEME_OR_PATH; + else + { + pathMark = i; + state = State.PATH; + } + break; + } + + continue; + } + + case SCHEME_OR_PATH: + { + switch (c) + { + case ':': + // must have been a scheme + _scheme = uri.substring(mark, i); + // Start again with scheme set + state = State.START; + break; + + case '/': + // must have been in a path and still are + state = State.PATH; + break; + + case ';': + // must have been in a path + mark = i + 1; + state = State.PARAM; + break; + + case '?': + // must have been in a path + _path = uri.substring(mark, i); + mark = i + 1; + state = State.QUERY; + break; + + case '%': + // must have be in an encoded path + encoded = true; + state = State.PATH; + break; + + case '#': + // must have been in a path + _path = uri.substring(mark, i); + state = State.FRAGMENT; + break; + + default: + break; + } + continue; + } + + case HOST_OR_PATH: + { + switch (c) + { + case '/': + _host = ""; + mark = i + 1; + state = State.HOST; + break; + + case '@': + case ';': + case '?': + case '#': + // was a path, look again + i--; + pathMark = mark; + state = State.PATH; + break; + + case '.': + // it is a path + encoded = true; + pathMark = mark; + state = State.PATH; + break; + + default: + // it is a path + pathMark = mark; + state = State.PATH; + } + continue; + } + + case HOST: + { + switch (c) + { + case '/': + _host = uri.substring(mark, i); + pathMark = mark = i; + state = State.PATH; + break; + case ':': + if (i > mark) + _host = uri.substring(mark, i); + mark = i + 1; + state = State.PORT; + break; + case '@': + if (_user != null) + throw new IllegalArgumentException("Bad authority"); + _user = uri.substring(mark, i); + mark = i + 1; + break; + + case '[': + state = State.IPV6; + break; + + default: + break; + } + break; + } + + case IPV6: + { + switch (c) + { + case '/': + throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri); + case ']': + c = uri.charAt(++i); + _host = uri.substring(mark, i); + if (c == ':') + { + mark = i + 1; + state = State.PORT; + } + else + { + pathMark = mark = i; + state = State.PATH; + } + break; + + default: + break; + } + + break; + } + + case PORT: + { + if (c == '@') + { + if (_user != null) + throw new IllegalArgumentException("Bad authority"); + // It wasn't a port, but a password! + _user = _host + ":" + uri.substring(mark, i); + mark = i + 1; + state = State.HOST; + } + else if (c == '/') + { + _port = TypeUtil.parseInt(uri, mark, i - mark, 10); + pathMark = mark = i; + state = State.PATH; + } + break; + } + + case PATH: + { + switch (c) + { + case ';': + mark = i + 1; + state = State.PARAM; + break; + case '?': + _path = uri.substring(pathMark, i); + mark = i + 1; + state = State.QUERY; + break; + case '#': + _path = uri.substring(pathMark, i); + mark = i + 1; + state = State.FRAGMENT; + break; + case '%': + encoded = true; + break; + case '.': + if ('/' == last) + encoded = true; + break; + default: + break; + } + break; + } + + case PARAM: + { + switch (c) + { + case '?': + _path = uri.substring(pathMark, i); + _param = uri.substring(mark, i); + mark = i + 1; + state = State.QUERY; + break; + case '#': + _path = uri.substring(pathMark, i); + _param = uri.substring(mark, i); + mark = i + 1; + state = State.FRAGMENT; + break; + case '/': + encoded = true; + // ignore internal params + state = State.PATH; + break; + case ';': + // multiple parameters + mark = i + 1; + break; + default: + break; + } + break; + } + + case QUERY: + { + if (c == '#') + { + _query = uri.substring(mark, i); + mark = i + 1; + state = State.FRAGMENT; + } + break; + } + + case ASTERISK: + { + throw new IllegalArgumentException("Bad character '*'"); + } + + case FRAGMENT: + { + _fragment = uri.substring(mark, end); + i = end; + break; + } + + default: + throw new IllegalStateException(state.toString()); + } + last = c; + } + + switch (state) + { + case START: + break; + case SCHEME_OR_PATH: + _path = uri.substring(mark, end); + break; + + case HOST_OR_PATH: + _path = uri.substring(mark, end); + break; + + case HOST: + if (end > mark) + _host = uri.substring(mark, end); + break; + + case IPV6: + throw new IllegalArgumentException("No closing ']' for ipv6 in " + uri); + + case PORT: + _port = TypeUtil.parseInt(uri, mark, end - mark, 10); + break; + + case ASTERISK: + break; + + case FRAGMENT: + _fragment = uri.substring(mark, end); + break; + + case PARAM: + _path = uri.substring(pathMark, end); + _param = uri.substring(mark, end); + break; + + case PATH: + _path = uri.substring(pathMark, end); + break; + + case QUERY: + _query = uri.substring(mark, end); + break; + + default: + throw new IllegalStateException(state.toString()); + } + + if (!encoded) + { + if (_param == null) + _decodedPath = _path; + else + _decodedPath = _path.substring(0, _path.length() - _param.length() - 1); + } + } } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 491cd123b1c5..eb035dfc24e3 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -18,35 +18,44 @@ package org.eclipse.jetty.http; -import java.util.Collections; import java.util.Iterator; import java.util.function.Supplier; public class MetaData implements Iterable { - private HttpVersion _httpVersion; - private final HttpFields _fields; - private long _contentLength; - private Supplier _trailers; - - public MetaData(HttpVersion version, HttpFields fields) + private static final Supplier SELF_SUPPLIED_TRAILORS = () -> null; + private static final HttpFieldList SUPPLIED_TRAILERS = new HttpFields().asImmutable(); + private final HttpVersion _httpVersion; + private final HttpFieldList _fields; + private final long _contentLengthKnown; + private final long _contentLengthField; + private final Supplier _trailerSupplier; + private HttpFieldList _trailers; + + public MetaData(HttpVersion version, HttpFieldList fields) { this(version, fields, Long.MIN_VALUE); } - public MetaData(HttpVersion version, HttpFields fields, long contentLength) + public MetaData(HttpVersion version, HttpFieldList fields, long contentLengthKnown) { - _httpVersion = version; - _fields = fields; - _contentLength = contentLength; + this(version, fields, contentLengthKnown, SELF_SUPPLIED_TRAILORS); } - protected void recycle() + public MetaData(HttpVersion version, HttpFieldList fields, long contentLengthKnown, Supplier trailers) { - _httpVersion = null; - if (_fields != null) - _fields.clear(); - _contentLength = Long.MIN_VALUE; + _httpVersion = version; + _fields = fields == null ? null : fields.asImmutable(); + _contentLengthKnown = contentLengthKnown; + _contentLengthField = _fields == null ? -1 : _fields.getLongField(HttpHeader.CONTENT_LENGTH); + if (trailers == SELF_SUPPLIED_TRAILORS) + _trailerSupplier = () -> _trailers; + else + { + _trailerSupplier = trailers; + if (trailers != null) + _trailers = SUPPLIED_TRAILERS; + } } public boolean isRequest() @@ -68,52 +77,49 @@ public HttpVersion getHttpVersion() } /** - * @param httpVersion the HTTP version to set + * @return the HTTP fields of this MetaData object */ - public void setHttpVersion(HttpVersion httpVersion) + public HttpFieldList getFields() { - _httpVersion = httpVersion; + return _fields; } - /** - * @return the HTTP fields of this MetaData object - */ - public HttpFields getFields() + public boolean mayHaveTrailers() { - return _fields; + return _trailers != null; + } + + public boolean hasTrailerSupplier() + { + return _trailers == SUPPLIED_TRAILERS; } - public Supplier getTrailerSupplier() + public Supplier getTrailerSupplier() { - return _trailers; + return _trailerSupplier; } - public void setTrailerSupplier(Supplier trailers) + public void setTrailers(HttpFieldList trailers) { + if (_trailers != null) + throw new IllegalStateException(); _trailers = trailers; } - /** - * @return the content length if available, otherwise {@link Long#MIN_VALUE} - */ + public long getContentLengthField() + { + return _contentLengthField; + } + public long getContentLength() { - if (_contentLength == Long.MIN_VALUE) - { - if (_fields != null) - { - HttpField field = _fields.getField(HttpHeader.CONTENT_LENGTH); - _contentLength = field == null ? -1 : field.getLongValue(); - } - } - return _contentLength; + return _contentLengthKnown; } @Override public Iterator iterator() { - HttpFields fields = getFields(); - return fields == null ? Collections.emptyIterator() : fields.iterator(); + return _fields.iterator(); } @Override @@ -129,56 +135,42 @@ public String toString() public static class Request extends MetaData { - private String _method; - private HttpURI _uri; + private final String _method; + private final HttpURI _uri; - public Request(HttpFields fields) + public Request(HttpFieldList fields) { this(null, null, null, fields); } - public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields) + public Request(String method, HttpURI uri, HttpVersion version, HttpFieldList fields) { this(method, uri, version, fields, Long.MIN_VALUE); } - public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength) + public Request(String method, HttpURI uri, HttpVersion version, HttpFieldList fields, long contentLength) { super(version, fields, contentLength); _method = method; _uri = uri; } - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields) + public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields) { this(method, scheme, hostPort, uri, version, fields, Long.MIN_VALUE); } - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) + public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields, long contentLength) { this(method, scheme == null ? null : scheme.asString(), hostPort, uri, version, fields, contentLength); } - public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) - { - this(method, new HttpURI(scheme, - hostPort == null ? null : hostPort.getHost(), - hostPort == null ? -1 : hostPort.getPort(), - uri), version, fields, contentLength); - } - - public Request(Request request) - { - this(request.getMethod(), new HttpURI(request.getURI()), request.getHttpVersion(), new HttpFields(request.getFields()), request.getContentLength()); - } - - @Override - public void recycle() + public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields, long contentLength) { - super.recycle(); - _method = null; - if (_uri != null) - _uri.clear(); + this(method, new HttpURI.Builder(scheme, + hostPort == null ? null : hostPort.getHost(), + hostPort == null ? -1 : hostPort.getPort(), + uri).build(), version, fields, contentLength); } @Override @@ -195,14 +187,6 @@ public String getMethod() return _method; } - /** - * @param method the HTTP method to set - */ - public void setMethod(String method) - { - _method = method; - } - /** * @return the HTTP URI */ @@ -211,14 +195,6 @@ public HttpURI getURI() return _uri; } - /** - * @param uri the HTTP URI to set - */ - public void setURI(HttpURI uri) - { - _uri = uri; - } - /** * @return the HTTP URI in string form */ @@ -235,7 +211,7 @@ public String getProtocol() @Override public String toString() { - HttpFields fields = getFields(); + HttpFieldList fields = getFields(); return String.format("%s{u=%s,%s,h=%d,cl=%d,p=%s}", getMethod(), getURI(), getHttpVersion(), fields == null ? -1 : fields.size(), getContentLength(), getProtocol()); } @@ -243,7 +219,7 @@ public String toString() public static class ConnectRequest extends Request { - private String _protocol; + private final String _protocol; public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { @@ -261,24 +237,12 @@ public String getProtocol() { return _protocol; } - - @Override - public void recycle() - { - super.recycle(); - _protocol = null; - } } public static class Response extends MetaData { - private int _status; - private String _reason; - - public Response() - { - this(null, 0, null); - } + private final int _status; + private final String _reason; public Response(HttpVersion version, int status, HttpFields fields) { @@ -287,13 +251,17 @@ public Response(HttpVersion version, int status, HttpFields fields) public Response(HttpVersion version, int status, HttpFields fields, long contentLength) { - super(version, fields, contentLength); - _status = status; + this(version, status, null, fields, contentLength); } public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength) { - super(version, fields, contentLength); + this(version, status, reason, fields, contentLength, null); + } + + public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength, Supplier trailers) + { + super(version, fields, contentLength, trailers); _reason = reason; _status = status; } @@ -320,26 +288,10 @@ public String getReason() return _reason; } - /** - * @param status the HTTP status to set - */ - public void setStatus(int status) - { - _status = status; - } - - /** - * @param reason the HTTP reason to set - */ - public void setReason(String reason) - { - _reason = reason; - } - @Override public String toString() { - HttpFields fields = getFields(); + HttpFieldList fields = getFields(); return String.format("%s{s=%d,h=%d,cl=%d}", getHttpVersion(), getStatus(), fields == null ? -1 : fields.size(), getContentLength()); } } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java index e5bdf2609aae..2059e55e390d 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java @@ -33,16 +33,21 @@ public class HttpGeneratorClientTest { public static final String[] connect = {null, "keep-alive", "close"}; - class Info extends MetaData.Request + class RequestInfo extends MetaData.Request { - Info(String method, String uri) + RequestInfo(String method, String uri, HttpFieldList fields) { - super(method, new HttpURI(uri), HttpVersion.HTTP_1_1, new HttpFields(), -1); + super(method, new HttpURI.Builder(method,uri).build(), HttpVersion.HTTP_1_1, fields, -1); } - public Info(String method, String uri, int contentLength) + RequestInfo(String method, String uri, HttpVersion version, HttpFieldList fields) { - super(method, new HttpURI(uri), HttpVersion.HTTP_1_1, new HttpFields(), contentLength); + super(method, new HttpURI.Builder(method,uri).build(), version, fields, -1); + } + + RequestInfo(String method, String uri, int contentLength, HttpFieldList fields) + { + super(method, new HttpURI.Builder(method,uri).build(), HttpVersion.HTTP_1_1, fields, contentLength); } } @@ -57,9 +62,10 @@ public void testGETRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("GET", "/index.html"); - info.getFields().add("Host", "something"); - info.getFields().add("User-Agent", "test"); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("User-Agent", "test"); + RequestInfo info = new RequestInfo("GET", "/index.html", fields); assertTrue(!gen.isChunking()); result = gen.generateRequest(info, null, null, null, true); @@ -94,27 +100,29 @@ public void testEmptyHeaders() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("GET", "/index.html"); - info.getFields().add("Host", "something"); - info.getFields().add("Null", null); - info.getFields().add("Empty", ""); - assertTrue(!gen.isChunking()); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("Null", null); + fields.add("Empty", ""); + RequestInfo info = new RequestInfo("GET", "/index.html", fields); + assertFalse(gen.isChunking()); result = gen.generateRequest(info, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); + assertFalse(gen.isChunking()); result = gen.generateRequest(info, header, null, null, true); assertEquals(HttpGenerator.Result.FLUSH, result); assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); - assertTrue(!gen.isChunking()); + assertFalse(gen.isChunking()); String out = BufferUtil.toString(header); BufferUtil.clear(header); result = gen.generateResponse(null, false, null, null, null, false); assertEquals(HttpGenerator.Result.DONE, result); assertEquals(HttpGenerator.State.END, gen.getState()); - assertTrue(!gen.isChunking()); + assertFalse(gen.isChunking()); assertEquals(0, gen.getContentPrepared()); assertThat(out, Matchers.containsString("GET /index.html HTTP/1.1")); @@ -128,10 +136,10 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - Info info = new Info("GET", "/index.html"); - info.getFields().add("Host", "localhost"); - info.getFields().add("Field", "SomeWhatLongValue"); - info.setHttpVersion(HttpVersion.HTTP_1_0); + HttpFields fields = new HttpFields(); + fields.add("Host", "localhost"); + fields.add("Field", "SomeWhatLongValue"); + RequestInfo info = new RequestInfo("GET", "/index.html", HttpVersion.HTTP_1_0, fields); HttpGenerator.Result result = gen.generateRequest(info, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -170,9 +178,10 @@ public void testPOSTRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("POST", "/index.html"); - info.getFields().add("Host", "something"); - info.getFields().add("User-Agent", "test"); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("User-Agent", "test"); + RequestInfo info = new RequestInfo("POST", "/index.html", fields); assertTrue(!gen.isChunking()); result = gen.generateRequest(info, null, null, null, true); @@ -209,9 +218,10 @@ public void testRequestWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("POST", "/index.html"); - info.getFields().add("Host", "something"); - info.getFields().add("User-Agent", "test"); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("User-Agent", "test"); + RequestInfo info = new RequestInfo("POST", "/index.html", fields); result = gen.generateRequest(info, null, null, content0, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -254,9 +264,10 @@ public void testRequestWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("POST", "/index.html"); - info.getFields().add("Host", "something"); - info.getFields().add("User-Agent", "test"); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("User-Agent", "test"); + RequestInfo info = new RequestInfo("POST", "/index.html", fields); result = gen.generateRequest(info, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -325,9 +336,10 @@ public void testRequestWithKnownContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - Info info = new Info("POST", "/index.html", 58); - info.getFields().add("Host", "something"); - info.getFields().add("User-Agent", "test"); + HttpFields fields = new HttpFields(); + fields.add("Host", "something"); + fields.add("User-Agent", "test"); + RequestInfo info = new RequestInfo("POST", "/index.html", 58, fields); result = gen.generateRequest(info, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); 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 f7ed242964db..f3abe97d6bc1 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 @@ -19,7 +19,6 @@ package org.eclipse.jetty.http; import java.nio.ByteBuffer; -import java.util.function.Supplier; import org.eclipse.jetty.util.BufferUtil; import org.junit.jupiter.api.Test; @@ -47,9 +46,10 @@ public void test09() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, new HttpFields(), 10); - info.getFields().add("Content-Type", "test/data"); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Content-Type", "test/data"); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, fields, 10); result = gen.generateResponse(info, false, null, null, content, true); assertEquals(HttpGenerator.Result.FLUSH, result); @@ -83,9 +83,10 @@ public void testSimple() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 10); - info.getFields().add("Content-Type", "test/data"); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Content-Type", "test/data"); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); result = gen.generateResponse(info, false, null, null, content, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -115,8 +116,9 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 302, null, new HttpFields(), 0); - info.getFields().add("Location", "http://somewhere/else"); + HttpFields fields = new HttpFields(); + fields.add("Location", "http://somewhere/else"); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 302, null, fields, 0); HttpGenerator.Result result = gen.generateResponse(info, false, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -150,9 +152,10 @@ public void test204() throws Exception HttpGenerator gen = new HttpGenerator(); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", new HttpFields(), 10); - info.getFields().add("Content-Type", "test/data"); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Content-Type", "test/data"); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", fields, 10); HttpGenerator.Result result = gen.generateResponse(info, false, header, null, content, true); @@ -186,9 +189,10 @@ public void testComplexChars() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", new HttpFields(), 10); - info.getFields().add("Content-Type", "test/data;\r\nextra=value"); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Content-Type", "test/data;\r\nextra=value"); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", fields, 10); result = gen.generateResponse(info, false, null, null, content, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -218,11 +222,12 @@ public void testComplexChars() throws Exception public void testSendServerXPoweredBy() throws Exception { ByteBuffer header = BufferUtil.allocate(8096); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - HttpFields fields = new HttpFields(); - fields.add(HttpHeader.SERVER, "SomeServer"); - fields.add(HttpHeader.X_POWERED_BY, "SomePower"); - MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); + HttpFields fields1 = new HttpFields(); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields1, -1); + HttpFields fields2 = new HttpFields(); + fields2.add(HttpHeader.SERVER, "SomeServer"); + fields2.add(HttpHeader.X_POWERED_BY, "SomePower"); + MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields2, -1); String head; HttpGenerator gen = new HttpGenerator(true, true); @@ -273,9 +278,10 @@ public void testResponseIncorrectContentLength() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 10); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add("Content-Length", "11"); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add("Content-Length", "11"); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); result = gen.generateResponse(info, false, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -298,8 +304,9 @@ public void testResponseNoContentPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 0); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); result = gen.generateResponse(info, false, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -331,9 +338,10 @@ public void testResponseKnownNoContentNotPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 0); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add("Connection", "close"); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add("Connection", "close"); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); result = gen.generateResponse(info, false, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -365,10 +373,11 @@ public void testResponseUpgrade() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 101, null, new HttpFields(), -1); - info.getFields().add("Upgrade", "WebSocket"); - info.getFields().add("Connection", "Upgrade"); - info.getFields().add("Sec-WebSocket-Accept", "123456789=="); + HttpFields fields = new HttpFields(); + fields.add("Upgrade", "WebSocket"); + fields.add("Connection", "Upgrade"); + fields.add("Sec-WebSocket-Accept", "123456789=="); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 101, null, fields, -1); result = gen.generateResponse(info, false, header, null, null, true); assertEquals(HttpGenerator.Result.FLUSH, result); @@ -400,8 +409,9 @@ public void testResponseWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); @@ -465,9 +475,10 @@ public void testResponseWithHintedChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); @@ -535,21 +546,18 @@ public void testResponseWithContentAndTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); - info.setTrailerSupplier(new Supplier() - { - @Override - public HttpFields get() + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, + () -> { - HttpFields trailer = new HttpFields(); - trailer.add("T-Name0", "T-ValueA"); - trailer.add("T-Name0", "T-ValueB"); - trailer.add("T-Name1", "T-ValueC"); - return trailer; - } - }); + HttpFields trailer1 = new HttpFields(); + trailer1.add("T-Name0", "T-ValueA"); + trailer1.add("T-Name0", "T-ValueB"); + trailer1.add("T-Name1", "T-ValueC"); + return trailer1.asImmutable(); + }); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -625,21 +633,18 @@ public void testResponseWithTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); - info.setTrailerSupplier(new Supplier() - { - @Override - public HttpFields get() + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, + () -> { - HttpFields trailer = new HttpFields(); - trailer.add("T-Name0", "T-ValueA"); - trailer.add("T-Name0", "T-ValueB"); - trailer.add("T-Name1", "T-ValueC"); - return trailer; - } - }); + HttpFields trailer1 = new HttpFields(); + trailer1.add("T-Name0", "T-ValueA"); + trailer1.add("T-Name0", "T-ValueB"); + trailer1.add("T-Name1", "T-ValueC"); + return trailer1; + }); result = gen.generateResponse(info, false, null, null, null, true); assertEquals(HttpGenerator.Result.NEED_HEADER, result); @@ -697,8 +702,9 @@ public void testResponseWithKnownContentLengthFromMetaData() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 59); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 59); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); @@ -745,9 +751,10 @@ public void testResponseWithKnownContentLengthFromHeader() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), -1); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); - info.getFields().add("Content-Length", "" + (content0.remaining() + content1.remaining())); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + fields.add("Content-Length", "" + (content0.remaining() + content1.remaining())); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); @@ -809,8 +816,9 @@ public void test100ThenResponseWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), BufferUtil.length(content0) + BufferUtil.length(content1)); - info.getFields().add("Last-Modified", DateGenerator.__01Jan1970); + HttpFields fields = new HttpFields(); + fields.add("Last-Modified", DateGenerator.__01Jan1970); + MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, BufferUtil.length(content0) + BufferUtil.length(content1)); result = gen.generateResponse(info, false, null, null, content0, false); assertEquals(HttpGenerator.Result.NEED_HEADER, result); assertEquals(HttpGenerator.State.START, gen.getState()); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index b01e873219f4..d3bf1f355a3d 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -60,10 +60,9 @@ public void testInvalidAddress() throws Exception private void assertInvalidURI(String invalidURI, String message) { - HttpURI uri = new HttpURI(); try { - uri.parse(invalidURI); + new HttpURI.Builder(invalidURI).build(); fail(message); } catch (IllegalArgumentException e) @@ -75,21 +74,26 @@ private void assertInvalidURI(String invalidURI, String message) @Test public void testParse() { - HttpURI uri = new HttpURI(); + HttpURI.Builder builder = new HttpURI.Builder(); + HttpURI uri; - uri.parse("*"); + builder.uri("*"); + uri = builder.build(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); - uri.parse("/foo/bar"); + builder.uri("/foo/bar"); + uri = builder.build(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); - uri.parse("//foo/bar"); + builder.uri("//foo/bar"); + uri = builder.build(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); - uri.parse("http://foo/bar"); + builder.uri("http://foo/bar"); + uri = builder.build(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -97,21 +101,21 @@ public void testParse() @Test public void testParseRequestTarget() { - HttpURI uri = new HttpURI(); + HttpURI uri; - uri.parseRequestTarget("GET", "*"); + uri = new HttpURI.Builder("GET", "*").build(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); - uri.parseRequestTarget("GET", "/foo/bar"); + uri = new HttpURI.Builder("GET", "/foo/bar").build(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); - uri.parseRequestTarget("GET", "//foo/bar"); + uri = new HttpURI.Builder("GET", "//foo/bar").build(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("//foo/bar")); - uri.parseRequestTarget("GET", "http://foo/bar"); + uri = new HttpURI.Builder("GET", "http://foo/bar").build(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -167,43 +171,44 @@ public void testParams() throws Exception } @Test - public void testMutableURI() + public void testMutableURIBuilder() { - HttpURI uri = new HttpURI("/foo/bar"); + HttpURI.Builder builder = new HttpURI.Builder("/foo/bar"); + HttpURI uri = builder.build(); assertEquals("/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri.setScheme("http"); + uri = builder.scheme("http").build(); assertEquals("http:/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri.setAuthority("host", 0); + uri = builder.authority("host", 0).build(); assertEquals("http://host/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri.setAuthority("host", 8888); + uri = builder.authority("host", 8888).build(); assertEquals("http://host:8888/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri.setPathQuery("/f%30%30;p0/bar;p1;p2"); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2").build(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals(null, uri.getQuery()); - uri.setPathQuery("/f%30%30;p0/bar;p1;p2?name=value"); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2?name=value").build(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?name=value", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals("name=value", uri.getQuery()); - uri.setQuery("other=123456"); + uri = builder.query("other=123456").build(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?other=123456", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); @@ -214,19 +219,20 @@ public void testMutableURI() @Test public void testSchemeAndOrAuthority() throws Exception { - HttpURI uri = new HttpURI("/path/info"); + HttpURI.Builder builder = new HttpURI.Builder("/path/info"); + HttpURI uri = builder.build(); assertEquals("/path/info", uri.toString()); - uri.setAuthority("host", 0); + uri = builder.authority("host", 0).build(); assertEquals("//host/path/info", uri.toString()); - uri.setAuthority("host", 8888); + uri = builder.authority("host", 8888).build(); assertEquals("//host:8888/path/info", uri.toString()); - uri.setScheme("http"); + uri = builder.scheme("http").build(); assertEquals("http://host:8888/path/info", uri.toString()); - uri.setAuthority(null, 0); + uri = builder.authority(null, 0).build(); assertEquals("http:/path/info", uri.toString()); } From f2f08e50b1f2e43133bc372c0d8297893ebcad45 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 16 Apr 2020 14:55:13 +0200 Subject: [PATCH 06/38] Immutable MetaData Fixes from review Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpFields.java | 19 +------------------ .../java/org/eclipse/jetty/http/HttpURI.java | 4 ++-- 2 files changed, 3 insertions(+), 20 deletions(-) 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 7b161f615751..270e0c77e7ab 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 @@ -587,24 +587,7 @@ public int hashCode() @Override public Iterator iterator() { - return new Iterator<>() - { - int _index = 0; - - @Override - public boolean hasNext() - { - return _index < _fields.length; - } - - @Override - public HttpField next() - { - if (_index < _fields.length) - return _fields[_index++]; - throw new NoSuchElementException(); - } - }; + return Arrays.stream(_fields).iterator(); } @Override diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index cf51446c499e..ff5d7c8a3a13 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -303,8 +303,8 @@ private enum State ASTERISK } - String _uri; - String _decodedPath; + private String _uri; + private String _decodedPath; private String _scheme; private String _user; private String _host; From 8d5b036fe54ae96194ae268895e8f7830672c426 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 17 Apr 2020 13:45:35 +0200 Subject: [PATCH 07/38] Immutable MetaData Passing tests upto and including jetty-server Signed-off-by: Greg Wilkins --- .../eclipse/jetty/client/HttpConnection.java | 6 +- .../jetty/client/HttpClientRedirectTest.java | 24 +- .../eclipse/jetty/client/HttpClientTest.java | 2 +- .../server/proxy/FastCGIProxyServlet.java | 2 +- .../org/eclipse/jetty/http/HttpFieldList.java | 19 +- .../org/eclipse/jetty/http/HttpFields.java | 35 +- .../java/org/eclipse/jetty/http/HttpURI.java | 104 +++--- .../jetty/http/GZIPContentDecoderTest.java | 4 +- .../eclipse/jetty/http/HttpFieldsTest.java | 10 +- .../org/eclipse/jetty/http/HttpURITest.java | 18 - .../jetty/http2/client/TrailersTest.java | 8 +- .../http2/server/HttpChannelOverHTTP2.java | 3 +- .../proxy/AsyncMiddleManServletTest.java | 2 +- .../jetty/proxy/ConnectHandlerTest.java | 2 +- .../jetty/proxy/ProxyServletFailureTest.java | 2 +- .../eclipse/jetty/proxy/ProxyServletTest.java | 32 +- .../jetty/server/CustomRequestLog.java | 8 +- .../org/eclipse/jetty/server/Dispatcher.java | 11 +- .../server/ForwardedRequestCustomizer.java | 72 ++-- .../jetty/server/HostHeaderCustomizer.java | 5 +- .../org/eclipse/jetty/server/HttpChannel.java | 7 +- .../jetty/server/HttpChannelOverHttp.java | 25 +- .../eclipse/jetty/server/HttpConnection.java | 2 +- .../eclipse/jetty/server/PushBuilderImpl.java | 2 +- .../org/eclipse/jetty/server/Request.java | 309 +++++++----------- .../eclipse/jetty/server/ResourceService.java | 4 +- .../org/eclipse/jetty/server/Response.java | 23 +- .../jetty/server/SecureRequestCustomizer.java | 5 +- .../java/org/eclipse/jetty/server/Server.java | 43 +-- .../jetty/server/handler/ContextHandler.java | 23 +- .../server/handler/ThreadLimitHandler.java | 7 +- .../server/handler/gzip/GzipHandler.java | 138 ++++---- .../server/HttpVersionCustomizerTest.java | 81 ----- .../eclipse/jetty/server/ResponseTest.java | 13 +- .../matchers/HttpFieldsContainsHeaderKey.java | 2 +- 35 files changed, 457 insertions(+), 596 deletions(-) delete mode 100644 jetty-server/src/test/java/org/eclipse/jetty/server/HttpVersionCustomizerTest.java diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index a20662f1827c..6c587d11f728 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -151,7 +151,7 @@ protected void normalizeRequest(Request request) HttpFields headers = request.getHeaders(); if (version.getVersion() <= 11) { - if (!headers.containsKey(HttpHeader.HOST.asString())) + if (!headers.contains(HttpHeader.HOST.asString())) headers.put(getHttpDestination().getHostField()); } @@ -163,7 +163,7 @@ protected void normalizeRequest(Request request) } else { - if (!headers.containsKey(HttpHeader.CONTENT_TYPE.asString())) + if (!headers.contains(HttpHeader.CONTENT_TYPE.asString())) { String contentType = content.getContentType(); if (contentType != null) @@ -180,7 +180,7 @@ protected void normalizeRequest(Request request) long contentLength = content.getLength(); if (contentLength >= 0) { - if (!headers.containsKey(HttpHeader.CONTENT_LENGTH.asString())) + if (!headers.contains(HttpHeader.CONTENT_LENGTH.asString())) headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf(contentLength)); } } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java index 442c317d4a5f..83f5e4ca0767 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java @@ -70,7 +70,7 @@ public void test303(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -86,7 +86,7 @@ public void test303302(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -102,7 +102,7 @@ public void test303302OnDifferentDestinations(Scenario scenario) throws Exceptio .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -119,7 +119,7 @@ public void test301(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -139,7 +139,7 @@ public void test301WithWrongMethod(Scenario scenario) throws Exception Response response = xx.getResponse(); assertNotNull(response); assertEquals(301, response.getStatus()); - assertTrue(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -158,7 +158,7 @@ public void test307WithRequestContent(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); assertArrayEquals(data, response.getContent()); } @@ -179,7 +179,7 @@ public void testMaxRedirections(Scenario scenario) throws Exception Response response = xx.getResponse(); assertNotNull(response); assertEquals(302, response.getStatus()); - assertTrue(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -195,7 +195,7 @@ public void test303WithConnectionCloseWithBigRequest(Scenario scenario) throws E .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -212,7 +212,7 @@ public void testDontFollowRedirects(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(303, response.getStatus()); - assertTrue(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -228,7 +228,7 @@ public void testRelativeLocation(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -244,7 +244,7 @@ public void testAbsoluteURIPathWithSpaces(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest @@ -260,7 +260,7 @@ public void testRelativeURIPathWithSpaces(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); } @ParameterizedTest diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java index fe2efa598db7..79a377408b1f 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java @@ -771,7 +771,7 @@ public void handle(String target, org.eclipse.jetty.server.Request baseRequest, assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(headerName)); + assertFalse(response.getHeaders().contains(headerName)); } @ParameterizedTest diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java index b4ea114221be..56eaeb6e656e 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java @@ -180,7 +180,7 @@ protected void sendProxyRequest(HttpServletRequest request, HttpServletResponse proxyRequest.attribute(REQUEST_QUERY_ATTRIBUTE, originalQuery); // If the Host header is missing, add it. - if (!proxyRequest.getHeaders().containsKey(HttpHeader.HOST.asString())) + if (!proxyRequest.getHeaders().contains(HttpHeader.HOST.asString())) { String host = request.getServerName(); int port = request.getServerPort(); diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java index 9bea960b5ef5..a5194ebd1b65 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.EnumSet; import java.util.Enumeration; import java.util.Iterator; import java.util.List; @@ -105,7 +106,17 @@ default boolean contains(HttpHeader header) return false; } - default boolean containsKey(String name) + default boolean contains(EnumSet headers) + { + for (HttpField f : this) + { + if (headers.contains(f.getHeader())) + return true; + } + return false; + } + + default boolean contains(String name) { for (HttpField f : this) { @@ -115,6 +126,12 @@ default boolean containsKey(String name) return false; } + @Deprecated + default boolean containsKey(String name) + { + return contains(name); + } + default String get(HttpHeader header) { for (HttpField f : this) 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 270e0c77e7ab..49b97a155799 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 @@ -58,16 +58,6 @@ public HttpFields(int capacity) _fields = new ArrayList<>(capacity); } - /** - * Initialize HttpFields from another. - * - * @param fields the fields to copy data from - */ - public HttpFields(HttpFields fields) - { - _fields = new ArrayList<>(fields._fields); - } - /** * Initialize HttpFields from another. * @@ -87,6 +77,31 @@ else if (fields instanceof HttpFields) } } + /** + * Initialize HttpFields from another and replace a field + * + * @param fields the fields to copy data from + * @param putField the replacement field + */ + public HttpFields(HttpFieldList fields, HttpField putField) + { + _fields = new ArrayList<>(fields.size() + 4); + boolean put = false; + for (HttpField f : fields) + { + if (putField.isSameName(f)) + { + if (!put) + _fields.add(putField); + put = true; + } + else + { + _fields.add(f); + } + } + } + /** * Get field value without parameters. Some field values can have parameters. This method separates the * value from the parameters and optionally populates a map with the parameters. For example: diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index ff5d7c8a3a13..31a38beb5eb5 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -20,10 +20,8 @@ import java.net.URI; import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import org.eclipse.jetty.util.MultiMap; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.UrlEncoded; @@ -93,7 +91,6 @@ public HttpURI(URI uri) public HttpURI(HttpURI baseUri, String pathQuery) { Builder builder = new Builder(baseUri, pathQuery); - _uri = builder._uri; _scheme = builder._scheme; _user = builder._user; _host = builder._host; @@ -119,29 +116,6 @@ public HttpURI(HttpURI baseUri, String pathQuery) _fragment = fragment; } - public void decodeQueryTo(MultiMap parameters) - { - if (_query == null) - return; - UrlEncoded.decodeUtf8To(_query, parameters); - } - - public void decodeQueryTo(MultiMap parameters, String encoding) - { - decodeQueryTo(parameters, Charset.forName(encoding)); - } - - public void decodeQueryTo(MultiMap parameters, Charset encoding) - { - if (_query == null) - return; - - if (encoding == null || StandardCharsets.UTF_8.equals(encoding)) - UrlEncoded.decodeUtf8To(_query, parameters); - else - UrlEncoded.decodeTo(_query, parameters, encoding); - } - @Override public boolean equals(Object o) { @@ -233,7 +207,7 @@ public boolean hasQuery() public boolean isAbsolute() { - return _scheme != null && !_scheme.isEmpty(); + return !StringUtil.isEmpty(_scheme); } @Override @@ -331,29 +305,33 @@ public Builder(String scheme, String host, int port, String path, String param, public Builder(HttpURI uri) { - _uri = uri._uri; - _scheme = uri._scheme; - _user = uri._user; - _host = uri._host; - _port = uri._port; - _path = uri._path; - _decodedPath = uri._decodedPath; - _param = uri._param; - _query = uri._query; - _fragment = uri._fragment; + uri(uri); } - public Builder(HttpURI uri, String pathQuery) + public Builder(HttpURI baseURI, String pathQuery) { _uri = null; - _scheme = uri._scheme; - _user = uri._user; - _host = uri._host; - _port = uri._port; + _scheme = baseURI._scheme; + _user = baseURI._user; + _host = baseURI._host; + _port = baseURI._port; if (pathQuery != null) parse(State.PATH, pathQuery); } + public Builder(HttpURI baseURI, String path, String param, String query) + { + _uri = null; + _scheme = baseURI._scheme; + _user = baseURI._user; + _host = baseURI._host; + _port = baseURI._port; + _path = path; + _param = param; + _query = query; + _fragment = null; + } + public Builder(String uri) { _port = -1; @@ -372,17 +350,17 @@ public Builder(URI uri) _user = uri.getUserInfo(); _path = uri.getRawPath(); - _decodedPath = uri.getPath(); - if (_decodedPath != null) + String pathParam = uri.getPath(); + if (pathParam != null) { - int p = _decodedPath.lastIndexOf(';'); + int p = pathParam.lastIndexOf(';'); if (p >= 0) - _param = _decodedPath.substring(p + 1); + _param = pathParam.substring(p + 1); + else + _decodedPath = pathParam; } _query = uri.getRawQuery(); _fragment = uri.getFragment(); - - _decodedPath = null; } public Builder(String scheme, String host, int port, String pathQuery) @@ -447,8 +425,6 @@ public void clear() public String decodedPath() { - if (_decodedPath == null && _path != null) - _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); return _decodedPath; } @@ -468,6 +444,7 @@ public String fragment() public Builder fragment(String fragment) { _fragment = fragment; + _uri = null; return this; } @@ -489,6 +466,7 @@ public String host() public Builder host(String host) { _host = host; + _uri = null; return this; } @@ -503,6 +481,7 @@ public Builder normalize() _port = 0; if (_port == 443 && HttpScheme.HTTPS.is(_scheme)) _port = 0; + _uri = null; return this; } @@ -518,6 +497,7 @@ public Builder param(String param) { _path += ";" + _param; } + _uri = null; return this; } @@ -569,6 +549,7 @@ public int port() public Builder port(int port) { _port = port; + _uri = null; return this; } @@ -589,6 +570,11 @@ public String scheme() return _scheme; } + public Builder scheme(HttpScheme scheme) + { + return scheme(scheme.asString()); + } + public Builder scheme(String scheme) { _scheme = scheme; @@ -614,6 +600,21 @@ public URI toURI() } } + public Builder uri(HttpURI uri) + { + _uri = uri._uri; + _scheme = uri._scheme; + _user = uri._user; + _host = uri._host; + _port = uri._port; + _path = uri._path; + _decodedPath = uri._decodedPath; + _param = uri._param; + _query = uri._query; + _fragment = uri._fragment; + return this; + } + public Builder uri(String uri) { clear(); @@ -639,6 +640,7 @@ public String user() public Builder user(String user) { _user = user; + _uri = null; return this; } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/GZIPContentDecoderTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/GZIPContentDecoderTest.java index 9fd0825538f3..50796d4bb352 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/GZIPContentDecoderTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/GZIPContentDecoderTest.java @@ -365,11 +365,11 @@ public void testBigBlockWithExtraBytes() throws Exception static final long UINT_MAX = 0xFFFFFFFFL; @ParameterizedTest - @ValueSource(longs = {INT_MAX, INT_MAX + 1, UINT_MAX, UINT_MAX + 1}) + @ValueSource(longs = {INT_MAX, INT_MAX + 1 /* TODO too slow , UINT_MAX, UINT_MAX + 1 */ }) public void testLargeGzipStream(long origSize) throws IOException { // Size chosen for trade off between speed of I/O vs speed of Gzip - final int BUFSIZE = 1024 * 1024; + final int BUFSIZE = 64 * 1024 * 1024; // Create a buffer to use over and over again to produce the uncompressed input byte[] cbuf = "0123456789ABCDEFGHIJKLMOPQRSTUVWXYZ".getBytes(StandardCharsets.UTF_8); 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 4a7a3f922d8d..7d63d92f07ad 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 @@ -688,8 +688,8 @@ public void testContains() throws Exception for (int i = 0; i < 8; i++) { - assertTrue(header.containsKey("n" + i)); - assertTrue(header.containsKey("N" + i)); + assertTrue(header.contains("n" + i)); + assertTrue(header.contains("N" + i)); assertFalse(header.contains("n" + i, "xyz"), "" + i); assertEquals(i >= 4, header.contains("n" + i, "def"), "" + i); } @@ -702,7 +702,7 @@ public void testContains() throws Exception assertFalse(header.contains(HttpHeader.ACCEPT, "def")); assertFalse(header.contains(HttpHeader.AGE, "abc")); - assertFalse(header.containsKey("n11")); + assertFalse(header.contains("n11")); } @ParameterizedTest @@ -714,7 +714,7 @@ public void testContainsKeyTrue(String keyName) HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); - assertTrue(fields.containsKey(keyName), "containsKey('" + keyName + "')"); + assertTrue(fields.contains(keyName), "containsKey('" + keyName + "')"); } @ParameterizedTest @@ -726,7 +726,7 @@ public void testContainsKeyFalse(String keyName) HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); - assertFalse(fields.containsKey(keyName), "containsKey('" + keyName + "')"); + assertFalse(fields.contains(keyName), "containsKey('" + keyName + "')"); } @Test diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index d3bf1f355a3d..385171226415 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -18,10 +18,6 @@ package org.eclipse.jetty.http; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; - -import org.eclipse.jetty.util.MultiMap; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -120,20 +116,6 @@ public void testParseRequestTarget() assertThat(uri.getPath(), is("/bar")); } - @Test - public void testExtB() throws Exception - { - // @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck - for (String value : new String[]{"a", "abcdABCD", "\u00C0", "\u697C", "\uD869\uDED5", "\uD840\uDC08"}) - { - HttpURI uri = new HttpURI("/path?value=" + URLEncoder.encode(value, "UTF-8")); - - MultiMap parameters = new MultiMap<>(); - uri.decodeQueryTo(parameters, StandardCharsets.UTF_8); - assertEquals(value, parameters.getString("value")); - } - } - @Test public void testAt() throws Exception { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 4426b71a70ce..77468042ba5d 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -72,7 +72,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); assertFalse(frame.isEndStream()); - assertTrue(request.getFields().containsKey("X-Request")); + assertTrue(request.getFields().contains("X-Request")); return new Stream.Listener.Adapter() { @Override @@ -80,7 +80,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) { MetaData trailer = frame.getMetaData(); assertTrue(frame.isEndStream()); - assertTrue(trailer.getFields().containsKey("X-Trailer")); + assertTrue(trailer.getFields().contains("X-Trailer")); latch.countDown(); } }; @@ -221,14 +221,14 @@ public void onHeaders(Stream stream, HeadersFrame frame) { MetaData.Response response = (MetaData.Response)frame.getMetaData(); assertEquals(HttpStatus.OK_200, response.getStatus()); - assertTrue(response.getFields().containsKey("X-Response")); + assertTrue(response.getFields().contains("X-Response")); assertFalse(frame.isEndStream()); responded = true; } else { MetaData trailer = frame.getMetaData(); - assertTrue(trailer.getFields().containsKey("X-Trailer")); + assertTrue(trailer.getFields().contains("X-Trailer")); assertTrue(frame.isEndStream()); latch.countDown(); } diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java index f83e43f985f4..cf112c25996d 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; @@ -108,7 +109,7 @@ public Runnable onRequest(HeadersFrame frame) try { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - HttpFields fields = request.getFields(); + HttpFieldList fields = request.getFields(); // HTTP/2 sends the Host header as the :authority // pseudo-header, so we need to synthesize a Host header. diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java index d9ec5e62597f..11bb328dd781 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/AsyncMiddleManServletTest.java @@ -1497,7 +1497,7 @@ protected ContentTransformer newServerResponseContentTransformer(HttpServletRequ .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } private Path prepareTargetTestsDir() throws IOException diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java index 220a349ddfbf..6be8f2ae0ca7 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ConnectHandlerTest.java @@ -308,7 +308,7 @@ protected boolean handleAuthentication(HttpServletRequest request, HttpServletRe HttpTester.Input in = HttpTester.from(input); HttpTester.Response response = HttpTester.parseResponse(in); assertEquals(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407, response.getStatus()); - assertTrue(response.containsKey("Proxy-Authenticate".toLowerCase(Locale.ENGLISH))); + assertTrue(response.contains("Proxy-Authenticate".toLowerCase(Locale.ENGLISH))); // Socket should be closed assertEquals(-1, input.read()); diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java index b47857304be2..620f3e9e5ba6 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletFailureTest.java @@ -381,7 +381,7 @@ protected void doGet(final HttpServletRequest request, final HttpServletResponse .timeout(3 * timeout, TimeUnit.MILLISECONDS) .send(); assertEquals(504, response.getStatus()); - assertFalse(response.getHeaders().containsKey(PROXIED_HEADER)); + assertFalse(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java index af55f6244369..d39e94d94579 100644 --- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java +++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java @@ -246,7 +246,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) assertEquals("OK", response.getReason()); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -280,7 +280,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO for (int i = 0; i < 10; ++i) { assertEquals(200, responses[i].getStatus()); - assertTrue(responses[i].getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(responses[i].getHeaders().contains(PROXIED_HEADER)); assertArrayEquals(content, responses[i].getContent()); } } @@ -311,7 +311,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); assertArrayEquals(content, response.getContent()); } @@ -350,7 +350,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -393,7 +393,7 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws I .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -531,7 +531,7 @@ public void onStartAsync(AsyncEvent event) .timeout(2 * timeout, TimeUnit.MILLISECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -626,14 +626,14 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); // Try again with an excluded host response = client.newRequest("127.0.0.1", port) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().containsKey(PROXIED_HEADER)); + assertFalse(response.getHeaders().contains(PROXIED_HEADER)); } public static Stream transparentImpls() @@ -685,7 +685,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -797,7 +797,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -827,7 +827,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } /** @@ -891,7 +891,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(302, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); } @ParameterizedTest @@ -920,7 +920,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response.getStatus()); - assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response.getHeaders().contains(PROXIED_HEADER)); assertArrayEquals(content, response.getContent()); } @@ -992,7 +992,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response1.getStatus()); - assertTrue(response1.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response1.getHeaders().contains(PROXIED_HEADER)); List cookies = client.getCookieStore().getCookies(); assertEquals(1, cookies.size()); assertEquals(name, cookies.get(0).getName()); @@ -1007,7 +1007,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response2.getStatus()); - assertTrue(response2.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response2.getHeaders().contains(PROXIED_HEADER)); cookies = client2.getCookieStore().getCookies(); assertEquals(1, cookies.size()); assertEquals(name, cookies.get(0).getName()); @@ -1018,7 +1018,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) .timeout(5, TimeUnit.SECONDS) .send(); assertEquals(200, response3.getStatus()); - assertTrue(response3.getHeaders().containsKey(PROXIED_HEADER)); + assertTrue(response3.getHeaders().contains(PROXIED_HEADER)); } finally { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java index e67ad99993d2..33ada4570b9e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java @@ -33,7 +33,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.QuotedCSV; import org.eclipse.jetty.http.pathmap.PathMappings; import org.eclipse.jetty.server.handler.ContextHandler; @@ -1193,7 +1193,7 @@ private static void logConnectionStatus(StringBuilder b, Request request, Respon private static void logRequestTrailer(String arg, StringBuilder b, Request request, Response response) { - HttpFields trailers = request.getTrailerHttpFields(); + HttpFieldList trailers = request.getTrailerHttpFields(); if (trailers != null) append(b, trailers.get(arg)); else @@ -1202,10 +1202,10 @@ private static void logRequestTrailer(String arg, StringBuilder b, Request reque private static void logResponseTrailer(String arg, StringBuilder b, Request request, Response response) { - Supplier supplier = response.getTrailers(); + Supplier supplier = response.getTrailers(); if (supplier != null) { - HttpFields trailers = supplier.get(); + HttpFieldList trailers = supplier.get(); if (trailers != null) append(b, trailers.get(arg)); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 6801e9b669f3..764e88340927 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -111,7 +111,7 @@ public void include(ServletRequest request, ServletResponse response) throws Ser attr._query = _uri.getQuery(); attr._mapping = null; //set by ServletHandler if (attr._query != null) - baseRequest.mergeQueryParameters(baseRequest.getQueryString(), attr._query, false); + baseRequest.mergeQueryParameters(baseRequest.getQueryString(), attr._query); baseRequest.setAttributes(attr); _contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response); @@ -189,8 +189,11 @@ protected void forward(ServletRequest request, ServletResponse response, Dispatc attr._mapping = old_mapping; } - HttpURI uri = new HttpURI(old_uri.getScheme(), old_uri.getHost(), old_uri.getPort(), - _uri.getPath(), _uri.getParam(), _uri.getQuery(), _uri.getFragment()); + String query = _uri.getQuery(); + if (query == null) + query = old_uri.getQuery(); + + HttpURI uri = new HttpURI.Builder(old_uri, _uri.getPath(), _uri.getParam(), query).build(); baseRequest.setHttpURI(uri); @@ -202,7 +205,7 @@ protected void forward(ServletRequest request, ServletResponse response, Dispatc { try { - baseRequest.mergeQueryParameters(old_uri.getQuery(), _uri.getQuery(), true); + baseRequest.mergeQueryParameters(old_uri.getQuery(), _uri.getQuery()); } catch (BadMessageException e) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index 41edf1655f7f..4c74cbeeba66 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -27,9 +27,11 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.QuotedCSVParser; import org.eclipse.jetty.server.HttpConfiguration.Customizer; import org.eclipse.jetty.util.ArrayTrie; @@ -373,17 +375,22 @@ public void setSslIsSecure(boolean sslIsSecure) @Override public void customize(Connector connector, HttpConfiguration config, Request request) { - HttpFields httpFields = request.getHttpFields(); + HttpFieldList httpFields = request.getHttpFields(); + boolean wasSecure = request.isSecure(); // Do a single pass through the header fields as it is a more efficient single iteration. Forwarded forwarded = new Forwarded(request, config); + boolean match = false; for (HttpField field : httpFields) { try { MethodHandle handle = _handles.get(field.getName()); if (handle != null) + { + match = true; handle.invoke(forwarded, field); + } } catch (Throwable t) { @@ -391,33 +398,42 @@ public void customize(Connector connector, HttpConfiguration config, Request req } } - if (forwarded._proto != null) + if (match) { - request.setScheme(forwarded._proto); - if (forwarded._proto.equalsIgnoreCase(config.getSecureScheme())) - request.setSecure(true); - } + HttpURI.Builder builder = new HttpURI.Builder(request.getHttpURI()); + if (forwarded._proto != null) + { + builder.scheme(forwarded._proto); + if (forwarded._proto.equalsIgnoreCase(config.getSecureScheme())) + request.setSecure(true); + } - if (forwarded._server != null && forwarded._host instanceof PortSetHostPort) - { - httpFields.put(new HostPortHttpField(forwarded._server, forwarded._host.getPort())); - request.setAuthority(forwarded._server, forwarded._host.getPort()); - } - else if (forwarded._host != null) - { - httpFields.put(new HostPortHttpField(forwarded._host)); - request.setAuthority(forwarded._host.getHost(), forwarded._host.getPort()); - } - else if (forwarded._server != null) - { - httpFields.put(new HostPortHttpField(forwarded._server)); - request.setAuthority(forwarded._server, 0); - } + if (forwarded._server != null && forwarded._host instanceof PortSetHostPort) + { + request.setHttpFields(new HttpFields(httpFields, + new HostPortHttpField(forwarded._server, forwarded._host.getPort()))); + builder.host(forwarded._server).port(forwarded._host.getPort()); + } + else if (forwarded._host != null) + { + request.setHttpFields(new HttpFields(httpFields, new HostPortHttpField(forwarded._host))); + builder.host(forwarded._host.getHost()).port(forwarded._host.getPort()); + } + else if (forwarded._server != null) + { + request.setHttpFields(new HttpFields(httpFields, new HostPortHttpField(forwarded._server))); + builder.host(forwarded._server).port(0); + } - if (forwarded._for != null) - { - int port = forwarded._for.getPort() > 0 ? forwarded._for.getPort() : request.getRemotePort(); - request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._for.getHost(), port)); + if (forwarded._for != null) + { + int port = forwarded._for.getPort() > 0 ? forwarded._for.getPort() : request.getRemotePort(); + request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._for.getHost(), port)); + } + + if (request.isSecure() && !wasSecure) + builder.scheme(HttpScheme.HTTPS); + request.setHttpURI(builder.build()); } } @@ -576,10 +592,7 @@ public void handleCipherSuite(HttpField field) { _request.setAttribute("javax.servlet.request.cipher_suite", field.getValue()); if (isSslIsSecure()) - { _request.setSecure(true); - _request.setScheme(_config.getSecureScheme()); - } } @SuppressWarnings("unused") @@ -587,10 +600,7 @@ public void handleSslSessionId(HttpField field) { _request.setAttribute("javax.servlet.request.ssl_session_id", field.getValue()); if (isSslIsSecure()) - { _request.setSecure(true); - _request.setScheme(_config.getSecureScheme()); - } } @SuppressWarnings("unused") diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java index a18d2d79576e..81b7eb914439 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java @@ -21,6 +21,8 @@ import java.util.Objects; import javax.servlet.http.HttpServletRequest; +import org.eclipse.jetty.http.HttpURI; + /** * Customizes requests that lack the {@code Host} header (for example, HTTP 1.0 requests). *

@@ -63,6 +65,7 @@ public HostHeaderCustomizer(String serverName, int serverPort) public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { if (request.getHeader("Host") == null) - request.setAuthority(serverName, serverPort); // TODO set the field as well? + // TODO set the field as well? + request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).host(serverName).port(serverPort).build()); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 7da6a20c4ca0..64455287c62d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -30,7 +30,6 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Supplier; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; @@ -83,8 +82,6 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor private final HttpChannel.Listener _combinedListener; @Deprecated private final List _transientListeners = new ArrayList<>(); - private HttpFields _trailers; - private final Supplier _trailerSupplier = () -> _trailers; private MetaData.Response _committedMetaData; private RequestLog _requestLog; private long _oldIdleTimeout; @@ -303,7 +300,6 @@ public void recycle() _committedMetaData = null; _requestLog = _connector == null ? null : _connector.getServer().getRequestLog(); _written = 0; - _trailers = null; _oldIdleTimeout = 0; _transientListeners.clear(); } @@ -687,7 +683,6 @@ public void onRequest(MetaData.Request request) if (idleTO >= 0 && _oldIdleTimeout != idleTO) setIdleTimeout(idleTO); - request.setTrailerSupplier(_trailerSupplier); _request.setMetaData(request); _request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme())); @@ -720,7 +715,7 @@ public void onTrailers(HttpFields trailers) { if (LOG.isDebugEnabled()) LOG.debug("onTrailers {} {}", this, trailers); - _trailers = trailers; + _request.getMetaData().setTrailers(trailers.asImmutable()); _combinedListener.onRequestTrailers(_request); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index 1994f27288bb..691ac22a45db 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -51,8 +51,11 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverHttp.class); private static final HttpField PREAMBLE_UPGRADE_H2C = new HttpField(HttpHeader.UPGRADE, "h2c"); private final HttpFields _fields = new HttpFields(); - private final MetaData.Request _metadata = new MetaData.Request(_fields); private final HttpConnection _httpConnection; + private String _method; + private String _uri; + private HttpVersion _version; + private MetaData.Request _metadata; private HttpField _connection; private HttpField _upgrade = null; private boolean _delayedForContent; @@ -66,7 +69,6 @@ public HttpChannelOverHttp(HttpConnection httpConnection, Connector connector, H { super(connector, config, endPoint, transport); _httpConnection = httpConnection; - _metadata.setURI(new HttpURI()); } @Override @@ -85,14 +87,17 @@ protected HttpInput newHttpInput(HttpChannelState state) public void recycle() { super.recycle(); + _method = null; + _uri = null; + _version = null; _unknownExpectation = false; _expect100Continue = false; _expect102Processing = false; - _metadata.recycle(); _connection = null; _fields.clear(); _upgrade = null; _trailers = null; + _metadata = null; } @Override @@ -110,9 +115,10 @@ public boolean isExpecting102Processing() @Override public void startRequest(String method, String uri, HttpVersion version) { - _metadata.setMethod(method); - _metadata.getURI().parseRequestTarget(method, uri); - _metadata.setHttpVersion(version); + // TODO should we have a MetaData.RequestBuilder class to hold these values? + _method = method; + _uri = uri; + _version = version; _unknownExpectation = false; _expect100Continue = false; _expect102Processing = false; @@ -138,7 +144,7 @@ public void parsedHeader(HttpField field) case EXPECT: { - if (_metadata.getHttpVersion() == HttpVersion.HTTP_1_1) + if (HttpVersion.HTTP_1_1.equals(_version)) { HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value); switch (expect == null ? HttpHeaderValue.UNKNOWN : expect) @@ -231,7 +237,7 @@ public void earlyEOF() { _httpConnection.getGenerator().setPersistent(false); // If we have no request yet, just close - if (_metadata.getMethod() == null) + if (_method == null) _httpConnection.close(); else if (onEarlyEOF() || _delayedForContent) { @@ -274,6 +280,8 @@ public void badMessage(BadMessageException failure) try { // Need to call onRequest, so RequestLog can reports as much as possible + if (_metadata == null) + _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).build(), _version, _fields); onRequest(_metadata); getRequest().getHttpInput().earlyEOF(); } @@ -288,6 +296,7 @@ public void badMessage(BadMessageException failure) @Override public boolean headerComplete() { + _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).build(), _version, _fields); onRequest(_metadata); if (_complianceViolations != null && !_complianceViolations.isEmpty()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index d54aeaf2d47f..62ff161aa3aa 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -736,7 +736,7 @@ private boolean reset(MetaData.Request request, MetaData.Response info, ByteBuff if (reset()) { _info = info; - _head = HttpMethod.HEAD.is(request.getMethod()); + _head = request != null && HttpMethod.HEAD.is(request.getMethod()); _content = content; _lastContent = last; _callback = callback; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index 78c78ac55083..95a6e63bf197 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -176,7 +176,7 @@ public void push() // _rawFields.add("Cookie","JSESSIONID="+_sessionId); } - HttpURI uri = HttpURI.createHttpURI(_request.getScheme(), _request.getServerName(), _request.getServerPort(), path, param, query, null); + HttpURI uri = new HttpURI.Builder(_request.getHttpURI(), path, param, query).build(); MetaData.Request push = new MetaData.Request(_method, uri, _request.getHttpVersion(), _fields); if (LOG.isDebugEnabled()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 689ecbd3270f..11e61893dc26 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -40,6 +40,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.servlet.AsyncContext; @@ -71,6 +72,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -196,7 +198,7 @@ public static HttpServletMapping getServletMapping(PathSpec pathSpec, String ser final String mapping; if (pathSpec instanceof ServletPathSpec) { - switch (((ServletPathSpec)pathSpec).getGroup()) + switch (pathSpec.getGroup()) { case ROOT: match = MappingMatch.CONTEXT_ROOT; @@ -273,7 +275,9 @@ public String toString() private final List _requestAttributeListeners = new ArrayList<>(); private final HttpInput _input; private MetaData.Request _metaData; - private String _originalUri; + private HttpFieldList _httpFields; + private HttpURI _uri; + private String _method; private String _contextPath; private String _servletPath; private String _pathInfo; @@ -297,7 +301,7 @@ public String toString() private MultiMap _queryParameters; private MultiMap _contentParameters; private MultiMap _parameters; - private String _queryEncoding; + private Charset _queryEncoding; private BufferedReader _reader; private String _readerEncoding; private InetSocketAddress _remote; @@ -316,16 +320,20 @@ public Request(HttpChannel channel, HttpInput input) _input = input; } - public HttpFields getHttpFields() + public HttpFieldList getHttpFields() { - MetaData.Request metadata = _metaData; - return metadata == null ? null : metadata.getFields(); + return _httpFields; + } + + public void setHttpFields(HttpFieldList fields) + { + _httpFields = fields.asImmutable(); } @Override public Map getTrailerFields() { - HttpFields trailersFields = getTrailerHttpFields(); + HttpFieldList trailersFields = getTrailerHttpFields(); if (trailersFields == null) return Collections.emptyMap(); Map trailers = new HashMap<>(); @@ -338,10 +346,10 @@ public Map getTrailerFields() return trailers; } - public HttpFields getTrailerHttpFields() + public HttpFieldList getTrailerHttpFields() { MetaData.Request metadata = _metaData; - Supplier trailers = metadata == null ? null : metadata.getTrailerSupplier(); + Supplier trailers = metadata == null ? null : metadata.getTrailerSupplier(); return trailers == null ? null : trailers.get(); } @@ -400,7 +408,7 @@ public PushBuilder newPushBuilder() } } - String id = null; + String id; try { HttpSession session = getSession(); @@ -433,10 +441,10 @@ public void addEventListener(final EventListener listener) if (listener instanceof AsyncListener) throw new IllegalArgumentException(listener.getClass().toString()); } - + /** * Remember a session that this request has just entered. - * + * * @param s the session */ public void enterSession(HttpSession s) @@ -464,7 +472,7 @@ private void leaveSession(Session session) } /** - * A response is being committed for a session, + * A response is being committed for a session, * potentially write the session out before the * client receives the response. * @param session the session @@ -527,36 +535,19 @@ else if (_parameters == null) } // protect against calls to recycled requests (which is illegal, but - // this gives better failures + // this gives better failures MultiMap parameters = _parameters; return parameters == null ? NO_PARAMS : parameters; } private void extractQueryParameters() { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - if (uri == null || !uri.hasQuery()) + if (_uri == null || StringUtil.isEmpty(_uri.getQuery())) _queryParameters = NO_PARAMS; else { _queryParameters = new MultiMap<>(); - if (_queryEncoding == null) - uri.decodeQueryTo(_queryParameters); - else - { - try - { - uri.decodeQueryTo(_queryParameters, _queryEncoding); - } - catch (UnsupportedEncodingException e) - { - if (LOG.isDebugEnabled()) - LOG.warn("Unable to decode query", e); - else - LOG.warn("Unable to decode query - {}", e.toString()); - } - } + UrlEncoded.decodeTo(_uri.getQuery(), _queryParameters, _queryEncoding); } } @@ -715,7 +706,7 @@ public Object getAttribute(String name) public Enumeration getAttributeNames() { if (_attributes == null) - return Collections.enumeration(Collections.emptyList()); + return Collections.enumeration(Collections.emptyList()); return AttributesMap.getAttributeNamesCopy(_attributes); } @@ -755,7 +746,7 @@ public String getCharacterEncoding() { if (_context != null) _characterEncoding = _context.getRequestCharacterEncoding(); - + if (_characterEncoding == null) { String contentType = getContentType(); @@ -787,19 +778,14 @@ public int getContentLength() return -1; long contentLength = metadata.getContentLength(); - if (contentLength != Long.MIN_VALUE) - { - if (contentLength > Integer.MAX_VALUE) - { - // Per ServletRequest#getContentLength() javadoc this must return -1 for values exceeding Integer.MAX_VALUE - return -1; - } - else - { - return (int)contentLength; - } - } - return (int)metadata.getFields().getLongField(HttpHeader.CONTENT_LENGTH.asString()); + if (contentLength == Long.MIN_VALUE) + contentLength = metadata.getFields().getLongField(HttpHeader.CONTENT_LENGTH.asString()); + + if (contentLength > Integer.MAX_VALUE) + // Per ServletRequest#getContentLength() javadoc this must return -1 for values exceeding Integer.MAX_VALUE + return -1; + + return (int)contentLength; } @Override @@ -893,8 +879,8 @@ public Cookie[] getCookies() @Override public long getDateHeader(String name) { - MetaData.Request metadata = _metaData; - return metadata == null ? -1 : metadata.getFields().getDateField(name); + HttpFieldList fields = _httpFields; + return fields == null ? null : fields.getDateField(name); } @Override @@ -906,26 +892,26 @@ public DispatcherType getDispatcherType() @Override public String getHeader(String name) { - MetaData.Request metadata = _metaData; - return metadata == null ? null : metadata.getFields().get(name); + HttpFieldList fields = _httpFields; + return fields == null ? null : fields.get(name); } @Override public Enumeration getHeaderNames() { - MetaData.Request metadata = _metaData; - return metadata == null ? Collections.emptyEnumeration() : metadata.getFields().getFieldNames(); + HttpFieldList fields = _httpFields; + return fields == null ? Collections.emptyEnumeration() : fields.getFieldNames(); } @Override public Enumeration getHeaders(String name) { - MetaData.Request metadata = _metaData; - if (metadata == null) + HttpFieldList fields = _httpFields; + if (fields == null) return Collections.emptyEnumeration(); - Enumeration e = metadata.getFields().getValues(name); + Enumeration e = fields.getValues(name); if (e == null) - return Collections.enumeration(Collections.emptyList()); + return Collections.enumeration(Collections.emptyList()); return e; } @@ -953,18 +939,18 @@ public ServletInputStream getInputStream() throws IOException @Override public int getIntHeader(String name) { - MetaData.Request metadata = _metaData; - return metadata == null ? -1 : (int)metadata.getFields().getLongField(name); + HttpFieldList fields = _httpFields; + return fields == null ? -1 : (int)fields.getLongField(name); } @Override public Locale getLocale() { - MetaData.Request metadata = _metaData; - if (metadata == null) + HttpFieldList fields = _httpFields; + if (fields == null) return Locale.getDefault(); - List acceptable = metadata.getFields().getQualityCSV(HttpHeader.ACCEPT_LANGUAGE); + List acceptable = fields.getQualityCSV(HttpHeader.ACCEPT_LANGUAGE); // handle no locale if (acceptable.isEmpty()) @@ -985,11 +971,11 @@ public Locale getLocale() @Override public Enumeration getLocales() { - MetaData.Request metadata = _metaData; - if (metadata == null) + HttpFieldList fields = _httpFields; + if (fields == null) return Collections.enumeration(__defaultLocale); - List acceptable = metadata.getFields().getQualityCSV(HttpHeader.ACCEPT_LANGUAGE); + List acceptable = fields.getQualityCSV(HttpHeader.ACCEPT_LANGUAGE); // handle no locale if (acceptable.isEmpty()) @@ -1074,10 +1060,7 @@ public int getLocalPort() @Override public String getMethod() { - MetaData.Request metadata = _metaData; - if (metadata != null) - return metadata.getMethod(); - return null; + return _method; } @Override @@ -1164,14 +1147,13 @@ public HttpVersion getHttpVersion() public String getQueryEncoding() { - return _queryEncoding; + return _queryEncoding.toString(); } @Override public String getQueryString() { - MetaData.Request metadata = _metaData; - return metadata == null ? null : metadata.getURI().getQuery(); + return _uri == null ? null : _uri.getQuery(); } @Override @@ -1344,22 +1326,13 @@ public StringBuilder getRootURL() @Override public String getScheme() { - MetaData.Request metadata = _metaData; - String scheme = metadata == null ? null : metadata.getURI().getScheme(); - return scheme == null ? HttpScheme.HTTP.asString() : scheme; + return _uri == null ? "http" : _uri.getScheme(); } @Override public String getServerName() { - MetaData.Request metadata = _metaData; - String name = metadata == null ? null : metadata.getURI().getHost(); - - // Return already determined host - if (name != null) - return name; - - return findServerName(); + return _uri == null ? findServerName() : _uri.getHost(); } private String findServerName() @@ -1384,9 +1357,7 @@ private String findServerName() @Override public int getServerPort() { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - int port = (uri == null || uri.getHost() == null) ? findServerPort() : uri.getPort(); + int port = _uri == null ? -1 : _uri.getPort(); // If no port specified, return the default port for the scheme if (port <= 0) @@ -1481,7 +1452,7 @@ public void onCompleted() } } } - + /** * Called when a response is about to be committed, ie sent * back to the client @@ -1497,21 +1468,21 @@ public void onResponseCommit() /** * Find a session that this request has already entered for the - * given SessionHandler + * given SessionHandler * * @param sessionHandler the SessionHandler (ie context) to check - * @return + * @return the session for the passed session handler or null */ public HttpSession getSession(SessionHandler sessionHandler) { if (_sessions == null || _sessions.size() == 0 || sessionHandler == null) return null; - + HttpSession session = null; - + for (HttpSession s:_sessions) { - Session ss = Session.class.cast(s); + Session ss = (Session)s; if (sessionHandler == ss.getSessionHandler()) { session = s; @@ -1521,7 +1492,7 @@ public HttpSession getSession(SessionHandler sessionHandler) } return session; } - + @Override public HttpSession getSession() { @@ -1574,34 +1545,32 @@ public long getTimeStamp() return _timeStamp; } - /** - * @return Returns the uri. - */ public HttpURI getHttpURI() { - MetaData.Request metadata = _metaData; - return metadata == null ? null : metadata.getURI(); + return _uri; } - /** - * @return Returns the original uri passed in metadata before customization/rewrite - */ - public String getOriginalURI() + public void setHttpURI(HttpURI uri) { - return _originalUri; + if (_uri != null && !Objects.equals(_uri.getQuery(), uri.getQuery())) + _parameters = _queryParameters = null; + _uri = uri; } /** - * @param uri the URI to set + * @return Returns the original uri passed in metadata before customization/rewrite */ - public void setHttpURI(HttpURI uri) + public String getOriginalURI() { MetaData.Request metadata = _metaData; - if (metadata != null) - { - metadata.setURI(uri); - _queryParameters = null; - } + if (metadata == null) + return null; + HttpURI uri = metadata.getURI(); + if (uri == null) + return null; + return uri.isAbsolute() && metadata.getHttpVersion() != HttpVersion.HTTP_2 + ? uri.toString() + : uri.getPathQuery(); } public UserIdentity getUserIdentity() @@ -1716,46 +1685,47 @@ public boolean isUserInRole(String role) /** * @param request the Request metadata */ - public void setMetaData(org.eclipse.jetty.http.MetaData.Request request) + public void setMetaData(MetaData.Request request) { _metaData = request; - HttpURI uri = request.getURI(); - _originalUri = uri.isAbsolute() && request.getHttpVersion() != HttpVersion.HTTP_2 - ? uri.toString() - : uri.getPathQuery(); - - if (uri.getScheme() == null) - uri.setScheme("http"); + _method = request.getMethod(); + _httpFields = request.getFields(); + final HttpURI uri = request.getURI(); - if (!uri.hasAuthority()) + if (uri.isAbsolute() && uri.hasAuthority()) + _uri = uri; + else { - HttpField field = getHttpFields().getField(HttpHeader.HOST); - if (field instanceof HostPortHttpField) + HttpURI.Builder builder = new HttpURI.Builder(uri); + if (!uri.isAbsolute()) + builder.scheme(HttpScheme.HTTP.asString()); + + if (!uri.hasAuthority()) { - HostPortHttpField authority = (HostPortHttpField)field; - uri.setAuthority(authority.getHost(), authority.getPort()); + HttpField field = getHttpFields().getField(HttpHeader.HOST); + if (field instanceof HostPortHttpField) + { + HostPortHttpField authority = (HostPortHttpField)field; + builder.host(authority.getHost()).port(authority.getPort()); + } + else + { + builder.host(findServerName()).port(findServerPort()); + } } + _uri = builder.build(); } String encoded = uri.getPath(); String path; if (encoded == null) - { path = uri.isAbsolute() ? "/" : null; - uri.setPath(path); - } else if (encoded.startsWith("/")) - { path = (encoded.length() == 1) ? "/" : URIUtil.canonicalPath(URIUtil.decodePath(encoded)); - } else if ("*".equals(encoded) || HttpMethod.CONNECT.is(getMethod())) - { path = encoded; - } else - { path = null; - } if (path == null || path.isEmpty()) { @@ -1778,7 +1748,9 @@ public boolean hasMetaData() protected void recycle() { _metaData = null; - _originalUri = null; + _httpFields = null; + _method = null; + _uri = null; if (_context != null) throw new IllegalStateException("Request in context!"); @@ -2021,16 +1993,7 @@ public void setHandled(boolean h) */ public void setMethod(String method) { - MetaData.Request metadata = _metaData; - if (metadata != null) - metadata.setMethod(method); - } - - public void setHttpVersion(HttpVersion version) - { - MetaData.Request metadata = _metaData; - if (metadata != null) - metadata.setHttpVersion(version); + _method = method; } public boolean isHead() @@ -2056,19 +2019,7 @@ public void setPathInfo(String pathInfo) */ public void setQueryEncoding(String queryEncoding) { - _queryEncoding = queryEncoding; - } - - /** - * @param queryString The queryString to set. - */ - public void setQueryString(String queryString) - { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - if (uri != null) - uri.setQuery(queryString); - _queryEncoding = null; //assume utf-8 + _queryEncoding = Charset.forName(queryEncoding); } /** @@ -2095,37 +2046,6 @@ public void setRequestedSessionIdFromCookie(boolean requestedSessionIdCookie) _requestedSessionIdFromCookie = requestedSessionIdCookie; } - public void setURIPathQuery(String requestURI) - { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - if (uri != null) - uri.setPathQuery(requestURI); - } - - /** - * @param scheme The scheme to set. - */ - public void setScheme(String scheme) - { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - if (uri != null) - uri.setScheme(scheme); - } - - /** - * @param host The host to set. - * @param port the port to set - */ - public void setAuthority(String host, int port) - { - MetaData.Request metadata = _metaData; - HttpURI uri = metadata == null ? null : metadata.getURI(); - if (uri != null) - uri.setAuthority(host, port); - } - /** * @param servletPath The servletPath to set. */ @@ -2218,21 +2138,21 @@ public boolean authenticate(HttpServletResponse response) throws IOException, Se //if already authenticated, return true if (getUserPrincipal() != null && getRemoteUser() != null && getAuthType() != null) return true; - + //do the authentication if (_authentication instanceof Authentication.Deferred) { setAuthentication(((Authentication.Deferred)_authentication).authenticate(this, response)); } - + //if the authentication did not succeed if (_authentication instanceof Authentication.Deferred) response.sendError(HttpStatus.UNAUTHORIZED_401); - + //if the authentication is incomplete, return false if (!(_authentication instanceof Authentication.ResponseSent)) return false; - + //something has gone wrong throw new ServletException("Authentication failed"); } @@ -2353,7 +2273,7 @@ public void logout() throws ServletException _authentication = ((Authentication.LogoutAuthentication)_authentication).logout(this); } - public void mergeQueryParameters(String oldQuery, String newQuery, boolean updateQueryString) + public void mergeQueryParameters(String oldQuery, String newQuery) { MultiMap newQueryParams = null; // Have to assume ENCODING because we can't know otherwise. @@ -2391,9 +2311,6 @@ else if (oldQueryParams == null || oldQueryParams.size() == 0) setQueryParameters(mergedQueryParams); resetParameters(); - - if (updateQueryString) - setQueryString(newQuery == null ? oldQuery : newQuery); } @Override diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index b8ce35ebdb28..480c283ff9c2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -488,10 +488,8 @@ protected boolean passConditionalHeaders(HttpServletRequest request, HttpServlet if (request instanceof Request) { // Find multiple fields by iteration as an optimization - HttpFields fields = ((Request)request).getHttpFields(); - for (int i = fields.size(); i-- > 0; ) + for (HttpField field : ((Request)request).getHttpFields()) { - HttpField field = fields.getField(i); if (field.getHeader() != null) { switch (field.getHeader()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index c4441d9ff802..371ffb51074b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -44,6 +44,7 @@ import org.eclipse.jetty.http.HttpCookie.SameSite; import org.eclipse.jetty.http.HttpCookie.SetCookieHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; @@ -62,15 +63,12 @@ import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** *

{@link Response} provides the implementation for {@link HttpServletResponse}.

*/ public class Response implements HttpServletResponse { - private static final Logger LOG = LoggerFactory.getLogger(Response.class); private static final int __MIN_BUFFER_SIZE = 1; private static final HttpField __EXPIRES_01JAN1970 = new PreEncodedHttpField(HttpHeader.EXPIRES, DateGenerator.__01Jan1970); @@ -100,7 +98,7 @@ public enum OutputType private OutputType _outputType = OutputType.NONE; private ResponseWriter _writer; private long _contentLength = -1; - private Supplier _trailers; + private Supplier _trailers; private enum EncodingFrom { @@ -247,7 +245,7 @@ public void addCookie(Cookie cookie) cookie.getValue(), cookie.getDomain(), cookie.getPath(), - (long)cookie.getMaxAge(), + cookie.getMaxAge(), httpOnly, cookie.getSecure(), comment, @@ -308,7 +306,7 @@ else if (!cookie.getPath().equals(oldCookie.getPath())) @Override public boolean containsHeader(String name) { - return _fields.containsKey(name); + return _fields.contains(name); } @Override @@ -1208,12 +1206,12 @@ public void resetBuffer() _out.reopen(); } - public Supplier getTrailers() + public Supplier getTrailers() { return _trailers; } - public void setTrailers(Supplier trailers) + public void setTrailers(Supplier trailers) { _trailers = trailers; } @@ -1238,8 +1236,7 @@ public void setTrailerFields(Supplier> trailers) protected MetaData.Response newResponseMetaData() { - MetaData.Response info = new MetaData.Response(_channel.getRequest().getHttpVersion(), getStatus(), getReason(), _fields, getLongContentLength()); - info.setTrailerSupplier(getTrailers()); + MetaData.Response info = new MetaData.Response(_channel.getRequest().getHttpVersion(), getStatus(), getReason(), _fields, getLongContentLength(), getTrailers()); return info; } @@ -1419,7 +1416,7 @@ public static HttpServletResponse unwrap(ServletResponse servletResponse) return (HttpServletResponse)servletResponse; } - private static class HttpFieldsSupplier implements Supplier + private static class HttpFieldsSupplier implements Supplier { private final Supplier> _supplier; @@ -1429,7 +1426,7 @@ public HttpFieldsSupplier(Supplier> trailers) } @Override - public HttpFields get() + public HttpFieldList get() { Map t = _supplier.get(); if (t == null) @@ -1439,7 +1436,7 @@ public HttpFields get() { fields.add(e.getKey(), e.getValue()); } - return fields; + return fields.asImmutable(); } public Supplier> getSupplier() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java index 2649849d5543..539f0242d258 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.ssl.SslConnection; @@ -206,13 +207,13 @@ public void customize(Connector connector, HttpConfiguration channelConfig, Requ SSLEngine sslEngine = sslConnection.getSSLEngine(); customize(sslEngine, request); - request.setScheme(HttpScheme.HTTPS.asString()); + request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).scheme(HttpScheme.HTTPS).build()); } else if (endp instanceof ProxyConnectionFactory.ProxyEndPoint) { ProxyConnectionFactory.ProxyEndPoint proxy = (ProxyConnectionFactory.ProxyEndPoint)endp; if (request.getHttpURI().getScheme() == null && proxy.getAttribute(ProxyConnectionFactory.TLS_VERSION) != null) - request.setScheme(HttpScheme.HTTPS.asString()); + request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).scheme(HttpScheme.HTTPS).build()); } if (HttpScheme.HTTPS.is(request.getScheme())) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 1566d6ba2f70..e60507e576c1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -28,7 +28,6 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -566,7 +565,8 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio final HttpChannelState state = channel.getRequest().getHttpChannelState(); final AsyncContextEvent event = state.getAsyncContextEvent(); final Request baseRequest = channel.getRequest(); - final HttpURI baseUri = event.getBaseURI(); + + HttpURI baseUri = event.getBaseURI(); String encodedPathQuery = event.getDispatchPath(); if (encodedPathQuery == null && baseUri == null) @@ -578,49 +578,28 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio // this is a dispatch with either a provided URI and/or a dispatched path // We will have to modify the request and then revert - final ServletContext context = event.getServletContext(); final HttpURI oldUri = baseRequest.getHttpURI(); - final String oldQuery = baseRequest.getQueryString(); final MultiMap oldQueryParams = baseRequest.getQueryParameters(); try { - baseRequest.resetParameters(); - HttpURI newUri = baseUri == null ? new HttpURI(oldUri) : baseUri; if (encodedPathQuery == null) { - baseRequest.setHttpURI(newUri); + baseRequest.setHttpURI(baseUri); } else { + ContextHandler.Context context = baseRequest.getContext(); if (context != null && !StringUtil.isEmpty(context.getContextPath())) - encodedPathQuery = URIUtil.addEncodedPaths(URIUtil.encodePath(context.getContextPath()), encodedPathQuery); + encodedPathQuery = URIUtil.addEncodedPaths(context.getContextHandler().getContextPathEncoded(), encodedPathQuery); - if (newUri.getQuery() == null) - { - // parse new path and query - newUri.setPathQuery(encodedPathQuery); - baseRequest.setHttpURI(newUri); - } - else - { - // do we have a new query in the encodedPathQuery - int q = encodedPathQuery.indexOf('?'); - if (q < 0) - { - // No query, so we can just set the encoded path - newUri.setPath(encodedPathQuery); - baseRequest.setHttpURI(newUri); - } - else - { - newUri.setPath(encodedPathQuery.substring(0, q)); - baseRequest.setHttpURI(newUri); - baseRequest.mergeQueryParameters(oldQuery, encodedPathQuery.substring(q + 1), true); - } - } + baseRequest.setHttpURI(new HttpURI(baseUri == null ? oldUri : baseUri, encodedPathQuery)); + + if (oldUri.getQuery() != null && baseRequest.getQueryString() != null) + // TODO why can't the old map be passed? + baseRequest.mergeQueryParameters(oldUri.getQuery(), baseRequest.getQueryString()); } - baseRequest.setPathInfo(newUri.getDecodedPath()); + baseRequest.setPathInfo(baseRequest.getHttpURI().getDecodedPath()); handleAsync(channel, event, baseRequest); } finally diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 494c11652eef..ea7bfac98bed 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -2132,8 +2132,6 @@ public String getMimeType(String file) @Override public RequestDispatcher getRequestDispatcher(String uriInContext) { - // uriInContext is encoded, potentially with query - if (uriInContext == null) return null; @@ -2142,16 +2140,19 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) try { - HttpURI uri = new HttpURI(null, null, 0, uriInContext); - - String pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); - if (pathInfo == null) - return null; - String contextPath = getContextPath(); - if (contextPath != null && contextPath.length() > 0) - uri.setPath(URIUtil.addPaths(contextPath, uri.getPath())); - + HttpURI uri; + String pathInfo; + if (StringUtil.isBlank(contextPath)) + { + uri = new HttpURI.Builder(null, null, 0, uriInContext).build(); + pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); + } + else + { + uri = new HttpURI.Builder(null, null, 0, URIUtil.addPaths(contextPath,uriInContext)).build(); + pathInfo = URIUtil.canonicalPath(uri.getDecodedPath().substring(contextPath.length())); + } return new Dispatcher(ContextHandler.this, uri, pathInfo); } catch (Exception e) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java index 5fbf5105d596..b0568afa54de 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java @@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.QuotedCSV; import org.eclipse.jetty.server.ForwardedRequestCustomizer; @@ -296,8 +295,7 @@ private String getForwarded(Request request) // This is the value from the closest proxy and the only one that // can be trusted. RFC7239 rfc7239 = new RFC7239(); - HttpFields httpFields = request.getHttpFields(); - for (HttpField field : httpFields) + for (HttpField field : request.getHttpFields()) { if (_forwardedHeader.equalsIgnoreCase(field.getName())) rfc7239.addValue(field.getValue()); @@ -315,8 +313,7 @@ private String getXForwardedFor(Request request) // This is the value from the closest proxy and the only one that // can be trusted. String forwardedFor = null; - HttpFields httpFields = request.getHttpFields(); - for (HttpField field : httpFields) + for (HttpField field : request.getHttpFields()) { if (_forwardedHeader.equalsIgnoreCase(field.getName())) forwardedFor = field.getValue(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index 59da37ce07ec..cc7107f2f67a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.EnumSet; -import java.util.ListIterator; import java.util.Set; import java.util.regex.Pattern; import java.util.zip.Deflater; @@ -33,6 +32,7 @@ import org.eclipse.jetty.http.CompressedContentFormat; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -151,6 +151,7 @@ */ public class GzipHandler extends HandlerWrapper implements GzipFactory { + public static final EnumSet ETAG_HEADERS = EnumSet.of(HttpHeader.IF_MATCH, HttpHeader.IF_NONE_MATCH); public static final String GZIP = "gzip"; public static final String DEFLATE = "deflate"; public static final int DEFAULT_MIN_GZIP_SIZE = 32; @@ -421,8 +422,7 @@ protected void doStart() throws Exception @Override public Deflater getDeflater(Request request, long contentLength) { - HttpFields httpFields = request.getHttpFields(); - String ua = httpFields.get(HttpHeader.USER_AGENT); + String ua = request.getHttpFields().get(HttpHeader.USER_AGENT); if (ua != null && !isAgentGzipable(ua)) { LOG.debug("{} excluded user agent {}", this, request); @@ -436,7 +436,7 @@ public Deflater getDeflater(Request request, long contentLength) } // check the accept encoding header - if (!httpFields.contains(HttpHeader.ACCEPT_ENCODING, "gzip")) + if (!request.getHttpFields().contains(HttpHeader.ACCEPT_ENCODING, "gzip")) { LOG.debug("{} excluded not gzip accept {}", this, request); return null; @@ -594,87 +594,99 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques } // Handle request inflation - if (_inflateBufferSize > 0) + HttpFieldList httpFields = baseRequest.getHttpFields(); + boolean inflated = _inflateBufferSize > 0 && httpFields.contains(HttpHeader.CONTENT_ENCODING, "gzip"); + if (inflated) { - boolean inflate = false; - for (ListIterator i = baseRequest.getHttpFields().listIterator(); i.hasNext(); ) - { - HttpField field = i.next(); - - if (field.getHeader() == HttpHeader.CONTENT_ENCODING) - { - if (field.getValue().equalsIgnoreCase("gzip")) - { - i.set(X_CE_GZIP); - inflate = true; - break; - } - - if (COMMA_GZIP.matcher(field.getValue()).matches()) - { - String v = field.getValue(); - v = v.substring(0, v.lastIndexOf(',')); - i.set(new HttpField(HttpHeader.CONTENT_ENCODING, v)); - i.add(X_CE_GZIP); - inflate = true; - break; - } - } - } - - if (inflate) - { - if (LOG.isDebugEnabled()) - LOG.debug("{} inflate {}", this, request); - - baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize)); - - for (ListIterator i = baseRequest.getHttpFields().listIterator(); i.hasNext(); ) - { - HttpField field = i.next(); - if (field.getHeader() == HttpHeader.CONTENT_LENGTH) - { - i.set(new HttpField("X-Content-Length", field.getValue())); - break; - } - } - } + if (LOG.isDebugEnabled()) + LOG.debug("{} inflate {}", this, request); + baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize)); } // Are we already being gzipped? HttpOutput out = baseRequest.getResponse().getHttpOutput(); HttpOutput.Interceptor interceptor = out.getInterceptor(); + boolean alreadyGzipped = false; while (interceptor != null) { if (interceptor instanceof GzipHttpOutputInterceptor) { - LOG.debug("{} already intercepting {}", this, request); - _handler.handle(target, baseRequest, request, response); - return; + alreadyGzipped = true; + break; } interceptor = interceptor.getNextInterceptor(); } - // Special handling for etags - for (ListIterator fields = baseRequest.getHttpFields().listIterator(); fields.hasNext(); ) + // Update headers for etags and inflation + if (inflated || httpFields.contains(ETAG_HEADERS)) { - HttpField field = fields.next(); - if (field.getHeader() == HttpHeader.IF_NONE_MATCH || field.getHeader() == HttpHeader.IF_MATCH) + HttpFields newFields = new HttpFields(httpFields.size() + 1); + for (HttpField field : httpFields) { - String etag = field.getValue(); - int i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote); - if (i > 0) + if (field.getHeader() == null) { - baseRequest.setAttribute("o.e.j.s.h.gzip.GzipHandler.etag", etag); - while (i >= 0) + newFields.add(field); + continue; + } + + switch (field.getHeader()) + { + case IF_MATCH: + case IF_NONE_MATCH: { - etag = etag.substring(0, i) + etag.substring(i + CompressedContentFormat.GZIP._etag.length()); - i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote, i); + String etag = field.getValue(); + int i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote); + if (i <= 0 || alreadyGzipped) + newFields.add(field); + else + { + baseRequest.setAttribute("o.e.j.s.h.gzip.GzipHandler.etag", etag); + while (i >= 0) + { + etag = etag.substring(0, i) + etag.substring(i + CompressedContentFormat.GZIP._etag.length()); + i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote, i); + } + newFields.add(new HttpField(field.getHeader(), etag)); + } + break; } - fields.set(new HttpField(field.getHeader(), etag)); + case CONTENT_LENGTH: + newFields.add(inflated ? new HttpField("X-Content-Length", field.getValue()) : field); + break; + + case CONTENT_ENCODING: + if (inflated) + { + if (field.getValue().equalsIgnoreCase("gzip")) + newFields.add(X_CE_GZIP); + else if (COMMA_GZIP.matcher(field.getValue()).matches()) + { + String v = field.getValue(); + v = v.substring(0, v.lastIndexOf(',')); + newFields.add(X_CE_GZIP); + newFields.add(new HttpField(HttpHeader.CONTENT_ENCODING, v)); + } + } + else + { + newFields.add(field); + } + break; + + default: + newFields.add(field); } } + baseRequest.setHttpFields(newFields); + } + + // Don't gzip if already gzipped; + if (alreadyGzipped) + { + LOG.debug("{} already intercepting {}", this, request); + _handler.handle(target, baseRequest, request, response); + return; } // If not a supported method - no Vary because no matter what client, this URI is always excluded diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpVersionCustomizerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpVersionCustomizerTest.java deleted file mode 100644 index a8e2a9131418..000000000000 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpVersionCustomizerTest.java +++ /dev/null @@ -1,81 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.server; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.SocketChannel; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.http.HttpStatus; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.http.tools.HttpTester; -import org.eclipse.jetty.server.handler.AbstractHandler; -import org.hamcrest.Matchers; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -public class HttpVersionCustomizerTest -{ - @Test - public void testCustomizeHttpVersion() throws Exception - { - Server server = new Server(); - HttpConfiguration httpConfig = new HttpConfiguration(); - httpConfig.addCustomizer((connector, config, request) -> request.setHttpVersion(HttpVersion.HTTP_1_1)); - ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig)); - server.addConnector(connector); - server.setHandler(new AbstractHandler() - { - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - baseRequest.setHandled(true); - response.setStatus(500); - assertEquals(HttpVersion.HTTP_1_1.asString(), request.getProtocol()); - response.setStatus(200); - response.getWriter().println("OK"); - } - }); - server.start(); - - try - { - try (SocketChannel socket = SocketChannel.open(new InetSocketAddress("localhost", connector.getLocalPort()))) - { - HttpTester.Request request = HttpTester.newRequest(); - request.setVersion(HttpVersion.HTTP_1_0); - socket.write(request.generate()); - - HttpTester.Response response = HttpTester.parseResponse(HttpTester.from(socket)); - assertNotNull(response); - assertThat(response.getStatus(), Matchers.equalTo(HttpStatus.OK_200)); - } - } - finally - { - server.stop(); - } - } -} diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index cb79e3f39233..af9a5733e71e 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -822,7 +822,7 @@ public void testStatusCodes(int code, String message, String expectedMessage) th assertEquals(null, response.getReason()); response.setHeader("Should-Be-Ignored", "value"); - assertFalse(response.getHttpFields().containsKey("Should-Be-Ignored")); + assertFalse(response.getHttpFields().contains("Should-Be-Ignored")); assertEquals(expectedMessage, response.getHttpChannel().getRequest().getAttribute(RequestDispatcher.ERROR_MESSAGE)); assertThat(response.getHttpChannel().getState().unhandle(), is(HttpChannelState.Action.SEND_ERROR)); @@ -861,7 +861,7 @@ public void testEncodeRedirect() { Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - request.setAuthority("myhost", 8888); + request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).host("myhost").port(8888).build()); request.setContextPath("/path"); assertEquals("http://myhost:8888/path/info;param?query=0&more=1#target", response.encodeURL("http://myhost:8888/path/info;param?query=0&more=1#target")); @@ -912,6 +912,7 @@ public void testEncodeRedirect() public void testSendRedirect() throws Exception { + // TODO parameterize String[][] tests = { // No cookie { @@ -949,10 +950,12 @@ public void testSendRedirect() Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - request.setScheme("http"); + HttpURI.Builder builder = new HttpURI.Builder(request.getHttpURI(), + "/path/info;param;jsessionid=12345?query=0&more=1#target"); + builder.scheme("http"); if (host != null) - request.setAuthority(host, port); - request.setURIPathQuery("/path/info;param;jsessionid=12345?query=0&more=1#target"); + builder.host(host).port(port); + request.setHttpURI(builder.build()); request.setContextPath("/path"); request.setRequestedSessionId("12345"); request.setRequestedSessionIdFromCookie(i > 2); diff --git a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsContainsHeaderKey.java b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsContainsHeaderKey.java index d46be1f396e1..1caaeb900108 100644 --- a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsContainsHeaderKey.java +++ b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsContainsHeaderKey.java @@ -47,7 +47,7 @@ public void describeTo(Description description) @Override protected boolean matchesSafely(HttpFields fields) { - return fields.containsKey(this.keyName); + return fields.contains(this.keyName); } public static Matcher containsKey(String keyName) From 8de4fb6ed9465a91b3c206f48223b8ce6e9a8834 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 17 Apr 2020 15:28:28 +0200 Subject: [PATCH 08/38] Immutable MetaData Cleanup of HttpURI.Builder API as suggested in PR. Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/http/HttpURI.java | 87 +++++++++++------- .../java/org/eclipse/jetty/http/MetaData.java | 2 +- .../jetty/http/HttpGeneratorClientTest.java | 6 +- .../org/eclipse/jetty/http/HttpURITest.java | 91 ++++++++++++++----- .../org/eclipse/jetty/server/Dispatcher.java | 2 +- .../server/ForwardedRequestCustomizer.java | 4 +- .../jetty/server/HostHeaderCustomizer.java | 2 +- .../jetty/server/HttpChannelOverHttp.java | 4 +- .../eclipse/jetty/server/PushBuilderImpl.java | 2 +- .../org/eclipse/jetty/server/Request.java | 4 +- .../jetty/server/SecureRequestCustomizer.java | 4 +- .../java/org/eclipse/jetty/server/Server.java | 2 +- .../jetty/server/handler/ContextHandler.java | 4 +- .../eclipse/jetty/server/ResponseTest.java | 6 +- 14 files changed, 144 insertions(+), 76 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 31a38beb5eb5..6a61cec7125f 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -21,6 +21,7 @@ import java.net.URI; import java.net.URISyntaxException; +import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; @@ -88,21 +89,7 @@ public HttpURI(URI uri) _fragment = builder._fragment; } - public HttpURI(HttpURI baseUri, String pathQuery) - { - Builder builder = new Builder(baseUri, pathQuery); - _scheme = builder._scheme; - _user = builder._user; - _host = builder._host; - _port = builder._port; - _path = builder._path; - _decodedPath = builder._decodedPath; - _param = builder._param; - _query = builder._query; - _fragment = builder._fragment; - } - - HttpURI(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) + private HttpURI(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) { _uri = uri; _scheme = scheme; @@ -116,6 +103,36 @@ public HttpURI(HttpURI baseUri, String pathQuery) _fragment = fragment; } + public static HttpURI.Builder empty() + { + return new HttpURI.Builder(); + } + + public static HttpURI.Builder from(HttpURI uri) + { + return new HttpURI.Builder(uri); + } + + public static HttpURI.Builder from(HttpURI uri, String pathQuery) + { + return new HttpURI.Builder(uri, pathQuery); + } + + public static HttpURI.Builder from(HttpURI uri, String path, String param, String query) + { + return new HttpURI.Builder(uri, path, param, query); + } + + public static HttpURI.Builder from(URI uri) + { + return new HttpURI.Builder(uri); + } + + public static HttpURI.Builder from(String uri) + { + return new HttpURI.Builder(uri); + } + @Override public boolean equals(Object o) { @@ -288,27 +305,16 @@ private enum State private String _query; private String _fragment; - public Builder() + Builder() { } - public Builder(String scheme, String host, int port, String path, String param, String query, String fragment) - { - _scheme = scheme; - _host = host; - _port = port; - _path = path; - _param = param; - _query = query; - _fragment = fragment; - } - - public Builder(HttpURI uri) + Builder(HttpURI uri) { uri(uri); } - public Builder(HttpURI baseURI, String pathQuery) + Builder(HttpURI baseURI, String pathQuery) { _uri = null; _scheme = baseURI._scheme; @@ -319,7 +325,7 @@ public Builder(HttpURI baseURI, String pathQuery) parse(State.PATH, pathQuery); } - public Builder(HttpURI baseURI, String path, String param, String query) + Builder(HttpURI baseURI, String path, String param, String query) { _uri = null; _scheme = baseURI._scheme; @@ -332,13 +338,13 @@ public Builder(HttpURI baseURI, String path, String param, String query) _fragment = null; } - public Builder(String uri) + Builder(String uri) { _port = -1; parse(State.START, uri); } - public Builder(URI uri) + Builder(URI uri) { _uri = null; @@ -404,7 +410,20 @@ public Builder authority(String host, int port) return this; } - public HttpURI build() + /** + * @param hostport the host and port combined + */ + public Builder authority(String hostport) + { + HostPort hp = new HostPort(hostport); + _user = null; + _host = hp.getHost(); + _port = hp.getPort(); + _uri = null; + return this; + } + + public HttpURI toHttpURI() { return new HttpURI(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); } @@ -585,7 +604,7 @@ public Builder scheme(String scheme) @Override public String toString() { - return build().toString(); + return toHttpURI().toString(); } public URI toURI() diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index eb035dfc24e3..08304221e4e7 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -170,7 +170,7 @@ public Request(String method, String scheme, HostPortHttpField hostPort, String this(method, new HttpURI.Builder(scheme, hostPort == null ? null : hostPort.getHost(), hostPort == null ? -1 : hostPort.getPort(), - uri).build(), version, fields, contentLength); + uri).toHttpURI(), version, fields, contentLength); } @Override diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java index 2059e55e390d..82f0db1a588d 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java @@ -37,17 +37,17 @@ class RequestInfo extends MetaData.Request { RequestInfo(String method, String uri, HttpFieldList fields) { - super(method, new HttpURI.Builder(method,uri).build(), HttpVersion.HTTP_1_1, fields, -1); + super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, -1); } RequestInfo(String method, String uri, HttpVersion version, HttpFieldList fields) { - super(method, new HttpURI.Builder(method,uri).build(), version, fields, -1); + super(method, new HttpURI.Builder(method,uri).toHttpURI(), version, fields, -1); } RequestInfo(String method, String uri, int contentLength, HttpFieldList fields) { - super(method, new HttpURI.Builder(method,uri).build(), HttpVersion.HTTP_1_1, fields, contentLength); + super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, contentLength); } } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index 385171226415..a913ce533b1a 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -29,6 +29,55 @@ public class HttpURITest { + @Test + public void testBuilder() throws Exception + { + HttpURI uri = HttpURI.empty() + .scheme("http") + .user("user:password") + .host("host") + .port(8888) + .path("/ignored/../p%61th;ignored/info") + .param("param") + .query("query=value") + .fragment("fragment") + .toHttpURI(); + + assertThat(uri.getScheme(), is("http")); + assertThat(uri.getUser(), is("user:password")); + assertThat(uri.getHost(), is("host")); + assertThat(uri.getPort(), is(8888)); + assertThat(uri.getPath(), is("/ignored/../p%61th;ignored/info;param")); + assertThat(uri.getDecodedPath(), is("/path/info")); + assertThat(uri.getParam(), is("param")); + assertThat(uri.getQuery(), is("query=value")); + assertThat(uri.getFragment(), is("fragment")); + assertThat(uri.getAuthority(), is("host:8888")); + assertThat(uri.toString(), is("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value#fragment")); + + uri = HttpURI.from(uri) + .scheme("https") + .user(null) + .authority("[::1]:8080") + .decodedPath("/some encoded/evening") + .param("id=12345") + .query(null) + .fragment(null) + .toHttpURI(); + + assertThat(uri.getScheme(), is("https")); + assertThat(uri.getUser(), nullValue()); + assertThat(uri.getHost(), is("[::1]")); + assertThat(uri.getPort(), is(8080)); + assertThat(uri.getPath(), is("/some%20encoded/evening;id=12345")); + assertThat(uri.getDecodedPath(), is("/some encoded/evening")); + assertThat(uri.getParam(), is("id=12345")); + assertThat(uri.getQuery(), nullValue()); + assertThat(uri.getFragment(), nullValue()); + assertThat(uri.getAuthority(), is("[::1]:8080")); + assertThat(uri.toString(), is("https://[::1]:8080/some%20encoded/evening;id=12345")); + } + @Test public void testExample() throws Exception { @@ -58,7 +107,7 @@ private void assertInvalidURI(String invalidURI, String message) { try { - new HttpURI.Builder(invalidURI).build(); + new HttpURI.Builder(invalidURI).toHttpURI(); fail(message); } catch (IllegalArgumentException e) @@ -74,22 +123,22 @@ public void testParse() HttpURI uri; builder.uri("*"); - uri = builder.build(); + uri = builder.toHttpURI(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); builder.uri("/foo/bar"); - uri = builder.build(); + uri = builder.toHttpURI(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); builder.uri("//foo/bar"); - uri = builder.build(); + uri = builder.toHttpURI(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); builder.uri("http://foo/bar"); - uri = builder.build(); + uri = builder.toHttpURI(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -99,19 +148,19 @@ public void testParseRequestTarget() { HttpURI uri; - uri = new HttpURI.Builder("GET", "*").build(); + uri = new HttpURI.Builder("GET", "*").toHttpURI(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); - uri = new HttpURI.Builder("GET", "/foo/bar").build(); + uri = new HttpURI.Builder("GET", "/foo/bar").toHttpURI(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); - uri = new HttpURI.Builder("GET", "//foo/bar").build(); + uri = new HttpURI.Builder("GET", "//foo/bar").toHttpURI(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("//foo/bar")); - uri = new HttpURI.Builder("GET", "http://foo/bar").build(); + uri = new HttpURI.Builder("GET", "http://foo/bar").toHttpURI(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -156,41 +205,41 @@ public void testParams() throws Exception public void testMutableURIBuilder() { HttpURI.Builder builder = new HttpURI.Builder("/foo/bar"); - HttpURI uri = builder.build(); + HttpURI uri = builder.toHttpURI(); assertEquals("/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.scheme("http").build(); + uri = builder.scheme("http").toHttpURI(); assertEquals("http:/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.authority("host", 0).build(); + uri = builder.authority("host", 0).toHttpURI(); assertEquals("http://host/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.authority("host", 8888).build(); + uri = builder.authority("host", 8888).toHttpURI(); assertEquals("http://host:8888/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2").build(); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2").toHttpURI(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals(null, uri.getQuery()); - uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2?name=value").build(); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2?name=value").toHttpURI(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?name=value", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals("name=value", uri.getQuery()); - uri = builder.query("other=123456").build(); + uri = builder.query("other=123456").toHttpURI(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?other=123456", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); @@ -202,19 +251,19 @@ public void testMutableURIBuilder() public void testSchemeAndOrAuthority() throws Exception { HttpURI.Builder builder = new HttpURI.Builder("/path/info"); - HttpURI uri = builder.build(); + HttpURI uri = builder.toHttpURI(); assertEquals("/path/info", uri.toString()); - uri = builder.authority("host", 0).build(); + uri = builder.authority("host", 0).toHttpURI(); assertEquals("//host/path/info", uri.toString()); - uri = builder.authority("host", 8888).build(); + uri = builder.authority("host", 8888).toHttpURI(); assertEquals("//host:8888/path/info", uri.toString()); - uri = builder.scheme("http").build(); + uri = builder.scheme("http").toHttpURI(); assertEquals("http://host:8888/path/info", uri.toString()); - uri = builder.authority(null, 0).build(); + uri = builder.authority(null, 0).toHttpURI(); assertEquals("http:/path/info", uri.toString()); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 764e88340927..197985cbd163 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -193,7 +193,7 @@ protected void forward(ServletRequest request, ServletResponse response, Dispatc if (query == null) query = old_uri.getQuery(); - HttpURI uri = new HttpURI.Builder(old_uri, _uri.getPath(), _uri.getParam(), query).build(); + HttpURI uri = HttpURI.from(old_uri, _uri.getPath(), _uri.getParam(), query).toHttpURI(); baseRequest.setHttpURI(uri); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index 4c74cbeeba66..ea04697e6f45 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -400,7 +400,7 @@ public void customize(Connector connector, HttpConfiguration config, Request req if (match) { - HttpURI.Builder builder = new HttpURI.Builder(request.getHttpURI()); + HttpURI.Builder builder = HttpURI.from(request.getHttpURI()); if (forwarded._proto != null) { builder.scheme(forwarded._proto); @@ -433,7 +433,7 @@ else if (forwarded._server != null) if (request.isSecure() && !wasSecure) builder.scheme(HttpScheme.HTTPS); - request.setHttpURI(builder.build()); + request.setHttpURI(builder.toHttpURI()); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java index 81b7eb914439..2c8ca9a33be7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java @@ -66,6 +66,6 @@ public void customize(Connector connector, HttpConfiguration channelConfig, Requ { if (request.getHeader("Host") == null) // TODO set the field as well? - request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).host(serverName).port(serverPort).build()); + request.setHttpURI(HttpURI.from(request.getHttpURI()).host(serverName).port(serverPort).toHttpURI()); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index 691ac22a45db..18b019b1b698 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -281,7 +281,7 @@ public void badMessage(BadMessageException failure) { // Need to call onRequest, so RequestLog can reports as much as possible if (_metadata == null) - _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).build(), _version, _fields); + _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).toHttpURI(), _version, _fields); onRequest(_metadata); getRequest().getHttpInput().earlyEOF(); } @@ -296,7 +296,7 @@ public void badMessage(BadMessageException failure) @Override public boolean headerComplete() { - _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).build(), _version, _fields); + _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).toHttpURI(), _version, _fields); onRequest(_metadata); if (_complianceViolations != null && !_complianceViolations.isEmpty()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index 95a6e63bf197..c450a094d74b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -176,7 +176,7 @@ public void push() // _rawFields.add("Cookie","JSESSIONID="+_sessionId); } - HttpURI uri = new HttpURI.Builder(_request.getHttpURI(), path, param, query).build(); + HttpURI uri = HttpURI.from(_request.getHttpURI(), path, param, query).normalize().toHttpURI(); MetaData.Request push = new MetaData.Request(_method, uri, _request.getHttpVersion(), _fields); if (LOG.isDebugEnabled()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 11e61893dc26..0a469cd7bb27 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1696,7 +1696,7 @@ public void setMetaData(MetaData.Request request) _uri = uri; else { - HttpURI.Builder builder = new HttpURI.Builder(uri); + HttpURI.Builder builder = HttpURI.from(uri); if (!uri.isAbsolute()) builder.scheme(HttpScheme.HTTP.asString()); @@ -1713,7 +1713,7 @@ public void setMetaData(MetaData.Request request) builder.host(findServerName()).port(findServerPort()); } } - _uri = builder.build(); + _uri = builder.toHttpURI(); } String encoded = uri.getPath(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java index 539f0242d258..13d21319039a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -207,13 +207,13 @@ public void customize(Connector connector, HttpConfiguration channelConfig, Requ SSLEngine sslEngine = sslConnection.getSSLEngine(); customize(sslEngine, request); - request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).scheme(HttpScheme.HTTPS).build()); + request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); } else if (endp instanceof ProxyConnectionFactory.ProxyEndPoint) { ProxyConnectionFactory.ProxyEndPoint proxy = (ProxyConnectionFactory.ProxyEndPoint)endp; if (request.getHttpURI().getScheme() == null && proxy.getAttribute(ProxyConnectionFactory.TLS_VERSION) != null) - request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).scheme(HttpScheme.HTTPS).build()); + request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); } if (HttpScheme.HTTPS.is(request.getScheme())) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index e60507e576c1..9a9155a76dad 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -592,7 +592,7 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio if (context != null && !StringUtil.isEmpty(context.getContextPath())) encodedPathQuery = URIUtil.addEncodedPaths(context.getContextHandler().getContextPathEncoded(), encodedPathQuery); - baseRequest.setHttpURI(new HttpURI(baseUri == null ? oldUri : baseUri, encodedPathQuery)); + baseRequest.setHttpURI(HttpURI.from(baseUri == null ? oldUri : baseUri, encodedPathQuery).toHttpURI()); if (oldUri.getQuery() != null && baseRequest.getQueryString() != null) // TODO why can't the old map be passed? diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index ea7bfac98bed..9bce345f0dea 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -2145,12 +2145,12 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) String pathInfo; if (StringUtil.isBlank(contextPath)) { - uri = new HttpURI.Builder(null, null, 0, uriInContext).build(); + uri = new HttpURI.Builder(null, null, 0, uriInContext).toHttpURI(); pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); } else { - uri = new HttpURI.Builder(null, null, 0, URIUtil.addPaths(contextPath,uriInContext)).build(); + uri = new HttpURI.Builder(null, null, 0, URIUtil.addPaths(contextPath,uriInContext)).toHttpURI(); pathInfo = URIUtil.canonicalPath(uri.getDecodedPath().substring(contextPath.length())); } return new Dispatcher(ContextHandler.this, uri, pathInfo); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index af9a5733e71e..b1a101d96c75 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -861,7 +861,7 @@ public void testEncodeRedirect() { Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - request.setHttpURI(new HttpURI.Builder(request.getHttpURI()).host("myhost").port(8888).build()); + request.setHttpURI(HttpURI.from(request.getHttpURI()).host("myhost").port(8888).toHttpURI()); request.setContextPath("/path"); assertEquals("http://myhost:8888/path/info;param?query=0&more=1#target", response.encodeURL("http://myhost:8888/path/info;param?query=0&more=1#target")); @@ -950,12 +950,12 @@ public void testSendRedirect() Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - HttpURI.Builder builder = new HttpURI.Builder(request.getHttpURI(), + HttpURI.Builder builder = HttpURI.from(request.getHttpURI(), "/path/info;param;jsessionid=12345?query=0&more=1#target"); builder.scheme("http"); if (host != null) builder.host(host).port(port); - request.setHttpURI(builder.build()); + request.setHttpURI(builder.toHttpURI()); request.setContextPath("/path"); request.setRequestedSessionId("12345"); request.setRequestedSessionIdFromCookie(i > 2); From c1010f3e628dff69f69945915f2b2b244829a73d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 17 Apr 2020 16:10:58 +0200 Subject: [PATCH 09/38] Immutable MetaData Added builder for MetaData.Request Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/http/MetaData.java | 36 ++++++++++++++++--- .../jetty/server/HttpChannelOverHttp.java | 31 ++++++---------- .../org/eclipse/jetty/server/Request.java | 6 ++-- .../server/handler/NcsaRequestLogTest.java | 10 ++++-- 4 files changed, 51 insertions(+), 32 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 08304221e4e7..a2c3e959f257 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -155,11 +155,6 @@ public Request(String method, HttpURI uri, HttpVersion version, HttpFieldList fi _uri = uri; } - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields) - { - this(method, scheme, hostPort, uri, version, fields, Long.MIN_VALUE); - } - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields, long contentLength) { this(method, scheme == null ? null : scheme.asString(), hostPort, uri, version, fields, contentLength); @@ -217,6 +212,37 @@ public String toString() } } + // TODO this is moderately specific to HttpChannelOverHttp, so unless it get's used elsewhere, it should be moved there. + public static class RequestBuilder extends HttpFields + { + private final HttpURI.Builder _uri = HttpURI.empty(); + private String _method; + private HttpVersion _version; + + public String method() + { + return _method; + } + + public void request(String method, String uri, HttpVersion version) + { + clear(); + _method = method; + _uri.uri(uri); + _version = version; + } + + public Request build() + { + return new Request(_method, _uri.toHttpURI(), _version, asImmutable()); + } + + public HttpVersion version() + { + return _version; + } + } + public static class ConnectRequest extends Request { private final String _protocol; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index 18b019b1b698..c8a2a7288d4e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; -import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; @@ -50,11 +49,8 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque { private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverHttp.class); private static final HttpField PREAMBLE_UPGRADE_H2C = new HttpField(HttpHeader.UPGRADE, "h2c"); - private final HttpFields _fields = new HttpFields(); private final HttpConnection _httpConnection; - private String _method; - private String _uri; - private HttpVersion _version; + private final MetaData.RequestBuilder _requestBuilder = new MetaData.RequestBuilder(); private MetaData.Request _metadata; private HttpField _connection; private HttpField _upgrade = null; @@ -87,14 +83,10 @@ protected HttpInput newHttpInput(HttpChannelState state) public void recycle() { super.recycle(); - _method = null; - _uri = null; - _version = null; _unknownExpectation = false; _expect100Continue = false; _expect102Processing = false; _connection = null; - _fields.clear(); _upgrade = null; _trailers = null; _metadata = null; @@ -115,10 +107,7 @@ public boolean isExpecting102Processing() @Override public void startRequest(String method, String uri, HttpVersion version) { - // TODO should we have a MetaData.RequestBuilder class to hold these values? - _method = method; - _uri = uri; - _version = version; + _requestBuilder.request(method, uri, version); _unknownExpectation = false; _expect100Continue = false; _expect102Processing = false; @@ -144,7 +133,7 @@ public void parsedHeader(HttpField field) case EXPECT: { - if (HttpVersion.HTTP_1_1.equals(_version)) + if (HttpVersion.HTTP_1_1.equals(_requestBuilder.version())) { HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value); switch (expect == null ? HttpHeaderValue.UNKNOWN : expect) @@ -192,7 +181,7 @@ public void parsedHeader(HttpField field) break; } } - _fields.add(field); + _requestBuilder.add(field); } @Override @@ -237,7 +226,7 @@ public void earlyEOF() { _httpConnection.getGenerator().setPersistent(false); // If we have no request yet, just close - if (_method == null) + if (_metadata == null) _httpConnection.close(); else if (onEarlyEOF() || _delayedForContent) { @@ -281,7 +270,7 @@ public void badMessage(BadMessageException failure) { // Need to call onRequest, so RequestLog can reports as much as possible if (_metadata == null) - _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).toHttpURI(), _version, _fields); + _metadata = _requestBuilder.build(); onRequest(_metadata); getRequest().getHttpInput().earlyEOF(); } @@ -296,7 +285,7 @@ public void badMessage(BadMessageException failure) @Override public boolean headerComplete() { - _metadata = new MetaData.Request(_method, new HttpURI.Builder(_method, _uri).toHttpURI(), _version, _fields); + _metadata = _requestBuilder.build(); onRequest(_metadata); if (_complianceViolations != null && !_complianceViolations.isEmpty()) @@ -323,7 +312,7 @@ public boolean headerComplete() if (_connection.contains(HttpHeaderValue.KEEP_ALIVE.asString())) persistent = true; else - persistent = _fields.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()); + persistent = _requestBuilder.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()); } else persistent = false; @@ -354,7 +343,7 @@ public boolean headerComplete() if (_connection.contains(HttpHeaderValue.CLOSE.asString())) persistent = false; else - persistent = !_fields.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()); // handle multiple connection fields + persistent = !_requestBuilder.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()); // handle multiple connection fields } else persistent = true; @@ -380,7 +369,7 @@ public boolean headerComplete() if (HttpMethod.PRI.is(_metadata.getMethod()) && "*".equals(_metadata.getURI().getPath()) && - _fields.size() == 0 && + _requestBuilder.size() == 0 && upgrade()) return true; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 0a469cd7bb27..def4257d6f0d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1568,9 +1568,9 @@ public String getOriginalURI() HttpURI uri = metadata.getURI(); if (uri == null) return null; - return uri.isAbsolute() && metadata.getHttpVersion() != HttpVersion.HTTP_2 - ? uri.toString() - : uri.getPathQuery(); + return uri.isAbsolute() && metadata.getHttpVersion() == HttpVersion.HTTP_2 + ? uri.getPathQuery() + : uri.toString(); } public UserIdentity getUserIdentity() diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java index 4ee0fb69ddfe..0a950764a7bb 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/NcsaRequestLogTest.java @@ -141,17 +141,21 @@ public void testRequestLine(String logType) throws Exception setup(logType); testHandlerServerStart(); + String log; + + /* _connector.getResponse("GET /foo?data=1 HTTP/1.0\nhost: host:80\n\n"); - String log = _entries.poll(5, TimeUnit.SECONDS); + log = _entries.poll(5, TimeUnit.SECONDS); assertThat(log, containsString("GET /foo?data=1 HTTP/1.0\" 200 ")); - +*/ _connector.getResponse("GET //bad/foo?data=1 HTTP/1.0\n\n"); log = _entries.poll(5, TimeUnit.SECONDS); assertThat(log, containsString("GET //bad/foo?data=1 HTTP/1.0\" 200 ")); - +/* _connector.getResponse("GET http://host:80/foo?data=1 HTTP/1.0\n\n"); log = _entries.poll(5, TimeUnit.SECONDS); assertThat(log, containsString("GET http://host:80/foo?data=1 HTTP/1.0\" 200 ")); + */ } @ParameterizedTest() From c0b98a3b3b4c3c9d8378f3fcb60f69376d6f07cc Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sat, 18 Apr 2020 09:13:51 +0200 Subject: [PATCH 10/38] Immutable MetaData more api fixes Signed-off-by: Greg Wilkins --- .../jetty/rewrite/handler/CompactPathRule.java | 3 ++- .../handler/ForwardedSchemeHeaderRule.java | 3 ++- .../rewrite/handler/RewritePatternRule.java | 18 ++++-------------- .../rewrite/handler/RewriteRegexRule.java | 13 ++++++++----- .../jetty/rewrite/handler/RuleContainer.java | 12 ++---------- 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java index d091820f089b..5dc4a853e682 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.URIUtil; @@ -42,7 +43,7 @@ public void applyURI(Request request, String oldURI, String newURI) throws IOExc String uri = request.getRequestURI(); if (uri.startsWith("/")) uri = URIUtil.compactPath(uri); - request.setURIPathQuery(uri); + request.setHttpURI(HttpURI.from(request.getHttpURI(), uri).toHttpURI()); } @Override diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java index 9295b8be393c..a21da99ffe5c 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java @@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; /** @@ -47,7 +48,7 @@ public void setScheme(String scheme) protected String apply(String target, String value, HttpServletRequest request, HttpServletResponse response) { Request baseRequest = Request.getBaseRequest(request); - baseRequest.setScheme(_scheme); + baseRequest.setHttpURI(HttpURI.from(baseRequest.getHttpURI()).scheme(_scheme).toHttpURI()); return target; } } diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java index aaf70aa1ddee..1fdab46b7f68 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.pathmap.ServletPathSpec; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.URIUtil; @@ -90,20 +91,9 @@ public String apply(String target, HttpServletRequest request, HttpServletRespon @Override public void applyURI(Request request, String oldURI, String newURI) throws IOException { - if (_query == null) - { - request.setURIPathQuery(newURI); - } - else - { - String queryString = request.getQueryString(); - if (queryString != null) - queryString = queryString + "&" + _query; - else - queryString = _query; - request.setURIPathQuery(newURI); - request.setQueryString(queryString); - } + HttpURI baseURI = request.getHttpURI(); + String query = URIUtil.addQueries(baseURI.getQuery(),_query); + request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), query).toHttpURI()); } /** diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java index fdfe75872169..a97fd55cb3fd 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java @@ -23,7 +23,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.annotation.Name; /** @@ -105,18 +107,19 @@ public String apply(String target, HttpServletRequest request, HttpServletRespon @Override public void applyURI(Request request, String oldURI, String newURI) throws IOException { + HttpURI baseURI = request.getHttpURI(); if (_query == null) { - request.setURIPathQuery(newURI); + request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), baseURI.getQuery()).toHttpURI()); } else { + // TODO why isn't _query used? String query = (String)request.getAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q"); + if (!_queryGroup) + query = URIUtil.addQueries(baseURI.getQuery(), query); - if (!_queryGroup && request.getQueryString() != null) - query = request.getQueryString() + "&" + query; - request.setURIPathQuery(newURI); - request.setQueryString(query); + request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), query).toHttpURI()); } } diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java index a1eff8f762dd..53ce4d7a08b9 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java @@ -25,7 +25,6 @@ import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.util.ArrayUtil; -import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.component.Dumpable; import org.slf4j.Logger; @@ -188,16 +187,9 @@ protected String apply(String target, HttpServletRequest request, HttpServletRes ((Rule.ApplyURI)rule).applyURI(baseRequest, baseRequest.getRequestURI(), encoded); else { - String uriPathQuery = encoded; HttpURI baseUri = baseRequest.getHttpURI(); - // Copy path params from original URI if present - if ((baseUri != null) && StringUtil.isNotBlank(baseUri.getParam())) - { - HttpURI uri = new HttpURI(uriPathQuery); - uri.setParam(baseUri.getParam()); - uriPathQuery = uri.toString(); - } - baseRequest.setURIPathQuery(uriPathQuery); + baseRequest.setHttpURI(HttpURI.from(baseUri,encoded) + .param(baseUri.getParam()).toHttpURI()); } } From 4c334e8611ce8dd894b8fa1bdc795a8cffc95d02 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sat, 18 Apr 2020 18:55:47 +0200 Subject: [PATCH 11/38] Immutable MetaData WIP making HttpFiels itself immutable. Currently working up to jetty-servlet. Need to consider if content-length really is meta data and how much and when can we trust it. Signed-off-by: Greg Wilkins --- .../jetty/embedded/FastFileServerTest.java | 4 +- .../jetty/embedded/FileServerTest.java | 4 +- .../jetty/embedded/FileServerXmlTest.java | 4 +- .../java/client/ConscryptHTTP2ClientTest.java | 4 +- .../alpn/java/client/JDK9HTTP2ClientTest.java | 4 +- .../eclipse/jetty/client/HttpConnection.java | 4 +- .../jetty/client/HttpContentResponse.java | 4 +- .../org/eclipse/jetty/client/HttpRequest.java | 5 +- .../eclipse/jetty/client/HttpResponse.java | 11 +- .../org/eclipse/jetty/client/api/Request.java | 4 +- .../eclipse/jetty/client/api/Response.java | 4 +- .../client/http/HttpChannelOverHTTP.java | 4 +- .../jetty/client/http/HttpSenderOverHTTP.java | 3 +- .../util/BufferingResponseListener.java | 4 +- .../client/util/MultiPartContentProvider.java | 10 +- .../client/util/MultiPartRequestContent.java | 10 +- .../client/http/HttpReceiverOverHTTPTest.java | 6 +- .../client/util/MultiPartContentTest.java | 7 +- .../src/main/java/embedded/HTTP2Docs.java | 4 +- .../client/http2/HTTP2ClientDocs.java | 18 +- .../server/http2/HTTP2ServerDocs.java | 7 +- .../fcgi/client/http/HttpChannelOverFCGI.java | 4 +- .../http/HttpClientTransportOverFCGI.java | 4 +- .../client/http/HttpConnectionOverFCGI.java | 4 +- .../fcgi/client/http/HttpSenderOverFCGI.java | 12 +- .../jetty/fcgi/generator/ClientGenerator.java | 4 +- .../jetty/fcgi/generator/ServerGenerator.java | 4 +- .../fcgi/parser/ResponseContentParser.java | 6 +- .../fcgi/generator/ClientGeneratorTest.java | 4 +- .../jetty/fcgi/parser/ClientParserTest.java | 10 +- .../fcgi/server/HttpChannelOverFCGI.java | 4 +- .../server/proxy/FastCGIProxyServlet.java | 6 +- .../org/eclipse/jetty/http/HttpField.java | 221 +++--- .../org/eclipse/jetty/http/HttpFieldList.java | 470 ------------ .../org/eclipse/jetty/http/HttpFields.java | 720 ++++++++---------- .../eclipse/jetty/http/HttpFieldsBuilder.java | 629 +++++++++++++++ .../org/eclipse/jetty/http/HttpGenerator.java | 23 +- .../org/eclipse/jetty/http/HttpParser.java | 2 +- .../java/org/eclipse/jetty/http/HttpURI.java | 4 +- .../java/org/eclipse/jetty/http/MetaData.java | 109 ++- .../eclipse/jetty/http/HttpFieldsTest.java | 137 ++-- .../jetty/http/HttpGeneratorClientTest.java | 20 +- .../http/HttpGeneratorServerHTTPTest.java | 4 +- .../jetty/http/HttpGeneratorServerTest.java | 42 +- .../jetty/http2/client/AbstractTest.java | 6 +- .../jetty/http2/client/AsyncIOTest.java | 10 +- .../jetty/http2/client/AsyncServletTest.java | 12 +- .../jetty/http2/client/ConnectTunnelTest.java | 5 +- .../jetty/http2/client/DataDemandTest.java | 19 +- .../http2/client/FlowControlStalledTest.java | 16 +- .../http2/client/FlowControlStrategyTest.java | 48 +- .../http2/client/FlowControlWindowsTest.java | 5 +- .../eclipse/jetty/http2/client/HTTP2Test.java | 58 +- .../jetty/http2/client/IdleTimeoutTest.java | 37 +- .../jetty/http2/client/InterleavingTest.java | 9 +- .../http2/client/MaxPushedStreamsTest.java | 9 +- .../jetty/http2/client/PrefaceTest.java | 7 +- .../jetty/http2/client/PriorityTest.java | 15 +- .../jetty/http2/client/ProxyProtocolTest.java | 6 +- .../eclipse/jetty/http2/client/ProxyTest.java | 6 +- .../http2/client/PushCacheFilterTest.java | 48 +- .../jetty/http2/client/RawHTTP2ProxyTest.java | 16 +- .../http2/client/SessionFailureTest.java | 3 +- .../http2/client/SmallThreadPoolLoadTest.java | 3 +- .../jetty/http2/client/StreamCloseTest.java | 27 +- .../jetty/http2/client/StreamCountTest.java | 10 +- .../jetty/http2/client/StreamResetTest.java | 37 +- .../jetty/http2/client/TrailersTest.java | 30 +- .../org/eclipse/jetty/http2/HTTP2Stream.java | 4 +- .../http2/frames/ContinuationParseTest.java | 4 +- .../frames/HeadersGenerateParseTest.java | 6 +- .../frames/PushPromiseGenerateParseTest.java | 6 +- .../jetty/http2/hpack/MetaDataBuilder.java | 10 +- .../jetty/http2/hpack/HpackEncoderTest.java | 11 +- .../jetty/http2/hpack/HpackPerfTest.java | 3 +- .../eclipse/jetty/http2/hpack/HpackTest.java | 105 +-- .../client/http/HttpReceiverOverHTTP2.java | 6 +- .../client/http/HttpSenderOverHTTP2.java | 14 +- .../http2/client/http/ContentLengthTest.java | 8 +- .../HttpClientTransportOverHTTP2Test.java | 12 +- .../client/http/PushedResourcesTest.java | 5 +- .../client/http/RequestTrailersTest.java | 14 +- .../client/http/ResponseTrailerTest.java | 3 +- .../server/HTTP2CServerConnectionFactory.java | 4 +- .../http2/server/HTTP2ServerConnection.java | 4 +- .../http2/server/HttpChannelOverHTTP2.java | 8 +- .../http2/server/HttpTransportOverHTTP2.java | 18 +- .../http2/server/AbstractServerTest.java | 4 +- .../eclipse/jetty/http2/server/CloseTest.java | 13 +- .../jetty/http2/server/HTTP2CServerTest.java | 5 +- .../jetty/http2/server/HTTP2ServerTest.java | 25 +- .../ForwardedSchemeHeaderRuleTest.java | 11 +- .../rewrite/handler/MsieSslRuleTest.java | 135 ++-- .../rewrite/handler/PatternRuleTest.java | 2 +- .../rewrite/handler/RewriteHandlerTest.java | 17 +- .../handler/RewritePatternRuleTest.java | 7 +- .../rewrite/handler/RewriteRegexRuleTest.java | 8 +- .../rewrite/handler/ValidUrlRuleTest.java | 13 +- .../handler/VirtualHostRuleContainerTest.java | 37 +- .../jetty/security/DataConstraintsTest.java | 3 +- .../SpnegoAuthenticatorTest.java | 12 +- .../jetty/server/ConnectionFactory.java | 4 +- .../jetty/server/CustomRequestLog.java | 8 +- .../server/ForwardedRequestCustomizer.java | 9 +- .../org/eclipse/jetty/server/HttpChannel.java | 7 +- .../jetty/server/HttpChannelOverHttp.java | 439 +++++------ .../eclipse/jetty/server/PushBuilderImpl.java | 6 +- .../org/eclipse/jetty/server/Request.java | 146 ++-- .../eclipse/jetty/server/ResourceService.java | 4 +- .../org/eclipse/jetty/server/Response.java | 18 +- .../java/org/eclipse/jetty/server/Server.java | 29 +- .../jetty/server/handler/ContextHandler.java | 14 +- .../jetty/server/handler/ErrorHandler.java | 7 +- .../server/handler/gzip/GzipHandler.java | 6 +- .../gzip/GzipHttpOutputInterceptor.java | 4 +- .../jetty/server/PartialRFC2616Test.java | 30 +- .../eclipse/jetty/server/ResponseTest.java | 2 +- .../core/client/ClientUpgradeRequest.java | 6 +- .../core/client/HttpUpgraderOverHTTP.java | 6 +- .../server/internal/RFC6455Handshaker.java | 4 +- .../core/WebSocketNegotiationTest.java | 8 +- .../jetty/websocket/core/WebSocketTester.java | 21 +- .../PerMessageDeflaterBufferSizeTest.java | 18 +- .../client/internal/JsrUpgradeListener.java | 6 +- .../websocket/javax/tests/NetworkFuzzer.java | 4 +- .../impl/JettyClientUpgradeRequest.java | 6 +- .../eclipse/jetty/http/tools/HttpTester.java | 4 +- .../matchers/HttpFieldsMatchersTest.java | 26 +- .../jetty/http/client/HttpTrailersTest.java | 24 +- .../client/ProxyWithDynamicTransportTest.java | 5 +- .../jetty/test/rfcs/RFC2616BaseTest.java | 19 +- .../jetty/test/webapp/HTTP1Servlet.java | 3 +- 132 files changed, 2273 insertions(+), 2167 deletions(-) delete mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java create mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java index 683a1905776f..b80dfbe308a4 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -79,7 +79,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java index e16a401ca90d..ad4ed1ac9278 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -80,7 +80,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java index 51c996fdf3ff..4421bc43b16a 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -79,7 +79,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java index 0de7d0121a38..8e49f2d1a555 100644 --- a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java @@ -26,7 +26,7 @@ import org.conscrypt.Conscrypt; import org.conscrypt.OpenSSLProvider; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -74,7 +74,7 @@ public void testConscryptHTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFields requestFields = new HttpFields(); + HttpFieldsBuilder requestFields = HttpFields.from(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); diff --git a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java index 00a25af7d06c..c8e7ec4cc83c 100644 --- a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java @@ -23,7 +23,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -63,7 +63,7 @@ public void testJDK9HTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFields requestFields = new HttpFields(); + HttpFieldsBuilder requestFields = HttpFields.from(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 6c587d11f728..3e08851494fb 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -30,7 +30,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.util.BytesRequestContent; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.util.HttpCookieStore; @@ -148,7 +148,7 @@ protected void normalizeRequest(Request request) // If we are HTTP 1.1, add the Host header HttpVersion version = request.getVersion(); - HttpFields headers = request.getHeaders(); + HttpFieldsBuilder headers = request.getHeaders(); if (version.getVersion() <= 11) { if (!headers.contains(HttpHeader.HOST.asString())) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java index 471f6e5f03eb..74524d91dfc6 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; public class HttpContentResponse implements ContentResponse @@ -75,7 +75,7 @@ public String getReason() } @Override - public HttpFields getHeaders() + public HttpFieldsBuilder getHeaders() { return response.getHeaders(); } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java index 92ec7e7ae8b2..e018476142ae 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java @@ -54,6 +54,7 @@ import org.eclipse.jetty.client.util.PathRequestContent; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -64,7 +65,7 @@ public class HttpRequest implements Request { private static final URI NULL_URI = URI.create("null:0"); - private final HttpFields headers = new HttpFields(); + private final HttpFieldsBuilder headers = HttpFields.empty(); private final Fields params = new Fields(true); private final List responseListeners = new ArrayList<>(); private final AtomicReference aborted = new AtomicReference<>(); @@ -353,7 +354,7 @@ public Map getAttributes() } @Override - public HttpFields getHeaders() + public HttpFieldsBuilder getHeaders() { return headers; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index fabb277bd443..bcd1c20408a0 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -25,17 +25,18 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; public class HttpResponse implements Response { - private final HttpFields headers = new HttpFields(); + private final HttpFieldsBuilder headers = HttpFields.empty(); private final Request request; private final List listeners; private HttpVersion version; private int status; private String reason; - private HttpFields trailers; + private HttpFieldsBuilder trailers; public HttpResponse(Request request, List listeners) { @@ -86,7 +87,7 @@ public HttpResponse reason(String reason) } @Override - public HttpFields getHeaders() + public HttpFieldsBuilder getHeaders() { return headers; } @@ -103,7 +104,7 @@ public List getListeners(Class type) return result; } - public HttpFields getTrailers() + public HttpFieldsBuilder getTrailers() { return trailers; } @@ -111,7 +112,7 @@ public HttpFields getTrailers() public HttpResponse trailer(HttpField trailer) { if (trailers == null) - trailers = new HttpFields(); + trailers = HttpFields.empty(); trailers.add(trailer); return this; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java index 53e67aab4f41..3d83ec94dcd0 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.util.InputStreamResponseListener; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -150,7 +150,7 @@ public interface Request /** * @return the headers of this request */ - HttpFields getHeaders(); + HttpFieldsBuilder getHeaders(); /** * @param name the name of the header diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java index 9c830cb1904e..14c91e1b5cb1 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.util.Callback; @@ -72,7 +72,7 @@ public interface Response /** * @return the headers of this response */ - HttpFields getHeaders(); + HttpFieldsBuilder getHeaders(); /** * Attempts to abort the receive of this response. diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java index 871c6d7f382f..fd416cdc3d31 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java @@ -24,7 +24,7 @@ import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -99,7 +99,7 @@ public void exchangeTerminated(HttpExchange exchange, Result result) super.exchangeTerminated(exchange, result); Response response = result.getResponse(); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); String closeReason = null; if (result.isFailed()) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java index 36f5271ea774..15f04ddbc5e0 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java @@ -78,8 +78,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool String query = request.getQuery(); if (query != null) path += "?" + query; - metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength); - metaData.setTrailerSupplier(request.getTrailers()); + metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength, request.getTrailers()); if (LOG.isDebugEnabled()) LOG.debug("Sending headers with content {} last={} for {}", BufferUtil.toDetailString(contentBuffer), lastContent, exchange.getRequest()); headersCallback.iterate(); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java index a605b5057ad9..17615c7aed10 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response.Listener; import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.util.BufferUtil; @@ -74,7 +74,7 @@ public void onHeaders(Response response) super.onHeaders(response); Request request = response.getRequest(); - HttpFields headers = response.getHeaders(); + HttpFieldsBuilder headers = response.getHeaders(); long length = headers.getLongField(HttpHeader.CONTENT_LENGTH.asString()); if (HttpMethod.HEAD.is(request.getMethod())) length = 0; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java index 8f40c1217ad0..14cc3366e405 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.client.Synchronizable; import org.eclipse.jetty.client.api.ContentProvider; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.util.Callback; @@ -129,7 +129,7 @@ private static String makeBoundary() * @param content the part content * @param fields the headers associated with this part */ - public void addFieldPart(String name, ContentProvider content, HttpFields fields) + public void addFieldPart(String name, ContentProvider content, HttpFieldsBuilder fields) { addPart(new Part(name, null, "text/plain", content, fields)); } @@ -150,7 +150,7 @@ public void addFieldPart(String name, ContentProvider content, HttpFields fields * @param content the part content * @param fields the headers associated with this part */ - public void addFilePart(String name, String fileName, ContentProvider content, HttpFields fields) + public void addFilePart(String name, String fileName, ContentProvider content, HttpFieldsBuilder fields) { addPart(new Part(name, fileName, "application/octet-stream", content, fields)); } @@ -222,11 +222,11 @@ private static class Part private final String fileName; private final String contentType; private final ContentProvider content; - private final HttpFields fields; + private final HttpFieldsBuilder fields; private final ByteBuffer headers; private final long length; - private Part(String name, String fileName, String contentType, ContentProvider content, HttpFields fields) + private Part(String name, String fileName, String contentType, ContentProvider content, HttpFieldsBuilder fields) { this.name = name; this.fileName = fileName; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java index 7acfdb20c895..f720dfd31b38 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java @@ -30,7 +30,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.util.Callback; @@ -145,7 +145,7 @@ public void fail(Throwable failure) * @param content the part content * @param fields the headers associated with this part */ - public void addFieldPart(String name, Request.Content content, HttpFields fields) + public void addFieldPart(String name, Request.Content content, HttpFieldsBuilder fields) { addPart(new Part(name, null, content, fields)); } @@ -164,7 +164,7 @@ public void addFieldPart(String name, Request.Content content, HttpFields fields * @param content the part content * @param fields the headers associated with this part */ - public void addFilePart(String name, String fileName, Request.Content content, HttpFields fields) + public void addFilePart(String name, String fileName, Request.Content content, HttpFieldsBuilder fields) { addPart(new Part(name, fileName, content, fields)); } @@ -215,11 +215,11 @@ private static class Part private final String name; private final String fileName; private final Request.Content content; - private final HttpFields fields; + private final HttpFieldsBuilder fields; private final ByteBuffer headers; private final long length; - private Part(String name, String fileName, Request.Content content, HttpFields fields) + private Part(String name, String fileName, Request.Content content, HttpFieldsBuilder fields) { this.name = name; this.fileName = fileName; diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java index 551f1e61c737..067572af8f8d 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java @@ -37,7 +37,7 @@ import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpCompliance; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.ByteArrayEndPoint; @@ -122,7 +122,7 @@ public void testReceiveNoResponseContent(HttpCompliance compliance) throws Excep assertEquals(200, response.getStatus()); assertEquals("OK", response.getReason()); assertSame(HttpVersion.HTTP_1_1, response.getVersion()); - HttpFields headers = response.getHeaders(); + HttpFieldsBuilder headers = response.getHeaders(); assertNotNull(headers); assertEquals(1, headers.size()); assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH)); @@ -148,7 +148,7 @@ public void testReceiveResponseContent(HttpCompliance compliance) throws Excepti assertEquals(200, response.getStatus()); assertEquals("OK", response.getReason()); assertSame(HttpVersion.HTTP_1_1, response.getVersion()); - HttpFields headers = response.getHeaders(); + HttpFieldsBuilder headers = response.getHeaders(); assertNotNull(headers); assertEquals(1, headers.size()); assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH)); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java index 947fce50d171..998ddadf1eb1 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java @@ -44,6 +44,7 @@ import org.eclipse.jetty.client.AbstractHttpClientServerTest; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.server.Request; @@ -144,7 +145,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put(HttpHeader.CONTENT_TYPE, "text/plain;charset=" + encoding.name()); BytesRequestContent content = new BytesRequestContent(value.getBytes(encoding)); multiPart.addFieldPart(name, content, fields); @@ -240,7 +241,7 @@ public void close() throws IOException closeLatch.countDown(); } }); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put(HttpHeader.CONTENT_TYPE, contentType); multiPart.addFilePart(name, fileName, content, fields); multiPart.close(); @@ -354,7 +355,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put(headerName, headerValue); multiPart.addFieldPart(field, new StringRequestContent(value, encoding), fields); multiPart.addFilePart(fileField, tmpPath.getFileName().toString(), new PathRequestContent(tmpPath), null); diff --git a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java index cd32db6cd052..daadb8cf901c 100644 --- a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java +++ b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java @@ -25,7 +25,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -48,7 +48,7 @@ public void dataDemanded() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index f15637ad8e5b..f1fda887f29c 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -26,7 +26,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -147,7 +147,7 @@ public void newStream() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); // The request metadata with method, URI and headers. @@ -172,7 +172,7 @@ public void newStreamWithData() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.CONTENT_TYPE, "application/json"); // The request metadata with method, URI and headers. @@ -213,7 +213,7 @@ public void responseListener() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -266,7 +266,7 @@ public void reset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -296,7 +296,7 @@ public void push() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -313,7 +313,7 @@ public Stream.Listener onPush(Stream pushedStream, PushPromiseFrame frame) // The pushed "request" URI. HttpURI pushedURI = pushedRequest.getURI(); // The pushed "request" headers. - HttpFields pushedRequestHeaders = pushedRequest.getFields(); + HttpFieldsBuilder pushedRequestHeaders = pushedRequest.getFields(); // If needed, retrieve the primary stream that triggered the push. Stream primaryStream = pushedStream.getSession().getStream(frame.getStreamId()); @@ -330,7 +330,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (metaData.isResponse()) { // The pushed "response" headers. - HttpFields pushedResponseHeaders = metaData.getFields(); + HttpFieldsBuilder pushedResponseHeaders = metaData.getFields(); } } @@ -358,7 +358,7 @@ public void pushReset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = new HttpFields(); + HttpFieldsBuilder requestHeaders = HttpFields.from(); requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java index 5b6658f76a3e..352c41aae629 100644 --- a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java @@ -23,7 +23,6 @@ import java.util.HashMap; import java.util.Map; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -202,7 +201,7 @@ private void respond(Stream stream, MetaData.Request request) // Prepare the response HEADERS frame. // The response HTTP status and HTTP headers. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); if (HttpMethod.GET.is(request.getMethod())) { @@ -296,13 +295,13 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // Push the favicon. HttpURI pushedURI = new HttpURI(request.getURI()); pushedURI.setPath("/favicon.ico"); - MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.from()); PushPromiseFrame promiseFrame = new PushPromiseFrame(stream.getId(), 0, pushedRequest); stream.push(promiseFrame, new Stream.Listener.Adapter()) .thenCompose(pushedStream -> { // Send the favicon "response". - MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); return pushedStream.headers(new HeadersFrame(pushedStream.getId(), pushedResponse, null, false)) .thenCompose(pushed -> pushed.data(new DataFrame(pushed.getId(), faviconBuffer, true))); }); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java index 61c8cd250332..702003c00332 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.fcgi.generator.Flusher; import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.IdleTimeout; import org.eclipse.jetty.util.Callback; @@ -150,7 +150,7 @@ public void exchangeTerminated(HttpExchange exchange, Result result) { super.exchangeTerminated(exchange, result); idle.onClose(); - HttpFields responseHeaders = result.getResponse().getHeaders(); + HttpFieldsBuilder responseHeaders = result.getResponse().getHeaders(); if (result.isFailed()) connection.close(result.getFailure()); else if (!connection.closeByHTTP(responseHeaders)) diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java index 4b8089b51d70..1d5c920ea3f9 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java @@ -32,7 +32,7 @@ import org.eclipse.jetty.client.api.Connection; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.fcgi.FCGI; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.ProcessorUtils; @@ -103,7 +103,7 @@ protected HttpConnectionOverFCGI newHttpConnection(EndPoint endPoint, HttpDestin return new HttpConnectionOverFCGI(endPoint, destination, promise); } - protected void customize(Request request, HttpFields fastCGIHeaders) + protected void customize(Request request, HttpFieldsBuilder fastCGIHeaders) { fastCGIHeaders.put(FCGI.Headers.DOCUMENT_ROOT, getScriptRoot()); } diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java index c4720e323187..2d6980ab3df3 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java @@ -43,7 +43,7 @@ import org.eclipse.jetty.fcgi.generator.Flusher; import org.eclipse.jetty.fcgi.parser.ClientParser; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.io.AbstractConnection; @@ -264,7 +264,7 @@ public boolean isClosed() return closed.get(); } - protected boolean closeByHTTP(HttpFields fields) + protected boolean closeByHTTP(HttpFieldsBuilder fields) { if (!fields.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString())) return false; diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index aed9d0c96e25..7017a820e2cc 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -31,7 +31,7 @@ import org.eclipse.jetty.fcgi.generator.ClientGenerator; import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Jetty; @@ -59,12 +59,12 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { Request request = exchange.getRequest(); // Copy the request headers to be able to convert them properly - HttpFields headers = new HttpFields(); + HttpFieldsBuilder headers = HttpFields.from(); for (HttpField field : request.getHeaders()) { headers.put(field); } - HttpFields fcgiHeaders = new HttpFields(); + HttpFieldsBuilder fcgiHeaders = HttpFields.from(); // FastCGI headers based on the URI URI uri = request.getURI(); @@ -74,12 +74,12 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool fcgiHeaders.put(FCGI.Headers.QUERY_STRING, query == null ? "" : query); // FastCGI headers based on HTTP headers - HttpField httpField = headers.remove(HttpHeader.AUTHORIZATION); + HttpField httpField = headers.getAndRemove(HttpHeader.AUTHORIZATION); if (httpField != null) fcgiHeaders.put(FCGI.Headers.AUTH_TYPE, httpField.getValue()); - httpField = headers.remove(HttpHeader.CONTENT_LENGTH); + httpField = headers.getAndRemove(HttpHeader.CONTENT_LENGTH); fcgiHeaders.put(FCGI.Headers.CONTENT_LENGTH, httpField == null ? "" : httpField.getValue()); - httpField = headers.remove(HttpHeader.CONTENT_TYPE); + httpField = headers.getAndRemove(HttpHeader.CONTENT_TYPE); fcgiHeaders.put(FCGI.Headers.CONTENT_TYPE, httpField == null ? "" : httpField.getValue()); // FastCGI headers that are not based on HTTP headers nor URI diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java index 1bddc5aba68e..e80c63349150 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; @@ -48,7 +48,7 @@ public ClientGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffe super(byteBufferPool, useDirectByteBuffers); } - public Result generateRequestHeaders(int request, HttpFields fields, Callback callback) + public Result generateRequestHeaders(int request, HttpFieldsBuilder fields, Callback callback) { request &= 0xFF_FF; diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java index 59562fa2cc90..fd5a50b0d518 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.BufferUtil; @@ -51,7 +51,7 @@ public ServerGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffe this.sendStatus200 = sendStatus200; } - public Result generateResponseHeaders(int request, int code, String reason, HttpFields fields, Callback callback) + public Result generateResponseHeaders(int request, int code, String reason, HttpFieldsBuilder fields, Callback callback) { request &= 0xFF_FF; diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index ade1a39b03c7..e0635f42c05c 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; @@ -84,7 +84,7 @@ protected void end(int request) private static class ResponseParser implements HttpParser.ResponseHandler { - private final HttpFields fields = new HttpFields(); + private final HttpFieldsBuilder fields = HttpFields.from(); private ClientParser.Listener listener; private final int request; private final FCGIHttpParser httpParser; @@ -227,7 +227,7 @@ private void notifyHeader(HttpField httpField) } } - private void notifyHeaders(HttpFields fields) + private void notifyHeaders(HttpFieldsBuilder fields) { if (fields != null) { diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java index 3900eadef188..576146e4cb61 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.fcgi.parser.ServerParser; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.junit.jupiter.api.Test; @@ -38,7 +38,7 @@ public class ClientGeneratorTest @Test public void testGenerateRequestHeaders() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); // Short name, short value final String shortShortName = "REQUEST_METHOD"; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java index 9238a48eef82..c103858ea049 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.fcgi.generator.ServerGenerator; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.junit.jupiter.api.Test; @@ -42,7 +42,7 @@ public class ClientParserTest public void testParseResponseHeaders() throws Exception { final int id = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); final int statusCode = 200; final String statusMessage = "OK"; @@ -112,7 +112,7 @@ public boolean onHeaders(int request) public void testParseNoResponseContent() throws Exception { final int id = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Content-Length", "0"); ByteBufferPool byteBufferPool = new MappedByteBufferPool(); @@ -157,7 +157,7 @@ public void onEnd(int request) public void testParseSmallResponseContent() throws Exception { final int id = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); ByteBuffer content = ByteBuffer.wrap(new byte[1024]); final int contentLength = content.remaining(); @@ -210,7 +210,7 @@ public void onEnd(int request) public void testParseLargeResponseContent() throws Exception { final int id = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); ByteBuffer content = ByteBuffer.wrap(new byte[128 * 1024]); final int contentLength = content.remaining(); diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java index ddba3fa5f70f..c1d7bb95ef46 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -43,7 +43,7 @@ public class HttpChannelOverFCGI extends HttpChannel { private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverFCGI.class); - private final HttpFields fields = new HttpFields(); + private final HttpFieldsBuilder fields = HttpFields.from(); private final Dispatcher dispatcher; private String method; private String path; diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java index 56eaeb6e656e..fcf9ecfd1c0a 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java @@ -38,7 +38,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.fcgi.client.http.HttpClientTransportOverFCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.proxy.AsyncProxyServlet; @@ -209,7 +209,7 @@ protected void sendProxyRequest(HttpServletRequest request, HttpServletResponse super.sendProxyRequest(request, proxyResponse, proxyRequest); } - protected void customizeFastCGIHeaders(Request proxyRequest, HttpFields fastCGIHeaders) + protected void customizeFastCGIHeaders(Request proxyRequest, HttpFieldsBuilder fastCGIHeaders) { for (String envName : fcgiEnvNames) { @@ -271,7 +271,7 @@ private ProxyHttpClientTransportOverFCGI(int selectors, String scriptRoot) } @Override - protected void customize(Request request, HttpFields fastCGIHeaders) + protected void customize(Request request, HttpFieldsBuilder fastCGIHeaders) { super.customize(request, fastCGIHeaders); customizeFastCGIHeaders(request, fastCGIHeaders); 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 3cea85380d82..ec9bf58c8147 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 @@ -62,43 +62,76 @@ public HttpField(String name, String value) this(HttpHeader.CACHE.get(name), name, value); } - public HttpHeader getHeader() + /** + * Get field value parameters. Some field values can have parameters. This method separates the + * value from the parameters and optionally populates a map with the parameters. For example: + * + *
+     *
+     * FieldName : Value ; param1=val1 ; param2=val2
+     *
+     * 
+ * + * @param value The Field value, possibly with parameters. + * @param parameters A map to populate with the parameters, or null + * @return The value. + */ + public static String getValueParameters(String value, Map parameters) { - return _header; - } + if (value == null) + return null; - public String getName() - { - return _name; - } + int i = value.indexOf(';'); + if (i < 0) + return value; + if (parameters == null) + return value.substring(0, i).trim(); - public String getLowerCaseName() - { - return _header != null ? _header.lowerCaseName() : StringUtil.asciiToLowerCase(_name); - } + StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); + while (tok1.hasMoreTokens()) + { + String token = tok1.nextToken(); + StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); + if (tok2.hasMoreTokens()) + { + String paramName = tok2.nextToken(); + String paramVal = null; + if (tok2.hasMoreTokens()) + paramVal = tok2.nextToken(); + parameters.put(paramName, paramVal); + } + } - public String getValue() - { - return _value; + return value.substring(0, i).trim(); } - public int getIntValue() + /** + * Get field value without parameters. Some field values can have parameters. This method separates the + * value from the parameters and optionally populates a map with the parameters. For example: + * + *
+     *
+     * FieldName : Value ; param1=val1 ; param2=val2
+     *
+     * 
+ * + * @param value The Field value, possibly with parameters. + * @return The value. + */ + public static String stripParameters(String value) { - return Integer.parseInt(_value); - } + if (value == null) + return null; - public long getLongValue() - { - return Long.parseLong(_value); + int i = value.indexOf(';'); + if (i < 0) + return value; + return value.substring(0, i).trim(); } - public String[] getValues() + public static String valueParameters(String value, Map parameters) { - if (_value == null) - return null; - - QuotedCSV list = new QuotedCSV(false, _value); - return list.getValues().toArray(new String[list.size()]); + return getValueParameters(value, parameters); } /** @@ -278,10 +311,66 @@ else if (c != '0' && c != '.') } @Override - public String toString() + public boolean equals(Object o) { - String v = getValue(); - return getName() + ": " + (v == null ? "" : v); + if (o == this) + return true; + if (!(o instanceof HttpField)) + return false; + HttpField field = (HttpField)o; + if (_header != field.getHeader()) + return false; + if (!_name.equalsIgnoreCase(field.getName())) + return false; + return Objects.equals(_value, field.getValue()); + } + + public HttpHeader getHeader() + { + return _header; + } + + public int getIntValue() + { + return Integer.parseInt(_value); + } + + public long getLongValue() + { + return Long.parseLong(_value); + } + + public String getLowerCaseName() + { + return _header != null ? _header.lowerCaseName() : StringUtil.asciiToLowerCase(_name); + } + + public String getName() + { + return _name; + } + + public String getValue() + { + return _value; + } + + public String[] getValues() + { + if (_value == null) + return null; + + QuotedCSV list = new QuotedCSV(false, _value); + return list.getValues().toArray(new String[list.size()]); + } + + @Override + public int hashCode() + { + int vhc = Objects.hashCode(_value); + if (_header == null) + return vhc ^ nameHashCode(); + return vhc ^ _header.hashCode(); } public boolean isSameName(HttpField field) @@ -295,6 +384,13 @@ public boolean isSameName(HttpField field) return _name.equalsIgnoreCase(field.getName()); } + @Override + public String toString() + { + String v = getValue(); + return getName() + ": " + (v == null ? "" : v); + } + private int nameHashCode() { int h = this.hash; @@ -315,30 +411,6 @@ private int nameHashCode() return h; } - @Override - public int hashCode() - { - int vhc = Objects.hashCode(_value); - if (_header == null) - return vhc ^ nameHashCode(); - return vhc ^ _header.hashCode(); - } - - @Override - public boolean equals(Object o) - { - if (o == this) - return true; - if (!(o instanceof HttpField)) - return false; - HttpField field = (HttpField)o; - if (_header != field.getHeader()) - return false; - if (!_name.equalsIgnoreCase(field.getName())) - return false; - return Objects.equals(_value, field.getValue()); - } - public static class IntValueHttpField extends HttpField { private final int _int; @@ -414,47 +486,4 @@ public long getLongValue() return _long; } } - - /** - * Get field value parameters. Some field values can have parameters. This method separates the - * value from the parameters and optionally populates a map with the parameters. For example: - * - *
-     *
-     * FieldName : Value ; param1=val1 ; param2=val2
-     *
-     * 
- * - * @param value The Field value, possibly with parameters. - * @param parameters A map to populate with the parameters, or null - * @return The value. - */ - public static String getValueParameters(String value, Map parameters) - { - if (value == null) - return null; - - int i = value.indexOf(';'); - if (i < 0) - return value; - if (parameters == null) - return value.substring(0, i).trim(); - - StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true); - while (tok1.hasMoreTokens()) - { - String token = tok1.nextToken(); - StringTokenizer tok2 = new QuotedStringTokenizer(token, "= "); - if (tok2.hasMoreTokens()) - { - String paramName = tok2.nextToken(); - String paramVal = null; - if (tok2.hasMoreTokens()) - paramVal = tok2.nextToken(); - parameters.put(paramName, paramVal); - } - } - - return value.substring(0, i).trim(); - } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java deleted file mode 100644 index a5194ebd1b65..000000000000 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldList.java +++ /dev/null @@ -1,470 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.http; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.function.ToIntFunction; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Interface that represents readonly list of {@link HttpField}s. - */ -public interface HttpFieldList extends Iterable -{ - default int asHashCode() - { - int hash = 0; - for (HttpField f : this) - hash ^= f.hashCode(); - return hash; - } - - HttpFieldList asImmutable(); - - default String asString() - { - StringBuilder buffer = new StringBuilder(); - for (HttpField field : this) - { - if (field != null) - { - String tmp = field.getName(); - if (tmp != null) - buffer.append(tmp); - buffer.append(": "); - tmp = field.getValue(); - if (tmp != null) - buffer.append(tmp); - buffer.append("\r\n"); - } - } - buffer.append("\r\n"); - return buffer.toString(); - } - - default boolean contains(HttpField field) - { - for (HttpField f : this) - { - if (f.isSameName(field) && (f.equals(field) || f.contains(field.getValue()))) - return true; - } - return false; - } - - default boolean contains(HttpHeader header, String value) - { - for (HttpField f : this) - { - if (f.getHeader() == header && f.contains(value)) - return true; - } - return false; - } - - default boolean contains(String name, String value) - { - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name) && f.contains(value)) - return true; - } - return false; - } - - default boolean contains(HttpHeader header) - { - for (HttpField f : this) - { - if (f.getHeader() == header) - return true; - } - return false; - } - - default boolean contains(EnumSet headers) - { - for (HttpField f : this) - { - if (headers.contains(f.getHeader())) - return true; - } - return false; - } - - default boolean contains(String name) - { - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - return true; - } - return false; - } - - @Deprecated - default boolean containsKey(String name) - { - return contains(name); - } - - default String get(HttpHeader header) - { - for (HttpField f : this) - { - if (f.getHeader() == header) - return f.getValue(); - } - return null; - } - - default String get(String header) - { - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(header)) - return f.getValue(); - } - return null; - } - - /** - * Get multiple field values of the same name, split - * as a {@link QuotedCSV} - * - * @param header The header - * @param keepQuotes True if the fields are kept quoted - * @return List the values with OWS stripped - */ - default List getCSV(HttpHeader header, boolean keepQuotes) - { - QuotedCSV values = null; - for (HttpField f : this) - { - if (f.getHeader() == header) - { - if (values == null) - values = new QuotedCSV(keepQuotes); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); - } - - /** - * Get multiple field values of the same name - * as a {@link QuotedCSV} - * - * @param name the case-insensitive field name - * @param keepQuotes True if the fields are kept quoted - * @return List the values with OWS stripped - */ - default List getCSV(String name, boolean keepQuotes) - { - QuotedCSV values = null; - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - { - if (values == null) - values = new QuotedCSV(keepQuotes); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); - } - - /** - * 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. - * - * @param name the case-insensitive field name - * @return the value of the field as a number of milliseconds since unix epoch - */ - default long getDateField(String name) - { - HttpField field = getField(name); - if (field == null) - return -1; - - String val = HttpField.getValueParameters(field.getValue(), null); - if (val == null) - return -1; - - final long date = DateParser.parseDate(val); - if (date == -1) - throw new IllegalArgumentException("Cannot convert date: " + val); - return date; - } - - /** - * Get a Field by index. - * - * @param index the field index - * @return A Field value or null if the Field value has not been set - */ - HttpField getField(int index); - - default HttpField getField(HttpHeader header) - { - for (HttpField f : this) - { - if (f.getHeader() == header) - return f; - } - return null; - } - - default HttpField getField(String name) - { - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - return f; - } - return null; - } - - /** - * Get enumeration of header _names. Returns an enumeration of strings representing the header - * _names for this request. - * - * @return an enumeration of field names - */ - default Enumeration getFieldNames() - { - return Collections.enumeration(getFieldNamesCollection()); - } - - /** - * Get Set of header names. - * - * @return the unique set of field names. - */ - default Set getFieldNamesCollection() - { - return stream().map(HttpField::getName).collect(Collectors.toSet()); - } - - /** - * Get multiple fields of the same header - * - * @param header the header - * @return List the fields - */ - default List getFields(HttpHeader header) - { - return stream().filter(f -> f.getHeader().equals(header)).collect(Collectors.toList()); - } - - /** - * 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 - * @return the value of the field as a long - * @throws NumberFormatException If bad long found - */ - default long getLongField(String name) throws NumberFormatException - { - HttpField field = getField(name); - return field == null ? -1L : field.getLongValue(); - } - - /** - * 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 header the header type - * @return the value of the field as a long - * @throws NumberFormatException If bad long found - */ - default long getLongField(HttpHeader header) throws NumberFormatException - { - HttpField field = getField(header); - return field == null ? -1L : field.getLongValue(); - } - - /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} - * - * @param header The header - * @return List the values in quality order with the q param and OWS stripped - */ - default List getQualityCSV(HttpHeader header) - { - return getQualityCSV(header, null); - } - - /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} - * - * @param header The header - * @param secondaryOrdering Function to apply an ordering other than specified by quality - * @return List the values in quality order with the q param and OWS stripped - */ - default List getQualityCSV(HttpHeader header, ToIntFunction secondaryOrdering) - { - QuotedQualityCSV values = null; - for (HttpField f : this) - { - if (f.getHeader() == header) - { - if (values == null) - values = new QuotedQualityCSV(secondaryOrdering); - values.addValue(f.getValue()); - } - } - - return values == null ? Collections.emptyList() : values.getValues(); - } - - /** - * Get multiple field values of the same name, split and - * sorted as a {@link QuotedQualityCSV} - * - * @param name the case-insensitive field name - * @return List the values in quality order with the q param and OWS stripped - */ - default List getQualityCSV(String name) - { - QuotedQualityCSV values = null; - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - { - if (values == null) - values = new QuotedQualityCSV(); - values.addValue(f.getValue()); - } - } - return values == null ? Collections.emptyList() : values.getValues(); - } - - /** - * Get multi headers - * - * @param name the case-insensitive field name - * @return Enumeration of the values - */ - default Enumeration getValues(String name) - { - Iterator i = iterator(); - return new Enumeration<>() - { - HttpField _field; - - @Override - public boolean hasMoreElements() - { - if (_field != null) - return true; - while (i.hasNext()) - { - HttpField f = i.next(); - if (f.getName().equalsIgnoreCase(name) && f.getValue() != null) - { - _field = f; - return true; - } - } - return false; - } - - @Override - public String nextElement() - { - if (hasMoreElements()) - { - String value = _field.getValue(); - _field = null; - return value; - } - throw new NoSuchElementException(); - } - }; - } - - /** - * Get multiple field values of the same name - * - * @param header the header - * @return List the values - */ - default List getValuesList(HttpHeader header) - { - final List list = new ArrayList<>(); - for (HttpField f : this) - { - if (f.getHeader() == header) - list.add(f.getValue()); - } - return list; - } - - /** - * Get multiple header of the same name - * - * @param name the case-insensitive field name - * @return List the header values - */ - default List getValuesList(String name) - { - final List list = new ArrayList<>(); - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - list.add(f.getValue()); - } - return list; - } - - default boolean isEqualTo(HttpFieldList that) - { - if (size() != that.size()) - return false; - - // Order is not important, so we cannot rely on List.equals(). // TODO is this true? - loop: - for (HttpField fi : this) - { - for (HttpField fa : that) - { - if (fi.equals(fa)) - continue loop; - } - return false; - } - return true; - } - - int size(); - - Stream stream(); -} 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 49b97a155799..031812993b47 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 @@ -19,287 +19,238 @@ package org.eclipse.jetty.http; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; import java.util.Enumeration; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; -import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; import java.util.stream.Stream; /** - * HTTP Fields. A collection of HTTP header and or Trailer fields. - * - *

This class is not synchronized as it is expected that modifications will only be performed by a - * single thread. - * - *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + * Interface that represents readonly list of {@link HttpField}s. */ -public class HttpFields implements Iterable, HttpFieldList +public interface HttpFields extends Iterable { - ArrayList _fields; + HttpFields EMPTY = empty().asImmutable(); - /** - * Initialize an empty HttpFields. - */ - public HttpFields() + static HttpFieldsBuilder empty() { - this(16); // Based on small sample of Chrome requests. + return new HttpFieldsBuilder(); } - /** - * Initialize an empty HttpFields. - * - * @param capacity the capacity of the http fields - */ - public HttpFields(int capacity) + static HttpFieldsBuilder empty(int capacity) { - _fields = new ArrayList<>(capacity); + return new HttpFieldsBuilder(capacity); } - /** - * Initialize HttpFields from another. - * - * @param fields the fields to copy data from - */ - public HttpFields(HttpFieldList fields) + static HttpFieldsBuilder from(HttpFields fields) { - if (fields instanceof Immutable) - _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); - else if (fields instanceof HttpFields) - _fields = new ArrayList<>(((HttpFields)fields)._fields); - else - { - _fields = new ArrayList<>(fields.size() + 4); - for (HttpField f : fields) - _fields.add(f); - } + return new HttpFieldsBuilder(fields); } - /** - * Initialize HttpFields from another and replace a field - * - * @param fields the fields to copy data from - * @param putField the replacement field - */ - public HttpFields(HttpFieldList fields, HttpField putField) + static HttpFieldsBuilder from(HttpFields fields, HttpField replaceField) { - _fields = new ArrayList<>(fields.size() + 4); - boolean put = false; - for (HttpField f : fields) - { - if (putField.isSameName(f)) - { - if (!put) - _fields.add(putField); - put = true; - } - else - { - _fields.add(f); - } - } + return new HttpFieldsBuilder(fields, replaceField); } - /** - * Get field value without parameters. Some field values can have parameters. This method separates the - * value from the parameters and optionally populates a map with the parameters. For example: - * - *

-     *
-     * FieldName : Value ; param1=val1 ; param2=val2
-     *
-     * 
- * - * @param value The Field value, possibly with parameters. - * @return The value. - */ - public static String stripParameters(String value) + static HttpFieldsBuilder from(HttpFields fields, EnumSet removeFields) { - if (value == null) - return null; + return new HttpFieldsBuilder(fields, removeFields); + } - int i = value.indexOf(';'); - if (i < 0) - return value; - return value.substring(0, i).trim(); + default int asHashCode() + { + int hash = 0; + for (HttpField f : this) + hash ^= f.hashCode(); + return hash; } - public static String valueParameters(String value, Map parameters) + HttpFields asImmutable(); + + default HttpFieldsBuilder asMutable() { - return HttpField.getValueParameters(value, parameters); + return from(this); } - /** - * 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. - */ - public void add(String name, String value) + default String asString() { - if (value == null) - return; + StringBuilder buffer = new StringBuilder(); + for (HttpField field : this) + { + if (field != null) + { + String tmp = field.getName(); + if (tmp != null) + buffer.append(tmp); + buffer.append(": "); + tmp = field.getValue(); + if (tmp != null) + buffer.append(tmp); + buffer.append("\r\n"); + } + } + buffer.append("\r\n"); + return buffer.toString(); + } - HttpField field = new HttpField(name, value); - add(field); + default boolean contains(HttpField field) + { + for (HttpField f : this) + { + if (f.isSameName(field) && (f.equals(field) || f.contains(field.getValue()))) + return true; + } + return false; } - public void add(HttpHeader header, HttpHeaderValue value) + default boolean contains(HttpHeader header, String value) { - add(header, value.toString()); + for (HttpField f : this) + { + if (f.getHeader() == header && f.contains(value)) + return true; + } + return false; } - /** - * 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 header the header - * @param value the value of the field. - */ - public void add(HttpHeader header, String value) + default boolean contains(String name, String value) { - if (value == null) - throw new IllegalArgumentException("null value"); + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name) && f.contains(value)) + return true; + } + return false; + } - HttpField field = new HttpField(header, value); - add(field); + default boolean contains(HttpHeader header) + { + for (HttpField f : this) + { + if (f.getHeader() == header) + return true; + } + return false; } - public void add(HttpField field) + default boolean contains(EnumSet headers) { - if (field != null) - _fields.add(field); + for (HttpField f : this) + { + if (headers.contains(f.getHeader())) + return true; + } + return false; } - /** - * Add fields from another HttpFields instance. Single valued fields are replaced, while all - * others are added. - * - * @param fields the fields to add - */ - public void add(HttpFieldList fields) + default boolean contains(String name) { - // TODO is this any different to addAll? + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + return true; + } + return false; + } - if (fields == null) - return; + @Deprecated + default boolean containsKey(String name) + { + return contains(name); + } - _fields.ensureCapacity(size() + fields.size() + 4); - Enumeration e = fields.getFieldNames(); - while (e.hasMoreElements()) + default String get(HttpHeader header) + { + for (HttpField f : this) { - String name = e.nextElement(); - Enumeration values = fields.getValues(name); - while (values.hasMoreElements()) - { - add(name, values.nextElement()); - } + if (f.getHeader() == header) + return f.getValue(); } + return null; } - public void addAll(HttpFieldList fields) + default String get(String header) { - _fields.ensureCapacity(size() + fields.size() + 4); - for (HttpField f : fields) - _fields.add(f); + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(header)) + return f.getValue(); + } + return null; } /** - * Add comma separated values, but only if not already - * present. + * Get multiple field values of the same name, split + * as a {@link QuotedCSV} * - * @param header The header to add the value(s) to - * @param values The value(s) to add - * @return True if headers were modified + * @param header The header + * @param keepQuotes True if the fields are kept quoted + * @return List the values with OWS stripped */ - public boolean addCSV(HttpHeader header, String... values) + default List getCSV(HttpHeader header, boolean keepQuotes) { - // TODO is the javadoc right ? - QuotedCSV existing = null; + QuotedCSV values = null; for (HttpField f : this) { if (f.getHeader() == header) { - if (existing == null) - existing = new QuotedCSV(false); - existing.addValue(f.getValue()); + if (values == null) + values = new QuotedCSV(keepQuotes); + values.addValue(f.getValue()); } } - - String value = addCSV(existing, values); - if (value != null) - { - add(header, value); - return true; - } - return false; + return values == null ? Collections.emptyList() : values.getValues(); } /** - * Add comma separated values, but only if not already - * present. + * Get multiple field values of the same name + * as a {@link QuotedCSV} * - * @param name The header to add the value(s) to - * @param values The value(s) to add - * @return True if headers were modified + * @param name the case-insensitive field name + * @param keepQuotes True if the fields are kept quoted + * @return List the values with OWS stripped */ - public boolean addCSV(String name, String... values) + default List getCSV(String name, boolean keepQuotes) { - // TODO is the javadoc right ? - QuotedCSV existing = null; + QuotedCSV values = null; for (HttpField f : this) { if (f.getName().equalsIgnoreCase(name)) { - if (existing == null) - existing = new QuotedCSV(false); - existing.addValue(f.getValue()); + if (values == null) + values = new QuotedCSV(keepQuotes); + values.addValue(f.getValue()); } } - String value = addCSV(existing, values); - if (value != null) - { - add(name, value); - return true; - } - return false; + return values == null ? Collections.emptyList() : values.getValues(); } /** - * Sets the value of a date field. + * 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. * - * @param name the field name - * @param date the field date value + * @param name the case-insensitive field name + * @return the value of the field as a number of milliseconds since unix epoch */ - public void addDateField(String name, long date) - { - String d = DateGenerator.formatDate(date); - add(name, d); - } - - @Override - public HttpFieldList asImmutable() - { - return new HttpFields.Immutable(_fields.toArray(new HttpField[0])); - } - - public void clear() + default long getDateField(String name) { - _fields.clear(); - } + HttpField field = getField(name); + if (field == null) + return -1; - @Override - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof HttpFields)) - return false; + String val = HttpField.getValueParameters(field.getValue(), null); + if (val == null) + return -1; - return isEqualTo((HttpFieldList)o); + final long date = DateParser.parseDate(val); + if (date == -1) + throw new IllegalArgumentException("Cannot convert date: " + val); + return date; } /** @@ -308,319 +259,244 @@ public boolean equals(Object o) * @param index the field index * @return A Field value or null if the Field value has not been set */ - @Override - public HttpField getField(int index) - { - if (index >= size()) - throw new NoSuchElementException(); - return _fields.get(index); - } - - @Override - public int hashCode() - { - return asHashCode(); - } - - @Override - public Iterator iterator() - { - return _fields.iterator(); - } + HttpField getField(int index); - public ListIterator listIterator() + default HttpField getField(HttpHeader header) { - return _fields.listIterator(); - } - - public void put(HttpField field) - { - boolean put = false; - for (ListIterator i = listIterator(); i.hasNext();) + for (HttpField f : this) { - HttpField f = i.next(); - if (f.isSameName(field)) - { - if (put) - i.remove(); - else - { - i.set(field); - put = true; - } - } + if (f.getHeader() == header) + return f; } - if (!put) - add(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(String name, String value) - { - if (value == null) - remove(name); - else - put(new HttpField(name, value)); + return null; } - public void put(HttpHeader header, HttpHeaderValue value) + default HttpField getField(String name) { - put(header, value.toString()); + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + return f; + } + return null; } /** - * Set a field. + * Get enumeration of header _names. Returns an enumeration of strings representing the header + * _names for this request. * - * @param header the header name of the field - * @param value the value of the field. If null the field is cleared. + * @return an enumeration of field names */ - public void put(HttpHeader header, String value) + default Enumeration getFieldNames() { - if (value == null) - remove(header); - else - put(new HttpField(header, value)); + return Collections.enumeration(getFieldNamesCollection()); } /** - * Set a field. + * Get Set of header names. * - * @param name the name of the field - * @param list the List value of the field. If null the field is cleared. + * @return the unique set of field names. */ - public void put(String name, List list) + default Set getFieldNamesCollection() { - remove(name); - for (String v : list) - { - if (v != null) - add(name, v); - } + return stream().map(HttpField::getName).collect(Collectors.toSet()); } /** - * Sets the value of a date field. + * Get multiple fields of the same header * - * @param name the field name - * @param date the field date value + * @param header the header + * @return List the fields */ - public void putDateField(HttpHeader name, long date) + default List getFields(HttpHeader header) { - String d = DateGenerator.formatDate(date); - put(name, d); + return stream().filter(f -> f.getHeader().equals(header)).collect(Collectors.toList()); } /** - * Sets the value of a date field. + * 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 field name - * @param date the field date value + * @param name the case-insensitive field name + * @return the value of the field as a long + * @throws NumberFormatException If bad long found */ - public void putDateField(String name, long date) + default long getLongField(String name) throws NumberFormatException { - String d = DateGenerator.formatDate(date); - put(name, d); + HttpField field = getField(name); + return field == null ? -1L : field.getLongValue(); } /** - * Sets the value of an long field. + * 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 field name - * @param value the field long value + * @param header the header type + * @return the value of the field as a long + * @throws NumberFormatException If bad long found */ - public void putLongField(HttpHeader name, long value) + default long getLongField(HttpHeader header) throws NumberFormatException { - String v = Long.toString(value); - put(name, v); + HttpField field = getField(header); + return field == null ? -1L : field.getLongValue(); } /** - * Sets the value of an long field. + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} * - * @param name the field name - * @param value the field long value + * @param header The header + * @return List the values in quality order with the q param and OWS stripped */ - public void putLongField(String name, long value) + default List getQualityCSV(HttpHeader header) { - String v = Long.toString(value); - put(name, v); + return getQualityCSV(header, null); } /** - * Remove a field. + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} * - * @param name the field to remove - * @return the header that was removed + * @param header The header + * @param secondaryOrdering Function to apply an ordering other than specified by quality + * @return List the values in quality order with the q param and OWS stripped */ - public HttpField remove(HttpHeader name) + default List getQualityCSV(HttpHeader header, ToIntFunction secondaryOrdering) { - HttpField removed = null; - for (ListIterator i = listIterator(); i.hasNext();) + QuotedQualityCSV values = null; + for (HttpField f : this) { - HttpField f = i.next(); - if (f.getHeader() == name) + if (f.getHeader() == header) { - removed = f; - i.remove(); + if (values == null) + values = new QuotedQualityCSV(secondaryOrdering); + values.addValue(f.getValue()); } } - return removed; + + return values == null ? Collections.emptyList() : values.getValues(); } /** - * Remove a field. + * Get multiple field values of the same name, split and + * sorted as a {@link QuotedQualityCSV} * - * @param name the field to remove - * @return the header that was removed + * @param name the case-insensitive field name + * @return List the values in quality order with the q param and OWS stripped */ - public HttpField remove(String name) + default List getQualityCSV(String name) { - HttpField removed = null; - for (ListIterator i = listIterator(); i.hasNext();) + QuotedQualityCSV values = null; + for (HttpField f : this) { - HttpField f = i.next(); if (f.getName().equalsIgnoreCase(name)) { - removed = f; - i.remove(); + if (values == null) + values = new QuotedQualityCSV(); + values.addValue(f.getValue()); } } - return removed; + return values == null ? Collections.emptyList() : values.getValues(); } - public int size() - { - return _fields.size(); - } - - @Override - public Stream stream() - { - return _fields.stream(); - } - - @Override - public String toString() - { - return asString(); - } - - protected String addCSV(QuotedCSV existing, String... values) + /** + * Get multi headers + * + * @param name the case-insensitive field name + * @return Enumeration of the values + */ + default Enumeration getValues(String name) { - // remove any existing values from the new values - boolean add = true; - if (existing != null && !existing.isEmpty()) + Iterator i = iterator(); + return new Enumeration<>() { - add = false; + HttpField _field; - for (int i = values.length; i-- > 0; ) + @Override + public boolean hasMoreElements() { - String unquoted = QuotedCSV.unquote(values[i]); - if (existing.getValues().contains(unquoted)) - values[i] = null; - else - add = true; + if (_field != null) + return true; + while (i.hasNext()) + { + HttpField f = i.next(); + if (f.getName().equalsIgnoreCase(name) && f.getValue() != null) + { + _field = f; + return true; + } + } + return false; } - } - if (add) - { - StringBuilder value = new StringBuilder(); - for (String v : values) + @Override + public String nextElement() { - if (v == null) - continue; - if (value.length() > 0) - value.append(", "); - value.append(v); + if (hasMoreElements()) + { + String value = _field.getValue(); + _field = null; + return value; + } + throw new NoSuchElementException(); } - if (value.length() > 0) - return value.toString(); - } - - return null; + }; } /** - * HTTP Fields. A collection of HTTP header and or Trailer fields. - * - *

This class is not synchronized as it is expected that modifications will only be performed by a - * single thread. + * Get multiple field values of the same name * - *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + * @param header the header + * @return List the values */ - private static class Immutable implements HttpFieldList + default List getValuesList(HttpHeader header) { - private final HttpField[] _fields; - - /** - * Initialize HttpFields from copy. - * - * @param fields the fields to copy data from - */ - Immutable(HttpField[] fields) - { - _fields = fields; - } - - @Override - public HttpFieldList asImmutable() - { - return this; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof Immutable)) - return false; - - return isEqualTo((HttpFieldList)o); - } - - @Override - public HttpField getField(int index) + final List list = new ArrayList<>(); + for (HttpField f : this) { - if (index >= _fields.length) - throw new NoSuchElementException(); - return _fields[index]; + if (f.getHeader() == header) + list.add(f.getValue()); } + return list; + } - @Override - public int hashCode() + /** + * Get multiple header of the same name + * + * @param name the case-insensitive field name + * @return List the header values + */ + default List getValuesList(String name) + { + final List list = new ArrayList<>(); + for (HttpField f : this) { - return asHashCode(); + if (f.getName().equalsIgnoreCase(name)) + list.add(f.getValue()); } + return list; + } - @Override - public Iterator iterator() - { - return Arrays.stream(_fields).iterator(); - } + default boolean isEqualTo(HttpFields that) + { + if (size() != that.size()) + return false; - @Override - public int size() + // Order is not important, so we cannot rely on List.equals(). // TODO is this true? + loop: + for (HttpField fi : this) { - return _fields.length; + for (HttpField fa : that) + { + if (fi.equals(fa)) + continue loop; + } + return false; } + return true; + } - @Override - public Stream stream() - { - return Arrays.stream(_fields); - } + int size(); - @Override - public String toString() - { - return asString(); - } - } + Stream stream(); } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java new file mode 100644 index 000000000000..b951ff011782 --- /dev/null +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java @@ -0,0 +1,629 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.http; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; +import java.util.stream.Stream; + +/** + * HTTP Fields. A collection of HTTP header and or Trailer fields. + * + *

This class is not synchronized as it is expected that modifications will only be performed by a + * single thread. + * + *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + */ +public class HttpFieldsBuilder implements Iterable, HttpFields +{ + ArrayList _fields; + + /** + * Initialize an empty HttpFields. + */ + protected HttpFieldsBuilder() + { + this(16); // Based on small sample of Chrome requests. + } + + /** + * Initialize an empty HttpFields. + * + * @param capacity the capacity of the http fields + */ + HttpFieldsBuilder(int capacity) + { + _fields = new ArrayList<>(capacity); + } + + /** + * Initialize HttpFields from another. + * + * @param fields the fields to copy data from + */ + HttpFieldsBuilder(HttpFields fields) + { + if (fields instanceof Immutable) + _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); + else if (fields instanceof HttpFieldsBuilder) + _fields = new ArrayList<>(((HttpFieldsBuilder)fields)._fields); + else + { + _fields = new ArrayList<>(fields.size() + 4); + for (HttpField f : fields) + _fields.add(f); + } + } + + /** + * Initialize HttpFields from another and replace a field + * + * @param fields the fields to copy data from + * @param replaceField the replacement field + */ + HttpFieldsBuilder(HttpFields fields, HttpField replaceField) + { + _fields = new ArrayList<>(fields.size() + 4); + boolean put = false; + for (HttpField f : fields) + { + if (replaceField.isSameName(f)) + { + if (!put) + _fields.add(replaceField); + put = true; + } + else + { + _fields.add(f); + } + } + if (!put) + _fields.add(replaceField); + } + + /** + * Initialize HttpFields from another and remove fields + * + * @param fields the fields to copy data from + * @param removeFields the the fields to remove + */ + HttpFieldsBuilder(HttpFields fields, EnumSet removeFields) + { + _fields = new ArrayList<>(fields.size()); + for (HttpField f : fields) + { + if (f.getHeader() == null || removeFields.contains(f.getHeader())) + _fields.add(f); + } + } + + /** + * 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. + * @return this builder + */ + public HttpFieldsBuilder add(String name, String value) + { + if (value != null) + return add(new HttpField(name, value)); + return this; + } + + public HttpFieldsBuilder add(HttpHeader header, HttpHeaderValue value) + { + return add(header, value.toString()); + } + + /** + * 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 header the header + * @param value the value of the field. + * @return this builder + */ + public HttpFieldsBuilder add(HttpHeader header, String value) + { + if (value == null) + throw new IllegalArgumentException("null value"); + + HttpField field = new HttpField(header, value); + return add(field); + } + + public HttpFieldsBuilder add(HttpField field) + { + if (field != null) + _fields.add(field); + return this; + } + + /** + * Add fields from another HttpFields instance. Single valued fields are replaced, while all + * others are added. + * + * @param fields the fields to add + * @return this builder + */ + public HttpFieldsBuilder add(HttpFields fields) + { + // TODO is this any different to addAll? + + if (fields == null) + return this; + + _fields.ensureCapacity(size() + fields.size() + 4); + Enumeration e = fields.getFieldNames(); + while (e.hasMoreElements()) + { + String name = e.nextElement(); + Enumeration values = fields.getValues(name); + while (values.hasMoreElements()) + { + add(name, values.nextElement()); + } + } + return this; + } + + public HttpFieldsBuilder addAll(HttpFields fields) + { + _fields.ensureCapacity(size() + fields.size() + 4); + for (HttpField f : fields) + _fields.add(f); + return this; + } + + /** + * Add comma separated values, but only if not already + * present. + * + * @param header The header to add the value(s) to + * @param values The value(s) to add + * @return this builder + */ + public HttpFieldsBuilder addCSV(HttpHeader header, String... values) + { + // TODO is the javadoc right ? + QuotedCSV existing = null; + for (HttpField f : this) + { + if (f.getHeader() == header) + { + if (existing == null) + existing = new QuotedCSV(false); + existing.addValue(f.getValue()); + } + } + String value = addCSV(existing, values); + if (value != null) + add(header, value); + return this; + } + + /** + * Add comma separated values, but only if not already + * present. + * + * @param name The header to add the value(s) to + * @param values The value(s) to add + * @return this builder + */ + public HttpFieldsBuilder addCSV(String name, String... values) + { + // TODO is the javadoc right ? + QuotedCSV existing = null; + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + { + if (existing == null) + existing = new QuotedCSV(false); + existing.addValue(f.getValue()); + } + } + String value = addCSV(existing, values); + if (value != null) + add(name, value); + return this; + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public HttpFieldsBuilder addDateField(String name, long date) + { + add(name, DateGenerator.formatDate(date)); + return this; + } + + @Override + public HttpFields asImmutable() + { + return new Immutable(_fields.toArray(new HttpField[0])); + } + + public HttpFieldsBuilder clear() + { + _fields.clear(); + return this; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof HttpFieldsBuilder)) + return false; + + return isEqualTo((HttpFields)o); + } + + /** + * Remove the first instance of a header and return previous value + * + * @param name the field to remove + * @return the header that was removed + */ + public HttpField getAndRemove(HttpHeader name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getHeader() == name) + { + i.remove(); + return f; + } + } + return null; + } + + /** + * Get a Field by index. + * + * @param index the field index + * @return A Field value or null if the Field value has not been set + */ + @Override + public HttpField getField(int index) + { + if (index >= size()) + throw new NoSuchElementException(); + return _fields.get(index); + } + + @Override + public int hashCode() + { + return asHashCode(); + } + + @Override + public Iterator iterator() + { + return _fields.iterator(); + } + + public ListIterator listIterator() + { + return _fields.listIterator(); + } + + public HttpFieldsBuilder put(HttpField field) + { + boolean put = false; + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.isSameName(field)) + { + if (put) + i.remove(); + else + { + i.set(field); + put = true; + } + } + } + if (!put) + add(field); + return this; + } + + /** + * Set a field. + * + * @param name the name of the field + * @param value the value of the field. If null the field is cleared. + * @return this builder + */ + public HttpFieldsBuilder put(String name, String value) + { + return (value == null) + ? remove(name) + : put(new HttpField(name, value)); + } + + public HttpFieldsBuilder put(HttpHeader header, HttpHeaderValue value) + { + return put(header, value.toString()); + } + + /** + * Set a field. + * + * @param header the header name of the field + * @param value the value of the field. If null the field is cleared. + * @return this builder + */ + public HttpFieldsBuilder put(HttpHeader header, String value) + { + return (value == null) + ? remove(header) + : put(new HttpField(header, value)); + } + + /** + * Set a field. + * + * @param name the name of the field + * @param list the List value of the field. If null the field is cleared. + * @return this builder + */ + public HttpFieldsBuilder put(String name, List list) + { + remove(name); + for (String v : list) + { + if (v != null) + add(name, v); + } + return this; + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public HttpFieldsBuilder putDateField(HttpHeader name, long date) + { + return put(name, DateGenerator.formatDate(date)); + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public HttpFieldsBuilder putDateField(String name, long date) + { + return put(name, DateGenerator.formatDate(date)); + } + + /** + * Sets the value of an long field. + * + * @param name the field name + * @param value the field long value + * @return this builder + */ + public HttpFieldsBuilder putLongField(HttpHeader name, long value) + { + return put(name, Long.toString(value)); + } + + /** + * Sets the value of an long field. + * + * @param name the field name + * @param value the field long value + * @return this builder + */ + public HttpFieldsBuilder putLongField(String name, long value) + { + return put(name, Long.toString(value)); + } + + /** + * Remove a field. + * + * @param name the field to remove + * @return this builder + */ + public HttpFieldsBuilder remove(HttpHeader name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getHeader() == name) + i.remove(); + } + return this; + } + + /** + * Remove a field. + * + * @param name the field to remove + * @return this builder + */ + public HttpFieldsBuilder remove(String name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getName().equalsIgnoreCase(name)) + i.remove(); + } + return this; + } + + public int size() + { + return _fields.size(); + } + + @Override + public Stream stream() + { + return _fields.stream(); + } + + @Override + public String toString() + { + return asString(); + } + + private String addCSV(QuotedCSV existing, String... values) + { + // remove any existing values from the new values + boolean add = true; + if (existing != null && !existing.isEmpty()) + { + add = false; + + for (int i = values.length; i-- > 0; ) + { + String unquoted = QuotedCSV.unquote(values[i]); + if (existing.getValues().contains(unquoted)) + values[i] = null; + else + add = true; + } + } + + if (add) + { + StringBuilder value = new StringBuilder(); + for (String v : values) + { + if (v == null) + continue; + if (value.length() > 0) + value.append(", "); + value.append(v); + } + if (value.length() > 0) + return value.toString(); + } + + return null; + } + + /** + * HTTP Fields. A collection of HTTP header and or Trailer fields. + * + *

This class is not synchronized as it is expected that modifications will only be performed by a + * single thread. + * + *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + */ + private static class Immutable implements HttpFields + { + final HttpField[] _fields; + + /** + * Initialize HttpFields from copy. + * + * @param fields the fields to copy data from + */ + Immutable(HttpField[] fields) + { + _fields = fields; + } + + @Override + public HttpFields asImmutable() + { + return this; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof Immutable)) + return false; + + return isEqualTo((HttpFields)o); + } + + @Override + public HttpField getField(int index) + { + if (index >= _fields.length) + throw new NoSuchElementException(); + return _fields[index]; + } + + @Override + public int hashCode() + { + return asHashCode(); + } + + @Override + public Iterator iterator() + { + return Arrays.stream(_fields).iterator(); + } + + @Override + public int size() + { + return _fields.length; + } + + @Override + public Stream stream() + { + return Arrays.stream(_fields); + } + + @Override + public String toString() + { + return asString(); + } + } +} 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 378f1209ce97..e980bf17311f 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 @@ -52,12 +52,7 @@ public class HttpGenerator public static final MetaData.Response CONTINUE_100_INFO = new MetaData.Response(HttpVersion.HTTP_1_1, 100, null, null, -1); public static final MetaData.Response PROGRESS_102_INFO = new MetaData.Response(HttpVersion.HTTP_1_1, 102, null, null, -1); public static final MetaData.Response RESPONSE_500_INFO = - new MetaData.Response(HttpVersion.HTTP_1_1, INTERNAL_SERVER_ERROR_500, null, new HttpFields() - { - { - put(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE); - } - }, 0); + new MetaData.Response(HttpVersion.HTTP_1_1, INTERNAL_SERVER_ERROR_500, null, HttpFields.empty().put(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE), 0); // states public enum State @@ -326,14 +321,14 @@ private Result completing(ByteBuffer chunk, ByteBuffer content) if (isChunking()) { - Supplier trailerSupplier = _info.getTrailerSupplier(); + Supplier trailerSupplier = _info.getTrailerSupplier(); if (_info.mayHaveTrailers()) { // Do we need a chunk buffer? if (chunk == null || chunk.capacity() <= CHUNK_SIZE) return Result.NEED_CHUNK_TRAILER; - HttpFieldList trailers = trailerSupplier.get(); + HttpFields trailers = trailerSupplier.get(); if (trailers != null) { @@ -498,7 +493,7 @@ private void prepareChunk(ByteBuffer chunk, int remaining) } } - private void generateTrailers(ByteBuffer buffer, HttpFieldList trailer) + private void generateTrailers(ByteBuffer buffer, HttpFields trailer) { // if we need CRLF add this to header if (_needCRLF) @@ -595,11 +590,11 @@ private void generateHeaders(ByteBuffer header, ByteBuffer content, boolean last boolean close = false; boolean chunkedHint = _info.hasTrailerSupplier(); boolean contentType = false; - long contentLength = _info.getContentLength(); + long contentLength = _info.getContentLengthKnown(); boolean contentLengthField = false; // Generate fields - HttpFieldList fields = _info.getFields(); + HttpFields fields = _info.getFields(); if (fields != null) { int n = fields.size(); @@ -680,13 +675,13 @@ else if (contentLength != field.getLongValue()) boolean assumedContentRequest = request != null && Boolean.TRUE.equals(ASSUMED_CONTENT_METHODS.get(request.getMethod())); boolean assumedContent = assumedContentRequest || contentType || chunkedHint; - boolean nocontentRequest = request != null && contentLength <= 0 && !assumedContent; + boolean noContentRequest = request != null && contentLength <= 0 && !assumedContent; if (_persistent == null) _persistent = http11 || (request != null && HttpMethod.CONNECT.is(request.getMethod())); // If the message is known not to have content - if (_noContentResponse || nocontentRequest) + if (_noContentResponse || noContentRequest) { // We don't need to indicate a body length _endOfContent = EndOfContent.NO_CONTENT; @@ -926,7 +921,7 @@ public static void putTo(HttpField field, ByteBuffer bufferInFillMode) } } - public static void putTo(HttpFields fields, ByteBuffer bufferInFillMode) + public static void putTo(HttpFieldsBuilder fields, ByteBuffer bufferInFillMode) { for (HttpField field : fields) { 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 1d6db1f0cf9b..d6563065651b 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 @@ -72,7 +72,7 @@ * is used to lookup common combinations of headers and values * (eg. "Connection: close"), or just header names (eg. "Connection:" ). * For headers who's value is not known statically (eg. Host, COOKIE) then a - * per parser dynamic Trie of {@link HttpFields} from previous parsed messages + * per parser dynamic Trie of {@link HttpFieldsBuilder} from previous parsed messages * is used to help the parsing of subsequent messages. *

*

diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 6a61cec7125f..11662951fab6 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -444,6 +444,8 @@ public void clear() public String decodedPath() { + if (_decodedPath == null && _path != null) + _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); return _decodedPath; } @@ -512,7 +514,7 @@ public String param() public Builder param(String param) { _param = param; - if (_path != null && !_path.contains(_param)) + if (_path != null && _param != null && !_path.contains(_param)) { _path += ";" + _param; } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 51a45537a851..0fa9b496186d 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -20,35 +20,34 @@ import java.util.Collections; import java.util.Iterator; +import java.util.function.Consumer; import java.util.function.Supplier; public class MetaData implements Iterable { - private static final Supplier SELF_SUPPLIED_TRAILORS = () -> null; - private static final HttpFieldList SUPPLIED_TRAILERS = new HttpFields().asImmutable(); + private static final Supplier SELF_SUPPLIED_TRAILORS = () -> null; + private static final HttpFields SUPPLIED_TRAILERS = HttpFields.empty().asImmutable(); private final HttpVersion _httpVersion; - private final HttpFieldList _fields; + private final HttpFields _fields; private final long _contentLengthKnown; - private final long _contentLengthField; - private final Supplier _trailerSupplier; - private HttpFieldList _trailers; + private final Supplier _trailerSupplier; + private HttpFields _trailers; - public MetaData(HttpVersion version, HttpFieldList fields) + public MetaData(HttpVersion version, HttpFields fields) { - this(version, fields, Long.MIN_VALUE); + this(version, fields, -1); } - public MetaData(HttpVersion version, HttpFieldList fields, long contentLengthKnown) + public MetaData(HttpVersion version, HttpFields fields, long contentLengthKnown) { this(version, fields, contentLengthKnown, SELF_SUPPLIED_TRAILORS); } - public MetaData(HttpVersion version, HttpFieldList fields, long contentLengthKnown, Supplier trailers) + public MetaData(HttpVersion version, HttpFields fields, long contentLengthKnown, Supplier trailers) { _httpVersion = version; _fields = fields == null ? null : fields.asImmutable(); _contentLengthKnown = contentLengthKnown; - _contentLengthField = _fields == null ? -1 : _fields.getLongField(HttpHeader.CONTENT_LENGTH); if (trailers == SELF_SUPPLIED_TRAILORS) _trailerSupplier = () -> _trailers; else @@ -80,7 +79,7 @@ public HttpVersion getHttpVersion() /** * @return the HTTP fields of this MetaData object */ - public HttpFieldList getFields() + public HttpFields getFields() { return _fields; } @@ -95,24 +94,19 @@ public boolean hasTrailerSupplier() return _trailers == SUPPLIED_TRAILERS; } - public Supplier getTrailerSupplier() + public Supplier getTrailerSupplier() { return _trailerSupplier; } - public void setTrailers(HttpFieldList trailers) + public void setTrailers(HttpFields trailers) { if (_trailers != null) throw new IllegalStateException(); _trailers = trailers; } - public long getContentLengthField() - { - return _contentLengthField; - } - - public long getContentLength() + public long getContentLengthKnown() { return _contentLengthKnown; } @@ -138,32 +132,44 @@ public String toString() public static class Request extends MetaData { + public static RequestBuilder from(String method, String uri, HttpVersion version) + { + return new RequestBuilder(method, uri, version); + } + + public static RequestBuilder from(String method, String uri, HttpVersion version, Consumer fieldBuilder) + { + RequestBuilder rb = new RequestBuilder(method, uri, version); + fieldBuilder.accept(rb._fieldBuilder); + return rb; + } + private final String _method; private final HttpURI _uri; - public Request(HttpFieldList fields) + public Request(HttpFields fields) { this(null, null, null, fields); } - public Request(String method, HttpURI uri, HttpVersion version, HttpFieldList fields) + public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields) { this(method, uri, version, fields, Long.MIN_VALUE); } - public Request(String method, HttpURI uri, HttpVersion version, HttpFieldList fields, long contentLength) + public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength) { super(version, fields, contentLength); _method = method; _uri = uri; } - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields, long contentLength) + public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) { this(method, scheme == null ? null : scheme.asString(), hostPort, uri, version, fields, contentLength); } - public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFieldList fields, long contentLength) + public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) { this(method, new HttpURI.Builder(scheme, hostPort == null ? null : hostPort.getHost(), @@ -171,6 +177,13 @@ public Request(String method, String scheme, HostPortHttpField hostPort, String uri).toHttpURI(), version, fields, contentLength); } + public Request(String method, HttpURI uri, HttpVersion version, HttpFieldsBuilder fields, long contentLength, Supplier trailers) + { + super(version, fields, contentLength, trailers); + _method = method; + _uri = uri; + } + @Override public boolean isRequest() { @@ -209,18 +222,31 @@ public String getProtocol() @Override public String toString() { - HttpFieldList fields = getFields(); + HttpFields fields = getFields(); return String.format("%s{u=%s,%s,h=%d,cl=%d,p=%s}", - getMethod(), getURI(), getHttpVersion(), fields == null ? -1 : fields.size(), getContentLength(), getProtocol()); + getMethod(), getURI(), getHttpVersion(), fields == null ? -1 : fields.size(), getContentLengthKnown(), getProtocol()); } } // TODO this is moderately specific to HttpChannelOverHttp, so unless it get's used elsewhere, it should be moved there. - public static class RequestBuilder extends HttpFields + public static class RequestBuilder { - private final HttpURI.Builder _uri = HttpURI.empty(); + private final HttpURI.Builder _uri; private String _method; private HttpVersion _version; + private final HttpFieldsBuilder _fieldBuilder = HttpFields.empty(); + + public RequestBuilder() + { + _uri = HttpURI.empty(); + } + + public RequestBuilder(String method, String uri, HttpVersion version) + { + _method = method; + _uri = HttpURI.from(uri); + _version = version; + } public String method() { @@ -229,15 +255,20 @@ public String method() public void request(String method, String uri, HttpVersion version) { - clear(); _method = method; _uri.uri(uri); _version = version; + _fieldBuilder.clear(); + } + + public HttpFieldsBuilder getFields() + { + return _fieldBuilder; } public Request build() { - return new Request(_method, _uri.toHttpURI(), _version, asImmutable()); + return new Request(_method, _uri.toHttpURI(), _version, _fieldBuilder.asImmutable()); } public HttpVersion version() @@ -250,12 +281,12 @@ public static class ConnectRequest extends Request { private final String _protocol; - public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) + public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String path, HttpFieldsBuilder fields, String protocol) { this(scheme == null ? null : scheme.asString(), authority, path, fields, protocol); } - public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) + public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFieldsBuilder fields, String protocol) { super(HttpMethod.CONNECT.asString(), scheme, authority, path, HttpVersion.HTTP_2, fields, Long.MIN_VALUE); _protocol = protocol; @@ -273,22 +304,22 @@ public static class Response extends MetaData private final int _status; private final String _reason; - public Response(HttpVersion version, int status, HttpFields fields) + public Response(HttpVersion version, int status, HttpFieldsBuilder fields) { this(version, status, fields, Long.MIN_VALUE); } - public Response(HttpVersion version, int status, HttpFields fields, long contentLength) + public Response(HttpVersion version, int status, HttpFieldsBuilder fields, long contentLength) { this(version, status, null, fields, contentLength); } - public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength) + public Response(HttpVersion version, int status, String reason, HttpFieldsBuilder fields, long contentLength) { this(version, status, reason, fields, contentLength, null); } - public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength, Supplier trailers) + public Response(HttpVersion version, int status, String reason, HttpFieldsBuilder fields, long contentLength, Supplier trailers) { super(version, fields, contentLength, trailers); _reason = reason; @@ -320,8 +351,8 @@ public String getReason() @Override public String toString() { - HttpFieldList fields = getFields(); - return String.format("%s{s=%d,h=%d,cl=%d}", getHttpVersion(), getStatus(), fields == null ? -1 : fields.size(), getContentLength()); + HttpFields fields = getFields(); + return String.format("%s{s=%d,h=%d,cl=%d}", getHttpVersion(), getStatus(), fields == null ? -1 : fields.size(), getContentLengthKnown()); } } } 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 7d63d92f07ad..037b764d9b69 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 @@ -47,7 +47,7 @@ public class HttpFieldsTest @Test public void testPut() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("name0", "value:0"); header.put("name1", "value1"); @@ -78,7 +78,7 @@ public void testPut() throws Exception @Test public void testPutTo() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("name0", "value0"); header.put("name1", "value:A"); @@ -99,12 +99,12 @@ public void testPutTo() throws Exception @Test public void testImmutable() throws Exception { - HttpFields builder = new HttpFields(); + HttpFieldsBuilder builder = HttpFields.empty(); builder.put("name0", "value0"); builder.put("name1", "value1"); - HttpFieldList header = builder.asImmutable(); + HttpFields header = builder.asImmutable(); assertEquals("value0", header.get("name0")); assertEquals("value0", header.get("Name0")); @@ -129,7 +129,7 @@ public void testImmutable() throws Exception @Test public void testGet() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("name0", "value0"); header.put("name1", "value1"); @@ -157,7 +157,7 @@ public void testGet() throws Exception @Test public void testGetKnown() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("Connection", "value0"); header.put(HttpHeader.ACCEPT, "value1"); @@ -175,7 +175,7 @@ public void testGetKnown() throws Exception @Test public void testCRLF() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("name0", "value\r\n0"); header.put("name\r\n1", "value1"); @@ -194,7 +194,7 @@ public void testCRLF() throws Exception @Test public void testCachedPut() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("Connection", "Keep-Alive"); header.put("tRansfer-EncOding", "CHUNKED"); @@ -214,7 +214,7 @@ public void testCachedPut() throws Exception @Test public void testRePut() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("name0", "value0"); header.put("name1", "xxxxxx"); @@ -254,7 +254,7 @@ public void testRePut() throws Exception @Test public void testRemovePut() throws Exception { - HttpFields header = new HttpFields(1); + HttpFieldsBuilder header = HttpFields.empty(1); header.put("name0", "value0"); header.put("name1", "value1"); @@ -292,7 +292,7 @@ public void testRemovePut() throws Exception @Test public void testAdd() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("name0", "value0"); fields.add("name1", "valueA"); @@ -354,7 +354,7 @@ public void testAddPreEncodedField() { final PreEncodedHttpField X_XSS_PROTECTION_FIELD = new PreEncodedHttpField("X-XSS-Protection", "1; mode=block"); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -365,7 +365,7 @@ public void testAddFinalHttpField() { final HttpField X_XSS_PROTECTION_FIELD = new HttpField("X-XSS-Protection", "1; mode=block"); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -374,7 +374,7 @@ public void testAddFinalHttpField() @Test public void testGetValues() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -414,7 +414,7 @@ public void testGetValues() throws Exception @Test public void testGetCSV() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -454,7 +454,7 @@ public void testGetCSV() throws Exception @Test public void testAddQuotedCSV() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("some", "value"); fields.add("name", "\"zero\""); @@ -464,46 +464,45 @@ public void testAddQuotedCSV() throws Exception fields.add("name", "four, I V"); List list = fields.getCSV("name", false); - assertEquals(HttpFields.valueParameters(list.get(0), null), "zero"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "one"); - assertEquals(HttpFields.valueParameters(list.get(2), null), "1 + 1"); - assertEquals(HttpFields.valueParameters(list.get(3), null), "three"); - assertEquals(HttpFields.valueParameters(list.get(4), null), "four"); - assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); - - assertTrue(fields.addCSV("name", "six")); + assertEquals(HttpField.valueParameters(list.get(0), null), "zero"); + assertEquals(HttpField.valueParameters(list.get(1), null), "one"); + assertEquals(HttpField.valueParameters(list.get(2), null), "1 + 1"); + assertEquals(HttpField.valueParameters(list.get(3), null), "three"); + assertEquals(HttpField.valueParameters(list.get(4), null), "four"); + assertEquals(HttpField.valueParameters(list.get(5), null), "I V"); + + fields.addCSV("name", "six"); list = fields.getCSV("name", false); - assertEquals(HttpFields.valueParameters(list.get(0), null), "zero"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "one"); - assertEquals(HttpFields.valueParameters(list.get(2), null), "1 + 1"); - assertEquals(HttpFields.valueParameters(list.get(3), null), "three"); - assertEquals(HttpFields.valueParameters(list.get(4), null), "four"); - assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); - assertEquals(HttpFields.valueParameters(list.get(6), null), "six"); - - assertTrue(fields.addCSV("name", "1 + 1", "7", "zero")); + assertEquals(HttpField.valueParameters(list.get(0), null), "zero"); + assertEquals(HttpField.valueParameters(list.get(1), null), "one"); + assertEquals(HttpField.valueParameters(list.get(2), null), "1 + 1"); + assertEquals(HttpField.valueParameters(list.get(3), null), "three"); + assertEquals(HttpField.valueParameters(list.get(4), null), "four"); + assertEquals(HttpField.valueParameters(list.get(5), null), "I V"); + assertEquals(HttpField.valueParameters(list.get(6), null), "six"); + + fields.addCSV("name", "1 + 1", "7", "zero"); list = fields.getCSV("name", false); - assertEquals(HttpFields.valueParameters(list.get(0), null), "zero"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "one"); - assertEquals(HttpFields.valueParameters(list.get(2), null), "1 + 1"); - assertEquals(HttpFields.valueParameters(list.get(3), null), "three"); - assertEquals(HttpFields.valueParameters(list.get(4), null), "four"); - assertEquals(HttpFields.valueParameters(list.get(5), null), "I V"); - assertEquals(HttpFields.valueParameters(list.get(6), null), "six"); - assertEquals(HttpFields.valueParameters(list.get(7), null), "7"); - assertFalse(fields.addCSV("name", "1 + 1", "7", "zero")); - - assertTrue(fields.addCSV(HttpHeader.ACCEPT, "en", "it")); + assertEquals(HttpField.valueParameters(list.get(0), null), "zero"); + assertEquals(HttpField.valueParameters(list.get(1), null), "one"); + assertEquals(HttpField.valueParameters(list.get(2), null), "1 + 1"); + assertEquals(HttpField.valueParameters(list.get(3), null), "three"); + assertEquals(HttpField.valueParameters(list.get(4), null), "four"); + assertEquals(HttpField.valueParameters(list.get(5), null), "I V"); + assertEquals(HttpField.valueParameters(list.get(6), null), "six"); + assertEquals(HttpField.valueParameters(list.get(7), null), "7"); + + fields.addCSV(HttpHeader.ACCEPT, "en", "it"); list = fields.getCSV(HttpHeader.ACCEPT, false); - assertEquals(HttpFields.valueParameters(list.get(0), null), "en"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "it"); - assertFalse(fields.addCSV(HttpHeader.ACCEPT, "en", "it")); + assertEquals(HttpField.valueParameters(list.get(0), null), "en"); + assertEquals(HttpField.valueParameters(list.get(1), null), "it"); + fields.addCSV(HttpHeader.ACCEPT, "en", "it"); } @Test public void testGetQualityCSV() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("some", "value"); fields.add("name", "zero;q=0.9,four;q=0.1"); @@ -514,18 +513,18 @@ public void testGetQualityCSV() throws Exception fields.add("name", "first;"); List list = fields.getQualityCSV("name"); - assertEquals(HttpFields.valueParameters(list.get(0), null), "first"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "zero"); - assertEquals(HttpFields.valueParameters(list.get(2), null), "one"); - assertEquals(HttpFields.valueParameters(list.get(3), null), "two"); - assertEquals(HttpFields.valueParameters(list.get(4), null), "three"); - assertEquals(HttpFields.valueParameters(list.get(5), null), "four"); + assertEquals(HttpField.valueParameters(list.get(0), null), "first"); + assertEquals(HttpField.valueParameters(list.get(1), null), "zero"); + assertEquals(HttpField.valueParameters(list.get(2), null), "one"); + assertEquals(HttpField.valueParameters(list.get(3), null), "two"); + assertEquals(HttpField.valueParameters(list.get(4), null), "three"); + assertEquals(HttpField.valueParameters(list.get(5), null), "four"); } @Test public void testGetQualityCSVHeader() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("some", "value"); fields.add("Accept", "zero;q=0.9,four;q=0.1"); @@ -536,18 +535,18 @@ public void testGetQualityCSVHeader() throws Exception fields.add("Accept", "first;"); List list = fields.getQualityCSV(HttpHeader.ACCEPT); - assertEquals(HttpFields.valueParameters(list.get(0), null), "first"); - assertEquals(HttpFields.valueParameters(list.get(1), null), "zero"); - assertEquals(HttpFields.valueParameters(list.get(2), null), "one"); - assertEquals(HttpFields.valueParameters(list.get(3), null), "two"); - assertEquals(HttpFields.valueParameters(list.get(4), null), "three"); - assertEquals(HttpFields.valueParameters(list.get(5), null), "four"); + assertEquals(HttpField.valueParameters(list.get(0), null), "first"); + assertEquals(HttpField.valueParameters(list.get(1), null), "zero"); + assertEquals(HttpField.valueParameters(list.get(2), null), "one"); + assertEquals(HttpField.valueParameters(list.get(3), null), "two"); + assertEquals(HttpField.valueParameters(list.get(4), null), "three"); + assertEquals(HttpField.valueParameters(list.get(5), null), "four"); } @Test public void testDateFields() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("D0", "Wed, 31 Dec 1969 23:59:59 GMT"); fields.put("D1", "Fri, 31 Dec 1999 23:59:59 GMT"); @@ -589,7 +588,7 @@ public void testDateFields() throws Exception @Test public void testNegDateFields() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.putDateField("Dzero", 0); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT", fields.get("Dzero")); @@ -607,7 +606,7 @@ public void testNegDateFields() throws Exception @Test public void testLongFields() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.put("I1", "42"); header.put("I2", " 43 99"); @@ -671,7 +670,7 @@ public void testLongFields() throws Exception @Test public void testContains() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); header.add("n0", ""); header.add("n1", ","); @@ -709,7 +708,7 @@ public void testContains() throws Exception @ValueSource(strings = {"Host", "host", "HOST", "HoSt", "Connection", "CONNECTION", "connection", "CoNnEcTiOn"}) public void testContainsKeyTrue(String keyName) { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -721,7 +720,7 @@ public void testContainsKeyTrue(String keyName) @ValueSource(strings = {"Content-Type", "Content-Length", "X-Bogus", ""}) public void testContainsKeyFalse(String keyName) { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -732,7 +731,7 @@ public void testContainsKeyFalse(String keyName) @Test public void testPreventNullField() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); assertThrows(NullPointerException.class, () -> { HttpField nullNullField = new HttpField(null, null, "bogus"); @@ -743,7 +742,7 @@ public void testPreventNullField() @Test public void testIteration() throws Exception { - HttpFields header = new HttpFields(); + HttpFieldsBuilder header = HttpFields.empty(); Iterator i = header.iterator(); assertThat(i.hasNext(), is(false)); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java index 82f0db1a588d..77ef401f6d01 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java @@ -35,17 +35,17 @@ public class HttpGeneratorClientTest class RequestInfo extends MetaData.Request { - RequestInfo(String method, String uri, HttpFieldList fields) + RequestInfo(String method, String uri, HttpFields fields) { super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, -1); } - RequestInfo(String method, String uri, HttpVersion version, HttpFieldList fields) + RequestInfo(String method, String uri, HttpVersion version, HttpFields fields) { super(method, new HttpURI.Builder(method,uri).toHttpURI(), version, fields, -1); } - RequestInfo(String method, String uri, int contentLength, HttpFieldList fields) + RequestInfo(String method, String uri, int contentLength, HttpFields fields) { super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, contentLength); } @@ -62,7 +62,7 @@ public void testGETRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("GET", "/index.html", fields); @@ -100,7 +100,7 @@ public void testEmptyHeaders() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("Null", null); fields.add("Empty", ""); @@ -136,7 +136,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "localhost"); fields.add("Field", "SomeWhatLongValue"); RequestInfo info = new RequestInfo("GET", "/index.html", HttpVersion.HTTP_1_0, fields); @@ -178,7 +178,7 @@ public void testPOSTRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -218,7 +218,7 @@ public void testRequestWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -264,7 +264,7 @@ public void testRequestWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -336,7 +336,7 @@ public void testRequestWithKnownContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", 58, fields); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java index ba845cca4abc..fbc3b129c8dd 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java @@ -78,7 +78,7 @@ public void testHTTP(Run run) throws Exception private static class Result { - private HttpFields _fields = new HttpFields(); + private HttpFieldsBuilder _fields = HttpFields.empty(); private final String _body; private final int _code; private String _connection; @@ -207,7 +207,7 @@ public String toString() return "[" + _code + "," + _contentType + "," + _contentLength + "," + (_body == null ? "null" : "content") + "]"; } - public HttpFields getHttpFields() + public HttpFieldsBuilder getHttpFields() { return _fields; } 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 f3abe97d6bc1..12182edfba0d 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 @@ -46,7 +46,7 @@ public void test09() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, fields, 10); @@ -83,7 +83,7 @@ public void testSimple() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -116,7 +116,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Location", "http://somewhere/else"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 302, null, fields, 0); @@ -152,7 +152,7 @@ public void test204() throws Exception HttpGenerator gen = new HttpGenerator(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", fields, 10); @@ -189,7 +189,7 @@ public void testComplexChars() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Content-Type", "test/data;\r\nextra=value"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", fields, 10); @@ -222,9 +222,9 @@ public void testComplexChars() throws Exception public void testSendServerXPoweredBy() throws Exception { ByteBuffer header = BufferUtil.allocate(8096); - HttpFields fields1 = new HttpFields(); + HttpFieldsBuilder fields1 = HttpFields.empty(); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields1, -1); - HttpFields fields2 = new HttpFields(); + HttpFieldsBuilder fields2 = HttpFields.empty(); fields2.add(HttpHeader.SERVER, "SomeServer"); fields2.add(HttpHeader.X_POWERED_BY, "SomePower"); MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields2, -1); @@ -278,7 +278,7 @@ public void testResponseIncorrectContentLength() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "11"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -304,7 +304,7 @@ public void testResponseNoContentPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -338,7 +338,7 @@ public void testResponseKnownNoContentNotPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Connection", "close"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -373,7 +373,7 @@ public void testResponseUpgrade() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Upgrade", "WebSocket"); fields.add("Connection", "Upgrade"); fields.add("Sec-WebSocket-Accept", "123456789=="); @@ -409,7 +409,7 @@ public void testResponseWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); @@ -475,7 +475,7 @@ public void testResponseWithHintedChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -546,13 +546,13 @@ public void testResponseWithContentAndTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFields trailer1 = new HttpFields(); + HttpFieldsBuilder trailer1 = HttpFields.empty(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -633,13 +633,13 @@ public void testResponseWithTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFields trailer1 = new HttpFields(); + HttpFieldsBuilder trailer1 = HttpFields.empty(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -702,7 +702,7 @@ public void testResponseWithKnownContentLengthFromMetaData() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 59); result = gen.generateResponse(info, false, null, null, content0, false); @@ -751,7 +751,7 @@ public void testResponseWithKnownContentLengthFromHeader() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "" + (content0.remaining() + content1.remaining())); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -816,7 +816,7 @@ public void test100ThenResponseWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, BufferUtil.length(content0) + BufferUtil.length(content1)); result = gen.generateResponse(info, false, null, null, content0, false); @@ -858,7 +858,7 @@ public void testConnectionKeepAliveWithAdditionalCustomValue() throws Exception { HttpGenerator generator = new HttpGenerator(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE); String customValue = "test"; fields.add(HttpHeader.CONNECTION, customValue); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java index b569943dfb5e..6778c03a4599 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java @@ -23,7 +23,7 @@ import javax.servlet.http.HttpServlet; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -109,12 +109,12 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, HttpFields fields) + protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) { return newRequest(method, "", fields); } - protected MetaData.Request newRequest(String method, String pathInfo, HttpFields fields) + protected MetaData.Request newRequest(String method, String pathInfo, HttpFieldsBuilder fields) { String host = "localhost"; int port = connector.getLocalPort(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java index 0332e1b610da..6d7b2673702a 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java @@ -35,7 +35,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.api.Stream; @@ -86,7 +86,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -137,7 +137,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -193,7 +193,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -266,7 +266,7 @@ public Map onPreface(Session session) } }); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java index 40a139127917..5f6f68ee19c2 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java @@ -34,7 +34,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -94,7 +94,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -131,7 +131,7 @@ public void testStartAsyncThenClientSessionIdleTimeout() throws Exception client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -168,7 +168,7 @@ public void testStartAsyncThenClientStreamIdleTimeout() throws Exception client.setIdleTimeout(10 * idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -217,7 +217,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) prepareClient(); client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -328,7 +328,7 @@ public void onStartAsync(AsyncEvent event) throws IOException client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch clientLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java index c37fae48a4a7..82ddd783f80a 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java @@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpURI; @@ -79,7 +78,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, HttpFields.from()); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { @@ -131,7 +130,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", new HttpFields(), "websocket"); + MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpFields.from(), "websocket"); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java index cc1a39f3389a..8774c17b44b8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java @@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -79,7 +78,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", new HttpFields()); + MetaData.Request post = newRequest("POST", HttpFields.from()); FuturePromise promise = new FuturePromise<>(); Queue clientQueue = new ConcurrentLinkedQueue<>(); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() @@ -177,7 +176,7 @@ public void testOnBeforeData() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -189,7 +188,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", new HttpFields()); + MetaData.Request post = newRequest("GET", HttpFields.from()); FuturePromise promise = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); CountDownLatch beforeDataLatch = new CountDownLatch(1); @@ -237,7 +236,7 @@ public void testDemandFromOnHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -249,7 +248,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", new HttpFields()); + MetaData.Request post = newRequest("GET", HttpFields.from()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -284,7 +283,7 @@ public void testOnBeforeDataDoesNotReenter() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -296,7 +295,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", new HttpFields()); + MetaData.Request post = newRequest("GET", HttpFields.from()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,7 +338,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) stream.demand(1); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -348,7 +347,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", new HttpFields()); + MetaData.Request post = newRequest("POST", HttpFields.from()); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java index 3fa78b45dc66..ec5893d06c34 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java @@ -29,7 +29,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -97,7 +97,7 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, String target, HttpFields fields) + protected MetaData.Request newRequest(String method, String target, HttpFieldsBuilder fields) { String host = "localhost"; int port = connector.getLocalPort(); @@ -140,7 +140,7 @@ protected void onStreamUnstalled(IStream stream) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); if (request.getURIString().endsWith("/stall")) { @@ -170,7 +170,7 @@ public void succeeded() CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", new HttpFields()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.from()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -188,7 +188,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the first be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", new HttpFields()); + request = newRequest("GET", "/", HttpFields.from()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); @@ -231,7 +231,7 @@ protected void onSessionUnstalled(ISession session) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); if (request.getURIString().endsWith("/stall")) { @@ -270,7 +270,7 @@ public Map onPreface(Session session) CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", new HttpFields()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.from()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -288,7 +288,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the session be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", new HttpFields()); + request = newRequest("GET", "/", HttpFields.from()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java index fc4f6f6e3691..0a2dd9d166ee 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -117,7 +117,7 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, HttpFields fields) + protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) { String host = "localhost"; int port = connector.getLocalPort(); @@ -192,7 +192,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getRecvWindow()); assertTrue(prefaceLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", new HttpFields()); + MetaData.Request request1 = newRequest("GET", HttpFields.from()); FuturePromise promise1 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request1, null, true), promise1, new Stream.Listener.Adapter()); HTTP2Stream clientStream1 = (HTTP2Stream)promise1.get(5, TimeUnit.SECONDS); @@ -216,7 +216,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) settingsLatch.await(5, TimeUnit.SECONDS); // Now create a new stream, it must pick up the new value. - MetaData.Request request2 = newRequest("POST", new HttpFields()); + MetaData.Request request2 = newRequest("POST", HttpFields.from()); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request2, null, true), promise2, new Stream.Listener.Adapter()); HTTP2Stream clientStream2 = (HTTP2Stream)promise2.get(5, TimeUnit.SECONDS); @@ -243,7 +243,7 @@ public void testFlowControlWithConcurrentSettings() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); @@ -286,7 +286,7 @@ public void onSettings(Session session, SettingsFrame frame) } }); - MetaData.Request request = newRequest("POST", new HttpFields()); + MetaData.Request request = newRequest("POST", HttpFields.from()); FuturePromise promise = new FuturePromise<>(); session.newStream(new HeadersFrame(request, null, false), promise, new Stream.Listener.Adapter()); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -327,7 +327,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); stream.headers(responseFrame, Callback.from(completable)); @@ -352,7 +352,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) final CountDownLatch dataLatch = new CountDownLatch(1); final Exchanger exchanger = new Exchanger<>(); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -424,7 +424,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -475,7 +475,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, null); @@ -527,7 +527,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) else { // For every stream, send down half the window size of data. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -546,7 +546,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) // First request is just to consume most of the session window. final List callbacks1 = new ArrayList<>(); final CountDownLatch prepareLatch = new CountDownLatch(1); - MetaData.Request request1 = newRequest("POST", new HttpFields()); + MetaData.Request request1 = newRequest("POST", HttpFields.from()); session.newStream(new HeadersFrame(request1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -561,7 +561,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(prepareLatch.await(5, TimeUnit.SECONDS)); // Second request will consume half of the remaining the session window. - MetaData.Request request2 = newRequest("GET", new HttpFields()); + MetaData.Request request2 = newRequest("GET", HttpFields.from()); session.newStream(new HeadersFrame(request2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -573,7 +573,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Third request will consume the whole session window, which is now stalled. // A fourth request will not be able to receive data. - MetaData.Request request3 = newRequest("GET", new HttpFields()); + MetaData.Request request3 = newRequest("GET", HttpFields.from()); session.newStream(new HeadersFrame(request3, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -585,7 +585,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Fourth request is now stalled. final CountDownLatch latch = new CountDownLatch(1); - MetaData.Request request4 = newRequest("GET", new HttpFields()); + MetaData.Request request4 = newRequest("GET", HttpFields.from()); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -621,7 +621,7 @@ public void testServerSendsBigContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -635,7 +635,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); final byte[] bytes = new byte[data.length]; final CountDownLatch latch = new CountDownLatch(1); @@ -667,7 +667,7 @@ public void testClientSendingInitialSmallWindow() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -699,7 +699,7 @@ public Map onPreface(Session session) byte[] responseData = new byte[requestData.length]; final ByteBuffer responseContent = ByteBuffer.wrap(responseData); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); final CountDownLatch latch = new CountDownLatch(1); @@ -759,7 +759,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole session and stream window. - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); session.newStream(requestFrame, Promise.from(completable), new Stream.Listener.Adapter()); @@ -843,7 +843,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole stream window. - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, new Stream.Listener.Adapter()); @@ -914,7 +914,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); final CountDownLatch resetLatch = new CountDownLatch(1); @@ -969,7 +969,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Succeed the callbacks when the stream is already remotely closed. callbacks.forEach(Callback::succeeded); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -993,7 +993,7 @@ public void onWindowUpdate(ISession session, IStream stream, WindowUpdateFrame f }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java index b9619728bea5..b64ed9fba967 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java @@ -24,7 +24,6 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -113,7 +112,7 @@ public void testClientFlowControlWindows() throws Exception assertEquals(clientSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); clientSession.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -163,7 +162,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(serverSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); clientSession.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter()); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index 8282dbb34071..381d84c3dc4c 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -35,7 +35,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -83,7 +83,7 @@ public void testRequestNoContentResponseNoContent() throws Exception Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -115,7 +115,7 @@ public void testRequestNoContentResponseEmptyContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), new Callback() { @Override @@ -130,7 +130,7 @@ public void succeeded() Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -172,7 +172,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(2); @@ -221,7 +221,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable streamCompletable = new Promise.Completable<>(); session.newStream(frame, streamCompletable, new Stream.Listener.Adapter() @@ -269,7 +269,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.putLongField(downloadBytes, random.nextInt(128 * 1024)); fields.put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); @@ -306,7 +306,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -344,7 +344,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); HostPortHttpField hostHeader = new HostPortHttpField(authority); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, hostHeader, servletPath, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -423,7 +423,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields(), 0); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from(), 0); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -440,7 +440,7 @@ public void onSettings(Session session, SettingsFrame frame) }); assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", new HttpFields()); + MetaData.Request request1 = newRequest("GET", HttpFields.from()); FuturePromise promise1 = new FuturePromise<>(); CountDownLatch exchangeLatch1 = new CountDownLatch(2); session.newStream(new HeadersFrame(request1, null, false), promise1, new Stream.Listener.Adapter() @@ -454,7 +454,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData.Request request2 = newRequest("GET", new HttpFields()); + MetaData.Request request2 = newRequest("GET", HttpFields.from()); FuturePromise promise2 = new FuturePromise<>(); CountDownLatch exchangeLatch2 = new CountDownLatch(2); session.newStream(new HeadersFrame(request2, null, false), promise2, new Stream.Listener.Adapter() @@ -469,7 +469,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream2 = promise2.get(5, TimeUnit.SECONDS); // The third stream must not be created. - MetaData.Request request3 = newRequest("GET", new HttpFields()); + MetaData.Request request3 = newRequest("GET", HttpFields.from()); CountDownLatch maxStreamsLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request3, null, false), new Promise.Adapter<>() { @@ -497,7 +497,7 @@ public void succeeded() assertEquals(1, session.getStreams().size()); // Create a fourth stream. - MetaData.Request request4 = newRequest("GET", new HttpFields()); + MetaData.Request request4 = newRequest("GET", HttpFields.from()); CountDownLatch exchangeLatch4 = new CountDownLatch(2); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>() { @@ -540,7 +540,7 @@ public void testInvalidAPIUsageOnClient() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { Callback.Completable completable = new Callback.Completable(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), completable); return new Stream.Listener.Adapter() { @@ -563,7 +563,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); CountDownLatch completeLatch = new CountDownLatch(2); @@ -635,7 +635,7 @@ public void testInvalidAPIUsageOnServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); DataFrame dataFrame = new DataFrame(stream.getId(), BufferUtil.EMPTY_BUFFER, true); // The call to headers() is legal, but slow. new Thread(() -> @@ -682,7 +682,7 @@ public void failed(Throwable x) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -706,7 +706,7 @@ public void testCleanGoAwayDoesNotTriggerFailureNotification() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); // Close cleanly. @@ -731,7 +731,7 @@ public void onFailure(Session session, Throwable failure) failureLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame request = new HeadersFrame(metaData, null, true); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter()); @@ -748,7 +748,7 @@ public void testGoAwayRespondedWithGoAway() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, null, Callback.NOOP); @@ -787,7 +787,7 @@ public void onClose(Session session, GoAwayFrame frame) closeLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame request = new HeadersFrame(metaData, null, true); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -811,7 +811,7 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFields requestFields = new HttpFields(); + HttpFieldsBuilder requestFields = HttpFields.from(); requestFields.put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); @@ -835,7 +835,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -878,7 +878,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/flush", new HttpFields()); + MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.from()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -925,7 +925,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) dataLatch.countDown(); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -949,7 +949,7 @@ public void onClose(Session session, GoAwayFrame frame) // Start 2 requests without completing them yet. CountDownLatch responseLatch = new CountDownLatch(2); - MetaData.Request metaData1 = newRequest("GET", new HttpFields()); + MetaData.Request metaData1 = newRequest("GET", HttpFields.from()); HeadersFrame request1 = new HeadersFrame(metaData1, null, false); FuturePromise promise1 = new FuturePromise<>(); Stream.Listener.Adapter listener = new Stream.Listener.Adapter() @@ -969,7 +969,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); stream1.data(new DataFrame(stream1.getId(), ByteBuffer.allocate(1), false), Callback.NOOP); - MetaData.Request metaData2 = newRequest("GET", new HttpFields()); + MetaData.Request metaData2 = newRequest("GET", HttpFields.from()); HeadersFrame request2 = new HeadersFrame(metaData2, null, false); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(request2, promise2, listener); @@ -987,7 +987,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // New requests should be immediately rejected. HostPortHttpField authority3 = new HostPortHttpField("localhost" + ":" + port); - MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP, authority3, servletPath, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP, authority3, servletPath, HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame request3 = new HeadersFrame(metaData3, null, false); FuturePromise promise3 = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java index de1f2306e72c..f6e6f119ee26 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java @@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.FlowControlStrategy; @@ -76,7 +75,7 @@ public void testServerEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -94,7 +93,7 @@ public void onClose(Session session, GoAwayFrame frame) } }); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -133,7 +132,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // The request is not replied, and the server should idle timeout. - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -161,7 +160,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // to avoid a race where the idle timeout fires // again before we can send the headers to the client. sleep(idleTimeout + idleTimeout / 2); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -180,7 +179,7 @@ public void onClose(Session session, GoAwayFrame frame) }); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -214,7 +213,7 @@ public void testClientEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -229,7 +228,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -266,7 +265,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -290,7 +289,7 @@ public void testClientNotEnforcingIdleTimeoutWithinCallback() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -307,7 +306,7 @@ public void onClose(Session session, GoAwayFrame frame) Session session = newClient(new Session.Listener.Adapter()); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -350,7 +349,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se final CountDownLatch dataLatch = new CountDownLatch(1); final CountDownLatch timeoutLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -411,7 +410,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) final CountDownLatch resetLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); // Stream does not end here, but we won't send any DATA frame. HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -455,7 +454,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -505,7 +504,7 @@ public void testClientStreamIdleTimeoutIsNotEnforcedWhenSending() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -518,7 +517,7 @@ public void onReset(Session session, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise() { @@ -575,7 +574,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) connector.setIdleTimeout(2 * delay); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", new HttpFields()); + MetaData.Request metaData = newRequest("POST", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); @@ -641,7 +640,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -655,7 +654,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Send one more request to consume the whole session flow control window. CountDownLatch resetLatch = new CountDownLatch(1); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java index fa5050045dda..94aa5b8d14c8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java @@ -30,7 +30,6 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -95,12 +94,12 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }; - HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); FuturePromise streamPromise1 = new FuturePromise<>(); session.newStream(headersFrame1, streamPromise1, streamListener); streamPromise1.get(5, TimeUnit.SECONDS); - HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); FuturePromise streamPromise2 = new FuturePromise<>(); session.newStream(headersFrame2, streamPromise2, streamListener); streamPromise2.get(5, TimeUnit.SECONDS); @@ -111,7 +110,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream serverStream1 = serverStreams.get(0); Stream serverStream2 = serverStreams.get(1); - MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); serverStream1.headers(new HeadersFrame(serverStream1.getId(), response1, null, false), Callback.NOOP); Random random = new Random(); @@ -120,7 +119,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) byte[] content2 = new byte[2 * ((ISession)serverStream2.getSession()).updateSendWindow(0)]; random.nextBytes(content2); - MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); serverStream2.headers(new HeadersFrame(serverStream2.getId(), response2, null, false), new Callback() { @Override diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java index 77c2a8fa4df7..35b7c85c079f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java @@ -27,7 +27,6 @@ import java.util.function.BinaryOperator; import java.util.stream.IntStream; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -78,7 +77,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) CompletableFuture> result = CompletableFuture.completedFuture(new ArrayList<>()); // Push maxPushed resources... IntStream.range(0, maxPushed) - .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, new HttpFields()))) + .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.from()))) .map(pushFrame -> { Promise.Completable promise = new Promise.Completable<>(); @@ -91,7 +90,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // ... then push one extra stream, the client must reject it... .thenApply(streams -> { - PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", new HttpFields())); + PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.from())); FuturePromise extraPromise = new FuturePromise<>(); stream.push(extraPushFrame, extraPromise, new Stream.Listener.Adapter() { @@ -113,7 +112,7 @@ public void onReset(Stream stream, ResetFrame frame) // ... then send the response. .thenRun(() -> { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); }); return null; @@ -122,7 +121,7 @@ public void onReset(Stream stream, ResetFrame frame) client.setMaxConcurrentPushedStreams(maxPushed); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java index d3cfa1c893ca..3830c04a6cfc 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java @@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -82,7 +81,7 @@ public void onAccept(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -110,7 +109,7 @@ public Map onPreface(Session session) }); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -224,7 +223,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java index 5b6b593d8181..ea55abcd5299 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java @@ -21,7 +21,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; @@ -48,7 +47,7 @@ public void testPriorityBeforeHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -60,7 +59,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertTrue(streamId > 0); CountDownLatch latch = new CountDownLatch(2); - MetaData metaData = newRequest("GET", new HttpFields()); + MetaData metaData = newRequest("GET", HttpFields.from()); HeadersFrame headersFrame = new HeadersFrame(streamId, metaData, null, true); session.newStream(headersFrame, new Promise.Adapter() { @@ -96,7 +95,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { beforeRequests.await(5, TimeUnit.SECONDS); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); afterRequests.countDown(); @@ -122,13 +121,13 @@ public void onHeaders(Stream stream, HeadersFrame frame) }; Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData1 = newRequest("GET", "/one", new HttpFields()); + MetaData metaData1 = newRequest("GET", "/one", HttpFields.from()); HeadersFrame headersFrame1 = new HeadersFrame(metaData1, null, true); FuturePromise promise1 = new FuturePromise<>(); session.newStream(headersFrame1, promise1, listener); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData metaData2 = newRequest("GET", "/two", new HttpFields()); + MetaData metaData2 = newRequest("GET", "/two", HttpFields.from()); HeadersFrame headersFrame2 = new HeadersFrame(metaData2, null, true); FuturePromise promise2 = new FuturePromise<>(); session.newStream(headersFrame2, promise2, listener); @@ -162,7 +161,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(priorityFrame.isExclusive(), priority.isExclusive()); latch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -170,7 +169,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData = newRequest("GET", "/one", new HttpFields()); + MetaData metaData = newRequest("GET", "/one", HttpFields.from()); HeadersFrame headersFrame = new HeadersFrame(metaData, priorityFrame, true); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java index c87752ac5a1c..3dcde83b9fe8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java @@ -29,7 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -119,7 +119,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); @@ -177,7 +177,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java index 10e3ea613b70..f8c36fd49289 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java @@ -31,7 +31,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -120,7 +120,7 @@ private Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - private MetaData.Request newRequest(String method, String path, HttpFields fields) + private MetaData.Request newRequest(String method, String path, HttpFieldsBuilder fields) { String host = "localhost"; int port = proxyConnector.getLocalPort(); @@ -165,7 +165,7 @@ protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletRes final CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/", new HttpFields()); + MetaData.Request metaData = newRequest("GET", "/", HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 05bb91789853..1fc73f53a380 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -32,7 +32,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -68,7 +68,7 @@ protected void customizeContext(ServletContextHandler context) } @Override - protected MetaData.Request newRequest(String method, String pathInfo, HttpFields fields) + protected MetaData.Request newRequest(String method, String pathInfo, HttpFieldsBuilder fields) { return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), contextPath + servletPath + pathInfo, HttpVersion.HTTP_2, fields); } @@ -102,7 +102,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -114,7 +114,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -206,7 +206,7 @@ else if (requestURI.endsWith(secondaryResource)) // The referrerURI does not point to the primary resource, so there will be no // resource association with the primary resource and therefore won't be pushed. final String referrerURI = "http://localhost:" + connector.getLocalPort(); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -218,7 +218,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -292,7 +292,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -304,7 +304,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -357,7 +357,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); // Make sure the session is sane by requesting the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); final CountDownLatch secondaryResponseLatch = new CountDownLatch(1); @@ -395,7 +395,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -406,7 +406,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -486,7 +486,7 @@ else if (requestURI.endsWith(secondaryResource2)) // Request for the primary, secondary and tertiary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(2); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -499,7 +499,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Request for the secondary resources. String secondaryURI1 = newURI(secondaryResource1); - HttpFields secondaryFields1 = new HttpFields(); + HttpFieldsBuilder secondaryFields1 = HttpFields.from(); secondaryFields1.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest1 = newRequest("GET", secondaryResource1, secondaryFields1); session.newStream(new HeadersFrame(secondaryRequest1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -511,7 +511,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the tertiary resource. - HttpFields tertiaryFields = new HttpFields(); + HttpFieldsBuilder tertiaryFields = HttpFields.from(); tertiaryFields.put(HttpHeader.REFERER, secondaryURI1); MetaData.Request tertiaryRequest = newRequest("GET", tertiaryResource, tertiaryFields); session.newStream(new HeadersFrame(tertiaryRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -528,7 +528,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); - HttpFields secondaryFields2 = new HttpFields(); + HttpFieldsBuilder secondaryFields2 = HttpFields.from(); secondaryFields2.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest2 = newRequest("GET", secondaryResource2, secondaryFields2); session.newStream(new HeadersFrame(secondaryRequest2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -604,7 +604,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Make sure that explicitly requesting a secondary resource, we get the tertiary pushed. CountDownLatch secondaryResponseLatch = new CountDownLatch(1); CountDownLatch secondaryPushLatch = new CountDownLatch(1); - MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, new HttpFields()); + MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.from()); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -675,7 +675,7 @@ else if ("secret".equals(credentials)) final Session session = newClient(new Session.Listener.Adapter()); // Login with the wrong credentials, causing a redirect to self. - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource + "?credentials=wrong", primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -690,7 +690,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) { // Follow the redirect. String location = response.getFields().get(HttpHeader.LOCATION); - HttpFields redirectFields = new HttpFields(); + HttpFieldsBuilder redirectFields = HttpFields.from(); redirectFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request redirectRequest = newRequest("GET", location, redirectFields); session.newStream(new HeadersFrame(redirectRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -768,7 +768,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -779,7 +779,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -861,7 +861,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -873,7 +873,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -956,7 +956,7 @@ public Map onPreface(Session session) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFields primaryFields = new HttpFields(); + HttpFieldsBuilder primaryFields = HttpFields.from(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -968,7 +968,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFields secondaryFields = new HttpFields(); + HttpFieldsBuilder secondaryFields = HttpFields.from(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java index c8ee642159f1..e34d206a61a4 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java @@ -31,7 +31,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -131,7 +131,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) LOGGER.debug("SERVER1 received {}", frame); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER1 sending {}", reply); @@ -167,7 +167,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 received {}", frame); callback.succeeded(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); Callback.Completable completable1 = new Callback.Completable(); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) @@ -183,7 +183,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) return completable2; }).thenRun(() -> { - MetaData trailer = new MetaData(HttpVersion.HTTP_2, new HttpFields()); + MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame end = new HeadersFrame(stream.getId(), trailer, null, true); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 sending {}", end); @@ -205,7 +205,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session clientSession = clientPromise.get(5, TimeUnit.SECONDS); // Send a request with trailers for server1. - HttpFields fields1 = new HttpFields(); + HttpFieldsBuilder fields1 = HttpFields.from(); fields1.put("X-Target", String.valueOf(connector1.getLocalPort())); MetaData.Request request1 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields1); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -230,10 +230,10 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); Stream stream1 = streamPromise1.get(5, TimeUnit.SECONDS); - stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, new HttpFields()), null, true), Callback.NOOP); + stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.from()), null, true), Callback.NOOP); // Send a request for server2. - HttpFields fields2 = new HttpFields(); + HttpFieldsBuilder fields2 = HttpFields.from(); fields2.put("X-Target", String.valueOf(connector2.getLocalPort())); MetaData.Request request2 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields2); FuturePromise streamPromise2 = new FuturePromise<>(); @@ -281,7 +281,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) LOGGER.debug("Received {} for {} on {}: {}", frame, stream, stream.getSession(), frame.getMetaData()); // Forward to the right server. MetaData metaData = frame.getMetaData(); - HttpFields fields = metaData.getFields(); + HttpFieldsBuilder fields = metaData.getFields(); int port = Integer.parseInt(fields.get("X-Target")); ClientToProxyToServer clientToProxyToServer = forwarders.computeIfAbsent(port, p -> new ClientToProxyToServer("localhost", p, client)); clientToProxyToServer.offer(stream, frame, Callback.NOOP); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java index fa16449be1c1..edf41b40f15c 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java @@ -24,7 +24,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http2.HTTP2Session; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.api.Stream; @@ -114,7 +113,7 @@ public void onFailure(Session session, Throwable failure) clientFailureLatch.countDown(); } }); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); Promise promise = new Promise.Adapter<>(); session.newStream(frame, promise, null); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java index 386d6b07311e..768189aec97e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java @@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; @@ -149,7 +148,7 @@ private boolean test(Session session, CountDownLatch latch) throws Exception int contentLength = random.nextInt(maxContentLength) + 1; long requestId = requestIds.incrementAndGet(); - MetaData.Request request = newRequest(method.asString(), "/" + requestId, new HttpFields()); + MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.from()); if (download) request.getFields().put("X-Download", String.valueOf(contentLength)); HeadersFrame requestFrame = new HeadersFrame(request, null, download); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java index fd12feda8900..f3cfe715d5b2 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java @@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -65,7 +64,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, null); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -82,7 +81,7 @@ public void testRequestClosedResponseClosedClosesStream() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, new Callback() { @@ -99,7 +98,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -124,7 +123,7 @@ public void testRequestDataClosedResponseDataClosedClosesStream() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(response, completable); @@ -153,7 +152,7 @@ public void succeeded() final CountDownLatch completeLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, false); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -196,7 +195,7 @@ public void testPushedStreamIsClosed() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", new HttpFields())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.from())); stream.push(pushFrame, new Promise.Adapter() { @Override @@ -216,14 +215,14 @@ public void succeeded() }); } }, new Stream.Listener.Adapter()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()), null, true); stream.headers(response, Callback.NOOP); return null; } }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); final CountDownLatch clientLatch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -257,7 +256,7 @@ public void testPushedStreamResetIsClosed() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", new HttpFields())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.from())); stream.push(pushFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -265,7 +264,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) { assertTrue(pushedStream.isReset()); assertTrue(pushedStream.isClosed()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()), null, true); stream.headers(response, Callback.NOOP); serverLatch.countDown(); } @@ -275,7 +274,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); final CountDownLatch clientLatch = new CountDownLatch(2); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,11 +338,11 @@ public void onFailure(Session session, Throwable failure) Session session = newClient(new Session.Listener.Adapter()); // First stream will be idle on server. - HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", new HttpFields()), null, true); + HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.from()), null, true); session.newStream(request1, new Promise.Adapter<>(), new Stream.Listener.Adapter()); // Second stream will fail on server. - HeadersFrame request2 = new HeadersFrame(newRequest("GET", new HttpFields()), null, true); + HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); session.newStream(request2, new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertTrue(latch.await(5, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java index 33bf8940d40c..18b82f6243b8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java @@ -26,7 +26,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.HTTP2Session; @@ -73,7 +73,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -98,7 +98,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -143,7 +143,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -166,7 +166,7 @@ public void onReset(Session session, ResetFrame frame) } }); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java index 2ec076e8b70b..4d6a4306f460 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java @@ -45,7 +45,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -104,7 +103,7 @@ public void testStreamSendingResetIsRemoved() throws Exception start(new ServerSessionListener.Adapter()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -142,7 +141,7 @@ public void onReset(Stream stream, ResetFrame frame) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -170,7 +169,7 @@ public void testStreamResetDoesNotCloseConnection() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -210,7 +209,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request1 = newRequest("GET", new HttpFields()); + MetaData.Request request1 = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame1 = new HeadersFrame(request1, null, false); FuturePromise promise1 = new FuturePromise<>(); final CountDownLatch stream1HeadersLatch = new CountDownLatch(1); @@ -233,7 +232,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); assertTrue(stream1HeadersLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request2 = newRequest("GET", new HttpFields()); + MetaData.Request request2 = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame2 = new HeadersFrame(request2, null, false); FuturePromise promise2 = new FuturePromise<>(); final CountDownLatch stream2DataLatch = new CountDownLatch(1); @@ -317,7 +316,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -404,7 +403,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -434,7 +433,7 @@ public void testClientResetConsumesQueuedData() throws Exception start(new EmptyHttpServlet()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -501,7 +500,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -532,7 +531,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } // Send one more request to consume the whole session flow control window, then reset it. - MetaData.Request request = newRequest("GET", "/x", new HttpFields()); + MetaData.Request request = newRequest("GET", "/x", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); // This request will get no event from the server since it's reset by the client. @@ -585,7 +584,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -648,7 +647,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -697,7 +696,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -774,7 +773,7 @@ public void onError(Throwable t) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -830,7 +829,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -907,7 +906,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = new HttpURI("http", host, port, servletPath); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); int streamId = 3; HeadersFrame headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); @@ -1010,7 +1009,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = new HttpURI("http", host, port, servletPath + "/1"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame headersFrame = new HeadersFrame(3, request, null, true); generator.control(lease, headersFrame); @@ -1021,7 +1020,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) // Send a second request. uri = new HttpURI("http", host, port, servletPath + "/2"); - request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields()); + request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); int streamId = 5; headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 77468042ba5d..10b6ede19bef 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -32,7 +32,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -89,7 +89,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Session session = newClient(new Session.Listener.Adapter()); - HttpFields requestFields = new HttpFields(); + HttpFieldsBuilder requestFields = HttpFields.from(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -98,7 +98,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream = streamPromise.get(5, TimeUnit.SECONDS); // Send the trailers. - HttpFields trailerFields = new HttpFields(); + HttpFieldsBuilder trailerFields = HttpFields.from(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -132,7 +132,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) } // Now we have the trailers. - HttpFields trailers = jettyRequest.getTrailerHttpFields(); + HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); assertNotNull(trailers); assertNotNull(trailers.get("X-Trailer")); } @@ -140,7 +140,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFields requestFields = new HttpFields(); + HttpFieldsBuilder requestFields = HttpFields.from(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -168,7 +168,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // Send the trailers. callback.thenRun(() -> { - HttpFields trailerFields = new HttpFields(); + HttpFieldsBuilder trailerFields = HttpFields.from(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -186,7 +186,7 @@ public void testTrailersSentByServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - HttpFields responseFields = new HttpFields(); + HttpFieldsBuilder responseFields = HttpFields.from(); responseFields.put("X-Response", "true"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, responseFields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); @@ -195,7 +195,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) @Override public void succeeded() { - HttpFields trailerFields = new HttpFields(); + HttpFieldsBuilder trailerFields = HttpFields.from(); trailerFields.put("X-Trailer", "true"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -207,7 +207,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -250,7 +250,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { Request jettyRequest = (Request)request; Response jettyResponse = jettyRequest.getResponse(); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); jettyResponse.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); @@ -262,7 +262,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", new HttpFields()); + MetaData.Request request = newRequest("GET", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); List frames = new ArrayList<>(); @@ -304,7 +304,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception start(new EmptyHttpServlet()); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", new HttpFields()); + MetaData.Request request = newRequest("POST", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -316,7 +316,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception completable.thenRun(() -> { // Invalid trailer: cannot contain pseudo headers. - HttpFields trailerFields = new HttpFields(); + HttpFieldsBuilder trailerFields = HttpFields.from(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -355,7 +355,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", new HttpFields()); + MetaData.Request request = newRequest("POST", HttpFields.from()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter() @@ -375,7 +375,7 @@ public void onReset(Stream stream, ResetFrame frame) // Disable checks for invalid headers. ((HTTP2Session)session).getGenerator().setValidateHpackEncoding(false); // Invalid trailer: cannot contain pseudo headers. - HttpFields trailerFields = new HttpFields(); + HttpFieldsBuilder trailerFields = HttpFields.from(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java index 3fefbdab6da0..955fc6f3b6e6 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MetaData; @@ -303,7 +303,7 @@ private void onHeaders(HeadersFrame frame, Callback callback) MetaData metaData = frame.getMetaData(); if (metaData.isRequest() || metaData.isResponse()) { - HttpFields fields = metaData.getFields(); + HttpFieldsBuilder fields = metaData.getFields(); long length = -1; if (fields != null && !HttpMethod.CONNECT.is(request.getMethod())) length = fields.getLongField(HttpHeader.CONTENT_LENGTH.asString()); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java index 3a6d00aa3568..2d887d1a3bb4 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -71,7 +71,7 @@ public void onConnectionFailure(int error, String reason) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java index fbf03eb91806..33bdac81feef 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -51,7 +51,7 @@ public void testGenerateParse() throws Exception HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder()); int streamId = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); @@ -124,7 +124,7 @@ public void onHeaders(HeadersFrame frame) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java index 886d6e3a4fd5..38aab37535dc 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java @@ -25,7 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -62,7 +62,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); @@ -115,7 +115,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index 31146eefd5b9..faa353dec650 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -21,6 +21,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; @@ -39,7 +40,7 @@ public class MetaDataBuilder private String _path; private String _protocol; private long _contentLength = Long.MIN_VALUE; - private HttpFields _fields = new HttpFields(); + private HttpFieldsBuilder _fields = HttpFields.empty(); private HpackException.StreamException _streamException; private boolean _request; private boolean _response; @@ -242,7 +243,7 @@ public MetaData build() throws HpackException.StreamException if (_request && _response) throw new HpackException.StreamException("Request and Response headers"); - HttpFields fields = _fields; + HttpFieldsBuilder fields = _fields; try { if (_request) @@ -260,20 +261,23 @@ public MetaData build() throws HpackException.StreamException if (isConnect) return new MetaData.ConnectRequest(_scheme, _authority, _path, fields, _protocol); else + // TODO is this really a known content length? return new MetaData.Request(_method, _scheme, _authority, _path, HttpVersion.HTTP_2, fields, _contentLength); } if (_response) { if (_status == null) throw new HpackException.StreamException("No Status"); + // TODO is this really a known content length? return new MetaData.Response(HttpVersion.HTTP_2, _status, fields, _contentLength); } + // TODO is this really a known content length? return new MetaData(HttpVersion.HTTP_2, fields, _contentLength); } finally { - _fields = new HttpFields(Math.max(16, fields.size() + 5)); + _fields = HttpFields.empty(Math.max(16, fields.size() + 5)); _request = false; _response = false; _status = null; diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java index 4d29aae6c87e..c4f65b176425 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java @@ -22,6 +22,7 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.util.BufferUtil; @@ -38,7 +39,7 @@ public class HpackEncoderTest public void testUnknownFieldsContextManagement() throws Exception { HpackEncoder encoder = new HpackEncoder(38 * 5); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); HttpField[] field = { @@ -151,8 +152,8 @@ public void testNeverIndexSetCookie() throws Exception HpackEncoder encoder = new HpackEncoder(38 * 5); ByteBuffer buffer = BufferUtil.allocate(4096); - HttpFields fields = new HttpFields(); - fields.put("set-cookie", "some cookie value"); + HttpFieldsBuilder fields = HttpFields.empty() + .put("set-cookie", "some cookie value"); // encode BufferUtil.clearToFill(buffer); @@ -180,7 +181,7 @@ public void testNeverIndexSetCookie() throws Exception @Test public void testFieldLargerThanTable() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); HpackEncoder encoder = new HpackEncoder(128); ByteBuffer buffer0 = BufferUtil.allocate(4096); @@ -244,7 +245,7 @@ public void testFieldLargerThanTable() throws Exception @Test public void testResize() throws Exception { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.add("host", "localhost0"); fields.add("cookie", "abcdefghij"); diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java index bfb43a168655..ec83cb823d4a 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java @@ -24,6 +24,7 @@ import java.util.Map; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; @@ -107,7 +108,7 @@ private void encodeStories(ByteBuffer buffer, Map[] stories, Str var kase = (Map)c; Object[] headers = (Object[])kase.get("headers"); // System.err.println(" "+headers); - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); for (Object header : headers) { @SuppressWarnings("unchecked") diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java index 329827897cb3..cde8ec5c919a 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java @@ -24,6 +24,7 @@ import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -52,23 +53,25 @@ public void encodeDecodeResponseTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFields fields0 = new HttpFields(); - fields0.add(HttpHeader.CONTENT_TYPE, "text/html"); - fields0.add(HttpHeader.CONTENT_LENGTH, "1024"); - fields0.add(new HttpField(HttpHeader.CONTENT_ENCODING, (String)null)); - fields0.add(ServerJetty); - fields0.add(XPowerJetty); - fields0.add(Date); - fields0.add(HttpHeader.SET_COOKIE, "abcdefghijklmnopqrstuvwxyz"); - fields0.add("custom-key", "custom-value"); + HttpFieldsBuilder fields0 = HttpFields.empty() + .add(HttpHeader.CONTENT_TYPE, "text/html") + .add(HttpHeader.CONTENT_LENGTH, "1024") + .add(new HttpField(HttpHeader.CONTENT_ENCODING, (String)null)) + .add(ServerJetty) + .add(XPowerJetty) + .add(Date) + .add(HttpHeader.SET_COOKIE, "abcdefghijklmnopqrstuvwxyz") + .add("custom-key", "custom-value"); Response original0 = new MetaData.Response(HttpVersion.HTTP_2, 200, fields0); BufferUtil.clearToFill(buffer); encoder.encode(buffer, original0); BufferUtil.flipToFlush(buffer, 0); Response decoded0 = (Response)decoder.decode(buffer); - original0.getFields().put(new HttpField(HttpHeader.CONTENT_ENCODING, "")); - assertMetaDataResponseSame(original0, decoded0); + + Response nullToEmpty = new MetaData.Response(HttpVersion.HTTP_2, 200, + fields0.put(new HttpField(HttpHeader.CONTENT_ENCODING, ""))); + assertMetaDataResponseSame(nullToEmpty, decoded0); // Same again? BufferUtil.clearToFill(buffer); @@ -78,14 +81,14 @@ public void encodeDecodeResponseTest() throws Exception assertMetaDataResponseSame(original0, decoded0b); - HttpFields fields1 = new HttpFields(); - fields1.add(HttpHeader.CONTENT_TYPE, "text/plain"); - fields1.add(HttpHeader.CONTENT_LENGTH, "1234"); - fields1.add(HttpHeader.CONTENT_ENCODING, " "); - fields1.add(ServerJetty); - fields1.add(XPowerJetty); - fields1.add(Date); - fields1.add("Custom-Key", "Other-Value"); + HttpFieldsBuilder fields1 = HttpFields.empty() + .add(HttpHeader.CONTENT_TYPE, "text/plain") + .add(HttpHeader.CONTENT_LENGTH, "1234") + .add(HttpHeader.CONTENT_ENCODING, " ") + .add(ServerJetty) + .add(XPowerJetty) + .add(Date) + .add("Custom-Key", "Other-Value"); Response original1 = new MetaData.Response(HttpVersion.HTTP_2, 200, fields1); // Same again? @@ -105,9 +108,9 @@ public void encodeDecodeTooLargeTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 164); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFields fields0 = new HttpFields(); - fields0.add("1234567890", "1234567890123456789012345678901234567890"); - fields0.add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"); + HttpFieldsBuilder fields0 = HttpFields.empty() + .add("1234567890", "1234567890123456789012345678901234567890") + .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); BufferUtil.clearToFill(buffer); @@ -117,10 +120,10 @@ public void encodeDecodeTooLargeTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFields fields1 = new HttpFields(); - fields1.add("1234567890", "1234567890123456789012345678901234567890"); - fields1.add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"); - fields1.add("x", "y"); + HttpFieldsBuilder fields1 = HttpFields.empty() + .add("1234567890", "1234567890123456789012345678901234567890") + .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR") + .add("x", "y"); MetaData original1 = new MetaData(HttpVersion.HTTP_2, fields1); BufferUtil.clearToFill(buffer); @@ -144,10 +147,10 @@ public void encodeDecodeNonAscii() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocate(16 * 1024); - HttpFields fields0 = new HttpFields(); + HttpFieldsBuilder fields0 = HttpFields.empty() // @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck - fields0.add("Cookie", "[\uD842\uDF9F]"); - fields0.add("custom-key", "[\uD842\uDF9F]"); + .add("Cookie", "[\uD842\uDF9F]") + .add("custom-key", "[\uD842\uDF9F]"); Response original0 = new MetaData.Response(HttpVersion.HTTP_2, 200, fields0); BufferUtil.clearToFill(buffer); @@ -167,9 +170,9 @@ public void evictReferencedFieldTest() throws Exception String longEnoughToBeEvicted = "012345678901234567890123456789012345678901234567890"; - HttpFields fields0 = new HttpFields(); - fields0.add(longEnoughToBeEvicted, "value"); - fields0.add("foo", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); + HttpFieldsBuilder fields0 = HttpFields.empty() + .add(longEnoughToBeEvicted, "value") + .add("foo", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); BufferUtil.clearToFill(buffer); @@ -184,9 +187,9 @@ public void evictReferencedFieldTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFields fields1 = new HttpFields(); - fields1.add(longEnoughToBeEvicted, "other_value"); - fields1.add("x", "y"); + HttpFieldsBuilder fields1 = HttpFields.empty() + .add(longEnoughToBeEvicted, "other_value") + .add("x", "y"); MetaData original1 = new MetaData(HttpVersion.HTTP_2, fields1); BufferUtil.clearToFill(buffer); @@ -207,15 +210,15 @@ public void testHopHeadersAreRemoved() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFields input = new HttpFields(); - input.put(HttpHeader.ACCEPT, "*"); - input.put(HttpHeader.CONNECTION, "TE, Upgrade, Custom"); - input.put("Custom", "Pizza"); - input.put(HttpHeader.KEEP_ALIVE, "true"); - input.put(HttpHeader.PROXY_CONNECTION, "foo"); - input.put(HttpHeader.TE, "1234567890abcdef"); - input.put(HttpHeader.TRANSFER_ENCODING, "chunked"); - input.put(HttpHeader.UPGRADE, "gold"); + HttpFieldsBuilder input = HttpFields.empty() + .add(HttpHeader.ACCEPT, "*") + .add(HttpHeader.CONNECTION, "TE, Upgrade, Custom") + .add("Custom", "Pizza") + .add(HttpHeader.KEEP_ALIVE, "true") + .add(HttpHeader.PROXY_CONNECTION, "foo") + .add(HttpHeader.TE, "1234567890abcdef") + .add(HttpHeader.TRANSFER_ENCODING, "chunked") + .add(HttpHeader.UPGRADE, "gold"); ByteBuffer buffer = BufferUtil.allocate(2048); BufferUtil.clearToFill(buffer); @@ -234,12 +237,12 @@ public void testTETrailers() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFields input = new HttpFields(); - input.put(HttpHeader.CONNECTION, "TE"); String teValue = "trailers"; - input.put(HttpHeader.TE, teValue); String trailerValue = "Custom"; - input.put(HttpHeader.TRAILER, trailerValue); + HttpFieldsBuilder input = HttpFields.empty() + .add(HttpHeader.CONNECTION, "TE") + .add(HttpHeader.TE, teValue) + .add(HttpHeader.TRAILER, trailerValue); ByteBuffer buffer = BufferUtil.allocate(2048); BufferUtil.clearToFill(buffer); @@ -259,9 +262,9 @@ public void testColonHeaders() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFields input = new HttpFields(); - input.put(":status", "200"); - input.put(":custom", "special"); + HttpFieldsBuilder input = HttpFields.empty() + .add(":status", "200") + .add(":custom", "special"); ByteBuffer buffer = BufferUtil.allocate(2048); BufferUtil.clearToFill(buffer); diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java index ea2e1f93a22c..d5b033f7d623 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java @@ -35,7 +35,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MetaData; @@ -94,7 +94,7 @@ void onHeaders(Stream stream, HeadersFrame frame) if (responseBegin(exchange)) { - HttpFields headers = response.getFields(); + HttpFieldsBuilder headers = response.getFields(); for (HttpField header : headers) { if (!responseHeader(exchange, header)) @@ -138,7 +138,7 @@ void onHeaders(Stream stream, HeadersFrame frame) } else // Response trailers. { - HttpFields trailers = metaData.getFields(); + HttpFieldsBuilder trailers = metaData.getFields(); trailers.forEach(httpResponse::trailer); // Previous DataFrames had endStream=false, so // add a poison pill to trigger response success diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java index c8057aae86c6..1a537b29e904 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpSender; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -81,7 +81,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool HttpURI uri = HttpURI.createHttpURI(request.getScheme(), request.getHost(), request.getPort(), path, null, request.getQuery(), null); metaData = new MetaData.Request(request.getMethod(), uri, HttpVersion.HTTP_2, request.getHeaders()); } - Supplier trailerSupplier = request.getTrailers(); + Supplier trailerSupplier = request.getTrailers(); metaData.setTrailerSupplier(trailerSupplier); HeadersFrame headersFrame; @@ -95,7 +95,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { if (BufferUtil.isEmpty(contentBuffer) && lastContent) { - HttpFields trailers = trailerSupplier == null ? null : trailerSupplier.get(); + HttpFieldsBuilder trailers = trailerSupplier == null ? null : trailerSupplier.get(); boolean endStream = trailers == null || trailers.size() == 0; headersFrame = new HeadersFrame(metaData, null, endStream); promise = new HeadersPromise(request, callback, stream -> @@ -140,17 +140,17 @@ private String relativize(String path) protected void sendContent(HttpExchange exchange, ByteBuffer contentBuffer, boolean lastContent, Callback callback) { Stream stream = getHttpChannel().getStream(); - Supplier trailerSupplier = exchange.getRequest().getTrailers(); + Supplier trailerSupplier = exchange.getRequest().getTrailers(); sendContent(stream, contentBuffer, lastContent, trailerSupplier, callback); } - private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, Supplier trailerSupplier, Callback callback) + private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, Supplier trailerSupplier, Callback callback) { boolean hasContent = buffer.hasRemaining(); if (lastContent) { // Call the trailers supplier as late as possible. - HttpFields trailers = trailerSupplier == null ? null : trailerSupplier.get(); + HttpFieldsBuilder trailers = trailerSupplier == null ? null : trailerSupplier.get(); boolean hasTrailers = trailers != null && trailers.size() > 0; if (hasContent) { @@ -188,7 +188,7 @@ private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, } } - private void sendTrailers(Stream stream, HttpFields trailers, Callback callback) + private void sendTrailers(Stream stream, HttpFieldsBuilder trailers, Callback callback) { MetaData metaData = new MetaData(HttpVersion.HTTP_2, trailers); HeadersFrame trailersFrame = new HeadersFrame(stream.getId(), metaData, null, true); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java index 461476937a6e..15387fcf512a 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java @@ -23,7 +23,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.gzip.GzipHandler; @@ -45,7 +45,7 @@ public void testZeroContentLengthAddedByServer(String method) throws Exception .method(method) .send(); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertEquals(0, contentLength); } @@ -68,7 +68,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r .method(method) .send(); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertEquals(data.length, contentLength); } @@ -98,7 +98,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r .method(method) .send(); - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertTrue(0 < contentLength && contentLength < data.length); } diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index aeac4cc8a37f..ad943b53c7bd 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -45,7 +45,7 @@ import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Origin; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -155,7 +155,7 @@ public void testResponseAbortSendsResetFrame() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), metaData, null, false), new Callback() { @Override @@ -232,7 +232,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) } else { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } return null; @@ -489,7 +489,7 @@ public void onHeaders(HeadersFrame request) try { // Response. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true); generator.control(lease, response); writeFrames(); @@ -563,7 +563,7 @@ public void test204WithContent() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { int streamId = stream.getId(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(streamId, response, null, false); Callback.Completable callback = new Callback.Completable(); stream.headers(responseFrame, callback); @@ -592,7 +592,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // Disable checks for invalid headers. ((HTTP2Session)stream.getSession()).getGenerator().setValidateHpackEncoding(false); // Produce an invalid HPACK block by adding a request pseudo-header to the response. - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put(":method", "get"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, fields, 0); int streamId = stream.getId(); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java index 9d958fb59c47..1ca0412b00b2 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.util.BufferingResponseListener; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -63,14 +62,14 @@ public void testPushedResourceCancelled() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { HttpURI pushURI = new HttpURI("http://localhost:" + connector.getLocalPort() + pushPath); - MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.from()); stream.push(new PushPromiseFrame(stream.getId(), 0, pushRequest), new Promise.Adapter<>() { @Override public void succeeded(Stream pushStream) { // Just send the normal response and wait for the reset. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } }, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java index 89f1e3f20abc..33074632462a 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.util.AsyncRequestContent; import org.eclipse.jetty.client.util.StringRequestContent; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -64,7 +64,7 @@ private void testEmptyTrailers(String content) throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -79,7 +79,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); request.trailers(() -> trailers); if (content != null) request.body(new StringRequestContent(content)); @@ -109,7 +109,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -119,7 +119,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); @@ -158,7 +158,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -168,7 +168,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java index 8525f2a73fc3..d2db50c25e7a 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java @@ -29,7 +29,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -89,7 +88,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r Session session = sessionPromise.get(5, TimeUnit.SECONDS); HttpURI uri = new HttpURI("http://" + host + ":" + port + "/"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame frame = new HeadersFrame(request, null, true); BlockingQueue headers = new LinkedBlockingQueue<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java index 677d65f3d93e..6a431f8823d5 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java @@ -19,7 +19,7 @@ package org.eclipse.jetty.http2.server; import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.MetaData.Request; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -71,7 +71,7 @@ public boolean isAcceptable(String protocol, String tlsProtocol, String tlsCiphe } @Override - public Connection upgradeConnection(Connector connector, EndPoint endPoint, Request request, HttpFields response101) throws BadMessageException + public Connection upgradeConnection(Connector connector, EndPoint endPoint, Request request, HttpFieldsBuilder response101) throws BadMessageException { if (LOG.isDebugEnabled()) LOG.debug("{} upgrading {}{}{}", this, request, System.lineSeparator(), request.getFields()); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java index 515f733dd16a..2915a1856579 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java @@ -32,7 +32,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; @@ -320,7 +320,7 @@ private HttpChannelOverHTTP2 pollHttpChannel() } } - public boolean upgrade(Request request, HttpFields responseFields) + public boolean upgrade(Request request, HttpFieldsBuilder responseFields) { if (HttpMethod.PRI.is(request.getMethod())) { diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java index cf112c25996d..9e2b64c69bb1 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java @@ -25,8 +25,8 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -109,7 +109,7 @@ public Runnable onRequest(HeadersFrame frame) try { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - HttpFieldList fields = request.getFields(); + HttpFields fields = request.getFields(); // HTTP/2 sends the Host header as the :authority // pseudo-header, so we need to synthesize a Host header. @@ -125,7 +125,7 @@ public Runnable onRequest(HeadersFrame frame) _expect100Continue = fields.contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); - HttpFields response = getResponse().getHttpFields(); + HttpFieldsBuilder response = getResponse().getHttpFields(); if (getHttpConfiguration().getSendServerVersion()) response.add(SERVER_VERSION); if (getHttpConfiguration().getSendXPoweredBy()) @@ -300,7 +300,7 @@ public InvocationType getInvocationType() @Override public Runnable onTrailer(HeadersFrame frame) { - HttpFields trailers = frame.getMetaData().getFields(); + HttpFieldsBuilder trailers = frame.getMetaData().getFields(); if (trailers.size() > 0) onTrailers(trailers); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java index cc0d662b6caa..7c1af0997028 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java @@ -23,7 +23,7 @@ import java.util.function.Supplier; import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -132,7 +132,7 @@ public void succeeded() { if (lastContent) { - HttpFields trailers = retrieveTrailers(); + HttpFieldsBuilder trailers = retrieveTrailers(); if (trailers != null) { if (transportCallback.start(new SendTrailers(getCallback(), trailers), false)) @@ -165,7 +165,7 @@ public void succeeded() } else { - HttpFields trailers = retrieveTrailers(); + HttpFieldsBuilder trailers = retrieveTrailers(); if (trailers != null) { if (transportCallback.start(new SendTrailers(callback, trailers), true)) @@ -197,7 +197,7 @@ public void succeeded() { if (lastContent) { - HttpFields trailers = retrieveTrailers(); + HttpFieldsBuilder trailers = retrieveTrailers(); if (trailers != null) { SendTrailers sendTrailers = new SendTrailers(callback, trailers); @@ -230,12 +230,12 @@ public void succeeded() } } - private HttpFields retrieveTrailers() + private HttpFieldsBuilder retrieveTrailers() { - Supplier supplier = metaData.getTrailerSupplier(); + Supplier supplier = metaData.getTrailerSupplier(); if (supplier == null) return null; - HttpFields trailers = supplier.get(); + HttpFieldsBuilder trailers = supplier.get(); if (trailers == null) return null; return trailers.size() == 0 ? null : trailers; @@ -507,9 +507,9 @@ private enum State private class SendTrailers extends Callback.Nested { - private final HttpFields trailers; + private final HttpFieldsBuilder trailers; - private SendTrailers(Callback callback, HttpFields trailers) + private SendTrailers(Callback callback, HttpFieldsBuilder trailers) { super(callback); this.trailers = trailers; diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java index 315e59237048..bb11bb2bb161 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java @@ -26,7 +26,7 @@ import javax.servlet.http.HttpServlet; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -78,7 +78,7 @@ private void prepareServer(ConnectionFactory connectionFactory) generator = new Generator(byteBufferPool); } - protected MetaData.Request newRequest(String method, HttpFields fields) + protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) { String host = "localhost"; int port = connector.getLocalPort(); diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java index f526bc3cdfa0..042219c74e86 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java @@ -28,7 +28,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -65,7 +64,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); // Reply with HEADERS. stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); closeLatch.await(5, TimeUnit.SECONDS); @@ -81,7 +80,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -133,7 +132,7 @@ public void testClientSendsGoAwayButDoesNotCloseConnectionServerCloses() throws public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -142,7 +141,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes("UTF-8"))); @@ -198,7 +197,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, "OK", Callback.NOOP); return null; @@ -209,7 +208,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java index 42111cd259ff..319f5058385f 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java @@ -33,7 +33,6 @@ import java.util.function.UnaryOperator; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -195,7 +194,7 @@ public void onData(DataFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.from()); generator.control(lease, new HeadersFrame(3, metaData, null, true)); for (ByteBuffer buffer : lease.getByteBuffers()) { @@ -233,7 +232,7 @@ public void testHTTP20Direct() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java index 650634fc2d96..a66bebc6f172 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java @@ -39,7 +39,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -82,7 +81,7 @@ public void testNoPrefaceBytes() throws Exception startServer(new HttpServlet() {}); // No preface bytes. - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new HeadersFrame(1, metaData, null, true)); @@ -127,7 +126,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -185,7 +184,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -361,7 +360,7 @@ public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateE ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector2.getLocalPort())) { @@ -399,7 +398,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -428,7 +427,7 @@ public void testRequestWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); return lease; }); @@ -443,7 +442,7 @@ public void testRequestWithPriorityWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); return lease; }); @@ -457,7 +456,7 @@ public void testRequestWithContinuationFramesWithEmptyHeadersFrame() throws Exce ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the HeadersFrame header and set the length to zero. List buffers = lease.getByteBuffers(); @@ -479,7 +478,7 @@ public void testRequestWithPriorityWithContinuationFramesWithEmptyHeadersFrame() ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); // Take the HeadersFrame header and set the length to just the priority frame. List buffers = lease.getByteBuffers(); @@ -500,7 +499,7 @@ public void testRequestWithContinuationFramesWithEmptyContinuationFrame() throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the ContinuationFrame header, duplicate it, and set the length to zero. List buffers = lease.getByteBuffers(); @@ -524,7 +523,7 @@ public void testRequestWithContinuationFramesWithEmptyLastContinuationFrame() th ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", new HttpFields()); + MetaData.Request metaData = newRequest("GET", HttpFields.from()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the last CONTINUATION frame and reset the flag. List buffers = lease.getByteBuffers(); @@ -562,7 +561,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) serverLatch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, new HttpFields()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java index ec5dd69f079c..1ce23f057e14 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.rewrite.handler; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpURI; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,15 +28,13 @@ public class ForwardedSchemeHeaderRuleTest extends AbstractRuleTestCase { private ForwardedSchemeHeaderRule _rule; - private HttpFields _requestHeaderFields; @BeforeEach public void init() throws Exception { start(false); _rule = new ForwardedSchemeHeaderRule(); - _requestHeaderFields = _request.getHttpFields(); - _request.setScheme(null); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme((String)null).toHttpURI()); } @Test @@ -73,13 +72,13 @@ public void testHeaderValue() throws Exception _rule.matchAndApply("/", _request, _response); assertEquals("https", _request.getScheme()); - _request.setScheme("other"); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme("other").toHttpURI()); // header value doesn't match rule's value setRequestHeader("Front-End-Https", "off"); _rule.matchAndApply("/", _request, _response); assertEquals("other", _request.getScheme()); - _request.setScheme(null); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme((String)null).toHttpURI()); // header value can be any value setRequestHeader("Front-End-Https", "any"); _rule.setHeaderValue(null); @@ -89,6 +88,6 @@ public void testHeaderValue() throws Exception private void setRequestHeader(String header, String headerValue) { - _requestHeaderFields.put(header, headerValue); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()).put(header, headerValue)); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java index a0e9e82375e3..57d888d0466f 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java @@ -19,12 +19,14 @@ package org.eclipse.jetty.rewrite.handler; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; public class MsieSslRuleTest extends AbstractRuleTestCase { @@ -39,32 +41,35 @@ public void init() throws Exception } @Test - public void testWin2kWithIE5() throws Exception + public void testWin2kSP1WithIE5() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"); + HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.01)"); + _request.setHttpFields(fields); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.01)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.01)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWin2kWithIE6() throws Exception + public void testWin2kSP1WithIE6() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.01)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -73,44 +78,48 @@ public void testWin2kWithIE6() throws Exception } @Test - public void testWin2kWithIE7() throws Exception + public void testWin2kSP1WithIE7() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.0)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.01)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWin2kSP1WithIE5() throws Exception + public void testWin2kWithIE5() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.01)"); + HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"); + _request.setHttpFields(fields); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.01)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.01)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWin2kSP1WithIE6() throws Exception + public void testWin2kWithIE6() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.01)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)") + .asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -119,107 +128,113 @@ public void testWin2kSP1WithIE6() throws Exception } @Test - public void testWin2kSP1WithIE7() throws Exception + public void testWin2kWithIE7() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.01)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinXpWithIE5() throws Exception + public void testWinVistaWithIE5() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"); + HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 6.0)"); + _request.setHttpFields(fields); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.1)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 6.0)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 6.0)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinXpWithIE6() throws Exception + public void testWinVistaWithIE6() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinXpWithIE7() throws Exception + public void testWinVistaWithIE7() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinVistaWithIE5() throws Exception + public void testWinXpWithIE5() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 6.0)"); + HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"); + _request.setHttpFields(fields); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 6.0)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.1)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 6.0)"); + fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.1)"); + _request.setHttpFields(fields); result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); assertEquals(_request.getRequestURI(), result); assertEquals(HttpHeaderValue.CLOSE.asString(), _response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinVistaWithIE6() throws Exception + public void testWinXpWithIE6() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test - public void testWinVistaWithIE7() throws Exception + public void testWinXpWithIE7() throws Exception { - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } @Test @@ -229,12 +244,12 @@ public void testWithoutSsl() throws Exception super.stop(); super.start(false); - HttpFields fields = _request.getHttpFields(); - fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"); + _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); - assertEquals(null, result); - assertEquals(null, _response.getHeader(HttpHeader.CONNECTION.asString())); + assertNull(result); + assertNull(_response.getHeader(HttpHeader.CONNECTION.asString())); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java index 587f5bea674a..dc86d701ed69 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java @@ -141,7 +141,7 @@ private void assertMatch(boolean flag, String[] matchCase) throws IOException new Request(null, null) { { - setMetaData(new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_1_0, new HttpFields())); + setMetaData(new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_1_0, HttpFields.empty())); } }, null ); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java index 49703c1799ea..33a717c4bce0 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java @@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.junit.jupiter.api.BeforeEach; @@ -83,7 +84,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setURIPathQuery("/xxx/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/xxx/bar").toHttpURI()); _request.setPathInfo("/xxx/bar"); _handler.handle("/xxx/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -97,7 +98,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(false); _handler.setRewritePathInfo(false); - _request.setURIPathQuery("/foo/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/foo/bar").toHttpURI()); _request.setPathInfo("/foo/bar"); _handler.handle("/foo/bar", _request, _request, _response); @@ -110,7 +111,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _handler.setOriginalPathAttribute(null); - _request.setURIPathQuery("/aaa/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -124,7 +125,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setURIPathQuery("/aaa/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -136,7 +137,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _rule2.setTerminating(true); - _request.setURIPathQuery("/aaa/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -152,7 +153,7 @@ public void test() throws Exception _request.setAttribute("target", null); _request.setAttribute("URI", null); _request.setAttribute("info", null); - _request.setURIPathQuery("/aaa/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(200, _response.getStatus()); @@ -171,7 +172,7 @@ public void testEncodedPattern() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setURIPathQuery("/ccc/x%20y"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/ccc/x%20y").toHttpURI()); _request.setPathInfo("/ccc/x y"); _handler.handle("/ccc/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -188,7 +189,7 @@ public void testEncodedRegex() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setURIPathQuery("/xxx/x%20y"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/xxx/x%20y").toHttpURI()); _request.setPathInfo("/xxx/x y"); _handler.handle("/xxx/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java index 280e22df079b..0d5a36586eaa 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java @@ -20,6 +20,7 @@ import java.io.IOException; +import org.eclipse.jetty.http.HttpURI; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -87,8 +88,7 @@ public void testRequestWithQueryString() throws IOException { String replacement = "/replace"; String queryString = "request=parameter"; - _request.setURIPathQuery("/old/context"); - _request.setQueryString(queryString); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/old/context", null, queryString).toHttpURI()); RewritePatternRule rewritePatternRule = new RewritePatternRule(); rewritePatternRule.setPattern("/old/context"); @@ -110,8 +110,7 @@ public void testRequestAndReplacementWithQueryString() throws IOException String[] split = replacement.split("\\?", 2); String path = split[0]; String queryString = split[1]; - _request.setURIPathQuery("/old/context"); - _request.setQueryString(requestQueryString); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/old/context", null, queryString).toHttpURI()); RewritePatternRule rewritePatternRule = new RewritePatternRule(); rewritePatternRule.setPattern("/old/context"); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java index ef9638fa39dc..3bf4125ae5e7 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java @@ -21,6 +21,7 @@ import java.nio.charset.StandardCharsets; import java.util.stream.Stream; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.util.MultiMap; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.UrlEncoded; @@ -62,12 +63,12 @@ public void testRequestUriEnabled(Scenario scenario) throws Exception RewriteRegexRule rule = new RewriteRegexRule(); reset(); - _request.setURIPathQuery(null); + _request.setHttpURI(HttpURI.from(_request.getHttpURI()).toHttpURI()); rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setURIPathQuery(scenario.uriPathQuery + (scenario.queryString == null ? "" : ("?" + scenario.queryString))); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),scenario.uriPathQuery, null, scenario.queryString).toHttpURI()); String result = rule.matchAndApply(scenario.uriPathQuery, _request, _response); assertEquals(scenario.expectedRequestURI, result); @@ -106,8 +107,7 @@ public void testContainedRequestUriEnabled(Scenario scenario) throws Exception rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setURIPathQuery(scenario.uriPathQuery); - _request.setQueryString(scenario.queryString); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),scenario.uriPathQuery, null, scenario.queryString).toHttpURI()); _request.getAttributes().clearAttributes(); String result = container.apply(URIUtil.decodePath(scenario.uriPathQuery), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java index 1da1486a9d9e..2d22c62f744b 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.rewrite.handler; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.server.Dispatcher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -43,7 +44,7 @@ public void init() throws Exception public void testValidUrl() throws Exception { _rule.setCode("404"); - _request.setURIPathQuery("/valid/uri.html"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/valid/uri.html").toHttpURI()); _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -54,7 +55,7 @@ public void testValidUrl() throws Exception public void testInvalidUrl() throws Exception { _rule.setCode("404"); - _request.setURIPathQuery("/invalid%0c/uri.html"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/invalid%0c/uri.html").toHttpURI()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -66,7 +67,7 @@ public void testInvalidUrlWithMessage() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setURIPathQuery("/%00/"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/%00/").toHttpURI()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -79,7 +80,7 @@ public void testInvalidJsp() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setURIPathQuery("/jsp/bean1.jsp%00"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/bean1.jsp%00").toHttpURI()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -93,7 +94,7 @@ public void testInvalidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setURIPathQuery("/jsp/shamrock-%00%E2%98%98.jsp"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/shamrock-%00%E2%98%98.jsp").toHttpURI()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -107,7 +108,7 @@ public void testValidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setURIPathQuery("/jsp/shamrock-%E2%98%98.jsp"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/shamrock-%E2%98%98.jsp").toHttpURI()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java index 300e7e82bdc6..5a434ef108f0 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.rewrite.handler; +import org.eclipse.jetty.http.HttpURI; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -49,7 +50,7 @@ public void init() throws Exception _fooContainerRule.setRules(new Rule[]{_fooRule}); start(false); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _handler.setServer(_server); _handler.start(); @@ -58,7 +59,7 @@ public void init() throws Exception @Test public void testArbitraryHost() throws Exception { - _request.setAuthority("cheese.com", 0); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("cheese.com", 0).toHttpURI()); _handler.setRules(new Rule[]{_rule, _fooContainerRule}); handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule, Host: cheese.com}: applied _rule"); @@ -67,7 +68,7 @@ public void testArbitraryHost() throws Exception @Test public void testVirtualHost() throws Exception { - _request.setAuthority("foo.com", 0); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); _handler.setRules(new Rule[]{_fooContainerRule}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: foo.com}: applied _fooRule"); @@ -76,8 +77,8 @@ public void testVirtualHost() throws Exception @Test public void testCascadingRules() throws Exception { - _request.setAuthority("foo.com", 0); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _rule.setTerminating(false); _fooRule.setTerminating(false); @@ -87,17 +88,17 @@ public void testCascadingRules() throws Exception handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule}: applied _rule, didn't match _fooRule"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _handler.setRules(new Rule[]{_fooContainerRule, _rule}); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: applied _fooRule, _rule"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _fooRule.setTerminating(true); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: (_fooRule is terminating); applied _fooRule, _rule"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _fooRule.setTerminating(false); _fooContainerRule.setTerminating(true); handleRequest(); @@ -107,7 +108,7 @@ public void testCascadingRules() throws Exception @Test public void testCaseInsensitiveHostname() throws Exception { - _request.setAuthority("Foo.com", 0); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("Foo.com", 0).toHttpURI()); _fooContainerRule.setVirtualHosts(new String[]{"foo.com"}); _handler.setRules(new Rule[]{_fooContainerRule}); @@ -118,21 +119,21 @@ public void testCaseInsensitiveHostname() throws Exception @Test public void testEmptyVirtualHost() throws Exception { - _request.setAuthority("cheese.com", 0); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("cheese.com", 0).toHttpURI()); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(null); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is null, Host: cheese.com}: apply _fooRule"); - _request.setURIPathQuery("/cheese/bar"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _fooContainerRule.setVirtualHosts(new String[]{}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is empty, Host: cheese.com}: apply _fooRule"); - _request.setURIPathQuery("/cheese/bar"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _fooContainerRule.setVirtualHosts(new String[]{null}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual host is null, Host: cheese.com}: apply _fooRule"); @@ -141,14 +142,14 @@ public void testEmptyVirtualHost() throws Exception @Test public void testMultipleVirtualHosts() throws Exception { - _request.setAuthority("foo.com", 0); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(new String[]{"cheese.com"}); handleRequest(); assertEquals("/cheese/bar", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com], Host: foo.com}: no effect"); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); _fooContainerRule.addVirtualHost("foo.com"); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com, foo.com], Host: foo.com}: apply _fooRule"); @@ -185,8 +186,8 @@ private void checkWildcardHost(boolean succeed, String[] ruleHosts, String[] req for (String host : requestHosts) { - _request.setAuthority(host, 0); - _request.setURIPathQuery("/cheese/bar"); + _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority(host, 0).toHttpURI()); + _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); handleRequest(); if (succeed) assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: " + host + "}: should apply _fooRule"); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java index 72d8650c4061..941a691e2f8f 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.security.authentication.BasicAuthenticator; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; @@ -71,7 +72,7 @@ public void startServer() @Override public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { - request.setScheme(HttpScheme.HTTPS.asString()); + request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); request.setSecure(true); } }); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java index af41cc266c88..83a4ba0ad89d 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java @@ -21,9 +21,7 @@ import java.io.IOException; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.Authentication; @@ -77,8 +75,7 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - MetaData.Request metadata = new MetaData.Request(new HttpFields()); - metadata.setURI(new HttpURI("http://localhost")); + MetaData.Request metadata = MetaData.Request.from(null,"http://localhost",null).build(); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); @@ -113,11 +110,10 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - HttpFields httpFields = new HttpFields(); + // Create a bogus Authorization header. We don't care about the actual credentials. - httpFields.add(HttpHeader.AUTHORIZATION, "Basic asdf"); - MetaData.Request metadata = new MetaData.Request(httpFields); - metadata.setURI(new HttpURI("http://localhost")); + MetaData.Request metadata = MetaData.Request.from(null,"http://localhost",null, + fields -> fields.add(HttpHeader.AUTHORIZATION, "Basic asdf")).build(); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java index ebba5f00a6cd..800b2642bc5a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java @@ -22,7 +22,7 @@ import java.util.List; import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -84,7 +84,7 @@ public interface Upgrading extends ConnectionFactory * indicate that the upgrade should proceed. * @throws BadMessageException Thrown to indicate the upgrade attempt was illegal and that a bad message response should be sent. */ - public Connection upgradeConnection(Connector connector, EndPoint endPoint, MetaData.Request upgradeRequest, HttpFields responseFields) throws BadMessageException; + public Connection upgradeConnection(Connector connector, EndPoint endPoint, MetaData.Request upgradeRequest, HttpFieldsBuilder responseFields) throws BadMessageException; } /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java index 33ada4570b9e..e67ad99993d2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CustomRequestLog.java @@ -33,7 +33,7 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import org.eclipse.jetty.http.HttpFieldList; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.QuotedCSV; import org.eclipse.jetty.http.pathmap.PathMappings; import org.eclipse.jetty.server.handler.ContextHandler; @@ -1193,7 +1193,7 @@ private static void logConnectionStatus(StringBuilder b, Request request, Respon private static void logRequestTrailer(String arg, StringBuilder b, Request request, Response response) { - HttpFieldList trailers = request.getTrailerHttpFields(); + HttpFields trailers = request.getTrailerHttpFields(); if (trailers != null) append(b, trailers.get(arg)); else @@ -1202,10 +1202,10 @@ private static void logRequestTrailer(String arg, StringBuilder b, Request reque private static void logResponseTrailer(String arg, StringBuilder b, Request request, Response response) { - Supplier supplier = response.getTrailers(); + Supplier supplier = response.getTrailers(); if (supplier != null) { - HttpFieldList trailers = supplier.get(); + HttpFields trailers = supplier.get(); if (trailers != null) append(b, trailers.get(arg)); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index ea04697e6f45..fd30b41becc7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; @@ -375,7 +374,7 @@ public void setSslIsSecure(boolean sslIsSecure) @Override public void customize(Connector connector, HttpConfiguration config, Request request) { - HttpFieldList httpFields = request.getHttpFields(); + HttpFields httpFields = request.getHttpFields(); boolean wasSecure = request.isSecure(); // Do a single pass through the header fields as it is a more efficient single iteration. @@ -410,18 +409,18 @@ public void customize(Connector connector, HttpConfiguration config, Request req if (forwarded._server != null && forwarded._host instanceof PortSetHostPort) { - request.setHttpFields(new HttpFields(httpFields, + request.setHttpFields(HttpFields.from(httpFields, new HostPortHttpField(forwarded._server, forwarded._host.getPort()))); builder.host(forwarded._server).port(forwarded._host.getPort()); } else if (forwarded._host != null) { - request.setHttpFields(new HttpFields(httpFields, new HostPortHttpField(forwarded._host))); + request.setHttpFields(HttpFields.from(httpFields, new HostPortHttpField(forwarded._host))); builder.host(forwarded._host.getHost()).port(forwarded._host.getPort()); } else if (forwarded._server != null) { - request.setHttpFields(new HttpFields(httpFields, new HostPortHttpField(forwarded._server))); + request.setHttpFields(HttpFields.from(httpFields, new HostPortHttpField(forwarded._server))); builder.host(forwarded._server).port(0); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 64455287c62d..1dcf381a23cd 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -36,6 +36,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; @@ -674,7 +675,7 @@ public void onRequest(MetaData.Request request) { _requests.incrementAndGet(); _request.setTimeStamp(System.currentTimeMillis()); - HttpFields fields = _response.getHttpFields(); + HttpFieldsBuilder fields = _response.getHttpFields(); if (_configuration.getSendDateHeader() && !fields.contains(HttpHeader.DATE)) fields.put(_connector.getServer().getDateField()); @@ -711,7 +712,7 @@ public boolean onContentComplete() return false; } - public void onTrailers(HttpFields trailers) + public void onTrailers(HttpFieldsBuilder trailers) { if (LOG.isDebugEnabled()) LOG.debug("onTrailers {} {}", this, trailers); @@ -791,7 +792,7 @@ public void onBadMessage(BadMessageException failure) if (action == Action.DISPATCH) { ByteBuffer content = null; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); ErrorHandler handler = getServer().getBean(ErrorHandler.class); if (handler != null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index c8a2a7288d4e..9e78930d744c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -59,7 +60,7 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque private boolean _expect100Continue = false; private boolean _expect102Processing = false; private List _complianceViolations; - private HttpFields _trailers; + private HttpFieldsBuilder _trailers; public HttpChannelOverHttp(HttpConnection httpConnection, Connector connector, HttpConfiguration config, EndPoint endPoint, HttpTransport transport) { @@ -68,128 +69,47 @@ public HttpChannelOverHttp(HttpConnection httpConnection, Connector connector, H } @Override - public boolean isUseOutputDirectByteBuffers() - { - return _httpConnection.isUseOutputDirectByteBuffers(); - } - - @Override - protected HttpInput newHttpInput(HttpChannelState state) - { - return new HttpInputOverHTTP(state); - } - - @Override - public void recycle() - { - super.recycle(); - _unknownExpectation = false; - _expect100Continue = false; - _expect102Processing = false; - _connection = null; - _upgrade = null; - _trailers = null; - _metadata = null; - } - - @Override - public boolean isExpecting100Continue() + public void abort(Throwable failure) { - return _expect100Continue; + super.abort(failure); + _httpConnection.getGenerator().setPersistent(false); } @Override - public boolean isExpecting102Processing() + public void badMessage(BadMessageException failure) { - return _expect102Processing; - } + _httpConnection.getGenerator().setPersistent(false); + try + { + // Need to call onRequest, so RequestLog can reports as much as possible + if (_metadata == null) + _metadata = _requestBuilder.build(); + onRequest(_metadata); + getRequest().getHttpInput().earlyEOF(); + } + catch (Exception e) + { + LOG.trace("IGNORED", e); + } - @Override - public void startRequest(String method, String uri, HttpVersion version) - { - _requestBuilder.request(method, uri, version); - _unknownExpectation = false; - _expect100Continue = false; - _expect102Processing = false; + onBadMessage(failure); } @Override - public void parsedHeader(HttpField field) + public boolean content(ByteBuffer content) { - HttpHeader header = field.getHeader(); - String value = field.getValue(); - if (header != null) - { - switch (header) - { - case CONNECTION: - _connection = field; - break; - - case HOST: - if (!(field instanceof HostPortHttpField) && value != null && !value.isEmpty()) - field = new HostPortHttpField(value); - break; - - case EXPECT: - { - if (HttpVersion.HTTP_1_1.equals(_requestBuilder.version())) - { - HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value); - switch (expect == null ? HttpHeaderValue.UNKNOWN : expect) - { - case CONTINUE: - _expect100Continue = true; - break; - - case PROCESSING: - _expect102Processing = true; - break; - - default: - String[] values = field.getValues(); - for (int i = 0; values != null && i < values.length; i++) - { - expect = HttpHeaderValue.CACHE.get(values[i].trim()); - if (expect == null) - _unknownExpectation = true; - else - { - switch (expect) - { - case CONTINUE: - _expect100Continue = true; - break; - case PROCESSING: - _expect102Processing = true; - break; - default: - _unknownExpectation = true; - } - } - } - } - } - break; - } - - case UPGRADE: - _upgrade = field; - break; - - default: - break; - } - } - _requestBuilder.add(field); + HttpInput.Content c = _httpConnection.newContent(content); + boolean handle = onContent(c) || _delayedForContent; + _delayedForContent = false; + return handle; } @Override - public void parsedTrailer(HttpField field) + public boolean contentComplete() { - if (_trailers == null) - _trailers = new HttpFields(); - _trailers.add(field); + boolean handle = onContentComplete() || _delayedForContent; + _delayedForContent = false; + return handle; } /** @@ -229,57 +149,16 @@ public void earlyEOF() if (_metadata == null) _httpConnection.close(); else if (onEarlyEOF() || _delayedForContent) - { + { _delayedForContent = false; handle(); } } @Override - public boolean content(ByteBuffer content) - { - HttpInput.Content c = _httpConnection.newContent(content); - boolean handle = onContent(c) || _delayedForContent; - _delayedForContent = false; - return handle; - } - - @Override - public void onAsyncWaitForContent() - { - _httpConnection.asyncReadFillInterested(); - } - - @Override - public void onBlockWaitForContent() - { - _httpConnection.blockingReadFillInterested(); - } - - @Override - public void onBlockWaitForContentFailure(Throwable failure) - { - _httpConnection.blockingReadFailure(failure); - } - - @Override - public void badMessage(BadMessageException failure) + public EndPoint getTunnellingEndPoint() { - _httpConnection.getGenerator().setPersistent(false); - try - { - // Need to call onRequest, so RequestLog can reports as much as possible - if (_metadata == null) - _metadata = _requestBuilder.build(); - onRequest(_metadata); - getRequest().getHttpInput().earlyEOF(); - } - catch (Exception e) - { - LOG.trace("IGNORED", e); - } - - onBadMessage(failure); + return getEndPoint(); } @Override @@ -312,7 +191,7 @@ public boolean headerComplete() if (_connection.contains(HttpHeaderValue.KEEP_ALIVE.asString())) persistent = true; else - persistent = _requestBuilder.contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()); + persistent = _requestBuilder.getFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()); } else persistent = false; @@ -343,7 +222,7 @@ public boolean headerComplete() if (_connection.contains(HttpHeaderValue.CLOSE.asString())) persistent = false; else - persistent = !_requestBuilder.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()); // handle multiple connection fields + persistent = !_requestBuilder.getFields().contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()); // handle multiple connection fields } else persistent = true; @@ -368,9 +247,9 @@ public boolean headerComplete() _upgrade = PREAMBLE_UPGRADE_H2C; if (HttpMethod.PRI.is(_metadata.getMethod()) && - "*".equals(_metadata.getURI().getPath()) && - _requestBuilder.size() == 0 && - upgrade()) + "*".equals(_metadata.getURI().getPath()) && + _requestBuilder.getFields().size() == 0 && + upgrade()) return true; badMessage(new BadMessageException(HttpStatus.UPGRADE_REQUIRED_426)); @@ -398,16 +277,172 @@ public boolean headerComplete() return !_delayedForContent; } - boolean onIdleTimeout(Throwable timeout) + @Override + public boolean isExpecting100Continue() { - if (_delayedForContent) + return _expect100Continue; + } + + @Override + public boolean isExpecting102Processing() + { + return _expect102Processing; + } + + @Override + public boolean isTunnellingSupported() + { + return true; + } + + @Override + public boolean isUseOutputDirectByteBuffers() + { + return _httpConnection.isUseOutputDirectByteBuffers(); + } + + @Override + public boolean messageComplete() + { + if (_trailers != null) + onTrailers(_trailers); + return onRequestComplete(); + } + + @Override + public void onAsyncWaitForContent() + { + _httpConnection.asyncReadFillInterested(); + } + + @Override + public void onBlockWaitForContent() + { + _httpConnection.blockingReadFillInterested(); + } + + @Override + public void onBlockWaitForContentFailure(Throwable failure) + { + _httpConnection.blockingReadFailure(failure); + } + + @Override + public void onComplianceViolation(ComplianceViolation.Mode mode, ComplianceViolation violation, String details) + { + if (_httpConnection.isRecordHttpComplianceViolations()) { - _delayedForContent = false; - getRequest().getHttpInput().onIdleTimeout(timeout); - execute(this); - return false; + if (_complianceViolations == null) + { + _complianceViolations = new ArrayList<>(); + } + String record = String.format("%s (see %s) in mode %s for %s in %s", + violation.getDescription(), violation.getURL(), mode, details, getHttpTransport()); + _complianceViolations.add(record); + if (LOG.isDebugEnabled()) + LOG.debug(record); } - return true; + } + + @Override + public void parsedHeader(HttpField field) + { + HttpHeader header = field.getHeader(); + String value = field.getValue(); + if (header != null) + { + switch (header) + { + case CONNECTION: + _connection = field; + break; + + case HOST: + if (!(field instanceof HostPortHttpField) && value != null && !value.isEmpty()) + field = new HostPortHttpField(value); + break; + + case EXPECT: + { + if (HttpVersion.HTTP_1_1.equals(_requestBuilder.version())) + { + HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value); + switch (expect == null ? HttpHeaderValue.UNKNOWN : expect) + { + case CONTINUE: + _expect100Continue = true; + break; + + case PROCESSING: + _expect102Processing = true; + break; + + default: + String[] values = field.getValues(); + for (int i = 0; values != null && i < values.length; i++) + { + expect = HttpHeaderValue.CACHE.get(values[i].trim()); + if (expect == null) + _unknownExpectation = true; + else + { + switch (expect) + { + case CONTINUE: + _expect100Continue = true; + break; + case PROCESSING: + _expect102Processing = true; + break; + default: + _unknownExpectation = true; + } + } + } + } + } + break; + } + + case UPGRADE: + _upgrade = field; + break; + + default: + break; + } + } + _requestBuilder.getFields().add(field); + } + + @Override + public void parsedTrailer(HttpField field) + { + if (_trailers == null) + _trailers = HttpFields.empty(); + _trailers.add(field); + } + + @Override + public void recycle() + { + super.recycle(); + _unknownExpectation = false; + _expect100Continue = false; + _expect102Processing = false; + _connection = null; + _upgrade = null; + _trailers = null; + _metadata = null; + } + + @Override + public void startRequest(String method, String uri, HttpVersion version) + { + _requestBuilder.request(method, uri, version); + _unknownExpectation = false; + _expect100Continue = false; + _expect102Processing = false; } @Override @@ -417,6 +452,19 @@ protected boolean checkAndPrepareUpgrade() return false; } + @Override + protected void handleException(Throwable x) + { + _httpConnection.getGenerator().setPersistent(false); + super.handleException(x); + } + + @Override + protected HttpInput newHttpInput(HttpChannelState state) + { + return new HttpInputOverHTTP(state); + } + /** *

Attempts to perform an HTTP/1.1 upgrade.

*

The upgrade looks up a {@link ConnectionFactory.Upgrading} from the connector @@ -454,7 +502,7 @@ private boolean upgrade() throws BadMessageException } // Create new connection - HttpFields response101 = new HttpFields(); + HttpFieldsBuilder response101 = HttpFields.empty(); Connection upgradeConnection = factory.upgradeConnection(getConnector(), getEndPoint(), _metadata, response101); if (upgradeConnection == null) { @@ -481,62 +529,15 @@ private boolean upgrade() throws BadMessageException return true; } - @Override - protected void handleException(Throwable x) - { - _httpConnection.getGenerator().setPersistent(false); - super.handleException(x); - } - - @Override - public void abort(Throwable failure) - { - super.abort(failure); - _httpConnection.getGenerator().setPersistent(false); - } - - @Override - public boolean contentComplete() - { - boolean handle = onContentComplete() || _delayedForContent; - _delayedForContent = false; - return handle; - } - - @Override - public boolean messageComplete() - { - if (_trailers != null) - onTrailers(_trailers); - return onRequestComplete(); - } - - @Override - public void onComplianceViolation(ComplianceViolation.Mode mode, ComplianceViolation violation, String details) + boolean onIdleTimeout(Throwable timeout) { - if (_httpConnection.isRecordHttpComplianceViolations()) + if (_delayedForContent) { - if (_complianceViolations == null) - { - _complianceViolations = new ArrayList<>(); - } - String record = String.format("%s (see %s) in mode %s for %s in %s", - violation.getDescription(), violation.getURL(), mode, details, getHttpTransport()); - _complianceViolations.add(record); - if (LOG.isDebugEnabled()) - LOG.debug(record); + _delayedForContent = false; + getRequest().getHttpInput().onIdleTimeout(timeout); + execute(this); + return false; } - } - - @Override - public boolean isTunnellingSupported() - { return true; } - - @Override - public EndPoint getTunnellingEndPoint() - { - return getEndPoint(); - } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index c450a094d74b..e950a0018d19 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -22,7 +22,7 @@ import javax.servlet.http.PushBuilder; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; @@ -41,14 +41,14 @@ public class PushBuilderImpl implements PushBuilder private static final HttpField JettyPush = new HttpField("x-http2-push", "PushBuilder"); private final Request _request; - private final HttpFields _fields; + private final HttpFieldsBuilder _fields; private String _method; private String _queryString; private String _sessionId; private String _path; private String _lastModified; - public PushBuilderImpl(Request request, HttpFields fields, String method, String queryString, String sessionId) + public PushBuilderImpl(Request request, HttpFieldsBuilder fields, String method, String queryString, String sessionId) { super(); _request = request; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index def4257d6f0d..ec84f6f211d7 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.EnumSet; import java.util.Enumeration; import java.util.EventListener; import java.util.HashMap; @@ -72,8 +73,8 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -151,6 +152,7 @@ public class Request implements HttpServletRequest private static final int INPUT_READER = 2; private static final MultiMap NO_PARAMS = new MultiMap<>(); + private static final MultiMap BAD_PARAMS = new MultiMap<>(); /** * Compare inputParameters to NO_PARAMS by Reference @@ -275,7 +277,7 @@ public String toString() private final List _requestAttributeListeners = new ArrayList<>(); private final HttpInput _input; private MetaData.Request _metaData; - private HttpFieldList _httpFields; + private HttpFields _httpFields; private HttpURI _uri; private String _method; private String _contextPath; @@ -320,12 +322,12 @@ public Request(HttpChannel channel, HttpInput input) _input = input; } - public HttpFieldList getHttpFields() + public HttpFields getHttpFields() { return _httpFields; } - public void setHttpFields(HttpFieldList fields) + public void setHttpFields(HttpFields fields) { _httpFields = fields.asImmutable(); } @@ -333,7 +335,7 @@ public void setHttpFields(HttpFieldList fields) @Override public Map getTrailerFields() { - HttpFieldList trailersFields = getTrailerHttpFields(); + HttpFields trailersFields = getTrailerHttpFields(); if (trailersFields == null) return Collections.emptyMap(); Map trailers = new HashMap<>(); @@ -346,10 +348,10 @@ public Map getTrailerFields() return trailers; } - public HttpFieldList getTrailerHttpFields() + public HttpFields getTrailerHttpFields() { MetaData.Request metadata = _metaData; - Supplier trailers = metadata == null ? null : metadata.getTrailerSupplier(); + Supplier trailers = metadata == null ? null : metadata.getTrailerSupplier(); return trailers == null ? null : trailers.get(); } @@ -368,45 +370,26 @@ public boolean isPushSupported() return !isPush() && getHttpChannel().getHttpTransport().isPushSupported(); } + private static EnumSet NOT_PUSHED_HEADERS = EnumSet.of( + HttpHeader.IF_MATCH, + HttpHeader.IF_RANGE, + HttpHeader.IF_UNMODIFIED_SINCE, + HttpHeader.RANGE, + HttpHeader.EXPECT, + HttpHeader.REFERER, + HttpHeader.COOKIE, + HttpHeader.AUTHORIZATION, + HttpHeader.IF_NONE_MATCH, + HttpHeader.IF_MODIFIED_SINCE + ); + @Override public PushBuilder newPushBuilder() { if (!isPushSupported()) return null; - HttpFields fields = new HttpFields(getHttpFields().size() + 5); - - for (HttpField field : getHttpFields()) - { - HttpHeader header = field.getHeader(); - if (header == null) - fields.add(field); - else - { - switch (header) - { - case IF_MATCH: - case IF_RANGE: - case IF_UNMODIFIED_SINCE: - case RANGE: - case EXPECT: - case REFERER: - case COOKIE: - continue; - - case AUTHORIZATION: - continue; - - case IF_NONE_MATCH: - case IF_MODIFIED_SINCE: - // TODO - continue; - - default: - fields.add(field); - } - } - } + HttpFieldsBuilder fields = HttpFields.from(getHttpFields(), NOT_PUSHED_HEADERS); String id; try @@ -511,16 +494,7 @@ private MultiMap getParameters() // Extract query string parameters; these may be replaced by a forward() // and may have already been extracted by mergeQueryParameters(). if (_queryParameters == null) - { - try - { - extractQueryParameters(); - } - catch (IllegalStateException | IllegalArgumentException e) - { - throw new BadMessageException("Unable to parse URI query", e); - } - } + extractQueryParameters(); // Do parameters need to be combined? if (isNoParams(_queryParameters) || _queryParameters.size() == 0) @@ -546,8 +520,16 @@ private void extractQueryParameters() _queryParameters = NO_PARAMS; else { - _queryParameters = new MultiMap<>(); - UrlEncoded.decodeTo(_uri.getQuery(), _queryParameters, _queryEncoding); + try + { + _queryParameters = new MultiMap<>(); + UrlEncoded.decodeTo(_uri.getQuery(), _queryParameters, _queryEncoding); + } + catch (IllegalStateException | IllegalArgumentException e) + { + _queryParameters = BAD_PARAMS; + throw new BadMessageException("Unable to parse URI query", e); + } } } @@ -562,7 +544,7 @@ private void extractContentParameters() int contentLength = getContentLength(); if (contentLength != 0 && _inputState == INPUT_NONE) { - String baseType = HttpFields.valueParameters(contentType, null); + String baseType = HttpField.valueParameters(contentType, null); if (MimeTypes.Type.FORM_ENCODED.is(baseType) && _channel.getHttpConfiguration().isFormEncodedMethod(getMethod())) { @@ -773,30 +755,23 @@ public HttpChannel getHttpChannel() @Override public int getContentLength() { - MetaData.Request metadata = _metaData; - if (metadata == null) - return -1; - - long contentLength = metadata.getContentLength(); - if (contentLength == Long.MIN_VALUE) - contentLength = metadata.getFields().getLongField(HttpHeader.CONTENT_LENGTH.asString()); - + long contentLength = getContentLengthLong(); if (contentLength > Integer.MAX_VALUE) // Per ServletRequest#getContentLength() javadoc this must return -1 for values exceeding Integer.MAX_VALUE return -1; - return (int)contentLength; } @Override public long getContentLengthLong() { - MetaData.Request metadata = _metaData; - if (metadata == null) - return -1L; - if (metadata.getContentLength() != Long.MIN_VALUE) - return metadata.getContentLength(); - return metadata.getFields().getLongField(HttpHeader.CONTENT_LENGTH.asString()); + // Even thought the metadata might know the real content length, + // we always look at the headers because the length may be changed by interceptors. + if (_httpFields == null) + return -1; + + // TODO should we cache this? + return _httpFields.getLongField(HttpHeader.CONTENT_LENGTH.asString()); } public long getContentRead() @@ -879,7 +854,7 @@ public Cookie[] getCookies() @Override public long getDateHeader(String name) { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; return fields == null ? null : fields.getDateField(name); } @@ -892,21 +867,21 @@ public DispatcherType getDispatcherType() @Override public String getHeader(String name) { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; return fields == null ? null : fields.get(name); } @Override public Enumeration getHeaderNames() { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; return fields == null ? Collections.emptyEnumeration() : fields.getFieldNames(); } @Override public Enumeration getHeaders(String name) { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; if (fields == null) return Collections.emptyEnumeration(); Enumeration e = fields.getValues(name); @@ -939,14 +914,14 @@ public ServletInputStream getInputStream() throws IOException @Override public int getIntHeader(String name) { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; return fields == null ? -1 : (int)fields.getLongField(name); } @Override public Locale getLocale() { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; if (fields == null) return Locale.getDefault(); @@ -957,7 +932,7 @@ public Locale getLocale() return Locale.getDefault(); String language = acceptable.get(0); - language = HttpFields.stripParameters(language); + language = HttpField.stripParameters(language); String country = ""; int dash = language.indexOf('-'); if (dash > -1) @@ -971,7 +946,7 @@ public Locale getLocale() @Override public Enumeration getLocales() { - HttpFieldList fields = _httpFields; + HttpFields fields = _httpFields; if (fields == null) return Collections.enumeration(__defaultLocale); @@ -983,7 +958,7 @@ public Enumeration getLocales() List locales = acceptable.stream().map(language -> { - language = HttpFields.stripParameters(language); + language = HttpField.stripParameters(language); String country = ""; int dash = language.indexOf('-'); if (dash > -1) @@ -1147,7 +1122,12 @@ public HttpVersion getHttpVersion() public String getQueryEncoding() { - return _queryEncoding.toString(); + return _queryEncoding == null ? null : _queryEncoding.toString(); + } + + Charset getQueryCharset() + { + return _queryEncoding; } @Override @@ -1288,8 +1268,7 @@ public String getRequestedSessionId() @Override public String getRequestURI() { - MetaData.Request metadata = _metaData; - return metadata == null ? null : metadata.getURI().getPath(); + return _uri == null ? null : _uri.getPath(); } @Override @@ -1552,7 +1531,7 @@ public HttpURI getHttpURI() public void setHttpURI(HttpURI uri) { - if (_uri != null && !Objects.equals(_uri.getQuery(), uri.getQuery())) + if (_uri != null && !Objects.equals(_uri.getQuery(), uri.getQuery()) && _queryParameters != BAD_PARAMS) _parameters = _queryParameters = null; _uri = uri; } @@ -2168,7 +2147,7 @@ public Part getPart(String name) throws IOException, ServletException public Collection getParts() throws IOException, ServletException { String contentType = getContentType(); - if (contentType == null || !MimeTypes.Type.MULTIPART_FORM_DATA.is(HttpFields.valueParameters(contentType, null))) + if (contentType == null || !MimeTypes.Type.MULTIPART_FORM_DATA.is(HttpField.valueParameters(contentType, null))) throw new ServletException("Unsupported Content-Type [" + contentType + "], expected [multipart/form-data]"); return getParts(null); } @@ -2289,10 +2268,11 @@ public void mergeQueryParameters(String oldQuery, String newQuery) oldQueryParams = new MultiMap<>(); try { - UrlEncoded.decodeTo(oldQuery, oldQueryParams, getQueryEncoding()); + UrlEncoded.decodeTo(oldQuery, oldQueryParams, getQueryCharset()); } catch (Throwable th) { + _queryParameters = BAD_PARAMS; throw new BadMessageException(400, "Bad query encoding", th); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 480c283ff9c2..82f19fe7843f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -40,7 +40,7 @@ import org.eclipse.jetty.http.DateParser; import org.eclipse.jetty.http.HttpContent; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.QuotedCSV; @@ -846,7 +846,7 @@ protected void putHeaders(HttpServletResponse response, HttpContent content, lon { Response r = (Response)response; r.putHeaders(content, contentLength, _etags); - HttpFields f = r.getHttpFields(); + HttpFieldsBuilder f = r.getHttpFields(); if (_acceptRanges) f.put(ACCEPT_RANGES); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 371ffb51074b..78592ec1e04d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -44,8 +44,8 @@ import org.eclipse.jetty.http.HttpCookie.SameSite; import org.eclipse.jetty.http.HttpCookie.SetCookieHttpField; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -85,7 +85,7 @@ public enum OutputType public static final String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include."; private final HttpChannel _channel; - private final HttpFields _fields = new HttpFields(); + private final HttpFieldsBuilder _fields = HttpFields.empty(); private final AtomicBiInteger _errorSentAndIncludes = new AtomicBiInteger(); // hi is errorSent flag, lo is include count private final HttpOutput _out; private int _status = HttpStatus.OK_200; @@ -98,7 +98,7 @@ public enum OutputType private OutputType _outputType = OutputType.NONE; private ResponseWriter _writer; private long _contentLength = -1; - private Supplier _trailers; + private Supplier _trailers; private enum EncodingFrom { @@ -1206,12 +1206,12 @@ public void resetBuffer() _out.reopen(); } - public Supplier getTrailers() + public Supplier getTrailers() { return _trailers; } - public void setTrailers(Supplier trailers) + public void setTrailers(Supplier trailers) { _trailers = trailers; } @@ -1307,7 +1307,7 @@ public String getReason() return _reason; } - public HttpFields getHttpFields() + public HttpFieldsBuilder getHttpFields() { return _fields; } @@ -1416,7 +1416,7 @@ public static HttpServletResponse unwrap(ServletResponse servletResponse) return (HttpServletResponse)servletResponse; } - private static class HttpFieldsSupplier implements Supplier + private static class HttpFieldsSupplier implements Supplier { private final Supplier> _supplier; @@ -1426,12 +1426,12 @@ public HttpFieldsSupplier(Supplier> trailers) } @Override - public HttpFieldList get() + public HttpFields get() { Map t = _supplier.get(); if (t == null) return null; - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); for (Map.Entry e : t.entrySet()) { fields.add(e.getKey(), e.getValue()); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 9a9155a76dad..f4c58f70ecb9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -28,10 +28,12 @@ import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpGenerator; @@ -588,13 +590,30 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio } else { - ContextHandler.Context context = baseRequest.getContext(); - if (context != null && !StringUtil.isEmpty(context.getContextPath())) - encodedPathQuery = URIUtil.addEncodedPaths(context.getContextHandler().getContextPathEncoded(), encodedPathQuery); + ServletContext servletContext = event.getServletContext(); + if (servletContext != null) + { + String encodedContextPath = servletContext instanceof ContextHandler.Context + ? ((ContextHandler.Context)servletContext).getContextHandler().getContextPathEncoded() + : URIUtil.encodePath(servletContext.getContextPath()); + if (!StringUtil.isEmpty(encodedContextPath)) + { + encodedPathQuery = URIUtil.canonicalPath(URIUtil.addEncodedPaths(encodedContextPath, encodedPathQuery)); + if (encodedPathQuery == null) + throw new BadMessageException(500,"Bad dispatch path"); + } + } - baseRequest.setHttpURI(HttpURI.from(baseUri == null ? oldUri : baseUri, encodedPathQuery).toHttpURI()); + if (baseUri == null) + baseUri = oldUri; + HttpURI.Builder builder = HttpURI.from(baseUri, encodedPathQuery); + if (StringUtil.isEmpty(builder.param())) + builder.param(baseUri.getParam()); + if (StringUtil.isEmpty(builder.query())) + builder.query(baseUri.getQuery()); + baseRequest.setHttpURI(builder.toHttpURI()); - if (oldUri.getQuery() != null && baseRequest.getQueryString() != null) + if (baseUri.getQuery() != null && baseRequest.getQueryString() != null) // TODO why can't the old map be passed? baseRequest.mergeQueryParameters(oldUri.getQuery(), baseRequest.getQueryString()); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 9bce345f0dea..8a7b16d9da67 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1208,7 +1208,7 @@ else if (_contextPath.length() == 1) if (_contextPath.length() == 1) baseRequest.setContextPath(""); else - baseRequest.setContextPath(getContextPathEncoded()); + baseRequest.setContextPath(getContextPathEncoded()); // TODO shouldn't this be decoded context path??? baseRequest.setServletPath(null); baseRequest.setPathInfo(pathInfo); } @@ -2143,15 +2143,21 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) String contextPath = getContextPath(); HttpURI uri; String pathInfo; - if (StringUtil.isBlank(contextPath)) + if (StringUtil.isEmpty(contextPath)) { uri = new HttpURI.Builder(null, null, 0, uriInContext).toHttpURI(); pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); + if (StringUtil.isEmpty(pathInfo)) + return null; } else { - uri = new HttpURI.Builder(null, null, 0, URIUtil.addPaths(contextPath,uriInContext)).toHttpURI(); - pathInfo = URIUtil.canonicalPath(uri.getDecodedPath().substring(contextPath.length())); + HttpURI.Builder builder = new HttpURI.Builder(null, null, 0, uriInContext); + if (StringUtil.isEmpty(URIUtil.canonicalPath(builder.decodedPath()))) + return null; + builder.path(URIUtil.addPaths(contextPath,builder.path())); + uri = builder.toHttpURI(); + pathInfo = uri.getDecodedPath().substring(contextPath.length()); } return new Dispatcher(ContextHandler.this, uri, pathInfo); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index 0e5445facf26..684f15cd4dd6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -36,7 +36,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MimeTypes; @@ -56,7 +56,7 @@ * An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or * {@link Server#setErrorHandler(ErrorHandler)}. * It is called by the HttpResponse.sendError method to write an error page via {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} - * or via {@link #badMessageError(int, String, HttpFields)} for bad requests for which a dispatch cannot be done. + * or via {@link #badMessageError(int, String, HttpFieldsBuilder)} for bad requests for which a dispatch cannot be done. */ public class ErrorHandler extends AbstractHandler { @@ -521,10 +521,11 @@ protected void writeErrorPageStacks(HttpServletRequest request, Writer writer) * @param fields The header fields that will be sent with the response. * @return The content as a ByteBuffer, or null for no body. */ - public ByteBuffer badMessageError(int status, String reason, HttpFields fields) + public ByteBuffer badMessageError(int status, String reason, HttpFieldsBuilder fields) { if (reason == null) reason = HttpStatus.getMessage(status); + // TODO only if a status allows a body! fields.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.TEXT_HTML_8859_1.asString()); return BufferUtil.toBuffer("

Bad Message " + status + "

reason: " + reason + "
"); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index cc7107f2f67a..eb4052640b93 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -32,8 +32,8 @@ import org.eclipse.jetty.http.CompressedContentFormat; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldList; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -594,7 +594,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques } // Handle request inflation - HttpFieldList httpFields = baseRequest.getHttpFields(); + HttpFields httpFields = baseRequest.getHttpFields(); boolean inflated = _inflateBufferSize > 0 && httpFields.contains(HttpHeader.CONTENT_ENCODING, "gzip"); if (inflated) { @@ -620,7 +620,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques // Update headers for etags and inflation if (inflated || httpFields.contains(ETAG_HEADERS)) { - HttpFields newFields = new HttpFields(httpFields.size() + 1); + HttpFieldsBuilder newFields = HttpFields.empty(httpFields.size() + 1); for (HttpField field : httpFields) { if (field.getHeader() == null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java index 3ec13e3a46b9..e2da22561c56 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java @@ -25,7 +25,7 @@ import java.util.zip.Deflater; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; @@ -175,7 +175,7 @@ protected void commit(ByteBuffer content, boolean complete, Callback callback) } // Has the Content-Encoding header already been set? - HttpFields fields = response.getHttpFields(); + HttpFieldsBuilder fields = response.getHttpFields(); String ce = fields.get(HttpHeader.CONTENT_ENCODING); if (ce != null) { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java index 52dd7d94c6b7..f98782f7f1aa 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java @@ -22,7 +22,9 @@ import java.util.List; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.LocalConnector.LocalEndPoint; @@ -81,11 +83,10 @@ public void test33() { try { - HttpFields fields = new HttpFields(); - - fields.put("D1", "Sun, 6 Nov 1994 08:49:37 GMT"); - fields.put("D2", "Sunday, 6-Nov-94 08:49:37 GMT"); - fields.put("D3", "Sun Nov 6 08:49:37 1994"); + HttpFieldsBuilder fields = HttpFields.empty() + .put("D1", "Sun, 6 Nov 1994 08:49:37 GMT") + .put("D2", "Sunday, 6-Nov-94 08:49:37 GMT") + .put("D3", "Sun Nov 6 08:49:37 1994"); Date d1 = new Date(fields.getDateField("D1")); Date d2 = new Date(fields.getDateField("D2")); Date d3 = new Date(fields.getDateField("D3")); @@ -99,7 +100,7 @@ public void test33() catch (Exception e) { e.printStackTrace(); - assertTrue(false); + fail(); } } @@ -274,16 +275,15 @@ public void test36d() throws Exception @Test public void test39() throws Exception { - HttpFields fields = new HttpFields(); - - fields.put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7"); + HttpFields fields = HttpFields.empty() + .put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7").asImmutable(); List list = fields.getQualityCSV("Q"); - assertEquals("aaa", HttpFields.valueParameters(list.get(0), null), "Quality parameters"); - assertEquals("aa2", HttpFields.valueParameters(list.get(1), null), "Quality parameters"); - assertEquals("abb", HttpFields.valueParameters(list.get(2), null), "Quality parameters"); - assertEquals("bbb", HttpFields.valueParameters(list.get(3), null), "Quality parameters"); - assertEquals("ccc", HttpFields.valueParameters(list.get(4), null), "Quality parameters"); - assertEquals("ddd", HttpFields.valueParameters(list.get(5), null), "Quality parameters"); + assertEquals("aaa", HttpField.valueParameters(list.get(0), null), "Quality parameters"); + assertEquals("aa2", HttpField.valueParameters(list.get(1), null), "Quality parameters"); + assertEquals("abb", HttpField.valueParameters(list.get(2), null), "Quality parameters"); + assertEquals("bbb", HttpField.valueParameters(list.get(3), null), "Quality parameters"); + assertEquals("ccc", HttpField.valueParameters(list.get(4), null), "Quality parameters"); + assertEquals("ddd", HttpField.valueParameters(list.get(5), null), "Quality parameters"); } @Test diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index b1a101d96c75..8b32af440a8d 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -1331,7 +1331,7 @@ public void testFlushAfterFullContent() throws Exception private Response getResponse() { _channel.recycle(); - _channel.getRequest().setMetaData(new MetaData.Request("GET", new HttpURI("/path/info"), HttpVersion.HTTP_1_0, new HttpFields())); + _channel.getRequest().setMetaData(new MetaData.Request("GET", new HttpURI("/path/info"), HttpVersion.HTTP_1_0, HttpFields.EMPTY)); BufferUtil.clear(_content); return _channel.getResponse(); } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java index c37918952fe0..8eb6e6a9a61a 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java @@ -38,7 +38,7 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -154,7 +154,7 @@ public List getSubProtocols() public void setSubProtocols(String... protocols) { - HttpFields headers = getHeaders(); + HttpFieldsBuilder headers = getHeaders(); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); for (String protocol : protocols) { @@ -164,7 +164,7 @@ public void setSubProtocols(String... protocols) public void setSubProtocols(List protocols) { - HttpFields headers = getHeaders(); + HttpFieldsBuilder headers = getHeaders(); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); for (String protocol : protocols) { diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java index a4e2dd6d62e4..ba28a3ae27fe 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.HttpResponse; import org.eclipse.jetty.client.HttpResponseException; import org.eclipse.jetty.client.HttpUpgrader; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -75,10 +75,10 @@ private String generateRandomKey() public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback) { HttpRequest request = (HttpRequest)response.getRequest(); - HttpFields requestHeaders = request.getHeaders(); + HttpFieldsBuilder requestHeaders = request.getHeaders(); if (requestHeaders.contains(HttpHeader.UPGRADE, "websocket")) { - HttpFields responseHeaders = response.getHeaders(); + HttpFieldsBuilder responseHeaders = response.getHeaders(); if (responseHeaders.contains(HttpHeader.CONNECTION, "upgrade")) { // Check the Accept hash diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java index 6c876730f02d..cf8ed3d497fd 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java @@ -23,7 +23,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -106,7 +106,7 @@ protected WebSocketConnection createWebSocketConnection(Request baseRequest, Web protected void prepareResponse(Response response, Negotiation negotiation) { response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); - HttpFields responseFields = response.getHttpFields(); + HttpFieldsBuilder responseFields = response.getHttpFields(); responseFields.put(UPGRADE_WEBSOCKET); responseFields.put(CONNECTION_UPGRADE); responseFields.put(HttpHeader.SEC_WEBSOCKET_ACCEPT, WebSocketCore.hashKey(((RFC6455Negotiation)negotiation).getKey())); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java index 5f9e5482426d..3492c9c19f88 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java @@ -31,7 +31,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.HttpChannel; @@ -255,7 +255,7 @@ public void testExtensionThatDoesNotExist() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFields httpFields = newUpgradeRequest("nonExistentExtensionName"); + HttpFieldsBuilder httpFields = newUpgradeRequest("nonExistentExtensionName"); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1)); String response = getUpgradeResponse(client.getInputStream()); @@ -336,7 +336,7 @@ public void testValidUpgradeRequest() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFields httpFields = newUpgradeRequest(null); + HttpFieldsBuilder httpFields = newUpgradeRequest(null); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1)); String response = getUpgradeResponse(client.getInputStream()); @@ -352,7 +352,7 @@ public void testInvalidUpgradeRequestNoKey() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFields httpFields = newUpgradeRequest(null); + HttpFieldsBuilder httpFields = newUpgradeRequest(null); httpFields.remove(HttpHeader.SEC_WEBSOCKET_KEY); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java index d54fa0938e5d..7748da0cac59 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java @@ -28,6 +28,7 @@ import java.util.Base64; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.ArrayByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool; @@ -86,17 +87,17 @@ protected Socket newClient(int port, String extensions) throws Exception return newClient(port, false, extensions); } - protected static HttpFields newUpgradeRequest(String extensions) + protected static HttpFieldsBuilder newUpgradeRequest(String extensions) { - HttpFields fields = new HttpFields(); - fields.add(HttpHeader.HOST, "127.0.0.1"); - fields.add(HttpHeader.UPGRADE, "websocket"); - fields.add(HttpHeader.CONNECTION, "Upgrade"); - fields.add(HttpHeader.SEC_WEBSOCKET_KEY, NON_RANDOM_KEY); - fields.add(HttpHeader.SEC_WEBSOCKET_VERSION, "13"); - fields.add(HttpHeader.PRAGMA, "no-cache"); - fields.add(HttpHeader.CACHE_CONTROL, "no-cache"); - fields.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "test"); + HttpFieldsBuilder fields = HttpFields.empty() + .add(HttpHeader.HOST, "127.0.0.1") + .add(HttpHeader.UPGRADE, "websocket") + .add(HttpHeader.CONNECTION, "Upgrade") + .add(HttpHeader.SEC_WEBSOCKET_KEY, NON_RANDOM_KEY) + .add(HttpHeader.SEC_WEBSOCKET_VERSION, "13") + .add(HttpHeader.PRAGMA, "no-cache") + .add(HttpHeader.CACHE_CONTROL, "no-cache") + .add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "test"); if (extensions != null) fields.add(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, extensions); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java index 8d3a40bae68e..d8e0b1f1c2fe 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.websocket.core.CoreSession; import org.eclipse.jetty.websocket.core.ExtensionConfig; @@ -106,7 +106,7 @@ public void testClientDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @deflate_buffer_size=" + deflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -121,7 +121,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFields requestHeaders = futureRequestHeaders.get(); + HttpFieldsBuilder requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -160,7 +160,7 @@ public void testClientInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @inflate_buffer_size=" + inflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -175,7 +175,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFields requestHeaders = futureRequestHeaders.get(); + HttpFieldsBuilder requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -215,7 +215,7 @@ public void testServerDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -230,7 +230,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFields responseHeaders = futureResponseHeaders.get(); + HttpFieldsBuilder responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -270,7 +270,7 @@ public void testServerInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -285,7 +285,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFields responseHeaders = futureResponseHeaders.get(); + HttpFieldsBuilder responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); diff --git a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java index 8ce0df47cdb3..ec5e72667aa6 100644 --- a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java +++ b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java @@ -28,7 +28,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.websocket.core.client.UpgradeListener; public class JsrUpgradeListener implements UpgradeListener @@ -48,7 +48,7 @@ public void onHandshakeRequest(HttpRequest request) return; } - HttpFields fields = request.getHeaders(); + HttpFieldsBuilder fields = request.getHeaders(); Map> originalHeaders = new HashMap<>(); fields.forEach((field) -> @@ -76,7 +76,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) HandshakeResponse handshakeResponse = () -> { - HttpFields fields = response.getHeaders(); + HttpFieldsBuilder fields = response.getHeaders(); Map> ret = new HashMap<>(); fields.forEach((field) -> { diff --git a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java index a82972a61a74..02a6bd0b9e4d 100644 --- a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java +++ b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java @@ -30,7 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; @@ -72,7 +72,7 @@ public NetworkFuzzer(LocalServer server, URI wsURI, Map requestH this.upgradeRequest = new RawUpgradeRequest(client, wsURI); if (requestHeaders != null) { - HttpFields fields = this.upgradeRequest.getHeaders(); + HttpFieldsBuilder fields = this.upgradeRequest.getHeaders(); requestHeaders.forEach((name, value) -> { fields.remove(name); diff --git a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java index 85ab93c0851e..25211c92ec86 100644 --- a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java +++ b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; @@ -49,14 +49,14 @@ public JettyClientUpgradeRequest(WebSocketCoreClient coreClient, UpgradeRequest if (request != null) { // Copy request details into actual request - HttpFields fields = getHeaders(); + HttpFieldsBuilder fields = getHeaders(); request.getHeaders().forEach(fields::put); // Copy manually created Cookies into place List cookies = request.getCookies(); if (cookies != null) { - HttpFields headers = getHeaders(); + HttpFieldsBuilder headers = getHeaders(); // TODO: remove existing Cookie header (if set)? for (HttpCookie cookie : cookies) { diff --git a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java index 6f0c62e6cdb1..1e9124035dec 100644 --- a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java +++ b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java @@ -28,7 +28,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; @@ -289,7 +289,7 @@ private static void parseResponse(Input in, HttpParser parser, Response r) throw } } - public abstract static class Message extends HttpFields implements HttpParser.HttpHandler + public abstract static class Message extends HttpFieldsBuilder implements HttpParser.HttpHandler { boolean _earlyEOF; boolean _complete = false; diff --git a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java index f7572db8b73e..fca5ba44d91f 100644 --- a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java +++ b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.http.tools.matchers; import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; @@ -30,10 +31,11 @@ public class HttpFieldsMatchersTest @Test public void testContainsHeader() { - HttpFields fields = new HttpFields(); - fields.put("a", "foo"); - fields.put("b", "bar"); - fields.put("c", "fizz"); + HttpFields fields = HttpFields.empty() + .put("a", "foo") + .put("b", "bar") + .put("c", "fizz") + .asImmutable(); MatcherAssert.assertThat(fields, HttpFieldsMatchers.containsHeader("a")); } @@ -41,10 +43,10 @@ public void testContainsHeader() @Test public void testNotContainsHeader() { - HttpFields fields = new HttpFields(); - fields.put("a", "foo"); - fields.put("b", "bar"); - fields.put("c", "fizz"); + HttpFieldsBuilder fields = HttpFields.empty() + .put("a", "foo") + .put("b", "bar") + .put("c", "fizz"); AssertionError x = Assertions.assertThrows(AssertionError.class, () -> { @@ -57,7 +59,7 @@ public void testNotContainsHeader() @Test public void testContainsHeaderMisMatch() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -73,7 +75,7 @@ public void testContainsHeaderMisMatch() @Test public void testContainsHeaderValueMisMatchNoSuchHeader() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -89,7 +91,7 @@ public void testContainsHeaderValueMisMatchNoSuchHeader() @Test public void testContainsHeaderValueMisMatchNoSuchValue() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -105,7 +107,7 @@ public void testContainsHeaderValueMisMatchNoSuchValue() @Test public void testContainsHeaderValue() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java index 138f809796f6..f88be942ac97 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java @@ -38,7 +38,7 @@ import org.eclipse.jetty.client.util.BytesRequestContent; import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Request; @@ -98,13 +98,13 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } // Now the trailers can be accessed. - HttpFields trailers = jettyRequest.getTrailerHttpFields(); + HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); } }); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); trailers.put(trailerName, trailerValue); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); @@ -135,12 +135,12 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } // Now the trailers can be accessed. - HttpFields trailers = jettyRequest.getTrailerHttpFields(); + HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); assertNull(trailers); } }); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); request = request.trailers(() -> trailers); ContentResponse response = request.timeout(5, TimeUnit.SECONDS).send(); @@ -177,7 +177,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r if (once.compareAndSet(false, true)) { - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); trailers.put(trailerName, trailerValue); jettyResponse.setTrailers(() -> trailers); } @@ -194,7 +194,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r try { HttpResponse httpResponse = (HttpResponse)r; - HttpFields trailers = httpResponse.getTrailers(); + HttpFieldsBuilder trailers = httpResponse.getTrailers(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); failure.set(null); @@ -240,7 +240,7 @@ public void testEmptyResponseTrailers(Transport transport) throws Exception @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); response.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); } @@ -253,7 +253,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r try { HttpResponse httpResponse = (HttpResponse)r; - HttpFields trailers = httpResponse.getTrailers(); + HttpFieldsBuilder trailers = httpResponse.getTrailers(); assertNull(trailers); failure.set(null); } @@ -282,7 +282,7 @@ public void testResponseTrailersWithLargeContent(Transport transport) throws Exc @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); trailers.put(trailerName, trailerValue); response.setTrailerFields(() -> @@ -317,7 +317,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r listener.await(5, TimeUnit.SECONDS); HttpResponse httpResponse = (HttpResponse)response; - HttpFields trailers = httpResponse.getTrailers(); + HttpFieldsBuilder trailers = httpResponse.getTrailers(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); } @@ -333,7 +333,7 @@ public void testResponseResetAlsoResetsTrailers(Transport transport) throws Exce protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Response jettyResponse = jettyRequest.getResponse(); - HttpFields trailers = new HttpFields(); + HttpFieldsBuilder trailers = HttpFields.from(); trailers.put("name", "value"); jettyResponse.setTrailers(() -> trailers); // Fill some other response field. diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java index 1988361ca0c1..7f1c9aae0e03 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java @@ -41,7 +41,6 @@ import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic; import org.eclipse.jetty.client.http.HttpClientConnectionFactory; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -442,7 +441,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, new HttpFields(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.from(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); @@ -527,7 +526,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, new HttpFields(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.from(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java index 3517b2a22298..e96cfe1306f7 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java @@ -27,7 +27,8 @@ import java.util.List; import java.util.TimeZone; -import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; @@ -136,7 +137,7 @@ public void test33() expected.set(Calendar.ZONE_OFFSET, 0); // Use GMT+0:00 expected.set(Calendar.DST_OFFSET, 0); // No Daylight Savings Offset - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); // RFC 822 Preferred Format fields.put("D1", "Sun, 6 Nov 1994 08:49:37 GMT"); @@ -333,16 +334,16 @@ public void test364() throws Throwable @Test public void test39() { - HttpFields fields = new HttpFields(); + HttpFieldsBuilder fields = HttpFields.from(); fields.put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7"); List list = fields.getQualityCSV("Q"); - assertEquals("aaa", HttpFields.valueParameters(list.get(0).toString(), null), "Quality parameters"); - assertEquals("aa2", HttpFields.valueParameters(list.get(1).toString(), null), "Quality parameters"); - assertEquals("abb", HttpFields.valueParameters(list.get(2).toString(), null), "Quality parameters"); - assertEquals("bbb", HttpFields.valueParameters(list.get(3).toString(), null), "Quality parameters"); - assertEquals("ccc", HttpFields.valueParameters(list.get(4).toString(), null), "Quality parameters"); - assertEquals("ddd", HttpFields.valueParameters(list.get(5).toString(), null), "Quality parameters"); + assertEquals("aaa", HttpField.valueParameters(list.get(0).toString(), null), "Quality parameters"); + assertEquals("aa2", HttpField.valueParameters(list.get(1).toString(), null), "Quality parameters"); + assertEquals("abb", HttpField.valueParameters(list.get(2).toString(), null), "Quality parameters"); + assertEquals("bbb", HttpField.valueParameters(list.get(3).toString(), null), "Quality parameters"); + assertEquals("ccc", HttpField.valueParameters(list.get(4).toString(), null), "Quality parameters"); + assertEquals("ddd", HttpField.valueParameters(list.get(5).toString(), null), "Quality parameters"); } /** diff --git a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java index 6e19307cbdc7..930e633fe8ca 100644 --- a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java +++ b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java @@ -28,7 +28,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -91,7 +90,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t public void succeeded(Session session) { HttpURI uri = new HttpURI(request.getScheme(), host, port, contextPath + "/h2"); - MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields()); + MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter() { From 23bcdd205555f292f73b4cd74c05bf9169234df6 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sun, 19 Apr 2020 17:18:49 +0200 Subject: [PATCH 12/38] Immutable MetaData WIP Need to consider if content-length really is meta data and how much and when can we trust it. Also need to consider difference between h2 and h1 authority in metadata. Signed-off-by: Greg Wilkins --- .../java/client/ConscryptHTTP2ClientTest.java | 3 +- .../alpn/java/client/JDK9HTTP2ClientTest.java | 3 +- .../eclipse/jetty/client/HttpConnection.java | 4 +- .../org/eclipse/jetty/client/api/Request.java | 4 +- .../util/BufferingResponseListener.java | 2 +- .../src/main/java/embedded/HTTP2Docs.java | 5 +- .../client/http2/HTTP2ClientDocs.java | 29 +++---- .../embedded/server/http/HTTPServerDocs.java | 4 +- .../server/http2/HTTP2ServerDocs.java | 10 +-- .../fcgi/client/http/HttpSenderOverFCGI.java | 9 +-- .../fcgi/parser/ResponseContentParser.java | 3 +- .../fcgi/generator/ClientGeneratorTest.java | 3 +- .../jetty/fcgi/parser/ClientParserTest.java | 9 ++- .../fcgi/server/HttpChannelOverFCGI.java | 3 +- .../org/eclipse/jetty/http/HttpGenerator.java | 2 +- .../java/org/eclipse/jetty/http/MetaData.java | 81 +++---------------- .../jetty/http2/client/AsyncIOTest.java | 9 ++- .../jetty/http2/client/AsyncServletTest.java | 11 +-- .../jetty/http2/client/ConnectTunnelTest.java | 4 +- .../jetty/http2/client/DataDemandTest.java | 19 ++--- .../http2/client/FlowControlStalledTest.java | 13 +-- .../http2/client/FlowControlStrategyTest.java | 45 ++++++----- .../http2/client/FlowControlWindowsTest.java | 5 +- .../eclipse/jetty/http2/client/HTTP2Test.java | 57 ++++++------- .../jetty/http2/client/IdleTimeoutTest.java | 37 ++++----- .../jetty/http2/client/InterleavingTest.java | 9 ++- .../http2/client/MaxPushedStreamsTest.java | 9 ++- .../jetty/http2/client/PrefaceTest.java | 7 +- .../jetty/http2/client/PriorityTest.java | 15 ++-- .../jetty/http2/client/ProxyProtocolTest.java | 5 +- .../eclipse/jetty/http2/client/ProxyTest.java | 3 +- .../http2/client/PushCacheFilterTest.java | 45 ++++++----- .../jetty/http2/client/RawHTTP2ProxyTest.java | 15 ++-- .../http2/client/SessionFailureTest.java | 2 +- .../http2/client/SmallThreadPoolLoadTest.java | 3 +- .../jetty/http2/client/StreamCloseTest.java | 27 ++++--- .../jetty/http2/client/StreamCountTest.java | 9 ++- .../jetty/http2/client/StreamResetTest.java | 37 ++++----- .../jetty/http2/client/TrailersTest.java | 27 ++++--- .../org/eclipse/jetty/http2/HTTP2Stream.java | 6 +- .../http2/frames/ContinuationParseTest.java | 3 +- .../frames/HeadersGenerateParseTest.java | 5 +- .../frames/PushPromiseGenerateParseTest.java | 5 +- .../jetty/http2/hpack/MetaDataBuilder.java | 4 +- .../eclipse/jetty/http2/hpack/HpackTest.java | 2 +- .../HttpClientTransportOverHTTP2Test.java | 11 +-- .../client/http/PushedResourcesTest.java | 5 +- .../client/http/RequestTrailersTest.java | 13 +-- .../client/http/ResponseTrailerTest.java | 2 +- .../eclipse/jetty/http2/server/CloseTest.java | 13 +-- .../jetty/http2/server/HTTP2CServerTest.java | 5 +- .../jetty/http2/server/HTTP2ServerTest.java | 25 +++--- .../jetty/proxy/AsyncMiddleManServlet.java | 2 +- .../SpnegoAuthenticatorTest.java | 9 ++- .../jetty/server/HttpChannelOverHttp.java | 39 ++++++++- .../org/eclipse/jetty/server/Request.java | 4 +- .../jetty/http/client/HttpTrailersTest.java | 13 +-- .../client/ProxyWithDynamicTransportTest.java | 5 +- .../jetty/test/rfcs/RFC2616BaseTest.java | 5 +- .../jetty/test/webapp/HTTP1Servlet.java | 2 +- 60 files changed, 391 insertions(+), 374 deletions(-) diff --git a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java index 8e49f2d1a555..8e27ce84654b 100644 --- a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java @@ -26,6 +26,7 @@ import org.conscrypt.Conscrypt; import org.conscrypt.OpenSSLProvider; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -74,7 +75,7 @@ public void testConscryptHTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.from(); + HttpFieldsBuilder requestFields = HttpFields.empty(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); diff --git a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java index c8e7ec4cc83c..a5a9f8078577 100644 --- a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java @@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -63,7 +64,7 @@ public void testJDK9HTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.from(); + HttpFieldsBuilder requestFields = HttpFields.empty(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 3e08851494fb..6c587d11f728 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -30,7 +30,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.util.BytesRequestContent; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.util.HttpCookieStore; @@ -148,7 +148,7 @@ protected void normalizeRequest(Request request) // If we are HTTP 1.1, add the Host header HttpVersion version = request.getVersion(); - HttpFieldsBuilder headers = request.getHeaders(); + HttpFields headers = request.getHeaders(); if (version.getVersion() <= 11) { if (!headers.contains(HttpHeader.HOST.asString())) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java index 3d83ec94dcd0..53e67aab4f41 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.util.InputStreamResponseListener; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -150,7 +150,7 @@ public interface Request /** * @return the headers of this request */ - HttpFieldsBuilder getHeaders(); + HttpFields getHeaders(); /** * @param name the name of the header diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java index 17615c7aed10..a8280c3ab470 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java @@ -75,7 +75,7 @@ public void onHeaders(Response response) Request request = response.getRequest(); HttpFieldsBuilder headers = response.getHeaders(); - long length = headers.getLongField(HttpHeader.CONTENT_LENGTH.asString()); + long length = headers.getLongField(HttpHeader.CONTENT_LENGTH); if (HttpMethod.HEAD.is(request.getMethod())) length = 0; if (length > maxLength) diff --git a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java index daadb8cf901c..627bda812911 100644 --- a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java +++ b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java @@ -25,6 +25,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; @@ -48,8 +49,8 @@ public void dataDemanded() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFieldsBuilder requestHeaders = HttpFields.empty() + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index f1fda887f29c..ba1e262e7dad 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; @@ -147,8 +148,8 @@ public void newStream() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFields requestHeaders = HttpFields.empty() + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); // The request metadata with method, URI and headers. MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); @@ -172,8 +173,8 @@ public void newStreamWithData() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.CONTENT_TYPE, "application/json"); + HttpFieldsBuilder requestHeaders = HttpFields.empty() + .put(HttpHeader.CONTENT_TYPE, "application/json"); // The request metadata with method, URI and headers. MetaData.Request request = new MetaData.Request("POST", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); @@ -213,8 +214,8 @@ public void responseListener() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFieldsBuilder requestHeaders = HttpFields.empty() + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -266,8 +267,8 @@ public void reset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFields requestHeaders = HttpFields.empty() + .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -296,8 +297,8 @@ public void push() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFields requestHeaders = HttpFields.empty() + .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -313,7 +314,7 @@ public Stream.Listener onPush(Stream pushedStream, PushPromiseFrame frame) // The pushed "request" URI. HttpURI pushedURI = pushedRequest.getURI(); // The pushed "request" headers. - HttpFieldsBuilder pushedRequestHeaders = pushedRequest.getFields(); + HttpFields pushedRequestHeaders = pushedRequest.getFields(); // If needed, retrieve the primary stream that triggered the push. Stream primaryStream = pushedStream.getSession().getStream(frame.getStreamId()); @@ -330,7 +331,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (metaData.isResponse()) { // The pushed "response" headers. - HttpFieldsBuilder pushedResponseHeaders = metaData.getFields(); + HttpFields pushedResponseHeaders = metaData.getFields(); } } @@ -358,8 +359,8 @@ public void pushReset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.from(); - requestHeaders.put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + HttpFieldsBuilder requestHeaders = HttpFields.empty() + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java index 3b2cedb7fbdf..269995b9a059 100644 --- a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java @@ -464,9 +464,7 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque { // Rewrite old paths to new paths. HttpURI uri = jettyRequest.getHttpURI(); - HttpURI newURI = new HttpURI(uri); - String newPath = "/new_path/" + path.substring("/old_path/".length()); - newURI.setPath(newPath); + HttpURI newURI = HttpURI.from(uri).path("/new_path/" + path.substring("/old_path/".length())).toHttpURI(); // Modify the request object. jettyRequest.setHttpURI(newURI); } diff --git a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java index 352c41aae629..965d7387181c 100644 --- a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -201,7 +202,7 @@ private void respond(Stream stream, MetaData.Request request) // Prepare the response HEADERS frame. // The response HTTP status and HTTP headers. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); if (HttpMethod.GET.is(request.getMethod())) { @@ -293,15 +294,14 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) if (pushEnabled && request.getURIString().endsWith("/index.html")) { // Push the favicon. - HttpURI pushedURI = new HttpURI(request.getURI()); - pushedURI.setPath("/favicon.ico"); - MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.from()); + HttpURI pushedURI = HttpURI.from(request.getURI()).path("/favicon.ico").toHttpURI(); + MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.empty()); PushPromiseFrame promiseFrame = new PushPromiseFrame(stream.getId(), 0, pushedRequest); stream.push(promiseFrame, new Stream.Listener.Adapter()) .thenCompose(pushedStream -> { // Send the favicon "response". - MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); return pushedStream.headers(new HeadersFrame(pushedStream.getId(), pushedResponse, null, false)) .thenCompose(pushed -> pushed.data(new DataFrame(pushed.getId(), faviconBuffer, true))); }); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index 7017a820e2cc..1ead07b8ad62 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.fcgi.generator.ClientGenerator; import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.Callback; @@ -59,12 +60,8 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { Request request = exchange.getRequest(); // Copy the request headers to be able to convert them properly - HttpFieldsBuilder headers = HttpFields.from(); - for (HttpField field : request.getHeaders()) - { - headers.put(field); - } - HttpFieldsBuilder fcgiHeaders = HttpFields.from(); + HttpFieldsBuilder headers = HttpFields.from(request.getHeaders()); + HttpFieldsBuilder fcgiHeaders = HttpFields.empty(); // FastCGI headers based on the URI URI uri = request.getURI(); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index e0635f42c05c..12aa2724c1ec 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; @@ -84,7 +85,7 @@ protected void end(int request) private static class ResponseParser implements HttpParser.ResponseHandler { - private final HttpFieldsBuilder fields = HttpFields.from(); + private final HttpFieldsBuilder fields = HttpFields.empty(); private ClientParser.Listener listener; private final int request; private final FCGIHttpParser httpParser; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java index 576146e4cb61..96a64d57b085 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.fcgi.parser.ServerParser; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; @@ -38,7 +39,7 @@ public class ClientGeneratorTest @Test public void testGenerateRequestHeaders() throws Exception { - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); // Short name, short value final String shortShortName = "REQUEST_METHOD"; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java index c103858ea049..78f869bbc638 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.fcgi.generator.ServerGenerator; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; @@ -42,7 +43,7 @@ public class ClientParserTest public void testParseResponseHeaders() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); final int statusCode = 200; final String statusMessage = "OK"; @@ -112,7 +113,7 @@ public boolean onHeaders(int request) public void testParseNoResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Content-Length", "0"); ByteBufferPool byteBufferPool = new MappedByteBufferPool(); @@ -157,7 +158,7 @@ public void onEnd(int request) public void testParseSmallResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); ByteBuffer content = ByteBuffer.wrap(new byte[1024]); final int contentLength = content.remaining(); @@ -210,7 +211,7 @@ public void onEnd(int request) public void testParseLargeResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); ByteBuffer content = ByteBuffer.wrap(new byte[128 * 1024]); final int contentLength = content.remaining(); diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java index c1d7bb95ef46..7b86bdf318aa 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; @@ -43,7 +44,7 @@ public class HttpChannelOverFCGI extends HttpChannel { private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverFCGI.class); - private final HttpFieldsBuilder fields = HttpFields.from(); + private final HttpFieldsBuilder fields = HttpFields.empty(); private final Dispatcher dispatcher; private String method; private String path; 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 e980bf17311f..de855df0ae68 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 @@ -590,7 +590,7 @@ private void generateHeaders(ByteBuffer header, ByteBuffer content, boolean last boolean close = false; boolean chunkedHint = _info.hasTrailerSupplier(); boolean contentType = false; - long contentLength = _info.getContentLengthKnown(); + long contentLength = _info.getContentLength(); boolean contentLengthField = false; // Generate fields diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 0fa9b496186d..6db19316cfe1 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -20,7 +20,6 @@ import java.util.Collections; import java.util.Iterator; -import java.util.function.Consumer; import java.util.function.Supplier; public class MetaData implements Iterable @@ -29,7 +28,7 @@ public class MetaData implements Iterable private static final HttpFields SUPPLIED_TRAILERS = HttpFields.empty().asImmutable(); private final HttpVersion _httpVersion; private final HttpFields _fields; - private final long _contentLengthKnown; + private final long _contentLength; private final Supplier _trailerSupplier; private HttpFields _trailers; @@ -38,16 +37,17 @@ public MetaData(HttpVersion version, HttpFields fields) this(version, fields, -1); } - public MetaData(HttpVersion version, HttpFields fields, long contentLengthKnown) + public MetaData(HttpVersion version, HttpFields fields, long contentLength) { - this(version, fields, contentLengthKnown, SELF_SUPPLIED_TRAILORS); + this(version, fields, contentLength, SELF_SUPPLIED_TRAILORS); } - public MetaData(HttpVersion version, HttpFields fields, long contentLengthKnown, Supplier trailers) + public MetaData(HttpVersion version, HttpFields fields, long contentLength, Supplier trailers) { _httpVersion = version; _fields = fields == null ? null : fields.asImmutable(); - _contentLengthKnown = contentLengthKnown; + + _contentLength = contentLength >= 0 ? contentLength : _fields == null ? -1 : _fields.getLongField(HttpHeader.CONTENT_LENGTH); if (trailers == SELF_SUPPLIED_TRAILORS) _trailerSupplier = () -> _trailers; else @@ -106,9 +106,9 @@ public void setTrailers(HttpFields trailers) _trailers = trailers; } - public long getContentLengthKnown() + public long getContentLength() { - return _contentLengthKnown; + return _contentLength; } @Override @@ -132,18 +132,6 @@ public String toString() public static class Request extends MetaData { - public static RequestBuilder from(String method, String uri, HttpVersion version) - { - return new RequestBuilder(method, uri, version); - } - - public static RequestBuilder from(String method, String uri, HttpVersion version, Consumer fieldBuilder) - { - RequestBuilder rb = new RequestBuilder(method, uri, version); - fieldBuilder.accept(rb._fieldBuilder); - return rb; - } - private final String _method; private final HttpURI _uri; @@ -224,56 +212,7 @@ public String toString() { HttpFields fields = getFields(); return String.format("%s{u=%s,%s,h=%d,cl=%d,p=%s}", - getMethod(), getURI(), getHttpVersion(), fields == null ? -1 : fields.size(), getContentLengthKnown(), getProtocol()); - } - } - - // TODO this is moderately specific to HttpChannelOverHttp, so unless it get's used elsewhere, it should be moved there. - public static class RequestBuilder - { - private final HttpURI.Builder _uri; - private String _method; - private HttpVersion _version; - private final HttpFieldsBuilder _fieldBuilder = HttpFields.empty(); - - public RequestBuilder() - { - _uri = HttpURI.empty(); - } - - public RequestBuilder(String method, String uri, HttpVersion version) - { - _method = method; - _uri = HttpURI.from(uri); - _version = version; - } - - public String method() - { - return _method; - } - - public void request(String method, String uri, HttpVersion version) - { - _method = method; - _uri.uri(uri); - _version = version; - _fieldBuilder.clear(); - } - - public HttpFieldsBuilder getFields() - { - return _fieldBuilder; - } - - public Request build() - { - return new Request(_method, _uri.toHttpURI(), _version, _fieldBuilder.asImmutable()); - } - - public HttpVersion version() - { - return _version; + getMethod(), getURI(), getHttpVersion(), fields == null ? -1 : fields.size(), getContentLength(), getProtocol()); } } @@ -352,7 +291,7 @@ public String getReason() public String toString() { HttpFields fields = getFields(); - return String.format("%s{s=%d,h=%d,cl=%d}", getHttpVersion(), getStatus(), fields == null ? -1 : fields.size(), getContentLengthKnown()); + return String.format("%s{s=%d,h=%d,cl=%d}", getHttpVersion(), getStatus(), fields == null ? -1 : fields.size(), getContentLength()); } } } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java index 6d7b2673702a..2ed06fbd0575 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; @@ -86,7 +87,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -137,7 +138,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -193,7 +194,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -266,7 +267,7 @@ public Map onPreface(Session session) } }); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java index 5f6f68ee19c2..2764c9b11ec3 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java @@ -34,6 +34,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MetaData; @@ -94,7 +95,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -131,7 +132,7 @@ public void testStartAsyncThenClientSessionIdleTimeout() throws Exception client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -168,7 +169,7 @@ public void testStartAsyncThenClientStreamIdleTimeout() throws Exception client.setIdleTimeout(10 * idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -217,7 +218,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) prepareClient(); client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -328,7 +329,7 @@ public void onStartAsync(AsyncEvent event) throws IOException client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch clientLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java index 82ddd783f80a..32205a9b6225 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java @@ -78,7 +78,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, HttpFields.empty()); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { @@ -130,7 +130,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpFields.from(), "websocket"); + MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpFields.empty(), "websocket"); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java index 8774c17b44b8..1b9e56f1a90f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -78,7 +79,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.from()); + MetaData.Request post = newRequest("POST", HttpFields.empty()); FuturePromise promise = new FuturePromise<>(); Queue clientQueue = new ConcurrentLinkedQueue<>(); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() @@ -176,7 +177,7 @@ public void testOnBeforeData() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -188,7 +189,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.from()); + MetaData.Request post = newRequest("GET", HttpFields.empty()); FuturePromise promise = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); CountDownLatch beforeDataLatch = new CountDownLatch(1); @@ -236,7 +237,7 @@ public void testDemandFromOnHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -248,7 +249,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.from()); + MetaData.Request post = newRequest("GET", HttpFields.empty()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -283,7 +284,7 @@ public void testOnBeforeDataDoesNotReenter() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -295,7 +296,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.from()); + MetaData.Request post = newRequest("GET", HttpFields.empty()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -338,7 +339,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) stream.demand(1); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -347,7 +348,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.from()); + MetaData.Request post = newRequest("POST", HttpFields.empty()); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java index ec5893d06c34..0d33463142ee 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java @@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -140,7 +141,7 @@ protected void onStreamUnstalled(IStream stream) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); if (request.getURIString().endsWith("/stall")) { @@ -170,7 +171,7 @@ public void succeeded() CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.from()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.empty()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -188,7 +189,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the first be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.from()); + request = newRequest("GET", "/", HttpFields.empty()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); @@ -231,7 +232,7 @@ protected void onSessionUnstalled(ISession session) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); if (request.getURIString().endsWith("/stall")) { @@ -270,7 +271,7 @@ public Map onPreface(Session session) CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.from()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.empty()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -288,7 +289,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the session be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.from()); + request = newRequest("GET", "/", HttpFields.empty()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java index 0a2dd9d166ee..e16917ddb83e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java @@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; @@ -192,7 +193,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getRecvWindow()); assertTrue(prefaceLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.from()); + MetaData.Request request1 = newRequest("GET", HttpFields.empty()); FuturePromise promise1 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request1, null, true), promise1, new Stream.Listener.Adapter()); HTTP2Stream clientStream1 = (HTTP2Stream)promise1.get(5, TimeUnit.SECONDS); @@ -216,7 +217,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) settingsLatch.await(5, TimeUnit.SECONDS); // Now create a new stream, it must pick up the new value. - MetaData.Request request2 = newRequest("POST", HttpFields.from()); + MetaData.Request request2 = newRequest("POST", HttpFields.empty()); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request2, null, true), promise2, new Stream.Listener.Adapter()); HTTP2Stream clientStream2 = (HTTP2Stream)promise2.get(5, TimeUnit.SECONDS); @@ -243,7 +244,7 @@ public void testFlowControlWithConcurrentSettings() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); @@ -286,7 +287,7 @@ public void onSettings(Session session, SettingsFrame frame) } }); - MetaData.Request request = newRequest("POST", HttpFields.from()); + MetaData.Request request = newRequest("POST", HttpFields.empty()); FuturePromise promise = new FuturePromise<>(); session.newStream(new HeadersFrame(request, null, false), promise, new Stream.Listener.Adapter()); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -327,7 +328,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); stream.headers(responseFrame, Callback.from(completable)); @@ -352,7 +353,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) final CountDownLatch dataLatch = new CountDownLatch(1); final Exchanger exchanger = new Exchanger<>(); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -424,7 +425,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -475,7 +476,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, null); @@ -527,7 +528,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) else { // For every stream, send down half the window size of data. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -546,7 +547,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) // First request is just to consume most of the session window. final List callbacks1 = new ArrayList<>(); final CountDownLatch prepareLatch = new CountDownLatch(1); - MetaData.Request request1 = newRequest("POST", HttpFields.from()); + MetaData.Request request1 = newRequest("POST", HttpFields.empty()); session.newStream(new HeadersFrame(request1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -561,7 +562,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(prepareLatch.await(5, TimeUnit.SECONDS)); // Second request will consume half of the remaining the session window. - MetaData.Request request2 = newRequest("GET", HttpFields.from()); + MetaData.Request request2 = newRequest("GET", HttpFields.empty()); session.newStream(new HeadersFrame(request2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -573,7 +574,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Third request will consume the whole session window, which is now stalled. // A fourth request will not be able to receive data. - MetaData.Request request3 = newRequest("GET", HttpFields.from()); + MetaData.Request request3 = newRequest("GET", HttpFields.empty()); session.newStream(new HeadersFrame(request3, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -585,7 +586,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Fourth request is now stalled. final CountDownLatch latch = new CountDownLatch(1); - MetaData.Request request4 = newRequest("GET", HttpFields.from()); + MetaData.Request request4 = newRequest("GET", HttpFields.empty()); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -621,7 +622,7 @@ public void testServerSendsBigContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -635,7 +636,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); final byte[] bytes = new byte[data.length]; final CountDownLatch latch = new CountDownLatch(1); @@ -667,7 +668,7 @@ public void testClientSendingInitialSmallWindow() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -699,7 +700,7 @@ public Map onPreface(Session session) byte[] responseData = new byte[requestData.length]; final ByteBuffer responseContent = ByteBuffer.wrap(responseData); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); final CountDownLatch latch = new CountDownLatch(1); @@ -759,7 +760,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole session and stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); session.newStream(requestFrame, Promise.from(completable), new Stream.Listener.Adapter()); @@ -843,7 +844,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, new Stream.Listener.Adapter()); @@ -914,7 +915,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); final CountDownLatch resetLatch = new CountDownLatch(1); @@ -969,7 +970,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Succeed the callbacks when the stream is already remotely closed. callbacks.forEach(Callback::succeeded); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -993,7 +994,7 @@ public void onWindowUpdate(ISession session, IStream stream, WindowUpdateFrame f }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java index b64ed9fba967..2d727d290493 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -112,7 +113,7 @@ public void testClientFlowControlWindows() throws Exception assertEquals(clientSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); clientSession.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -162,7 +163,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(serverSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); clientSession.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter()); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index 381d84c3dc4c..227ae3f54652 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -83,7 +84,7 @@ public void testRequestNoContentResponseNoContent() throws Exception Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -115,7 +116,7 @@ public void testRequestNoContentResponseEmptyContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), new Callback() { @Override @@ -130,7 +131,7 @@ public void succeeded() Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -172,7 +173,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(2); @@ -221,7 +222,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable streamCompletable = new Promise.Completable<>(); session.newStream(frame, streamCompletable, new Stream.Listener.Adapter() @@ -269,7 +270,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.putLongField(downloadBytes, random.nextInt(128 * 1024)); fields.put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); @@ -306,7 +307,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -344,7 +345,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); HostPortHttpField hostHeader = new HostPortHttpField(authority); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -423,7 +424,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from(), 0); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty(), 0); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -440,7 +441,7 @@ public void onSettings(Session session, SettingsFrame frame) }); assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.from()); + MetaData.Request request1 = newRequest("GET", HttpFields.empty()); FuturePromise promise1 = new FuturePromise<>(); CountDownLatch exchangeLatch1 = new CountDownLatch(2); session.newStream(new HeadersFrame(request1, null, false), promise1, new Stream.Listener.Adapter() @@ -454,7 +455,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData.Request request2 = newRequest("GET", HttpFields.from()); + MetaData.Request request2 = newRequest("GET", HttpFields.empty()); FuturePromise promise2 = new FuturePromise<>(); CountDownLatch exchangeLatch2 = new CountDownLatch(2); session.newStream(new HeadersFrame(request2, null, false), promise2, new Stream.Listener.Adapter() @@ -469,7 +470,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream2 = promise2.get(5, TimeUnit.SECONDS); // The third stream must not be created. - MetaData.Request request3 = newRequest("GET", HttpFields.from()); + MetaData.Request request3 = newRequest("GET", HttpFields.empty()); CountDownLatch maxStreamsLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request3, null, false), new Promise.Adapter<>() { @@ -497,7 +498,7 @@ public void succeeded() assertEquals(1, session.getStreams().size()); // Create a fourth stream. - MetaData.Request request4 = newRequest("GET", HttpFields.from()); + MetaData.Request request4 = newRequest("GET", HttpFields.empty()); CountDownLatch exchangeLatch4 = new CountDownLatch(2); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>() { @@ -540,7 +541,7 @@ public void testInvalidAPIUsageOnClient() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { Callback.Completable completable = new Callback.Completable(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), completable); return new Stream.Listener.Adapter() { @@ -563,7 +564,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); CountDownLatch completeLatch = new CountDownLatch(2); @@ -635,7 +636,7 @@ public void testInvalidAPIUsageOnServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); DataFrame dataFrame = new DataFrame(stream.getId(), BufferUtil.EMPTY_BUFFER, true); // The call to headers() is legal, but slow. new Thread(() -> @@ -682,7 +683,7 @@ public void failed(Throwable x) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -706,7 +707,7 @@ public void testCleanGoAwayDoesNotTriggerFailureNotification() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); // Close cleanly. @@ -731,7 +732,7 @@ public void onFailure(Session session, Throwable failure) failureLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame request = new HeadersFrame(metaData, null, true); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter()); @@ -748,7 +749,7 @@ public void testGoAwayRespondedWithGoAway() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, null, Callback.NOOP); @@ -787,7 +788,7 @@ public void onClose(Session session, GoAwayFrame frame) closeLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame request = new HeadersFrame(metaData, null, true); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -811,7 +812,7 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.from(); + HttpFieldsBuilder requestFields = HttpFields.empty(); requestFields.put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); @@ -835,7 +836,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -878,7 +879,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.empty()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -925,7 +926,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) dataLatch.countDown(); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -949,7 +950,7 @@ public void onClose(Session session, GoAwayFrame frame) // Start 2 requests without completing them yet. CountDownLatch responseLatch = new CountDownLatch(2); - MetaData.Request metaData1 = newRequest("GET", HttpFields.from()); + MetaData.Request metaData1 = newRequest("GET", HttpFields.empty()); HeadersFrame request1 = new HeadersFrame(metaData1, null, false); FuturePromise promise1 = new FuturePromise<>(); Stream.Listener.Adapter listener = new Stream.Listener.Adapter() @@ -969,7 +970,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); stream1.data(new DataFrame(stream1.getId(), ByteBuffer.allocate(1), false), Callback.NOOP); - MetaData.Request metaData2 = newRequest("GET", HttpFields.from()); + MetaData.Request metaData2 = newRequest("GET", HttpFields.empty()); HeadersFrame request2 = new HeadersFrame(metaData2, null, false); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(request2, promise2, listener); @@ -987,7 +988,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // New requests should be immediately rejected. HostPortHttpField authority3 = new HostPortHttpField("localhost" + ":" + port); - MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP, authority3, servletPath, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP, authority3, servletPath, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame request3 = new HeadersFrame(metaData3, null, false); FuturePromise promise3 = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java index f6e6f119ee26..cfb200b77ef8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java @@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.FlowControlStrategy; @@ -75,7 +76,7 @@ public void testServerEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -93,7 +94,7 @@ public void onClose(Session session, GoAwayFrame frame) } }); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -132,7 +133,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // The request is not replied, and the server should idle timeout. - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -160,7 +161,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // to avoid a race where the idle timeout fires // again before we can send the headers to the client. sleep(idleTimeout + idleTimeout / 2); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -179,7 +180,7 @@ public void onClose(Session session, GoAwayFrame frame) }); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -213,7 +214,7 @@ public void testClientEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -228,7 +229,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -265,7 +266,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -289,7 +290,7 @@ public void testClientNotEnforcingIdleTimeoutWithinCallback() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -306,7 +307,7 @@ public void onClose(Session session, GoAwayFrame frame) Session session = newClient(new Session.Listener.Adapter()); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -349,7 +350,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se final CountDownLatch dataLatch = new CountDownLatch(1); final CountDownLatch timeoutLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -410,7 +411,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) final CountDownLatch resetLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); // Stream does not end here, but we won't send any DATA frame. HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -454,7 +455,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -504,7 +505,7 @@ public void testClientStreamIdleTimeoutIsNotEnforcedWhenSending() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -517,7 +518,7 @@ public void onReset(Session session, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise() { @@ -574,7 +575,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) connector.setIdleTimeout(2 * delay); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.from()); + MetaData.Request metaData = newRequest("POST", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); @@ -640,7 +641,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -654,7 +655,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Send one more request to consume the whole session flow control window. CountDownLatch resetLatch = new CountDownLatch(1); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java index 94aa5b8d14c8..022fcb2c8b69 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java @@ -30,6 +30,7 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -94,12 +95,12 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }; - HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); FuturePromise streamPromise1 = new FuturePromise<>(); session.newStream(headersFrame1, streamPromise1, streamListener); streamPromise1.get(5, TimeUnit.SECONDS); - HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); FuturePromise streamPromise2 = new FuturePromise<>(); session.newStream(headersFrame2, streamPromise2, streamListener); streamPromise2.get(5, TimeUnit.SECONDS); @@ -110,7 +111,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream serverStream1 = serverStreams.get(0); Stream serverStream2 = serverStreams.get(1); - MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); serverStream1.headers(new HeadersFrame(serverStream1.getId(), response1, null, false), Callback.NOOP); Random random = new Random(); @@ -119,7 +120,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) byte[] content2 = new byte[2 * ((ISession)serverStream2.getSession()).updateSendWindow(0)]; random.nextBytes(content2); - MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); serverStream2.headers(new HeadersFrame(serverStream2.getId(), response2, null, false), new Callback() { @Override diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java index 35b7c85c079f..292063f3f52f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java @@ -27,6 +27,7 @@ import java.util.function.BinaryOperator; import java.util.stream.IntStream; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -77,7 +78,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) CompletableFuture> result = CompletableFuture.completedFuture(new ArrayList<>()); // Push maxPushed resources... IntStream.range(0, maxPushed) - .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.from()))) + .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.empty()))) .map(pushFrame -> { Promise.Completable promise = new Promise.Completable<>(); @@ -90,7 +91,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // ... then push one extra stream, the client must reject it... .thenApply(streams -> { - PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.from())); + PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.empty())); FuturePromise extraPromise = new FuturePromise<>(); stream.push(extraPushFrame, extraPromise, new Stream.Listener.Adapter() { @@ -112,7 +113,7 @@ public void onReset(Stream stream, ResetFrame frame) // ... then send the response. .thenRun(() -> { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); }); return null; @@ -121,7 +122,7 @@ public void onReset(Stream stream, ResetFrame frame) client.setMaxConcurrentPushedStreams(maxPushed); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java index 3830c04a6cfc..80a09acd5553 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java @@ -33,6 +33,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -81,7 +82,7 @@ public void onAccept(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -109,7 +110,7 @@ public Map onPreface(Session session) }); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -223,7 +224,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java index ea55abcd5299..b821c3dce7df 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java @@ -21,6 +21,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; @@ -47,7 +48,7 @@ public void testPriorityBeforeHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -59,7 +60,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertTrue(streamId > 0); CountDownLatch latch = new CountDownLatch(2); - MetaData metaData = newRequest("GET", HttpFields.from()); + MetaData metaData = newRequest("GET", HttpFields.empty()); HeadersFrame headersFrame = new HeadersFrame(streamId, metaData, null, true); session.newStream(headersFrame, new Promise.Adapter() { @@ -95,7 +96,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { beforeRequests.await(5, TimeUnit.SECONDS); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); afterRequests.countDown(); @@ -121,13 +122,13 @@ public void onHeaders(Stream stream, HeadersFrame frame) }; Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData1 = newRequest("GET", "/one", HttpFields.from()); + MetaData metaData1 = newRequest("GET", "/one", HttpFields.empty()); HeadersFrame headersFrame1 = new HeadersFrame(metaData1, null, true); FuturePromise promise1 = new FuturePromise<>(); session.newStream(headersFrame1, promise1, listener); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData metaData2 = newRequest("GET", "/two", HttpFields.from()); + MetaData metaData2 = newRequest("GET", "/two", HttpFields.empty()); HeadersFrame headersFrame2 = new HeadersFrame(metaData2, null, true); FuturePromise promise2 = new FuturePromise<>(); session.newStream(headersFrame2, promise2, listener); @@ -161,7 +162,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(priorityFrame.isExclusive(), priority.isExclusive()); latch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -169,7 +170,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData = newRequest("GET", "/one", HttpFields.from()); + MetaData metaData = newRequest("GET", "/one", HttpFields.empty()); HeadersFrame headersFrame = new HeadersFrame(metaData, priorityFrame, true); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java index 3dcde83b9fe8..62c49c7774c4 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -119,7 +120,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); @@ -177,7 +178,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java index f8c36fd49289..40778cdafb2d 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -165,7 +166,7 @@ protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletRes final CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", "/", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 1fc73f53a380..8a7eaada9b41 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; @@ -102,7 +103,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -114,7 +115,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -206,7 +207,7 @@ else if (requestURI.endsWith(secondaryResource)) // The referrerURI does not point to the primary resource, so there will be no // resource association with the primary resource and therefore won't be pushed. final String referrerURI = "http://localhost:" + connector.getLocalPort(); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -218,7 +219,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -292,7 +293,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -304,7 +305,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -357,7 +358,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); // Make sure the session is sane by requesting the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); final CountDownLatch secondaryResponseLatch = new CountDownLatch(1); @@ -395,7 +396,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -406,7 +407,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -486,7 +487,7 @@ else if (requestURI.endsWith(secondaryResource2)) // Request for the primary, secondary and tertiary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(2); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -499,7 +500,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Request for the secondary resources. String secondaryURI1 = newURI(secondaryResource1); - HttpFieldsBuilder secondaryFields1 = HttpFields.from(); + HttpFieldsBuilder secondaryFields1 = HttpFields.empty(); secondaryFields1.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest1 = newRequest("GET", secondaryResource1, secondaryFields1); session.newStream(new HeadersFrame(secondaryRequest1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -511,7 +512,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the tertiary resource. - HttpFieldsBuilder tertiaryFields = HttpFields.from(); + HttpFieldsBuilder tertiaryFields = HttpFields.empty(); tertiaryFields.put(HttpHeader.REFERER, secondaryURI1); MetaData.Request tertiaryRequest = newRequest("GET", tertiaryResource, tertiaryFields); session.newStream(new HeadersFrame(tertiaryRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -528,7 +529,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); - HttpFieldsBuilder secondaryFields2 = HttpFields.from(); + HttpFieldsBuilder secondaryFields2 = HttpFields.empty(); secondaryFields2.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest2 = newRequest("GET", secondaryResource2, secondaryFields2); session.newStream(new HeadersFrame(secondaryRequest2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -604,7 +605,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Make sure that explicitly requesting a secondary resource, we get the tertiary pushed. CountDownLatch secondaryResponseLatch = new CountDownLatch(1); CountDownLatch secondaryPushLatch = new CountDownLatch(1); - MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.from()); + MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.empty()); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -675,7 +676,7 @@ else if ("secret".equals(credentials)) final Session session = newClient(new Session.Listener.Adapter()); // Login with the wrong credentials, causing a redirect to self. - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource + "?credentials=wrong", primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -690,7 +691,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) { // Follow the redirect. String location = response.getFields().get(HttpHeader.LOCATION); - HttpFieldsBuilder redirectFields = HttpFields.from(); + HttpFieldsBuilder redirectFields = HttpFields.empty(); redirectFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request redirectRequest = newRequest("GET", location, redirectFields); session.newStream(new HeadersFrame(redirectRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -768,7 +769,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -779,7 +780,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -861,7 +862,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -873,7 +874,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -956,7 +957,7 @@ public Map onPreface(Session session) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.from(); + HttpFieldsBuilder primaryFields = HttpFields.empty(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -968,7 +969,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.from(); + HttpFieldsBuilder secondaryFields = HttpFields.empty(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java index e34d206a61a4..b7bc0a479d8e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java @@ -31,6 +31,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -131,7 +132,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) LOGGER.debug("SERVER1 received {}", frame); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER1 sending {}", reply); @@ -167,7 +168,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 received {}", frame); callback.succeeded(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); Callback.Completable completable1 = new Callback.Completable(); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) @@ -183,7 +184,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) return completable2; }).thenRun(() -> { - MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.from()); + MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame end = new HeadersFrame(stream.getId(), trailer, null, true); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 sending {}", end); @@ -205,7 +206,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session clientSession = clientPromise.get(5, TimeUnit.SECONDS); // Send a request with trailers for server1. - HttpFieldsBuilder fields1 = HttpFields.from(); + HttpFieldsBuilder fields1 = HttpFields.empty(); fields1.put("X-Target", String.valueOf(connector1.getLocalPort())); MetaData.Request request1 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields1); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -230,10 +231,10 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); Stream stream1 = streamPromise1.get(5, TimeUnit.SECONDS); - stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.from()), null, true), Callback.NOOP); + stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.empty()), null, true), Callback.NOOP); // Send a request for server2. - HttpFieldsBuilder fields2 = HttpFields.from(); + HttpFieldsBuilder fields2 = HttpFields.empty(); fields2.put("X-Target", String.valueOf(connector2.getLocalPort())); MetaData.Request request2 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields2); FuturePromise streamPromise2 = new FuturePromise<>(); @@ -281,7 +282,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) LOGGER.debug("Received {} for {} on {}: {}", frame, stream, stream.getSession(), frame.getMetaData()); // Forward to the right server. MetaData metaData = frame.getMetaData(); - HttpFieldsBuilder fields = metaData.getFields(); + HttpFields fields = metaData.getFields(); int port = Integer.parseInt(fields.get("X-Target")); ClientToProxyToServer clientToProxyToServer = forwarders.computeIfAbsent(port, p -> new ClientToProxyToServer("localhost", p, client)); clientToProxyToServer.offer(stream, frame, Callback.NOOP); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java index edf41b40f15c..0cb100d76e8c 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java @@ -113,7 +113,7 @@ public void onFailure(Session session, Throwable failure) clientFailureLatch.countDown(); } }); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); Promise promise = new Promise.Adapter<>(); session.newStream(frame, promise, null); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java index 768189aec97e..d4937786cfe0 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; @@ -148,7 +149,7 @@ private boolean test(Session session, CountDownLatch latch) throws Exception int contentLength = random.nextInt(maxContentLength) + 1; long requestId = requestIds.incrementAndGet(); - MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.from()); + MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.empty()); if (download) request.getFields().put("X-Download", String.valueOf(contentLength)); HeadersFrame requestFrame = new HeadersFrame(request, null, download); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java index f3cfe715d5b2..fc898805a547 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java @@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -64,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, null); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -81,7 +82,7 @@ public void testRequestClosedResponseClosedClosesStream() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, new Callback() { @@ -98,7 +99,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -123,7 +124,7 @@ public void testRequestDataClosedResponseDataClosedClosesStream() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(response, completable); @@ -152,7 +153,7 @@ public void succeeded() final CountDownLatch completeLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, false); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -195,7 +196,7 @@ public void testPushedStreamIsClosed() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.from())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.empty())); stream.push(pushFrame, new Promise.Adapter() { @Override @@ -215,14 +216,14 @@ public void succeeded() }); } }, new Stream.Listener.Adapter()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()), null, true); stream.headers(response, Callback.NOOP); return null; } }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); final CountDownLatch clientLatch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -256,7 +257,7 @@ public void testPushedStreamResetIsClosed() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.from())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.empty())); stream.push(pushFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -264,7 +265,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) { assertTrue(pushedStream.isReset()); assertTrue(pushedStream.isClosed()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()), null, true); stream.headers(response, Callback.NOOP); serverLatch.countDown(); } @@ -274,7 +275,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); final CountDownLatch clientLatch = new CountDownLatch(2); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -338,11 +339,11 @@ public void onFailure(Session session, Throwable failure) Session session = newClient(new Session.Listener.Adapter()); // First stream will be idle on server. - HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.from()), null, true); + HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.empty()), null, true); session.newStream(request1, new Promise.Adapter<>(), new Stream.Listener.Adapter()); // Second stream will fail on server. - HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.from()), null, true); + HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); session.newStream(request2, new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertTrue(latch.await(5, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java index 18b82f6243b8..36f1b16e7b60 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -73,7 +74,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -98,7 +99,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -143,7 +144,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -166,7 +167,7 @@ public void onReset(Session session, ResetFrame frame) } }); - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java index 4d6a4306f460..da44f619a209 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java @@ -45,6 +45,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -103,7 +104,7 @@ public void testStreamSendingResetIsRemoved() throws Exception start(new ServerSessionListener.Adapter()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -141,7 +142,7 @@ public void onReset(Stream stream, ResetFrame frame) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -169,7 +170,7 @@ public void testStreamResetDoesNotCloseConnection() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -209,7 +210,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request1 = newRequest("GET", HttpFields.from()); + MetaData.Request request1 = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame1 = new HeadersFrame(request1, null, false); FuturePromise promise1 = new FuturePromise<>(); final CountDownLatch stream1HeadersLatch = new CountDownLatch(1); @@ -232,7 +233,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); assertTrue(stream1HeadersLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request2 = newRequest("GET", HttpFields.from()); + MetaData.Request request2 = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame2 = new HeadersFrame(request2, null, false); FuturePromise promise2 = new FuturePromise<>(); final CountDownLatch stream2DataLatch = new CountDownLatch(1); @@ -316,7 +317,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -403,7 +404,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -433,7 +434,7 @@ public void testClientResetConsumesQueuedData() throws Exception start(new EmptyHttpServlet()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -500,7 +501,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -531,7 +532,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } // Send one more request to consume the whole session flow control window, then reset it. - MetaData.Request request = newRequest("GET", "/x", HttpFields.from()); + MetaData.Request request = newRequest("GET", "/x", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); // This request will get no event from the server since it's reset by the client. @@ -584,7 +585,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -647,7 +648,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -696,7 +697,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -773,7 +774,7 @@ public void onError(Throwable t) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -829,7 +830,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -906,7 +907,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = new HttpURI("http", host, port, servletPath); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); int streamId = 3; HeadersFrame headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); @@ -1009,7 +1010,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = new HttpURI("http", host, port, servletPath + "/1"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame headersFrame = new HeadersFrame(3, request, null, true); generator.control(lease, headersFrame); @@ -1020,7 +1021,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) // Send a second request. uri = new HttpURI("http", host, port, servletPath + "/2"); - request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); + request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); int streamId = 5; headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 10b6ede19bef..0f4b21a26028 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; @@ -89,7 +90,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.from(); + HttpFieldsBuilder requestFields = HttpFields.empty(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -98,7 +99,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream = streamPromise.get(5, TimeUnit.SECONDS); // Send the trailers. - HttpFieldsBuilder trailerFields = HttpFields.from(); + HttpFieldsBuilder trailerFields = HttpFields.empty(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -140,7 +141,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.from(); + HttpFieldsBuilder requestFields = HttpFields.empty(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -168,7 +169,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // Send the trailers. callback.thenRun(() -> { - HttpFieldsBuilder trailerFields = HttpFields.from(); + HttpFieldsBuilder trailerFields = HttpFields.empty(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -186,7 +187,7 @@ public void testTrailersSentByServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - HttpFieldsBuilder responseFields = HttpFields.from(); + HttpFieldsBuilder responseFields = HttpFields.empty(); responseFields.put("X-Response", "true"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, responseFields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); @@ -195,7 +196,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) @Override public void succeeded() { - HttpFieldsBuilder trailerFields = HttpFields.from(); + HttpFieldsBuilder trailerFields = HttpFields.empty(); trailerFields.put("X-Trailer", "true"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -207,7 +208,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -250,7 +251,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { Request jettyRequest = (Request)request; Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); jettyResponse.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); @@ -262,7 +263,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.from()); + MetaData.Request request = newRequest("GET", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); List frames = new ArrayList<>(); @@ -304,7 +305,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception start(new EmptyHttpServlet()); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.from()); + MetaData.Request request = newRequest("POST", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -316,7 +317,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception completable.thenRun(() -> { // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.from(); + HttpFieldsBuilder trailerFields = HttpFields.empty(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -355,7 +356,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.from()); + MetaData.Request request = newRequest("POST", HttpFields.empty()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter() @@ -375,7 +376,7 @@ public void onReset(Stream stream, ResetFrame frame) // Disable checks for invalid headers. ((HTTP2Session)session).getGenerator().setValidateHpackEncoding(false); // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.from(); + HttpFieldsBuilder trailerFields = HttpFields.empty(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); diff --git a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java index 955fc6f3b6e6..31ecd83ae548 100644 --- a/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java +++ b/jetty-http2/http2-common/src/main/java/org/eclipse/jetty/http2/HTTP2Stream.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.MetaData; @@ -303,10 +303,10 @@ private void onHeaders(HeadersFrame frame, Callback callback) MetaData metaData = frame.getMetaData(); if (metaData.isRequest() || metaData.isResponse()) { - HttpFieldsBuilder fields = metaData.getFields(); + HttpFields fields = metaData.getFields(); long length = -1; if (fields != null && !HttpMethod.CONNECT.is(request.getMethod())) - length = fields.getLongField(HttpHeader.CONTENT_LENGTH.asString()); + length = fields.getLongField(HttpHeader.CONTENT_LENGTH); dataLength = length >= 0 ? length : Long.MIN_VALUE; } diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java index 2d887d1a3bb4..401faf958683 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -71,7 +72,7 @@ public void onConnectionFailure(int error, String reason) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java index 33bdac81feef..dd71dd41c92d 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -51,7 +52,7 @@ public void testGenerateParse() throws Exception HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder()); int streamId = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); @@ -124,7 +125,7 @@ public void onHeaders(HeadersFrame frame) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java index 38aab37535dc..3edda68f204f 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -62,7 +63,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); @@ -115,7 +116,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index faa353dec650..bf4013ba8385 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -32,6 +32,7 @@ public class MetaDataBuilder { private final int _maxSize; + private final HttpFieldsBuilder _fields = HttpFields.empty(); private int _size; private Integer _status; private String _method; @@ -40,7 +41,6 @@ public class MetaDataBuilder private String _path; private String _protocol; private long _contentLength = Long.MIN_VALUE; - private HttpFieldsBuilder _fields = HttpFields.empty(); private HpackException.StreamException _streamException; private boolean _request; private boolean _response; @@ -277,7 +277,7 @@ public MetaData build() throws HpackException.StreamException } finally { - _fields = HttpFields.empty(Math.max(16, fields.size() + 5)); + _fields.clear(); _request = false; _response = false; _status = null; diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java index cde8ec5c919a..393ea5ec5a2e 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java @@ -79,7 +79,7 @@ public void encodeDecodeResponseTest() throws Exception BufferUtil.flipToFlush(buffer, 0); Response decoded0b = (Response)decoder.decode(buffer); - assertMetaDataResponseSame(original0, decoded0b); + assertMetaDataResponseSame(nullToEmpty, decoded0b); HttpFieldsBuilder fields1 = HttpFields.empty() .add(HttpHeader.CONTENT_TYPE, "text/plain") diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index ad943b53c7bd..7c761017f53c 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -45,6 +45,7 @@ import org.eclipse.jetty.client.HttpProxy; import org.eclipse.jetty.client.Origin; import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; @@ -155,7 +156,7 @@ public void testResponseAbortSendsResetFrame() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), metaData, null, false), new Callback() { @Override @@ -232,7 +233,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) } else { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } return null; @@ -489,7 +490,7 @@ public void onHeaders(HeadersFrame request) try { // Response. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true); generator.control(lease, response); writeFrames(); @@ -563,7 +564,7 @@ public void test204WithContent() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { int streamId = stream.getId(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(streamId, response, null, false); Callback.Completable callback = new Callback.Completable(); stream.headers(responseFrame, callback); @@ -592,7 +593,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // Disable checks for invalid headers. ((HTTP2Session)stream.getSession()).getGenerator().setValidateHpackEncoding(false); // Produce an invalid HPACK block by adding a request pseudo-header to the response. - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put(":method", "get"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, fields, 0); int streamId = stream.getId(); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java index 1ca0412b00b2..5ad4beacdc75 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.util.BufferingResponseListener; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -62,14 +63,14 @@ public void testPushedResourceCancelled() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { HttpURI pushURI = new HttpURI("http://localhost:" + connector.getLocalPort() + pushPath); - MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.empty()); stream.push(new PushPromiseFrame(stream.getId(), 0, pushRequest), new Promise.Adapter<>() { @Override public void succeeded(Stream pushStream) { // Just send the normal response and wait for the reset. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } }, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java index 33074632462a..9b15717ea504 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java @@ -27,6 +27,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.util.AsyncRequestContent; import org.eclipse.jetty.client.util.StringRequestContent; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -64,7 +65,7 @@ private void testEmptyTrailers(String content) throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -79,7 +80,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); request.trailers(() -> trailers); if (content != null) request.body(new StringRequestContent(content)); @@ -109,7 +110,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -119,7 +120,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); @@ -158,7 +159,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -168,7 +169,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java index d2db50c25e7a..62c91f435a30 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java @@ -88,7 +88,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r Session session = sessionPromise.get(5, TimeUnit.SECONDS); HttpURI uri = new HttpURI("http://" + host + ":" + port + "/"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); BlockingQueue headers = new LinkedBlockingQueue<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java index 042219c74e86..a814e6d8580f 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java @@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -64,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); // Reply with HEADERS. stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); closeLatch.await(5, TimeUnit.SECONDS); @@ -80,7 +81,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -132,7 +133,7 @@ public void testClientSendsGoAwayButDoesNotCloseConnectionServerCloses() throws public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -141,7 +142,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes("UTF-8"))); @@ -197,7 +198,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, "OK", Callback.NOOP); return null; @@ -208,7 +209,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java index 319f5058385f..3ba86cc1f8aa 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java @@ -33,6 +33,7 @@ import java.util.function.UnaryOperator; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -194,7 +195,7 @@ public void onData(DataFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.empty()); generator.control(lease, new HeadersFrame(3, metaData, null, true)); for (ByteBuffer buffer : lease.getByteBuffers()) { @@ -232,7 +233,7 @@ public void testHTTP20Direct() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java index a66bebc6f172..119eae5fbdcb 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java @@ -39,6 +39,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -81,7 +82,7 @@ public void testNoPrefaceBytes() throws Exception startServer(new HttpServlet() {}); // No preface bytes. - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new HeadersFrame(1, metaData, null, true)); @@ -126,7 +127,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -184,7 +185,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -360,7 +361,7 @@ public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateE ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector2.getLocalPort())) { @@ -398,7 +399,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -427,7 +428,7 @@ public void testRequestWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); return lease; }); @@ -442,7 +443,7 @@ public void testRequestWithPriorityWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); return lease; }); @@ -456,7 +457,7 @@ public void testRequestWithContinuationFramesWithEmptyHeadersFrame() throws Exce ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the HeadersFrame header and set the length to zero. List buffers = lease.getByteBuffers(); @@ -478,7 +479,7 @@ public void testRequestWithPriorityWithContinuationFramesWithEmptyHeadersFrame() ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); // Take the HeadersFrame header and set the length to just the priority frame. List buffers = lease.getByteBuffers(); @@ -499,7 +500,7 @@ public void testRequestWithContinuationFramesWithEmptyContinuationFrame() throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the ContinuationFrame header, duplicate it, and set the length to zero. List buffers = lease.getByteBuffers(); @@ -523,7 +524,7 @@ public void testRequestWithContinuationFramesWithEmptyLastContinuationFrame() th ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.from()); + MetaData.Request metaData = newRequest("GET", HttpFields.empty()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the last CONTINUATION frame and reset the flag. List buffers = lease.getByteBuffers(); @@ -561,7 +562,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) serverLatch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.from()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncMiddleManServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncMiddleManServlet.java index 68f053a3cecc..cd5c5e2fbadb 100644 --- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncMiddleManServlet.java +++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncMiddleManServlet.java @@ -439,7 +439,7 @@ public void onBegin(Response serverResponse) @Override public void onHeaders(Response serverResponse) { - contentLength = serverResponse.getHeaders().getLongField(HttpHeader.CONTENT_LENGTH.asString()); + contentLength = serverResponse.getHeaders().getLongField(HttpHeader.CONTENT_LENGTH); onServerResponseHeaders(clientRequest, proxyResponse, serverResponse); } diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java index 83a4ba0ad89d..3873a32fb3cf 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java @@ -21,7 +21,9 @@ import java.io.IOException; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.Authentication; @@ -75,7 +77,7 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - MetaData.Request metadata = MetaData.Request.from(null,"http://localhost",null).build(); + MetaData.Request metadata = new MetaData.Request(null, HttpURI.from("http://localhost").toHttpURI(), null, HttpFields.empty()); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); @@ -112,8 +114,9 @@ public void flush() throws IOException {} Response res = channel.getResponse(); // Create a bogus Authorization header. We don't care about the actual credentials. - MetaData.Request metadata = MetaData.Request.from(null,"http://localhost",null, - fields -> fields.add(HttpHeader.AUTHORIZATION, "Basic asdf")).build(); + + MetaData.Request metadata = new MetaData.Request(null, HttpURI.from("http://localhost").toHttpURI(), null, + HttpFields.empty().add(HttpHeader.AUTHORIZATION, "Basic asdf")); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index 9e78930d744c..e21bafa9914b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -36,6 +36,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; @@ -51,7 +52,7 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverHttp.class); private static final HttpField PREAMBLE_UPGRADE_H2C = new HttpField(HttpHeader.UPGRADE, "h2c"); private final HttpConnection _httpConnection; - private final MetaData.RequestBuilder _requestBuilder = new MetaData.RequestBuilder(); + private final RequestBuilder _requestBuilder = new RequestBuilder(); private MetaData.Request _metadata; private HttpField _connection; private HttpField _upgrade = null; @@ -540,4 +541,40 @@ boolean onIdleTimeout(Throwable timeout) } return true; } + + private static class RequestBuilder + { + private final HttpFieldsBuilder _fieldBuilder = HttpFields.empty(); + private final HttpURI.Builder _uri = HttpURI.empty(); + private String _method; + private HttpVersion _version; + + public String method() + { + return _method; + } + + public void request(String method, String uri, HttpVersion version) + { + _method = method; + _uri.uri(uri); + _version = version; + _fieldBuilder.clear(); + } + + public HttpFieldsBuilder getFields() + { + return _fieldBuilder; + } + + public MetaData.Request build() + { + return new MetaData.Request(_method, _uri.toHttpURI(), _version, _fieldBuilder); + } + + public HttpVersion version() + { + return _version; + } + } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index ec84f6f211d7..4043d79eb3c1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -771,7 +771,9 @@ public long getContentLengthLong() return -1; // TODO should we cache this? - return _httpFields.getLongField(HttpHeader.CONTENT_LENGTH.asString()); + return _httpFields.getLongField(HttpHeader.CONTENT_LENGTH); + + // TODO should we return metaData.getContentLength() if field is not found? } public long getContentRead() diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java index f88be942ac97..30a24f855eb5 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java @@ -38,6 +38,7 @@ import org.eclipse.jetty.client.util.BytesRequestContent; import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; @@ -104,7 +105,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } }); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); trailers.put(trailerName, trailerValue); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); @@ -140,7 +141,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } }); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); request = request.trailers(() -> trailers); ContentResponse response = request.timeout(5, TimeUnit.SECONDS).send(); @@ -177,7 +178,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r if (once.compareAndSet(false, true)) { - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); trailers.put(trailerName, trailerValue); jettyResponse.setTrailers(() -> trailers); } @@ -240,7 +241,7 @@ public void testEmptyResponseTrailers(Transport transport) throws Exception @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); response.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); } @@ -282,7 +283,7 @@ public void testResponseTrailersWithLargeContent(Transport transport) throws Exc @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); trailers.put(trailerName, trailerValue); response.setTrailerFields(() -> @@ -333,7 +334,7 @@ public void testResponseResetAlsoResetsTrailers(Transport transport) throws Exce protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.from(); + HttpFieldsBuilder trailers = HttpFields.empty(); trailers.put("name", "value"); jettyResponse.setTrailers(() -> trailers); // Fill some other response field. diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java index 7f1c9aae0e03..0d6c3e6b648a 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java @@ -41,6 +41,7 @@ import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic; import org.eclipse.jetty.client.http.HttpClientConnectionFactory; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -441,7 +442,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.from(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.empty(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); @@ -526,7 +527,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.from(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.empty(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java index e96cfe1306f7..c3a0e7546c48 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java @@ -28,6 +28,7 @@ import java.util.TimeZone; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; @@ -137,7 +138,7 @@ public void test33() expected.set(Calendar.ZONE_OFFSET, 0); // Use GMT+0:00 expected.set(Calendar.DST_OFFSET, 0); // No Daylight Savings Offset - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); // RFC 822 Preferred Format fields.put("D1", "Sun, 6 Nov 1994 08:49:37 GMT"); @@ -334,7 +335,7 @@ public void test364() throws Throwable @Test public void test39() { - HttpFieldsBuilder fields = HttpFields.from(); + HttpFieldsBuilder fields = HttpFields.empty(); fields.put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7"); List list = fields.getQualityCSV("Q"); diff --git a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java index 930e633fe8ca..0bd57b868c69 100644 --- a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java +++ b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java @@ -90,7 +90,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t public void succeeded(Session session) { HttpURI uri = new HttpURI(request.getScheme(), host, port, contextPath + "/h2"); - MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.from()); + MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter() { From a953f425bc05b09e543313fba8d22f58c06b354a Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Sun, 19 Apr 2020 19:06:39 +0200 Subject: [PATCH 13/38] Immutable MetaData WIP jetty-client and jetty-servlet passing tests. Signed-off-by: Greg Wilkins --- .../client/AuthenticationProtocolHandler.java | 2 +- .../eclipse/jetty/client/HttpConnection.java | 9 +++--- .../org/eclipse/jetty/client/HttpRequest.java | 28 +++++++++++++++++++ .../org/eclipse/jetty/client/api/Request.java | 27 ++++++++++++++++++ .../embedded/client/http/HTTPClientDocs.java | 12 ++++++-- .../core/client/HttpUpgraderOverHTTP.java | 16 +++++++---- .../core/client/HttpUpgraderOverHTTP2.java | 4 ++- 7 files changed, 84 insertions(+), 14 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java index 0e6f070a439a..35067e47a262 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AuthenticationProtocolHandler.java @@ -256,7 +256,7 @@ private void copyIfAbsent(HttpRequest oldRequest, Request newRequest, HttpHeader { HttpField field = oldRequest.getHeaders().getField(header); if (field != null && !newRequest.getHeaders().contains(header)) - newRequest.getHeaders().put(field); + newRequest.put(field); } private void forwardSuccessComplete(HttpRequest request, Response response) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 6c587d11f728..f18df06dc16b 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -30,6 +30,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.util.BytesRequestContent; +import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; @@ -152,7 +153,7 @@ protected void normalizeRequest(Request request) if (version.getVersion() <= 11) { if (!headers.contains(HttpHeader.HOST.asString())) - headers.put(getHttpDestination().getHostField()); + request.put(getHttpDestination().getHostField()); } // Add content headers @@ -168,20 +169,20 @@ protected void normalizeRequest(Request request) String contentType = content.getContentType(); if (contentType != null) { - headers.put(HttpHeader.CONTENT_TYPE, contentType); + request.put(new HttpField(HttpHeader.CONTENT_TYPE, contentType)); } else { contentType = getHttpClient().getDefaultRequestContentType(); if (contentType != null) - headers.put(HttpHeader.CONTENT_TYPE, contentType); + request.put(new HttpField(HttpHeader.CONTENT_TYPE, contentType)); } } long contentLength = content.getLength(); if (contentLength >= 0) { if (!headers.contains(HttpHeader.CONTENT_LENGTH.asString())) - headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf(contentLength)); + request.put(new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH, contentLength)); } } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java index e018476142ae..5a9f03bcd6e8 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java @@ -290,6 +290,34 @@ public Request accept(String... accepts) return this; } + @Override + public Request set(HttpFields fields) + { + headers.clear().add(fields); + return this; + } + + @Override + public Request remove(HttpHeader header) + { + headers.remove(header); + return this; + } + + @Override + public Request put(HttpField field) + { + headers.put(field); + return this; + } + + @Override + public Request add(HttpField field) + { + headers.add(field); + return this; + } + @Override public Request header(String name, String value) { diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java index 53e67aab4f41..57be0277f82a 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.util.InputStreamResponseListener; +import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; @@ -152,6 +153,32 @@ public interface Request */ HttpFields getHeaders(); + /** Set the headers, clearing any existing headers + * @param fields The fields to set + * @return this request object + */ + Request set(HttpFields fields); + + /** + * @param header the header to remove + * @return this request object + */ + Request remove(HttpHeader header); + + /** + * @param field the field to add + * @return this request object + * @see #header(HttpHeader, String) + */ + Request add(HttpField field); + + /** + * @param field the field to put + * @return this request object + * @see #header(HttpHeader, String) + */ + Request put(HttpField field); + /** * @param name the name of the header * @param value the value of the header diff --git a/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java index 60161cf3c218..b9ff3e81078d 100644 --- a/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java @@ -63,6 +63,7 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.http.ClientConnectionFactoryOverHTTP2; import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; @@ -78,6 +79,11 @@ @SuppressWarnings("unused") public class HTTPClientDocs { + + public static final PreEncodedHttpField H2C_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "h2c"); + public static final PreEncodedHttpField H2_SETTINGS_FIELD = new PreEncodedHttpField(HttpHeader.HTTP2_SETTINGS, ""); + public static final PreEncodedHttpField H2_UPGRADE_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade, HTTP2-Settings"); + public void start() throws Exception { // tag::start[] @@ -798,9 +804,9 @@ public void dynamicClearText() throws Exception // Make a clear-text upgrade request from HTTP/1.1 to HTTP/2. // The request will start as HTTP/1.1, but the response will be HTTP/2. ContentResponse upgradedResponse = client.newRequest("host", 8080) - .header(HttpHeader.UPGRADE, "h2c") - .header(HttpHeader.HTTP2_SETTINGS, "") - .header(HttpHeader.CONNECTION, "Upgrade, HTTP2-Settings") + .add(H2C_UPGRADE_FIELD) + .add(H2_SETTINGS_FIELD) + .add(H2_UPGRADE_CONNECTION_FIELD) .send(); // end::dynamicClearText[] } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java index ba28a3ae27fe..046e83b8785f 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java @@ -30,6 +30,7 @@ import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.websocket.core.WebSocketConstants; @@ -37,6 +38,11 @@ public class HttpUpgraderOverHTTP implements HttpUpgrader { + public static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + public static final PreEncodedHttpField WS_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "websocket"); + public static final PreEncodedHttpField WS_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade"); + public static final PreEncodedHttpField PRAGMA_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.PRAGMA, "no-cache"); + public static final PreEncodedHttpField CACHE_CONTROL_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, "no-cache"); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP(ClientUpgradeRequest clientUpgradeRequest) @@ -48,17 +54,17 @@ public HttpUpgraderOverHTTP(ClientUpgradeRequest clientUpgradeRequest) public void prepare(HttpRequest request) { request.method(HttpMethod.GET).version(HttpVersion.HTTP_1_1); - request.header(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); - request.header(HttpHeader.UPGRADE, "websocket"); - request.header(HttpHeader.CONNECTION, "Upgrade"); + request.add(WS_VERSIONS_FIELD); + request.add(WS_UPGRADE_FIELD); + request.add(WS_CONNECTION_FIELD); request.header(HttpHeader.SEC_WEBSOCKET_KEY, generateRandomKey()); // Per the hybi list: Add no-cache headers to avoid compatibility issue. // There are some proxies that rewrite "Connection: upgrade" to // "Connection: close" in the response if a request doesn't contain // these headers. - request.header(HttpHeader.PRAGMA, "no-cache"); - request.header(HttpHeader.CACHE_CONTROL, "no-cache"); + request.add(PRAGMA_NO_CACHE_FIELD); + request.add(CACHE_CONTROL_NO_CACHE_FIELD); // Notify the UpgradeListeners now the headers are set. clientUpgradeRequest.requestComplete(); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java index 12e1a1bba423..1fbba0f11023 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java @@ -23,12 +23,14 @@ import org.eclipse.jetty.client.HttpUpgrader; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.websocket.core.WebSocketConstants; public class HttpUpgraderOverHTTP2 implements HttpUpgrader { + public static final PreEncodedHttpField SPEC_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP2(ClientUpgradeRequest clientUpgradeRequest) @@ -41,7 +43,7 @@ public void prepare(HttpRequest request) { request.method(HttpMethod.CONNECT); request.upgradeProtocol("websocket"); - request.header(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + request.add(SPEC_VERSION_FIELD); // Notify the UpgradeListeners now the headers are set. clientUpgradeRequest.requestComplete(); From fb81db19733e7a8d8f872a9e60396dc3108b32d7 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 12:18:02 +0200 Subject: [PATCH 14/38] Immutable MetaData WIP Better align the style of immutability between `HttpFields` and `HttpURI`. They both now have static build() and from() methods, plus Builder and Immutable implementations. Potentially `Builder` could be renamed as `Mutable` Signed-off-by: Greg Wilkins --- .../java/client/ConscryptHTTP2ClientTest.java | 4 +- .../alpn/java/client/JDK9HTTP2ClientTest.java | 4 +- .../org/eclipse/jetty/client/HttpRequest.java | 2 +- .../eclipse/jetty/client/HttpResponse.java | 4 +- .../jetty/client/http/HttpSenderOverHTTP.java | 2 +- .../client/util/MultiPartContentTest.java | 6 +- .../src/main/java/embedded/HTTP2Docs.java | 4 +- .../client/http2/HTTP2ClientDocs.java | 24 +- .../embedded/server/http/HTTPServerDocs.java | 2 +- .../server/http2/HTTP2ServerDocs.java | 8 +- .../fcgi/client/http/HttpSenderOverFCGI.java | 4 +- .../fcgi/parser/ResponseContentParser.java | 2 +- .../fcgi/generator/ClientGeneratorTest.java | 2 +- .../jetty/fcgi/parser/ClientParserTest.java | 8 +- .../fcgi/server/HttpChannelOverFCGI.java | 2 +- .../org/eclipse/jetty/http/HttpFields.java | 14 +- .../eclipse/jetty/http/HttpFieldsBuilder.java | 2 +- .../org/eclipse/jetty/http/HttpGenerator.java | 2 +- .../java/org/eclipse/jetty/http/HttpURI.java | 531 +++++++++++------- .../java/org/eclipse/jetty/http/MetaData.java | 19 +- .../eclipse/jetty/http/HttpFieldsTest.java | 50 +- .../jetty/http/HttpGeneratorClientTest.java | 20 +- .../http/HttpGeneratorServerHTTPTest.java | 2 +- .../jetty/http/HttpGeneratorServerTest.java | 42 +- .../eclipse/jetty/http/HttpURIParseTest.java | 6 +- .../org/eclipse/jetty/http/HttpURITest.java | 92 +-- .../jetty/http2/client/HTTP2Client.java | 2 +- .../jetty/http2/client/AbstractTest.java | 2 +- .../jetty/http2/client/AsyncIOTest.java | 8 +- .../jetty/http2/client/AsyncServletTest.java | 10 +- .../jetty/http2/client/DataDemandTest.java | 18 +- .../http2/client/FlowControlStalledTest.java | 14 +- .../http2/client/FlowControlStrategyTest.java | 46 +- .../http2/client/FlowControlWindowsTest.java | 4 +- .../eclipse/jetty/http2/client/HTTP2Test.java | 56 +- .../jetty/http2/client/IdleTimeoutTest.java | 36 +- .../jetty/http2/client/InterleavingTest.java | 8 +- .../http2/client/MaxPushedStreamsTest.java | 8 +- .../jetty/http2/client/PrefaceTest.java | 6 +- .../jetty/http2/client/PriorityTest.java | 14 +- .../jetty/http2/client/ProxyProtocolTest.java | 8 +- .../eclipse/jetty/http2/client/ProxyTest.java | 4 +- .../http2/client/PushCacheFilterTest.java | 46 +- .../jetty/http2/client/RawHTTP2ProxyTest.java | 16 +- .../http2/client/SmallThreadPoolLoadTest.java | 2 +- .../jetty/http2/client/StreamCloseTest.java | 26 +- .../jetty/http2/client/StreamCountTest.java | 8 +- .../jetty/http2/client/StreamResetTest.java | 40 +- .../jetty/http2/client/TrailersTest.java | 26 +- .../http2/frames/ContinuationParseTest.java | 4 +- .../frames/HeadersGenerateParseTest.java | 8 +- .../frames/PushPromiseGenerateParseTest.java | 8 +- .../jetty/http2/hpack/MetaDataBuilder.java | 26 +- .../jetty/http2/hpack/HpackEncoderTest.java | 8 +- .../jetty/http2/hpack/HpackPerfTest.java | 2 +- .../eclipse/jetty/http2/hpack/HpackTest.java | 20 +- .../client/http/HttpConnectionOverHTTP2.java | 2 +- .../HttpClientTransportOverHTTP2Test.java | 10 +- .../client/http/PushedResourcesTest.java | 6 +- .../client/http/RequestTrailersTest.java | 12 +- .../client/http/ResponseTrailerTest.java | 2 +- .../http2/server/HTTP2ServerConnection.java | 2 +- .../http2/server/HttpChannelOverHTTP2.java | 14 +- .../http2/server/HttpTransportOverHTTP2.java | 7 +- .../http2/server/AbstractServerTest.java | 2 +- .../eclipse/jetty/http2/server/CloseTest.java | 12 +- .../jetty/http2/server/HTTP2CServerTest.java | 4 +- .../jetty/http2/server/HTTP2ServerTest.java | 24 +- .../jetty/proxy/AbstractProxyServlet.java | 10 +- .../rewrite/handler/CompactPathRule.java | 2 +- .../handler/ForwardedSchemeHeaderRule.java | 2 +- .../rewrite/handler/RewritePatternRule.java | 2 +- .../rewrite/handler/RewriteRegexRule.java | 4 +- .../jetty/rewrite/handler/RuleContainer.java | 4 +- .../ForwardedSchemeHeaderRuleTest.java | 8 +- .../rewrite/handler/MsieSslRuleTest.java | 26 +- .../rewrite/handler/PatternRuleTest.java | 2 +- .../rewrite/handler/RewriteHandlerTest.java | 16 +- .../handler/RewritePatternRuleTest.java | 4 +- .../rewrite/handler/RewriteRegexRuleTest.java | 6 +- .../rewrite/handler/ValidUrlRuleTest.java | 12 +- .../handler/VirtualHostRuleContainerTest.java | 36 +- .../jetty/security/DataConstraintsTest.java | 2 +- .../SpnegoAuthenticatorTest.java | 6 +- .../org/eclipse/jetty/server/Dispatcher.java | 5 +- .../server/ForwardedRequestCustomizer.java | 10 +- .../jetty/server/HostHeaderCustomizer.java | 2 +- .../org/eclipse/jetty/server/HttpChannel.java | 4 +- .../jetty/server/HttpChannelOverHttp.java | 10 +- .../eclipse/jetty/server/PushBuilderImpl.java | 2 +- .../org/eclipse/jetty/server/Request.java | 8 +- .../org/eclipse/jetty/server/Response.java | 8 +- .../jetty/server/SecureRequestCustomizer.java | 4 +- .../java/org/eclipse/jetty/server/Server.java | 8 +- .../jetty/server/handler/ContextHandler.java | 10 +- .../server/handler/gzip/GzipHandler.java | 2 +- .../jetty/server/PartialRFC2616Test.java | 4 +- .../eclipse/jetty/server/ResponseTest.java | 8 +- .../jetty/servlets/PushCacheFilter.java | 2 +- .../servlets/PushSessionCacheFilter.java | 2 +- .../jetty/servlets/AbstractDoSFilterTest.java | 2 +- .../jetty/websocket/core/WebSocketTester.java | 2 +- .../eclipse/jetty/http/tools/HttpTester.java | 2 +- .../matchers/HttpFieldsMatchersTest.java | 12 +- .../jetty/http/client/HttpTrailersTest.java | 12 +- .../client/ProxyWithDynamicTransportTest.java | 4 +- .../jetty/test/rfcs/RFC2616BaseTest.java | 4 +- 107 files changed, 898 insertions(+), 810 deletions(-) diff --git a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java index 8e27ce84654b..e3c8cd58e41d 100644 --- a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java @@ -75,9 +75,9 @@ public void testConscryptHTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.empty(); + HttpFieldsBuilder requestFields = HttpFields.build(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); - MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java index a5a9f8078577..e1d6aea8f543 100644 --- a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java @@ -64,9 +64,9 @@ public void testJDK9HTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.empty(); + HttpFieldsBuilder requestFields = HttpFields.build(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); - MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java index 5a9f03bcd6e8..f3d04a0b61e2 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java @@ -65,7 +65,7 @@ public class HttpRequest implements Request { private static final URI NULL_URI = URI.create("null:0"); - private final HttpFieldsBuilder headers = HttpFields.empty(); + private final HttpFieldsBuilder headers = HttpFields.build(); private final Fields params = new Fields(true); private final List responseListeners = new ArrayList<>(); private final AtomicReference aborted = new AtomicReference<>(); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index bcd1c20408a0..1b337fd0b937 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -30,7 +30,7 @@ public class HttpResponse implements Response { - private final HttpFieldsBuilder headers = HttpFields.empty(); + private final HttpFieldsBuilder headers = HttpFields.build(); private final Request request; private final List listeners; private HttpVersion version; @@ -112,7 +112,7 @@ public HttpFieldsBuilder getTrailers() public HttpResponse trailer(HttpField trailer) { if (trailers == null) - trailers = HttpFields.empty(); + trailers = HttpFields.build(); trailers.add(trailer); return this; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java index 15f04ddbc5e0..4210490088fa 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java @@ -78,7 +78,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool String query = request.getQuery(); if (query != null) path += "?" + query; - metaData = new MetaData.Request(request.getMethod(), new HttpURI(path), request.getVersion(), request.getHeaders(), contentLength, request.getTrailers()); + metaData = new MetaData.Request(request.getMethod(), HttpURI.from(path), request.getVersion(), request.getHeaders(), contentLength, request.getTrailers()); if (LOG.isDebugEnabled()) LOG.debug("Sending headers with content {} last={} for {}", BufferUtil.toDetailString(contentBuffer), lastContent, exchange.getRequest()); headersCallback.iterate(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java index 998ddadf1eb1..293ace217ad2 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java @@ -145,7 +145,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put(HttpHeader.CONTENT_TYPE, "text/plain;charset=" + encoding.name()); BytesRequestContent content = new BytesRequestContent(value.getBytes(encoding)); multiPart.addFieldPart(name, content, fields); @@ -241,7 +241,7 @@ public void close() throws IOException closeLatch.countDown(); } }); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put(HttpHeader.CONTENT_TYPE, contentType); multiPart.addFilePart(name, fileName, content, fields); multiPart.close(); @@ -355,7 +355,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put(headerName, headerValue); multiPart.addFieldPart(field, new StringRequestContent(value, encoding), fields); multiPart.addFilePart(fileField, tmpPath.getFileName().toString(), new PathRequestContent(tmpPath), null); diff --git a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java index 627bda812911..c4750932325b 100644 --- a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java +++ b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java @@ -49,9 +49,9 @@ public void dataDemanded() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.empty() + HttpFieldsBuilder requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); // tag::dataDemanded[] diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index ba1e262e7dad..7b65374eba6e 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -148,11 +148,11 @@ public void newStream() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFields requestHeaders = HttpFields.empty() + HttpFields requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); // The request metadata with method, URI and headers. - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); // The HTTP/2 HEADERS frame, with endStream=true // to signal that this request has no content. @@ -173,11 +173,11 @@ public void newStreamWithData() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFieldsBuilder requestHeaders = HttpFields.empty() + HttpFieldsBuilder requestHeaders = HttpFields.build() .put(HttpHeader.CONTENT_TYPE, "application/json"); // The request metadata with method, URI and headers. - MetaData.Request request = new MetaData.Request("POST", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("POST", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); // The HTTP/2 HEADERS frame, with endStream=false to // signal that there will be more frames in this stream. @@ -214,9 +214,9 @@ public void responseListener() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.empty() + HttpFieldsBuilder requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); // tag::responseListener[] @@ -267,9 +267,9 @@ public void reset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = HttpFields.empty() + HttpFields requestHeaders = HttpFields.build() .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); // tag::reset[] @@ -297,9 +297,9 @@ public void push() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields requestHeaders = HttpFields.empty() + HttpFields requestHeaders = HttpFields.build() .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); // tag::push[] @@ -359,9 +359,9 @@ public void pushReset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.empty() + HttpFieldsBuilder requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); - MetaData.Request request = new MetaData.Request("GET", new HttpURI("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); + MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); // tag::pushReset[] diff --git a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java index 269995b9a059..0519c58d3ecf 100644 --- a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java @@ -464,7 +464,7 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque { // Rewrite old paths to new paths. HttpURI uri = jettyRequest.getHttpURI(); - HttpURI newURI = HttpURI.from(uri).path("/new_path/" + path.substring("/old_path/".length())).toHttpURI(); + HttpURI newURI = HttpURI.build(uri).path("/new_path/" + path.substring("/old_path/".length())); // Modify the request object. jettyRequest.setHttpURI(newURI); } diff --git a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java index 965d7387181c..483e8f942035 100644 --- a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java @@ -202,7 +202,7 @@ private void respond(Stream stream, MetaData.Request request) // Prepare the response HEADERS frame. // The response HTTP status and HTTP headers. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); if (HttpMethod.GET.is(request.getMethod())) { @@ -294,14 +294,14 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) if (pushEnabled && request.getURIString().endsWith("/index.html")) { // Push the favicon. - HttpURI pushedURI = HttpURI.from(request.getURI()).path("/favicon.ico").toHttpURI(); - MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.empty()); + HttpURI pushedURI = HttpURI.build(request.getURI()).path("/favicon.ico").asImmutable(); + MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.build()); PushPromiseFrame promiseFrame = new PushPromiseFrame(stream.getId(), 0, pushedRequest); stream.push(promiseFrame, new Stream.Listener.Adapter()) .thenCompose(pushedStream -> { // Send the favicon "response". - MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); return pushedStream.headers(new HeadersFrame(pushedStream.getId(), pushedResponse, null, false)) .thenCompose(pushed -> pushed.data(new DataFrame(pushed.getId(), faviconBuffer, true))); }); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index 1ead07b8ad62..d04f83ef8fde 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -60,8 +60,8 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { Request request = exchange.getRequest(); // Copy the request headers to be able to convert them properly - HttpFieldsBuilder headers = HttpFields.from(request.getHeaders()); - HttpFieldsBuilder fcgiHeaders = HttpFields.empty(); + HttpFieldsBuilder headers = HttpFields.build(request.getHeaders()); + HttpFieldsBuilder fcgiHeaders = HttpFields.build(); // FastCGI headers based on the URI URI uri = request.getURI(); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index 12aa2724c1ec..a5a66335c45b 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -85,7 +85,7 @@ protected void end(int request) private static class ResponseParser implements HttpParser.ResponseHandler { - private final HttpFieldsBuilder fields = HttpFields.empty(); + private final HttpFieldsBuilder fields = HttpFields.build(); private ClientParser.Listener listener; private final int request; private final FCGIHttpParser httpParser; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java index 96a64d57b085..8ae2501d0a58 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java @@ -39,7 +39,7 @@ public class ClientGeneratorTest @Test public void testGenerateRequestHeaders() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); // Short name, short value final String shortShortName = "REQUEST_METHOD"; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java index 78f869bbc638..672164d78d44 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java @@ -43,7 +43,7 @@ public class ClientParserTest public void testParseResponseHeaders() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); final int statusCode = 200; final String statusMessage = "OK"; @@ -113,7 +113,7 @@ public boolean onHeaders(int request) public void testParseNoResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Content-Length", "0"); ByteBufferPool byteBufferPool = new MappedByteBufferPool(); @@ -158,7 +158,7 @@ public void onEnd(int request) public void testParseSmallResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); ByteBuffer content = ByteBuffer.wrap(new byte[1024]); final int contentLength = content.remaining(); @@ -211,7 +211,7 @@ public void onEnd(int request) public void testParseLargeResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); ByteBuffer content = ByteBuffer.wrap(new byte[128 * 1024]); final int contentLength = content.remaining(); diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java index 7b86bdf318aa..d85b36ea2e05 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java @@ -44,7 +44,7 @@ public class HttpChannelOverFCGI extends HttpChannel { private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverFCGI.class); - private final HttpFieldsBuilder fields = HttpFields.empty(); + private final HttpFieldsBuilder fields = HttpFields.build(); private final Dispatcher dispatcher; private String method; private String path; 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 031812993b47..893e145ecc95 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 @@ -35,29 +35,29 @@ */ public interface HttpFields extends Iterable { - HttpFields EMPTY = empty().asImmutable(); + HttpFields EMPTY = build().asImmutable(); - static HttpFieldsBuilder empty() + static HttpFieldsBuilder build() { return new HttpFieldsBuilder(); } - static HttpFieldsBuilder empty(int capacity) + static HttpFieldsBuilder build(int capacity) { return new HttpFieldsBuilder(capacity); } - static HttpFieldsBuilder from(HttpFields fields) + static HttpFieldsBuilder build(HttpFields fields) { return new HttpFieldsBuilder(fields); } - static HttpFieldsBuilder from(HttpFields fields, HttpField replaceField) + static HttpFieldsBuilder build(HttpFields fields, HttpField replaceField) { return new HttpFieldsBuilder(fields, replaceField); } - static HttpFieldsBuilder from(HttpFields fields, EnumSet removeFields) + static HttpFieldsBuilder build(HttpFields fields, EnumSet removeFields) { return new HttpFieldsBuilder(fields, removeFields); } @@ -74,7 +74,7 @@ default int asHashCode() default HttpFieldsBuilder asMutable() { - return from(this); + return build(this); } default String asString() diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java index b951ff011782..9821ee5ed58e 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java @@ -112,7 +112,7 @@ else if (fields instanceof HttpFieldsBuilder) */ HttpFieldsBuilder(HttpFields fields, EnumSet removeFields) { - _fields = new ArrayList<>(fields.size()); + _fields = new ArrayList<>(Math.max(fields.size() + 4, 16)); for (HttpField f : fields) { if (f.getHeader() == null || removeFields.contains(f.getHeader())) 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 de855df0ae68..9a084a12695e 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 @@ -52,7 +52,7 @@ public class HttpGenerator public static final MetaData.Response CONTINUE_100_INFO = new MetaData.Response(HttpVersion.HTTP_1_1, 100, null, null, -1); public static final MetaData.Response PROGRESS_102_INFO = new MetaData.Response(HttpVersion.HTTP_1_1, 102, null, null, -1); public static final MetaData.Response RESPONSE_500_INFO = - new MetaData.Response(HttpVersion.HTTP_1_1, INTERNAL_SERVER_ERROR_500, null, HttpFields.empty().put(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE), 0); + new MetaData.Response(HttpVersion.HTTP_1_1, INTERNAL_SERVER_ERROR_500, null, HttpFields.build().put(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE), 0); // states public enum State diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 11662951fab6..bab8baece50e 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -46,238 +46,335 @@ * return value of {@link #getDecodedPath()}. If there are multiple parameters, the * {@link #getParam()} method returns only the last one. */ -public class HttpURI +public interface HttpURI { - private final String _scheme; - private final String _user; - private final String _host; - private final int _port; - private final String _path; - private final String _param; - private final String _query; - private final String _fragment; - private String _uri; - private String _decodedPath; - - public HttpURI(String uri) - { - Builder builder = new Builder(uri); - _uri = builder._uri; - _scheme = builder._scheme; - _user = builder._user; - _host = builder._host; - _port = builder._port; - _path = builder._path; - _decodedPath = builder._decodedPath; - _param = builder._param; - _query = builder._query; - _fragment = builder._fragment; - } - - public HttpURI(URI uri) - { - Builder builder = new Builder(uri); - _uri = builder._uri; - _scheme = builder._scheme; - _user = builder._user; - _host = builder._host; - _port = builder._port; - _path = builder._path; - _decodedPath = builder._decodedPath; - _param = builder._param; - _query = builder._query; - _fragment = builder._fragment; - } - - private HttpURI(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) - { - _uri = uri; - _scheme = scheme; - _user = user; - _host = host; - _port = port; - _path = path; - _decodedPath = decodedPath; - _param = param; - _query = query; - _fragment = fragment; - } - - public static HttpURI.Builder empty() + static HttpURI.Builder build() { return new HttpURI.Builder(); } - public static HttpURI.Builder from(HttpURI uri) + static HttpURI.Builder build(HttpURI uri) { return new HttpURI.Builder(uri); } - public static HttpURI.Builder from(HttpURI uri, String pathQuery) + static HttpURI.Builder build(HttpURI uri, String pathQuery) { return new HttpURI.Builder(uri, pathQuery); } - public static HttpURI.Builder from(HttpURI uri, String path, String param, String query) + static HttpURI.Builder build(HttpURI uri, String path, String param, String query) { return new HttpURI.Builder(uri, path, param, query); } - public static HttpURI.Builder from(URI uri) + static HttpURI.Builder build(URI uri) { return new HttpURI.Builder(uri); } - public static HttpURI.Builder from(String uri) + static HttpURI.Builder build(String uri) { return new HttpURI.Builder(uri); } - @Override - public boolean equals(Object o) + static HttpURI from(URI uri) { - if (o == this) - return true; - if (!(o instanceof HttpURI)) - return false; - return toString().equals(o.toString()); + return new HttpURI.Immutable(uri); } - public String getAuthority() + static HttpURI from(String uri) { - if (_port > 0) - return _host + ":" + _port; - return _host; + return new HttpURI.Immutable(uri); } - public String getDecodedPath() + static HttpURI from(String method, String uri) { - if (_decodedPath == null && _path != null) - _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); - return _decodedPath; + if (HttpMethod.CONNECT.is(method)) + return new Immutable(uri, null, null, null, -1, uri, null, null, null, null); + return new HttpURI.Builder(uri).asImmutable(); } - public String getFragment() - { - return _fragment; - } + String getAuthority(); - public String getHost() - { - // Return null for empty host to retain compatibility with java.net.URI - if (_host != null && _host.isEmpty()) - return null; - return _host; - } + String getDecodedPath(); - public String getParam() - { - return _param; - } + String getFragment(); + + String getHost(); + + String getParam(); /** * The parsed Path. * * @return the path as parsed on valid URI. null for invalid URI. */ - public String getPath() - { - return _path; - } + String getPath(); - public String getPathQuery() - { - if (_query == null) - return _path; - return _path + "?" + _query; - } + String getPathQuery(); - public int getPort() - { - return _port; - } + int getPort(); - public String getQuery() - { - return _query; - } + String getQuery(); - public String getScheme() - { - return _scheme; - } + String getScheme(); - public String getUser() - { - return _user; - } + String getUser(); - public boolean hasAuthority() - { - return _host != null; - } + boolean hasAuthority(); - public boolean hasQuery() - { - return _query != null && !_query.isEmpty(); - } + boolean hasQuery(); - public boolean isAbsolute() + boolean isAbsolute(); + + HttpURI asImmutable(); + + HttpURI.Builder asMutable(); + + default URI toURI() { - return !StringUtil.isEmpty(_scheme); + try + { + String query = getQuery(); + return new URI(getScheme(), null, getHost(), getPort(), getPath(), query == null ? null : UrlEncoded.decodeString(query), getFragment()); + } + catch (URISyntaxException x) + { + throw new RuntimeException(x); + } } - @Override - public String toString() + class Immutable implements HttpURI { - if (_uri == null) + private final String _scheme; + private final String _user; + private final String _host; + private final int _port; + private final String _path; + private final String _param; + private final String _query; + private final String _fragment; + private String _uri; + private String _decodedPath; + + private Immutable(String uri) { - StringBuilder out = new StringBuilder(); + Builder builder = new Builder(uri); + _uri = builder._uri; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; + } - if (_scheme != null) - out.append(_scheme).append(':'); + private Immutable(URI uri) + { + Builder builder = new Builder(uri); + _uri = builder._uri; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; + } - if (_host != null) - { - out.append("//"); - if (_user != null) - out.append(_user).append('@'); - out.append(_host); - } + private Immutable(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) + { + _uri = uri; + _scheme = scheme; + _user = user; + _host = host; + _port = port; + _path = path; + _decodedPath = decodedPath; + _param = param; + _query = query; + _fragment = fragment; + } + @Override + public boolean equals(Object o) + { + if (o == this) + return true; + if (!(o instanceof HttpURI)) + return false; + return toString().equals(o.toString()); + } + + @Override + public String getAuthority() + { if (_port > 0) - out.append(':').append(_port); + return _host + ":" + _port; + return _host; + } - if (_path != null) - out.append(_path); + @Override + public String getDecodedPath() + { + if (_decodedPath == null && _path != null) + _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); + return _decodedPath; + } - if (_query != null) - out.append('?').append(_query); + @Override + public String getFragment() + { + return _fragment; + } - if (_fragment != null) - out.append('#').append(_fragment); + @Override + public String getHost() + { + // Return null for empty host to retain compatibility with java.net.URI + if (_host != null && _host.isEmpty()) + return null; + return _host; + } - if (out.length() > 0) - _uri = out.toString(); - else - _uri = ""; + @Override + public String getParam() + { + return _param; } - return _uri; - } - public URI toURI() - { - try + /** + * The parsed Path. + * + * @return the path as parsed on valid URI. null for invalid URI. + */ + @Override + public String getPath() { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + return _path; } - catch (URISyntaxException x) + + @Override + public String getPathQuery() { - throw new RuntimeException(x); + if (_query == null) + return _path; + return _path + "?" + _query; + } + + @Override + public int getPort() + { + return _port; + } + + @Override + public String getQuery() + { + return _query; + } + + @Override + public String getScheme() + { + return _scheme; + } + + @Override + public String getUser() + { + return _user; + } + + @Override + public boolean hasAuthority() + { + return _host != null; + } + + @Override + public boolean hasQuery() + { + return _query != null && !_query.isEmpty(); + } + + @Override + public boolean isAbsolute() + { + return !StringUtil.isEmpty(_scheme); + } + + @Override + public URI toURI() + { + try + { + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + } + catch (URISyntaxException x) + { + throw new RuntimeException(x); + } + } + + @Override + public HttpURI asImmutable() + { + return this; + } + + @Override + public HttpURI.Builder asMutable() + { + return build(this); + } + + @Override + public String toString() + { + if (_uri == null) + { + StringBuilder out = new StringBuilder(); + + if (_scheme != null) + out.append(_scheme).append(':'); + + if (_host != null) + { + out.append("//"); + if (_user != null) + out.append(_user).append('@'); + out.append(_host); + } + + if (_port > 0) + out.append(':').append(_port); + + if (_path != null) + out.append(_path); + + if (_query != null) + out.append('?').append(_query); + + if (_fragment != null) + out.append('#').append(_fragment); + + if (out.length() > 0) + _uri = out.toString(); + else + _uri = ""; + } + return _uri; } } - public static class Builder + class Builder implements HttpURI { private enum State { @@ -305,46 +402,46 @@ private enum State private String _query; private String _fragment; - Builder() + private Builder() { } - Builder(HttpURI uri) + private Builder(HttpURI uri) { uri(uri); } - Builder(HttpURI baseURI, String pathQuery) + private Builder(HttpURI baseURI, String pathQuery) { _uri = null; - _scheme = baseURI._scheme; - _user = baseURI._user; - _host = baseURI._host; - _port = baseURI._port; + _scheme = baseURI.getScheme(); + _user = baseURI.getUser(); + _host = baseURI.getHost(); + _port = baseURI.getPort(); if (pathQuery != null) parse(State.PATH, pathQuery); } - Builder(HttpURI baseURI, String path, String param, String query) + private Builder(HttpURI baseURI, String path, String param, String query) { _uri = null; - _scheme = baseURI._scheme; - _user = baseURI._user; - _host = baseURI._host; - _port = baseURI._port; + _scheme = baseURI.getScheme(); + _user = baseURI.getUser(); + _host = baseURI.getHost(); + _port = baseURI.getPort(); _path = path; _param = param; _query = query; _fragment = null; } - Builder(String uri) + private Builder(String uri) { _port = -1; parse(State.START, uri); } - Builder(URI uri) + private Builder(URI uri) { _uri = null; @@ -369,7 +466,7 @@ private enum State _fragment = uri.getFragment(); } - public Builder(String scheme, String host, int port, String pathQuery) + private Builder(String scheme, String host, int port, String pathQuery) { _uri = null; @@ -381,16 +478,20 @@ public Builder(String scheme, String host, int port, String pathQuery) parse(State.PATH, pathQuery); } - public Builder(String method, String uri) + @Override + public HttpURI asImmutable() { - _uri = uri; - if (HttpMethod.CONNECT.is(method)) - _path = uri; - else - parse(uri.startsWith("/") ? State.PATH : State.START, uri); + return new Immutable(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); } - public String authority() + @Override + public HttpURI.Builder asMutable() + { + return this; + } + + @Override + public String getAuthority() { if (_port > 0) return _host + ":" + _port; @@ -423,11 +524,6 @@ public Builder authority(String hostport) return this; } - public HttpURI toHttpURI() - { - return new HttpURI(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); - } - public void clear() { _uri = null; @@ -442,7 +538,8 @@ public void clear() _user = null; } - public String decodedPath() + @Override + public String getDecodedPath() { if (_decodedPath == null && _path != null) _decodedPath = URIUtil.canonicalPath(URIUtil.decodePath(_path)); @@ -457,7 +554,8 @@ public Builder decodedPath(String path) return this; } - public String fragment() + @Override + public String getFragment() { return _fragment; } @@ -469,17 +567,20 @@ public Builder fragment(String fragment) return this; } + @Override public boolean hasAuthority() { return _host != null; } + @Override public boolean hasQuery() { return _query != null && !_query.isEmpty(); } - public String host() + @Override + public String getHost() { return _host; } @@ -491,6 +592,7 @@ public Builder host(String host) return this; } + @Override public boolean isAbsolute() { return _scheme != null && !_scheme.isEmpty(); @@ -506,7 +608,8 @@ public Builder normalize() return this; } - public String param() + @Override + public String getParam() { return _param; } @@ -522,12 +625,8 @@ public Builder param(String param) return this; } - /** - * The parsed Path. - * - * @return the path as parsed on valid URI. null for invalid URI. - */ - public String path() + @Override + public String getPath() { return _path; } @@ -543,7 +642,8 @@ public Builder path(String path) return this; } - public String pathQuery() + @Override + public String getPathQuery() { if (_query == null) return _path; @@ -562,7 +662,8 @@ public Builder pathQuery(String pathQuery) return this; } - public int port() + @Override + public int getPort() { return _port; } @@ -574,7 +675,8 @@ public Builder port(int port) return this; } - public String query() + @Override + public String getQuery() { return _query; } @@ -586,7 +688,8 @@ public Builder query(String query) return this; } - public String scheme() + @Override + public String getScheme() { return _scheme; } @@ -606,7 +709,7 @@ public Builder scheme(String scheme) @Override public String toString() { - return toHttpURI().toString(); + return asImmutable().toString(); } public URI toURI() @@ -623,16 +726,16 @@ public URI toURI() public Builder uri(HttpURI uri) { - _uri = uri._uri; - _scheme = uri._scheme; - _user = uri._user; - _host = uri._host; - _port = uri._port; - _path = uri._path; - _decodedPath = uri._decodedPath; - _param = uri._param; - _query = uri._query; - _fragment = uri._fragment; + _uri = null; + _scheme = uri.getScheme(); + _user = uri.getUser(); + _host = uri.getHost(); + _port = uri.getPort(); + _path = uri.getPath(); + _decodedPath = uri.getDecodedPath(); + _param = uri.getParam(); + _query = uri.getQuery(); + _fragment = uri.getFragment(); return this; } @@ -653,7 +756,7 @@ public Builder uri(String uri, int offset, int length) return this; } - public String user() + public String getUser() { return _user; } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 6db19316cfe1..4eb3889e7720 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -25,7 +25,7 @@ public class MetaData implements Iterable { private static final Supplier SELF_SUPPLIED_TRAILORS = () -> null; - private static final HttpFields SUPPLIED_TRAILERS = HttpFields.empty().asImmutable(); + private static final HttpFields SUPPLIED_TRAILERS = HttpFields.build(HttpFields.EMPTY).asImmutable(); private final HttpVersion _httpVersion; private final HttpFields _fields; private final long _contentLength; @@ -149,20 +149,15 @@ public Request(String method, HttpURI uri, HttpVersion version, HttpFields field { super(version, fields, contentLength); _method = method; - _uri = uri; - } - - public Request(String method, HttpScheme scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) - { - this(method, scheme == null ? null : scheme.asString(), hostPort, uri, version, fields, contentLength); + _uri = uri.asImmutable(); } - public Request(String method, String scheme, HostPortHttpField hostPort, String uri, HttpVersion version, HttpFields fields, long contentLength) + public Request(String method, String scheme, HostPortHttpField authority, String uri, HttpVersion version, HttpFields fields, long contentLength) { - this(method, new HttpURI.Builder(scheme, - hostPort == null ? null : hostPort.getHost(), - hostPort == null ? -1 : hostPort.getPort(), - uri).toHttpURI(), version, fields, contentLength); + // TODO review this constructor + this(method, + HttpURI.build().scheme(scheme).host(authority == null ? null : authority.getHost()).port(authority == null ? -1 : authority.getPort()).pathQuery(uri), + version, fields, contentLength); } public Request(String method, HttpURI uri, HttpVersion version, HttpFieldsBuilder fields, long contentLength, Supplier trailers) 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 037b764d9b69..81f95407060b 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 @@ -47,7 +47,7 @@ public class HttpFieldsTest @Test public void testPut() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("name0", "value:0"); header.put("name1", "value1"); @@ -78,7 +78,7 @@ public void testPut() throws Exception @Test public void testPutTo() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("name0", "value0"); header.put("name1", "value:A"); @@ -99,7 +99,7 @@ public void testPutTo() throws Exception @Test public void testImmutable() throws Exception { - HttpFieldsBuilder builder = HttpFields.empty(); + HttpFieldsBuilder builder = HttpFields.build(); builder.put("name0", "value0"); builder.put("name1", "value1"); @@ -129,7 +129,7 @@ public void testImmutable() throws Exception @Test public void testGet() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("name0", "value0"); header.put("name1", "value1"); @@ -157,7 +157,7 @@ public void testGet() throws Exception @Test public void testGetKnown() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("Connection", "value0"); header.put(HttpHeader.ACCEPT, "value1"); @@ -175,7 +175,7 @@ public void testGetKnown() throws Exception @Test public void testCRLF() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("name0", "value\r\n0"); header.put("name\r\n1", "value1"); @@ -194,7 +194,7 @@ public void testCRLF() throws Exception @Test public void testCachedPut() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("Connection", "Keep-Alive"); header.put("tRansfer-EncOding", "CHUNKED"); @@ -214,7 +214,7 @@ public void testCachedPut() throws Exception @Test public void testRePut() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("name0", "value0"); header.put("name1", "xxxxxx"); @@ -254,7 +254,7 @@ public void testRePut() throws Exception @Test public void testRemovePut() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(1); + HttpFieldsBuilder header = HttpFields.build(1); header.put("name0", "value0"); header.put("name1", "value1"); @@ -292,7 +292,7 @@ public void testRemovePut() throws Exception @Test public void testAdd() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("name0", "value0"); fields.add("name1", "valueA"); @@ -354,7 +354,7 @@ public void testAddPreEncodedField() { final PreEncodedHttpField X_XSS_PROTECTION_FIELD = new PreEncodedHttpField("X-XSS-Protection", "1; mode=block"); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -365,7 +365,7 @@ public void testAddFinalHttpField() { final HttpField X_XSS_PROTECTION_FIELD = new HttpField("X-XSS-Protection", "1; mode=block"); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -374,7 +374,7 @@ public void testAddFinalHttpField() @Test public void testGetValues() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -414,7 +414,7 @@ public void testGetValues() throws Exception @Test public void testGetCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -454,7 +454,7 @@ public void testGetCSV() throws Exception @Test public void testAddQuotedCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("some", "value"); fields.add("name", "\"zero\""); @@ -502,7 +502,7 @@ public void testAddQuotedCSV() throws Exception @Test public void testGetQualityCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("some", "value"); fields.add("name", "zero;q=0.9,four;q=0.1"); @@ -524,7 +524,7 @@ public void testGetQualityCSV() throws Exception @Test public void testGetQualityCSVHeader() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("some", "value"); fields.add("Accept", "zero;q=0.9,four;q=0.1"); @@ -546,7 +546,7 @@ public void testGetQualityCSVHeader() throws Exception @Test public void testDateFields() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("D0", "Wed, 31 Dec 1969 23:59:59 GMT"); fields.put("D1", "Fri, 31 Dec 1999 23:59:59 GMT"); @@ -588,7 +588,7 @@ public void testDateFields() throws Exception @Test public void testNegDateFields() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.putDateField("Dzero", 0); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT", fields.get("Dzero")); @@ -606,7 +606,7 @@ public void testNegDateFields() throws Exception @Test public void testLongFields() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.put("I1", "42"); header.put("I2", " 43 99"); @@ -670,7 +670,7 @@ public void testLongFields() throws Exception @Test public void testContains() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); header.add("n0", ""); header.add("n1", ","); @@ -708,7 +708,7 @@ public void testContains() throws Exception @ValueSource(strings = {"Host", "host", "HOST", "HoSt", "Connection", "CONNECTION", "connection", "CoNnEcTiOn"}) public void testContainsKeyTrue(String keyName) { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -720,7 +720,7 @@ public void testContainsKeyTrue(String keyName) @ValueSource(strings = {"Content-Type", "Content-Length", "X-Bogus", ""}) public void testContainsKeyFalse(String keyName) { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -731,7 +731,7 @@ public void testContainsKeyFalse(String keyName) @Test public void testPreventNullField() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); assertThrows(NullPointerException.class, () -> { HttpField nullNullField = new HttpField(null, null, "bogus"); @@ -742,7 +742,7 @@ public void testPreventNullField() @Test public void testIteration() throws Exception { - HttpFieldsBuilder header = HttpFields.empty(); + HttpFieldsBuilder header = HttpFields.build(); Iterator i = header.iterator(); assertThat(i.hasNext(), is(false)); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java index 77ef401f6d01..660c204ed7ed 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java @@ -37,17 +37,17 @@ class RequestInfo extends MetaData.Request { RequestInfo(String method, String uri, HttpFields fields) { - super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, -1); + super(method, HttpURI.from(method,uri), HttpVersion.HTTP_1_1, fields, -1); } RequestInfo(String method, String uri, HttpVersion version, HttpFields fields) { - super(method, new HttpURI.Builder(method,uri).toHttpURI(), version, fields, -1); + super(method, HttpURI.from(method,uri), version, fields, -1); } RequestInfo(String method, String uri, int contentLength, HttpFields fields) { - super(method, new HttpURI.Builder(method,uri).toHttpURI(), HttpVersion.HTTP_1_1, fields, contentLength); + super(method, HttpURI.from(method,uri), HttpVersion.HTTP_1_1, fields, contentLength); } } @@ -62,7 +62,7 @@ public void testGETRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("GET", "/index.html", fields); @@ -100,7 +100,7 @@ public void testEmptyHeaders() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("Null", null); fields.add("Empty", ""); @@ -136,7 +136,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "localhost"); fields.add("Field", "SomeWhatLongValue"); RequestInfo info = new RequestInfo("GET", "/index.html", HttpVersion.HTTP_1_0, fields); @@ -178,7 +178,7 @@ public void testPOSTRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -218,7 +218,7 @@ public void testRequestWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -264,7 +264,7 @@ public void testRequestWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -336,7 +336,7 @@ public void testRequestWithKnownContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", 58, fields); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java index fbc3b129c8dd..bd4377c29382 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java @@ -78,7 +78,7 @@ public void testHTTP(Run run) throws Exception private static class Result { - private HttpFieldsBuilder _fields = HttpFields.empty(); + private HttpFieldsBuilder _fields = HttpFields.build(); private final String _body; private final int _code; private String _connection; 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 12182edfba0d..8a5b05177cfc 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 @@ -46,7 +46,7 @@ public void test09() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, fields, 10); @@ -83,7 +83,7 @@ public void testSimple() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -116,7 +116,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Location", "http://somewhere/else"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 302, null, fields, 0); @@ -152,7 +152,7 @@ public void test204() throws Exception HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", fields, 10); @@ -189,7 +189,7 @@ public void testComplexChars() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Content-Type", "test/data;\r\nextra=value"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", fields, 10); @@ -222,9 +222,9 @@ public void testComplexChars() throws Exception public void testSendServerXPoweredBy() throws Exception { ByteBuffer header = BufferUtil.allocate(8096); - HttpFieldsBuilder fields1 = HttpFields.empty(); + HttpFieldsBuilder fields1 = HttpFields.build(); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields1, -1); - HttpFieldsBuilder fields2 = HttpFields.empty(); + HttpFieldsBuilder fields2 = HttpFields.build(); fields2.add(HttpHeader.SERVER, "SomeServer"); fields2.add(HttpHeader.X_POWERED_BY, "SomePower"); MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields2, -1); @@ -278,7 +278,7 @@ public void testResponseIncorrectContentLength() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "11"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -304,7 +304,7 @@ public void testResponseNoContentPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -338,7 +338,7 @@ public void testResponseKnownNoContentNotPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Connection", "close"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -373,7 +373,7 @@ public void testResponseUpgrade() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Upgrade", "WebSocket"); fields.add("Connection", "Upgrade"); fields.add("Sec-WebSocket-Accept", "123456789=="); @@ -409,7 +409,7 @@ public void testResponseWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); @@ -475,7 +475,7 @@ public void testResponseWithHintedChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -546,13 +546,13 @@ public void testResponseWithContentAndTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFieldsBuilder trailer1 = HttpFields.empty(); + HttpFieldsBuilder trailer1 = HttpFields.build(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -633,13 +633,13 @@ public void testResponseWithTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFieldsBuilder trailer1 = HttpFields.empty(); + HttpFieldsBuilder trailer1 = HttpFields.build(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -702,7 +702,7 @@ public void testResponseWithKnownContentLengthFromMetaData() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 59); result = gen.generateResponse(info, false, null, null, content0, false); @@ -751,7 +751,7 @@ public void testResponseWithKnownContentLengthFromHeader() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "" + (content0.remaining() + content1.remaining())); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -816,7 +816,7 @@ public void test100ThenResponseWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, BufferUtil.length(content0) + BufferUtil.length(content1)); result = gen.generateResponse(info, false, null, null, content0, false); @@ -858,7 +858,7 @@ public void testConnectionKeepAliveWithAdditionalCustomValue() throws Exception { HttpGenerator generator = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE); String customValue = "test"; fields.add(HttpHeader.CONNECTION, customValue); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java index b0710d3c16b9..7b20da955632 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java @@ -162,7 +162,7 @@ public static Stream data() @MethodSource("data") public void testParseString(String input, String scheme, String host, Integer port, String path, String param, String query, String fragment) throws Exception { - HttpURI httpUri = new HttpURI(input); + HttpURI httpUri = HttpURI.from(input); try { @@ -210,7 +210,7 @@ public void testParseURI(String input, String scheme, String host, Integer port, } assumeTrue(javaUri != null, "Skipping, not a valid input URI: " + input); - HttpURI httpUri = new HttpURI(javaUri); + HttpURI httpUri = HttpURI.from(javaUri); assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(scheme)); assertThat("[" + input + "] .host", httpUri.getHost(), is(host)); @@ -238,7 +238,7 @@ public void testCompareToJavaNetURI(String input, String scheme, String host, In } assumeTrue(javaUri != null, "Skipping, not a valid input URI"); - HttpURI httpUri = new HttpURI(javaUri); + HttpURI httpUri = HttpURI.from(javaUri); assertThat("[" + input + "] .scheme", httpUri.getScheme(), is(javaUri.getScheme())); assertThat("[" + input + "] .host", httpUri.getHost(), is(javaUri.getHost())); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index a913ce533b1a..de1e1b3b283d 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -32,7 +32,7 @@ public class HttpURITest @Test public void testBuilder() throws Exception { - HttpURI uri = HttpURI.empty() + HttpURI uri = HttpURI.build() .scheme("http") .user("user:password") .host("host") @@ -41,7 +41,7 @@ public void testBuilder() throws Exception .param("param") .query("query=value") .fragment("fragment") - .toHttpURI(); + .asImmutable(); assertThat(uri.getScheme(), is("http")); assertThat(uri.getUser(), is("user:password")); @@ -55,7 +55,7 @@ public void testBuilder() throws Exception assertThat(uri.getAuthority(), is("host:8888")); assertThat(uri.toString(), is("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value#fragment")); - uri = HttpURI.from(uri) + uri = HttpURI.build(uri) .scheme("https") .user(null) .authority("[::1]:8080") @@ -63,7 +63,7 @@ public void testBuilder() throws Exception .param("id=12345") .query(null) .fragment(null) - .toHttpURI(); + .asImmutable(); assertThat(uri.getScheme(), is("https")); assertThat(uri.getUser(), nullValue()); @@ -81,7 +81,7 @@ public void testBuilder() throws Exception @Test public void testExample() throws Exception { - HttpURI uri = new HttpURI("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value#fragment"); + HttpURI uri = HttpURI.from("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value#fragment"); assertThat(uri.getScheme(), is("http")); assertThat(uri.getUser(), is("user:password")); @@ -107,7 +107,7 @@ private void assertInvalidURI(String invalidURI, String message) { try { - new HttpURI.Builder(invalidURI).toHttpURI(); + HttpURI.build(invalidURI); fail(message); } catch (IllegalArgumentException e) @@ -119,26 +119,26 @@ private void assertInvalidURI(String invalidURI, String message) @Test public void testParse() { - HttpURI.Builder builder = new HttpURI.Builder(); + HttpURI.Builder builder = HttpURI.build(); HttpURI uri; builder.uri("*"); - uri = builder.toHttpURI(); + uri = builder.asImmutable(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); builder.uri("/foo/bar"); - uri = builder.toHttpURI(); + uri = builder.asImmutable(); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); builder.uri("//foo/bar"); - uri = builder.toHttpURI(); + uri = builder.asImmutable(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); builder.uri("http://foo/bar"); - uri = builder.toHttpURI(); + uri = builder.asImmutable(); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -148,19 +148,19 @@ public void testParseRequestTarget() { HttpURI uri; - uri = new HttpURI.Builder("GET", "*").toHttpURI(); + uri = HttpURI.from("GET", "*"); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("*")); - uri = new HttpURI.Builder("GET", "/foo/bar").toHttpURI(); + uri = HttpURI.from("GET", "/foo/bar"); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("/foo/bar")); - uri = new HttpURI.Builder("GET", "//foo/bar").toHttpURI(); + uri = HttpURI.from("GET", "//foo/bar"); assertThat(uri.getHost(), nullValue()); assertThat(uri.getPath(), is("//foo/bar")); - uri = new HttpURI.Builder("GET", "http://foo/bar").toHttpURI(); + uri = HttpURI.from("GET", "http://foo/bar"); assertThat(uri.getHost(), is("foo")); assertThat(uri.getPath(), is("/bar")); } @@ -168,34 +168,34 @@ public void testParseRequestTarget() @Test public void testAt() throws Exception { - HttpURI uri = new HttpURI("/@foo/bar"); + HttpURI uri = HttpURI.from("/@foo/bar"); assertEquals("/@foo/bar", uri.getPath()); } @Test public void testParams() throws Exception { - HttpURI uri = new HttpURI("/foo/bar"); + HttpURI uri = HttpURI.from("/foo/bar"); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); assertEquals(null, uri.getParam()); - uri = new HttpURI("/foo/bar;jsessionid=12345"); + uri = HttpURI.from("/foo/bar;jsessionid=12345"); assertEquals("/foo/bar;jsessionid=12345", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); assertEquals("jsessionid=12345", uri.getParam()); - uri = new HttpURI("/foo;abc=123/bar;jsessionid=12345"); + uri = HttpURI.from("/foo;abc=123/bar;jsessionid=12345"); assertEquals("/foo;abc=123/bar;jsessionid=12345", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); assertEquals("jsessionid=12345", uri.getParam()); - uri = new HttpURI("/foo;abc=123/bar;jsessionid=12345?name=value"); + uri = HttpURI.from("/foo;abc=123/bar;jsessionid=12345?name=value"); assertEquals("/foo;abc=123/bar;jsessionid=12345", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); assertEquals("jsessionid=12345", uri.getParam()); - uri = new HttpURI("/foo;abc=123/bar;jsessionid=12345#target"); + uri = HttpURI.from("/foo;abc=123/bar;jsessionid=12345#target"); assertEquals("/foo;abc=123/bar;jsessionid=12345", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); assertEquals("jsessionid=12345", uri.getParam()); @@ -204,42 +204,42 @@ public void testParams() throws Exception @Test public void testMutableURIBuilder() { - HttpURI.Builder builder = new HttpURI.Builder("/foo/bar"); - HttpURI uri = builder.toHttpURI(); + HttpURI.Builder builder = HttpURI.build("/foo/bar"); + HttpURI uri = builder.asImmutable(); assertEquals("/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.scheme("http").toHttpURI(); + uri = builder.scheme("http").asImmutable(); assertEquals("http:/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.authority("host", 0).toHttpURI(); + uri = builder.authority("host", 0).asImmutable(); assertEquals("http://host/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.authority("host", 8888).toHttpURI(); + uri = builder.authority("host", 8888).asImmutable(); assertEquals("http://host:8888/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); assertEquals("/foo/bar", uri.getDecodedPath()); - uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2").toHttpURI(); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2").asImmutable(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals(null, uri.getQuery()); - uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2?name=value").toHttpURI(); + uri = builder.pathQuery("/f%30%30;p0/bar;p1;p2?name=value").asImmutable(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?name=value", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); assertEquals("p2", uri.getParam()); assertEquals("name=value", uri.getQuery()); - uri = builder.query("other=123456").toHttpURI(); + uri = builder.query("other=123456").asImmutable(); assertEquals("http://host:8888/f%30%30;p0/bar;p1;p2?other=123456", uri.toString()); assertEquals("/f%30%30;p0/bar;p1;p2", uri.getPath()); assertEquals("/f00/bar", uri.getDecodedPath()); @@ -250,27 +250,27 @@ public void testMutableURIBuilder() @Test public void testSchemeAndOrAuthority() throws Exception { - HttpURI.Builder builder = new HttpURI.Builder("/path/info"); - HttpURI uri = builder.toHttpURI(); + HttpURI.Builder builder = HttpURI.build("/path/info"); + HttpURI uri = builder.asImmutable(); assertEquals("/path/info", uri.toString()); - uri = builder.authority("host", 0).toHttpURI(); + uri = builder.authority("host", 0).asImmutable(); assertEquals("//host/path/info", uri.toString()); - uri = builder.authority("host", 8888).toHttpURI(); + uri = builder.authority("host", 8888).asImmutable(); assertEquals("//host:8888/path/info", uri.toString()); - uri = builder.scheme("http").toHttpURI(); + uri = builder.scheme("http").asImmutable(); assertEquals("http://host:8888/path/info", uri.toString()); - uri = builder.authority(null, 0).toHttpURI(); + uri = builder.authority(null, 0).asImmutable(); assertEquals("http:/path/info", uri.toString()); } @Test public void testBasicAuthCredentials() throws Exception { - HttpURI uri = new HttpURI("http://user:password@example.com:8888/blah"); + HttpURI uri = HttpURI.from("http://user:password@example.com:8888/blah"); assertEquals("http://user:password@example.com:8888/blah", uri.toString()); assertEquals(uri.getAuthority(), "example.com:8888"); assertEquals(uri.getUser(), "user:password"); @@ -279,34 +279,34 @@ public void testBasicAuthCredentials() throws Exception @Test public void testCanonicalDecoded() throws Exception { - HttpURI uri = new HttpURI("/path/.info"); + HttpURI uri = HttpURI.from("/path/.info"); assertEquals("/path/.info", uri.getDecodedPath()); - uri = new HttpURI("/path/./info"); + uri = HttpURI.from("/path/./info"); assertEquals("/path/info", uri.getDecodedPath()); - uri = new HttpURI("/path/../info"); + uri = HttpURI.from("/path/../info"); assertEquals("/info", uri.getDecodedPath()); - uri = new HttpURI("/./path/info."); + uri = HttpURI.from("/./path/info."); assertEquals("/path/info.", uri.getDecodedPath()); - uri = new HttpURI("./path/info/."); + uri = HttpURI.from("./path/info/."); assertEquals("path/info/", uri.getDecodedPath()); - uri = new HttpURI("http://host/path/.info"); + uri = HttpURI.from("http://host/path/.info"); assertEquals("/path/.info", uri.getDecodedPath()); - uri = new HttpURI("http://host/path/./info"); + uri = HttpURI.from("http://host/path/./info"); assertEquals("/path/info", uri.getDecodedPath()); - uri = new HttpURI("http://host/path/../info"); + uri = HttpURI.from("http://host/path/../info"); assertEquals("/info", uri.getDecodedPath()); - uri = new HttpURI("http://host/./path/info."); + uri = HttpURI.from("http://host/./path/info."); assertEquals("/path/info.", uri.getDecodedPath()); - uri = new HttpURI("http:./path/info/."); + uri = HttpURI.from("http:./path/info/."); assertEquals("path/info/", uri.getDecodedPath()); } } diff --git a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java index 314932134ffb..2e26a34f2c4f 100644 --- a/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java +++ b/jetty-http2/http2-client/src/main/java/org/eclipse/jetty/http2/client/HTTP2Client.java @@ -68,7 +68,7 @@ * HttpFields requestFields = new HttpFields(); * requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); * // Prepare the HTTP request object. - * MetaData.Request request = new MetaData.Request("PUT", new HttpURI("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); + * MetaData.Request request = new MetaData.Request("PUT", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); * // Create the HTTP/2 HEADERS frame representing the HTTP request. * HeadersFrame headersFrame = new HeadersFrame(request, null, false); * diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java index 6778c03a4599..d05cdf85c011 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java @@ -119,7 +119,7 @@ protected MetaData.Request newRequest(String method, String pathInfo, HttpFields String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField(authority), servletPath + pathInfo, HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), servletPath + pathInfo, HttpVersion.HTTP_2, fields, -1); } @AfterEach diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java index 2ed06fbd0575..051aecc576df 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java @@ -87,7 +87,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -138,7 +138,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -194,7 +194,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); @@ -267,7 +267,7 @@ public Map onPreface(Session session) } }); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java index 2764c9b11ec3..3214fd1e20a8 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java @@ -95,7 +95,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @@ -132,7 +132,7 @@ public void testStartAsyncThenClientSessionIdleTimeout() throws Exception client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -169,7 +169,7 @@ public void testStartAsyncThenClientStreamIdleTimeout() throws Exception client.setIdleTimeout(10 * idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -218,7 +218,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) prepareClient(); client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -329,7 +329,7 @@ public void onStartAsync(AsyncEvent event) throws IOException client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch clientLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java index 1b9e56f1a90f..484ae412832e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java @@ -79,7 +79,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.empty()); + MetaData.Request post = newRequest("POST", HttpFields.build()); FuturePromise promise = new FuturePromise<>(); Queue clientQueue = new ConcurrentLinkedQueue<>(); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() @@ -177,7 +177,7 @@ public void testOnBeforeData() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -189,7 +189,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.empty()); + MetaData.Request post = newRequest("GET", HttpFields.build()); FuturePromise promise = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); CountDownLatch beforeDataLatch = new CountDownLatch(1); @@ -237,7 +237,7 @@ public void testDemandFromOnHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -249,7 +249,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.empty()); + MetaData.Request post = newRequest("GET", HttpFields.build()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -284,7 +284,7 @@ public void testOnBeforeDataDoesNotReenter() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -296,7 +296,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.empty()); + MetaData.Request post = newRequest("GET", HttpFields.build()); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,7 +339,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) stream.demand(1); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -348,7 +348,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.empty()); + MetaData.Request post = newRequest("POST", HttpFields.build()); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java index 0d33463142ee..764be0d435fe 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java @@ -103,7 +103,7 @@ protected MetaData.Request newRequest(String method, String target, HttpFieldsBu String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField(authority), target, HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), target, HttpVersion.HTTP_2, fields, -1); } @AfterEach @@ -141,7 +141,7 @@ protected void onStreamUnstalled(IStream stream) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); if (request.getURIString().endsWith("/stall")) { @@ -171,7 +171,7 @@ public void succeeded() CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.empty()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.build()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -189,7 +189,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the first be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.empty()); + request = newRequest("GET", "/", HttpFields.build()); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); @@ -232,7 +232,7 @@ protected void onSessionUnstalled(ISession session) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); if (request.getURIString().endsWith("/stall")) { @@ -271,7 +271,7 @@ public Map onPreface(Session session) CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.empty()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.build()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -289,7 +289,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the session be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.empty()); + request = newRequest("GET", "/", HttpFields.build()); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java index e16917ddb83e..e084678af8fa 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java @@ -123,7 +123,7 @@ protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), "/", HttpVersion.HTTP_2, fields, -1); } @AfterEach @@ -193,7 +193,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getRecvWindow()); assertTrue(prefaceLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.empty()); + MetaData.Request request1 = newRequest("GET", HttpFields.build()); FuturePromise promise1 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request1, null, true), promise1, new Stream.Listener.Adapter()); HTTP2Stream clientStream1 = (HTTP2Stream)promise1.get(5, TimeUnit.SECONDS); @@ -217,7 +217,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) settingsLatch.await(5, TimeUnit.SECONDS); // Now create a new stream, it must pick up the new value. - MetaData.Request request2 = newRequest("POST", HttpFields.empty()); + MetaData.Request request2 = newRequest("POST", HttpFields.build()); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request2, null, true), promise2, new Stream.Listener.Adapter()); HTTP2Stream clientStream2 = (HTTP2Stream)promise2.get(5, TimeUnit.SECONDS); @@ -244,7 +244,7 @@ public void testFlowControlWithConcurrentSettings() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); @@ -287,7 +287,7 @@ public void onSettings(Session session, SettingsFrame frame) } }); - MetaData.Request request = newRequest("POST", HttpFields.empty()); + MetaData.Request request = newRequest("POST", HttpFields.build()); FuturePromise promise = new FuturePromise<>(); session.newStream(new HeadersFrame(request, null, false), promise, new Stream.Listener.Adapter()); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -328,7 +328,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); stream.headers(responseFrame, Callback.from(completable)); @@ -353,7 +353,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) final CountDownLatch dataLatch = new CountDownLatch(1); final Exchanger exchanger = new Exchanger<>(); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -425,7 +425,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -476,7 +476,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, null); @@ -528,7 +528,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) else { // For every stream, send down half the window size of data. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -547,7 +547,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) // First request is just to consume most of the session window. final List callbacks1 = new ArrayList<>(); final CountDownLatch prepareLatch = new CountDownLatch(1); - MetaData.Request request1 = newRequest("POST", HttpFields.empty()); + MetaData.Request request1 = newRequest("POST", HttpFields.build()); session.newStream(new HeadersFrame(request1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -562,7 +562,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(prepareLatch.await(5, TimeUnit.SECONDS)); // Second request will consume half of the remaining the session window. - MetaData.Request request2 = newRequest("GET", HttpFields.empty()); + MetaData.Request request2 = newRequest("GET", HttpFields.build()); session.newStream(new HeadersFrame(request2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -574,7 +574,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Third request will consume the whole session window, which is now stalled. // A fourth request will not be able to receive data. - MetaData.Request request3 = newRequest("GET", HttpFields.empty()); + MetaData.Request request3 = newRequest("GET", HttpFields.build()); session.newStream(new HeadersFrame(request3, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -586,7 +586,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Fourth request is now stalled. final CountDownLatch latch = new CountDownLatch(1); - MetaData.Request request4 = newRequest("GET", HttpFields.empty()); + MetaData.Request request4 = newRequest("GET", HttpFields.build()); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -622,7 +622,7 @@ public void testServerSendsBigContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -636,7 +636,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); final byte[] bytes = new byte[data.length]; final CountDownLatch latch = new CountDownLatch(1); @@ -668,7 +668,7 @@ public void testClientSendingInitialSmallWindow() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -700,7 +700,7 @@ public Map onPreface(Session session) byte[] responseData = new byte[requestData.length]; final ByteBuffer responseContent = ByteBuffer.wrap(responseData); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); final CountDownLatch latch = new CountDownLatch(1); @@ -760,7 +760,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole session and stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); session.newStream(requestFrame, Promise.from(completable), new Stream.Listener.Adapter()); @@ -844,7 +844,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, new Stream.Listener.Adapter()); @@ -915,7 +915,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); final CountDownLatch resetLatch = new CountDownLatch(1); @@ -970,7 +970,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Succeed the callbacks when the stream is already remotely closed. callbacks.forEach(Callback::succeeded); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -994,7 +994,7 @@ public void onWindowUpdate(ISession session, IStream stream, WindowUpdateFrame f }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java index 2d727d290493..3a87e6a10804 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java @@ -113,7 +113,7 @@ public void testClientFlowControlWindows() throws Exception assertEquals(clientSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.build(), -1); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); clientSession.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -163,7 +163,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(serverSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP, hostPort, "/", HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.build(), -1); HeadersFrame frame = new HeadersFrame(request, null, true); clientSession.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter()); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index 227ae3f54652..c233f13fb559 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -84,7 +84,7 @@ public void testRequestNoContentResponseNoContent() throws Exception Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -116,7 +116,7 @@ public void testRequestNoContentResponseEmptyContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), new Callback() { @Override @@ -131,7 +131,7 @@ public void succeeded() Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -173,7 +173,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(2); @@ -222,7 +222,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable streamCompletable = new Promise.Completable<>(); session.newStream(frame, streamCompletable, new Stream.Listener.Adapter() @@ -270,7 +270,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.putLongField(downloadBytes, random.nextInt(128 * 1024)); fields.put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); @@ -307,7 +307,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); @@ -345,7 +345,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); HostPortHttpField hostHeader = new HostPortHttpField(authority); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.build(), -1); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -424,7 +424,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty(), 0); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build(), 0); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -441,7 +441,7 @@ public void onSettings(Session session, SettingsFrame frame) }); assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.empty()); + MetaData.Request request1 = newRequest("GET", HttpFields.build()); FuturePromise promise1 = new FuturePromise<>(); CountDownLatch exchangeLatch1 = new CountDownLatch(2); session.newStream(new HeadersFrame(request1, null, false), promise1, new Stream.Listener.Adapter() @@ -455,7 +455,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData.Request request2 = newRequest("GET", HttpFields.empty()); + MetaData.Request request2 = newRequest("GET", HttpFields.build()); FuturePromise promise2 = new FuturePromise<>(); CountDownLatch exchangeLatch2 = new CountDownLatch(2); session.newStream(new HeadersFrame(request2, null, false), promise2, new Stream.Listener.Adapter() @@ -470,7 +470,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream2 = promise2.get(5, TimeUnit.SECONDS); // The third stream must not be created. - MetaData.Request request3 = newRequest("GET", HttpFields.empty()); + MetaData.Request request3 = newRequest("GET", HttpFields.build()); CountDownLatch maxStreamsLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request3, null, false), new Promise.Adapter<>() { @@ -498,7 +498,7 @@ public void succeeded() assertEquals(1, session.getStreams().size()); // Create a fourth stream. - MetaData.Request request4 = newRequest("GET", HttpFields.empty()); + MetaData.Request request4 = newRequest("GET", HttpFields.build()); CountDownLatch exchangeLatch4 = new CountDownLatch(2); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>() { @@ -541,7 +541,7 @@ public void testInvalidAPIUsageOnClient() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { Callback.Completable completable = new Callback.Completable(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, false), completable); return new Stream.Listener.Adapter() { @@ -564,7 +564,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); CountDownLatch completeLatch = new CountDownLatch(2); @@ -636,7 +636,7 @@ public void testInvalidAPIUsageOnServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); DataFrame dataFrame = new DataFrame(stream.getId(), BufferUtil.EMPTY_BUFFER, true); // The call to headers() is legal, but slow. new Thread(() -> @@ -683,7 +683,7 @@ public void failed(Throwable x) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -707,7 +707,7 @@ public void testCleanGoAwayDoesNotTriggerFailureNotification() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); // Close cleanly. @@ -732,7 +732,7 @@ public void onFailure(Session session, Throwable failure) failureLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame request = new HeadersFrame(metaData, null, true); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter()); @@ -749,7 +749,7 @@ public void testGoAwayRespondedWithGoAway() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, null, Callback.NOOP); @@ -788,7 +788,7 @@ public void onClose(Session session, GoAwayFrame frame) closeLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame request = new HeadersFrame(metaData, null, true); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -812,7 +812,7 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.empty(); + HttpFieldsBuilder requestFields = HttpFields.build(); requestFields.put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); @@ -836,7 +836,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -879,7 +879,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.build()); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -926,7 +926,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) dataLatch.countDown(); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -950,7 +950,7 @@ public void onClose(Session session, GoAwayFrame frame) // Start 2 requests without completing them yet. CountDownLatch responseLatch = new CountDownLatch(2); - MetaData.Request metaData1 = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData1 = newRequest("GET", HttpFields.build()); HeadersFrame request1 = new HeadersFrame(metaData1, null, false); FuturePromise promise1 = new FuturePromise<>(); Stream.Listener.Adapter listener = new Stream.Listener.Adapter() @@ -970,7 +970,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); stream1.data(new DataFrame(stream1.getId(), ByteBuffer.allocate(1), false), Callback.NOOP); - MetaData.Request metaData2 = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData2 = newRequest("GET", HttpFields.build()); HeadersFrame request2 = new HeadersFrame(metaData2, null, false); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(request2, promise2, listener); @@ -988,7 +988,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // New requests should be immediately rejected. HostPortHttpField authority3 = new HostPortHttpField("localhost" + ":" + port); - MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP, authority3, servletPath, HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP.asString(), authority3, servletPath, HttpVersion.HTTP_2, HttpFields.build(), -1); HeadersFrame request3 = new HeadersFrame(metaData3, null, false); FuturePromise promise3 = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java index cfb200b77ef8..02a4d14a9f58 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java @@ -76,7 +76,7 @@ public void testServerEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -94,7 +94,7 @@ public void onClose(Session session, GoAwayFrame frame) } }); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -133,7 +133,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // The request is not replied, and the server should idle timeout. - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -161,7 +161,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // to avoid a race where the idle timeout fires // again before we can send the headers to the client. sleep(idleTimeout + idleTimeout / 2); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -180,7 +180,7 @@ public void onClose(Session session, GoAwayFrame frame) }); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -214,7 +214,7 @@ public void testClientEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -229,7 +229,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -266,7 +266,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -290,7 +290,7 @@ public void testClientNotEnforcingIdleTimeoutWithinCallback() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -307,7 +307,7 @@ public void onClose(Session session, GoAwayFrame frame) Session session = newClient(new Session.Listener.Adapter()); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -350,7 +350,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se final CountDownLatch dataLatch = new CountDownLatch(1); final CountDownLatch timeoutLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -411,7 +411,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) final CountDownLatch resetLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); // Stream does not end here, but we won't send any DATA frame. HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -455,7 +455,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -505,7 +505,7 @@ public void testClientStreamIdleTimeoutIsNotEnforcedWhenSending() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -518,7 +518,7 @@ public void onReset(Session session, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise() { @@ -575,7 +575,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) connector.setIdleTimeout(2 * delay); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.empty()); + MetaData.Request metaData = newRequest("POST", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); @@ -641,7 +641,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -655,7 +655,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Send one more request to consume the whole session flow control window. CountDownLatch resetLatch = new CountDownLatch(1); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java index 022fcb2c8b69..22d9c887fca6 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java @@ -95,12 +95,12 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }; - HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); FuturePromise streamPromise1 = new FuturePromise<>(); session.newStream(headersFrame1, streamPromise1, streamListener); streamPromise1.get(5, TimeUnit.SECONDS); - HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); FuturePromise streamPromise2 = new FuturePromise<>(); session.newStream(headersFrame2, streamPromise2, streamListener); streamPromise2.get(5, TimeUnit.SECONDS); @@ -111,7 +111,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream serverStream1 = serverStreams.get(0); Stream serverStream2 = serverStreams.get(1); - MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); serverStream1.headers(new HeadersFrame(serverStream1.getId(), response1, null, false), Callback.NOOP); Random random = new Random(); @@ -120,7 +120,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) byte[] content2 = new byte[2 * ((ISession)serverStream2.getSession()).updateSendWindow(0)]; random.nextBytes(content2); - MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); serverStream2.headers(new HeadersFrame(serverStream2.getId(), response2, null, false), new Callback() { @Override diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java index 292063f3f52f..0e0f2df207e5 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java @@ -78,7 +78,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) CompletableFuture> result = CompletableFuture.completedFuture(new ArrayList<>()); // Push maxPushed resources... IntStream.range(0, maxPushed) - .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.empty()))) + .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.build()))) .map(pushFrame -> { Promise.Completable promise = new Promise.Completable<>(); @@ -91,7 +91,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // ... then push one extra stream, the client must reject it... .thenApply(streams -> { - PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.empty())); + PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.build())); FuturePromise extraPromise = new FuturePromise<>(); stream.push(extraPushFrame, extraPromise, new Stream.Listener.Adapter() { @@ -113,7 +113,7 @@ public void onReset(Stream stream, ResetFrame frame) // ... then send the response. .thenRun(() -> { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); }); return null; @@ -122,7 +122,7 @@ public void onReset(Stream stream, ResetFrame frame) client.setMaxConcurrentPushedStreams(maxPushed); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java index 80a09acd5553..83f84fa35fa9 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java @@ -82,7 +82,7 @@ public void onAccept(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -110,7 +110,7 @@ public Map onPreface(Session session) }); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -224,7 +224,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java index b821c3dce7df..637fa6479566 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java @@ -48,7 +48,7 @@ public void testPriorityBeforeHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -60,7 +60,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertTrue(streamId > 0); CountDownLatch latch = new CountDownLatch(2); - MetaData metaData = newRequest("GET", HttpFields.empty()); + MetaData metaData = newRequest("GET", HttpFields.build()); HeadersFrame headersFrame = new HeadersFrame(streamId, metaData, null, true); session.newStream(headersFrame, new Promise.Adapter() { @@ -96,7 +96,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { beforeRequests.await(5, TimeUnit.SECONDS); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); afterRequests.countDown(); @@ -122,13 +122,13 @@ public void onHeaders(Stream stream, HeadersFrame frame) }; Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData1 = newRequest("GET", "/one", HttpFields.empty()); + MetaData metaData1 = newRequest("GET", "/one", HttpFields.build()); HeadersFrame headersFrame1 = new HeadersFrame(metaData1, null, true); FuturePromise promise1 = new FuturePromise<>(); session.newStream(headersFrame1, promise1, listener); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData metaData2 = newRequest("GET", "/two", HttpFields.empty()); + MetaData metaData2 = newRequest("GET", "/two", HttpFields.build()); HeadersFrame headersFrame2 = new HeadersFrame(metaData2, null, true); FuturePromise promise2 = new FuturePromise<>(); session.newStream(headersFrame2, promise2, listener); @@ -162,7 +162,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(priorityFrame.isExclusive(), priority.isExclusive()); latch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -170,7 +170,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData = newRequest("GET", "/one", HttpFields.empty()); + MetaData metaData = newRequest("GET", "/one", HttpFields.build()); HeadersFrame headersFrame = new HeadersFrame(metaData, priorityFrame, true); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java index 62c49c7774c4..3183afb3e721 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java @@ -120,9 +120,9 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; - MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -178,9 +178,9 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; - MetaData.Request metaData = new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java index 40778cdafb2d..9e837695e135 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java @@ -126,7 +126,7 @@ private MetaData.Request newRequest(String method, String path, HttpFieldsBuilde String host = "localhost"; int port = proxyConnector.getLocalPort(); String authority = host + ":" + port; - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField(authority), path, HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), path, HttpVersion.HTTP_2, fields, -1); } @AfterEach @@ -166,7 +166,7 @@ protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletRes final CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", "/", HttpFields.build()); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 8a7eaada9b41..5f6ef4b361eb 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -71,7 +71,7 @@ protected void customizeContext(ServletContextHandler context) @Override protected MetaData.Request newRequest(String method, String pathInfo, HttpFieldsBuilder fields) { - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), contextPath + servletPath + pathInfo, HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), contextPath + servletPath + pathInfo, HttpVersion.HTTP_2, fields, -1); } private String newURI(String pathInfo) @@ -103,7 +103,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -115,7 +115,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -207,7 +207,7 @@ else if (requestURI.endsWith(secondaryResource)) // The referrerURI does not point to the primary resource, so there will be no // resource association with the primary resource and therefore won't be pushed. final String referrerURI = "http://localhost:" + connector.getLocalPort(); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -219,7 +219,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -293,7 +293,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -305,7 +305,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -358,7 +358,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); // Make sure the session is sane by requesting the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); final CountDownLatch secondaryResponseLatch = new CountDownLatch(1); @@ -396,7 +396,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -407,7 +407,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -487,7 +487,7 @@ else if (requestURI.endsWith(secondaryResource2)) // Request for the primary, secondary and tertiary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(2); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -500,7 +500,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Request for the secondary resources. String secondaryURI1 = newURI(secondaryResource1); - HttpFieldsBuilder secondaryFields1 = HttpFields.empty(); + HttpFieldsBuilder secondaryFields1 = HttpFields.build(); secondaryFields1.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest1 = newRequest("GET", secondaryResource1, secondaryFields1); session.newStream(new HeadersFrame(secondaryRequest1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -512,7 +512,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the tertiary resource. - HttpFieldsBuilder tertiaryFields = HttpFields.empty(); + HttpFieldsBuilder tertiaryFields = HttpFields.build(); tertiaryFields.put(HttpHeader.REFERER, secondaryURI1); MetaData.Request tertiaryRequest = newRequest("GET", tertiaryResource, tertiaryFields); session.newStream(new HeadersFrame(tertiaryRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -529,7 +529,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); - HttpFieldsBuilder secondaryFields2 = HttpFields.empty(); + HttpFieldsBuilder secondaryFields2 = HttpFields.build(); secondaryFields2.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest2 = newRequest("GET", secondaryResource2, secondaryFields2); session.newStream(new HeadersFrame(secondaryRequest2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -605,7 +605,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Make sure that explicitly requesting a secondary resource, we get the tertiary pushed. CountDownLatch secondaryResponseLatch = new CountDownLatch(1); CountDownLatch secondaryPushLatch = new CountDownLatch(1); - MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.empty()); + MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.build()); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -676,7 +676,7 @@ else if ("secret".equals(credentials)) final Session session = newClient(new Session.Listener.Adapter()); // Login with the wrong credentials, causing a redirect to self. - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource + "?credentials=wrong", primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -691,7 +691,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) { // Follow the redirect. String location = response.getFields().get(HttpHeader.LOCATION); - HttpFieldsBuilder redirectFields = HttpFields.empty(); + HttpFieldsBuilder redirectFields = HttpFields.build(); redirectFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request redirectRequest = newRequest("GET", location, redirectFields); session.newStream(new HeadersFrame(redirectRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -769,7 +769,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -780,7 +780,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -862,7 +862,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -874,7 +874,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -957,7 +957,7 @@ public Map onPreface(Session session) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.empty(); + HttpFieldsBuilder primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -969,7 +969,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.empty(); + HttpFieldsBuilder secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java index b7bc0a479d8e..065f76a4092a 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java @@ -132,7 +132,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) LOGGER.debug("SERVER1 received {}", frame); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER1 sending {}", reply); @@ -168,7 +168,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 received {}", frame); callback.succeeded(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); Callback.Completable completable1 = new Callback.Completable(); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) @@ -184,7 +184,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) return completable2; }).thenRun(() -> { - MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.empty()); + MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.build()); HeadersFrame end = new HeadersFrame(stream.getId(), trailer, null, true); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 sending {}", end); @@ -206,9 +206,9 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session clientSession = clientPromise.get(5, TimeUnit.SECONDS); // Send a request with trailers for server1. - HttpFieldsBuilder fields1 = HttpFields.empty(); + HttpFieldsBuilder fields1 = HttpFields.build(); fields1.put("X-Target", String.valueOf(connector1.getLocalPort())); - MetaData.Request request1 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields1); + MetaData.Request request1 = new MetaData.Request("GET", HttpURI.from("http://localhost/server1"), HttpVersion.HTTP_2, fields1); FuturePromise streamPromise1 = new FuturePromise<>(); CountDownLatch latch1 = new CountDownLatch(1); clientSession.newStream(new HeadersFrame(request1, null, false), streamPromise1, new Stream.Listener.Adapter() @@ -231,12 +231,12 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); Stream stream1 = streamPromise1.get(5, TimeUnit.SECONDS); - stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.empty()), null, true), Callback.NOOP); + stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.build()), null, true), Callback.NOOP); // Send a request for server2. - HttpFieldsBuilder fields2 = HttpFields.empty(); + HttpFieldsBuilder fields2 = HttpFields.build(); fields2.put("X-Target", String.valueOf(connector2.getLocalPort())); - MetaData.Request request2 = new MetaData.Request("GET", new HttpURI("http://localhost/server1"), HttpVersion.HTTP_2, fields2); + MetaData.Request request2 = new MetaData.Request("GET", HttpURI.from("http://localhost/server1"), HttpVersion.HTTP_2, fields2); FuturePromise streamPromise2 = new FuturePromise<>(); CountDownLatch latch2 = new CountDownLatch(1); clientSession.newStream(new HeadersFrame(request2, null, false), streamPromise2, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java index d4937786cfe0..ced4866c906f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java @@ -149,7 +149,7 @@ private boolean test(Session session, CountDownLatch latch) throws Exception int contentLength = random.nextInt(maxContentLength) + 1; long requestId = requestIds.incrementAndGet(); - MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.empty()); + MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.build()); if (download) request.getFields().put("X-Download", String.valueOf(contentLength)); HeadersFrame requestFrame = new HeadersFrame(request, null, download); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java index fc898805a547..fdeb4fbaeac6 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java @@ -65,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, null); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -82,7 +82,7 @@ public void testRequestClosedResponseClosedClosesStream() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, new Callback() { @@ -99,7 +99,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -124,7 +124,7 @@ public void testRequestDataClosedResponseDataClosedClosesStream() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(response, completable); @@ -153,7 +153,7 @@ public void succeeded() final CountDownLatch completeLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, false); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -196,7 +196,7 @@ public void testPushedStreamIsClosed() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.empty())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.build())); stream.push(pushFrame, new Promise.Adapter() { @Override @@ -216,14 +216,14 @@ public void succeeded() }); } }, new Stream.Listener.Adapter()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()), null, true); stream.headers(response, Callback.NOOP); return null; } }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); final CountDownLatch clientLatch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -257,7 +257,7 @@ public void testPushedStreamResetIsClosed() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.empty())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.build())); stream.push(pushFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -265,7 +265,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) { assertTrue(pushedStream.isReset()); assertTrue(pushedStream.isClosed()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()), null, true); stream.headers(response, Callback.NOOP); serverLatch.countDown(); } @@ -275,7 +275,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); final CountDownLatch clientLatch = new CountDownLatch(2); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,11 +339,11 @@ public void onFailure(Session session, Throwable failure) Session session = newClient(new Session.Listener.Adapter()); // First stream will be idle on server. - HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.empty()), null, true); + HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.build()), null, true); session.newStream(request1, new Promise.Adapter<>(), new Stream.Listener.Adapter()); // Second stream will fail on server. - HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); session.newStream(request2, new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertTrue(latch.await(5, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java index 36f1b16e7b60..aed40e923547 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java @@ -74,7 +74,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -99,7 +99,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -144,7 +144,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } @@ -167,7 +167,7 @@ public void onReset(Session session, ResetFrame frame) } }); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java index da44f619a209..3812067b4ba3 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java @@ -104,7 +104,7 @@ public void testStreamSendingResetIsRemoved() throws Exception start(new ServerSessionListener.Adapter()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -142,7 +142,7 @@ public void onReset(Stream stream, ResetFrame frame) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -170,7 +170,7 @@ public void testStreamResetDoesNotCloseConnection() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -210,7 +210,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request1 = newRequest("GET", HttpFields.empty()); + MetaData.Request request1 = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame1 = new HeadersFrame(request1, null, false); FuturePromise promise1 = new FuturePromise<>(); final CountDownLatch stream1HeadersLatch = new CountDownLatch(1); @@ -233,7 +233,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); assertTrue(stream1HeadersLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request2 = newRequest("GET", HttpFields.empty()); + MetaData.Request request2 = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame2 = new HeadersFrame(request2, null, false); FuturePromise promise2 = new FuturePromise<>(); final CountDownLatch stream2DataLatch = new CountDownLatch(1); @@ -317,7 +317,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -404,7 +404,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -434,7 +434,7 @@ public void testClientResetConsumesQueuedData() throws Exception start(new EmptyHttpServlet()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -501,7 +501,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -532,7 +532,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } // Send one more request to consume the whole session flow control window, then reset it. - MetaData.Request request = newRequest("GET", "/x", HttpFields.empty()); + MetaData.Request request = newRequest("GET", "/x", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); // This request will get no event from the server since it's reset by the client. @@ -585,7 +585,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -648,7 +648,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -697,7 +697,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -774,7 +774,7 @@ public void onError(Throwable t) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -830,7 +830,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -906,8 +906,8 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Max session HTTP/2 flow control window. generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); - HttpURI uri = new HttpURI("http", host, port, servletPath); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); + HttpURI uri = HttpURI.from("http", host, port, servletPath); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); int streamId = 3; HeadersFrame headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); @@ -1009,8 +1009,8 @@ private void service2(HttpServletRequest request, HttpServletResponse response) // Max session HTTP/2 flow control window. generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); - HttpURI uri = new HttpURI("http", host, port, servletPath + "/1"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); + HttpURI uri = HttpURI.from("http", host, port, servletPath + "/1"); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); HeadersFrame headersFrame = new HeadersFrame(3, request, null, true); generator.control(lease, headersFrame); @@ -1021,7 +1021,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) // Send a second request. uri = new HttpURI("http", host, port, servletPath + "/2"); - request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); + request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); int streamId = 5; headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 0f4b21a26028..4669c1d9be67 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -90,7 +90,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.empty(); + HttpFieldsBuilder requestFields = HttpFields.build(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -99,7 +99,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream = streamPromise.get(5, TimeUnit.SECONDS); // Send the trailers. - HttpFieldsBuilder trailerFields = HttpFields.empty(); + HttpFieldsBuilder trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -141,7 +141,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.empty(); + HttpFieldsBuilder requestFields = HttpFields.build(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -169,7 +169,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // Send the trailers. callback.thenRun(() -> { - HttpFieldsBuilder trailerFields = HttpFields.empty(); + HttpFieldsBuilder trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -187,7 +187,7 @@ public void testTrailersSentByServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - HttpFieldsBuilder responseFields = HttpFields.empty(); + HttpFieldsBuilder responseFields = HttpFields.build(); responseFields.put("X-Response", "true"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, responseFields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); @@ -196,7 +196,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) @Override public void succeeded() { - HttpFieldsBuilder trailerFields = HttpFields.empty(); + HttpFieldsBuilder trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -208,7 +208,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -251,7 +251,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { Request jettyRequest = (Request)request; Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); jettyResponse.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); @@ -263,7 +263,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.empty()); + MetaData.Request request = newRequest("GET", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); List frames = new ArrayList<>(); @@ -305,7 +305,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception start(new EmptyHttpServlet()); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.empty()); + MetaData.Request request = newRequest("POST", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -317,7 +317,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception completable.thenRun(() -> { // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.empty(); + HttpFieldsBuilder trailerFields = HttpFields.build(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -356,7 +356,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.empty()); + MetaData.Request request = newRequest("POST", HttpFields.build()); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter() @@ -376,7 +376,7 @@ public void onReset(Stream stream, ResetFrame frame) // Disable checks for invalid headers. ((HTTP2Session)session).getGenerator().setValidateHpackEncoding(false); // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.empty(); + HttpFieldsBuilder trailerFields = HttpFields.build(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java index 401faf958683..70c5c405d80b 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java @@ -72,10 +72,10 @@ public void onConnectionFailure(int error, String reason) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.generateHeaders(lease, streamId, metaData, null, true); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java index dd71dd41c92d..e757574604e6 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java @@ -52,10 +52,10 @@ public void testGenerateParse() throws Exception HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder()); int streamId = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); final List frames = new ArrayList<>(); Parser parser = new Parser(byteBufferPool, new Parser.Listener.Adapter() @@ -125,10 +125,10 @@ public void onHeaders(HeadersFrame frame) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); PriorityFrame priorityFrame = new PriorityFrame(streamId, 3 * streamId, 200, true); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java index 3edda68f204f..9213c7f21fe3 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java @@ -63,10 +63,10 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); // Iterate a few times to be sure generator and parser are properly reset. for (int i = 0; i < 2; ++i) @@ -116,10 +116,10 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Accept", "text/html"); fields.put("User-Agent", "Jetty"); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); // Iterate a few times to be sure generator and parser are properly reset. for (int i = 0; i < 2; ++i) diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index bf4013ba8385..516778e809c9 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -32,7 +32,7 @@ public class MetaDataBuilder { private final int _maxSize; - private final HttpFieldsBuilder _fields = HttpFields.empty(); + private final HttpFieldsBuilder _fields = HttpFields.build(); private int _size; private Integer _status; private String _method; @@ -141,7 +141,9 @@ else if (header != null) _authority = (HostPortHttpField)field; else if (value != null) _authority = new AuthorityHttpField(value); + _fields.add(_authority); // TODO does this need to be lowercase "host" } + _request = true; break; @@ -163,15 +165,9 @@ else if (value != null) break; case HOST: - // :authority fields must come first. If we have one, ignore the host header as far as authority goes. + // if the :authority fields has come first then ignore the host header. if (_authority == null) - { - if (field instanceof HostPortHttpField) - _authority = (HostPortHttpField)field; - else if (value != null) - _authority = new AuthorityHttpField(value); - } - _fields.add(field); + _fields.add(field); break; case CONTENT_LENGTH: @@ -261,18 +257,22 @@ public MetaData build() throws HpackException.StreamException if (isConnect) return new MetaData.ConnectRequest(_scheme, _authority, _path, fields, _protocol); else - // TODO is this really a known content length? - return new MetaData.Request(_method, _scheme, _authority, _path, HttpVersion.HTTP_2, fields, _contentLength); + return new MetaData.Request( + _method, + _scheme == null ? HttpScheme.HTTP.asString() : _scheme.asString(), + _authority, + _path, + HttpVersion.HTTP_2, + fields, + _contentLength); } if (_response) { if (_status == null) throw new HpackException.StreamException("No Status"); - // TODO is this really a known content length? return new MetaData.Response(HttpVersion.HTTP_2, _status, fields, _contentLength); } - // TODO is this really a known content length? return new MetaData(HttpVersion.HTTP_2, fields, _contentLength); } finally diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java index c4f65b176425..ad3eb3641202 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java @@ -39,7 +39,7 @@ public class HpackEncoderTest public void testUnknownFieldsContextManagement() throws Exception { HpackEncoder encoder = new HpackEncoder(38 * 5); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); HttpField[] field = { @@ -152,7 +152,7 @@ public void testNeverIndexSetCookie() throws Exception HpackEncoder encoder = new HpackEncoder(38 * 5); ByteBuffer buffer = BufferUtil.allocate(4096); - HttpFieldsBuilder fields = HttpFields.empty() + HttpFieldsBuilder fields = HttpFields.build() .put("set-cookie", "some cookie value"); // encode @@ -181,7 +181,7 @@ public void testNeverIndexSetCookie() throws Exception @Test public void testFieldLargerThanTable() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); HpackEncoder encoder = new HpackEncoder(128); ByteBuffer buffer0 = BufferUtil.allocate(4096); @@ -245,7 +245,7 @@ public void testFieldLargerThanTable() throws Exception @Test public void testResize() throws Exception { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.add("host", "localhost0"); fields.add("cookie", "abcdefghij"); diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java index ec83cb823d4a..ace537223ca2 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java @@ -108,7 +108,7 @@ private void encodeStories(ByteBuffer buffer, Map[] stories, Str var kase = (Map)c; Object[] headers = (Object[])kase.get("headers"); // System.err.println(" "+headers); - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); for (Object header : headers) { @SuppressWarnings("unchecked") diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java index 393ea5ec5a2e..2bce2880e2db 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java @@ -53,7 +53,7 @@ public void encodeDecodeResponseTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.empty() + HttpFieldsBuilder fields0 = HttpFields.build() .add(HttpHeader.CONTENT_TYPE, "text/html") .add(HttpHeader.CONTENT_LENGTH, "1024") .add(new HttpField(HttpHeader.CONTENT_ENCODING, (String)null)) @@ -81,7 +81,7 @@ public void encodeDecodeResponseTest() throws Exception assertMetaDataResponseSame(nullToEmpty, decoded0b); - HttpFieldsBuilder fields1 = HttpFields.empty() + HttpFieldsBuilder fields1 = HttpFields.build() .add(HttpHeader.CONTENT_TYPE, "text/plain") .add(HttpHeader.CONTENT_LENGTH, "1234") .add(HttpHeader.CONTENT_ENCODING, " ") @@ -108,7 +108,7 @@ public void encodeDecodeTooLargeTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 164); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.empty() + HttpFieldsBuilder fields0 = HttpFields.build() .add("1234567890", "1234567890123456789012345678901234567890") .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); @@ -120,7 +120,7 @@ public void encodeDecodeTooLargeTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFieldsBuilder fields1 = HttpFields.empty() + HttpFieldsBuilder fields1 = HttpFields.build() .add("1234567890", "1234567890123456789012345678901234567890") .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR") .add("x", "y"); @@ -147,7 +147,7 @@ public void encodeDecodeNonAscii() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocate(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.empty() + HttpFieldsBuilder fields0 = HttpFields.build() // @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck .add("Cookie", "[\uD842\uDF9F]") .add("custom-key", "[\uD842\uDF9F]"); @@ -170,7 +170,7 @@ public void evictReferencedFieldTest() throws Exception String longEnoughToBeEvicted = "012345678901234567890123456789012345678901234567890"; - HttpFieldsBuilder fields0 = HttpFields.empty() + HttpFieldsBuilder fields0 = HttpFields.build() .add(longEnoughToBeEvicted, "value") .add("foo", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); @@ -187,7 +187,7 @@ public void evictReferencedFieldTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFieldsBuilder fields1 = HttpFields.empty() + HttpFieldsBuilder fields1 = HttpFields.build() .add(longEnoughToBeEvicted, "other_value") .add("x", "y"); MetaData original1 = new MetaData(HttpVersion.HTTP_2, fields1); @@ -210,7 +210,7 @@ public void testHopHeadersAreRemoved() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFieldsBuilder input = HttpFields.empty() + HttpFieldsBuilder input = HttpFields.build() .add(HttpHeader.ACCEPT, "*") .add(HttpHeader.CONNECTION, "TE, Upgrade, Custom") .add("Custom", "Pizza") @@ -239,7 +239,7 @@ public void testTETrailers() throws Exception String teValue = "trailers"; String trailerValue = "Custom"; - HttpFieldsBuilder input = HttpFields.empty() + HttpFieldsBuilder input = HttpFields.build() .add(HttpHeader.CONNECTION, "TE") .add(HttpHeader.TE, teValue) .add(HttpHeader.TRAILER, trailerValue); @@ -262,7 +262,7 @@ public void testColonHeaders() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFieldsBuilder input = HttpFields.empty() + HttpFieldsBuilder input = HttpFields.build() .add(":status", "200") .add(":custom", "special"); diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpConnectionOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpConnectionOverHTTP2.java index 4f537b3fe571..3fec7112c12c 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpConnectionOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpConnectionOverHTTP2.java @@ -105,7 +105,7 @@ public void upgrade(Map context) // In case of HTTP/1.1 upgrade to HTTP/2, the request is HTTP/1.1 // (with upgrade) for a resource, and the response is HTTP/2. // Create the implicit stream#1 so that it can receive the HTTP/2 response. - MetaData.Request metaData = new MetaData.Request(request.getMethod(), new HttpURI(request.getURI()), HttpVersion.HTTP_2, request.getHeaders()); + MetaData.Request metaData = new MetaData.Request(request.getMethod(), HttpURI.from(request.getURI()), HttpVersion.HTTP_2, request.getHeaders()); // We do not support upgrade requests with content, so endStream=true. HeadersFrame frame = new HeadersFrame(metaData, null, true); IStream stream = ((HTTP2Session)session).newLocalStream(frame, null); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index 7c761017f53c..f1ca05758b47 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -156,7 +156,7 @@ public void testResponseAbortSendsResetFrame() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), metaData, null, false), new Callback() { @Override @@ -233,7 +233,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) } else { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } return null; @@ -490,7 +490,7 @@ public void onHeaders(HeadersFrame request) try { // Response. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true); generator.control(lease, response); writeFrames(); @@ -564,7 +564,7 @@ public void test204WithContent() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { int streamId = stream.getId(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(streamId, response, null, false); Callback.Completable callback = new Callback.Completable(); stream.headers(responseFrame, callback); @@ -593,7 +593,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // Disable checks for invalid headers. ((HTTP2Session)stream.getSession()).getGenerator().setValidateHpackEncoding(false); // Produce an invalid HPACK block by adding a request pseudo-header to the response. - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put(":method", "get"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, fields, 0); int streamId = stream.getId(); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java index 5ad4beacdc75..3e43015be6d9 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java @@ -62,15 +62,15 @@ public void testPushedResourceCancelled() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - HttpURI pushURI = new HttpURI("http://localhost:" + connector.getLocalPort() + pushPath); - MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.empty()); + HttpURI pushURI = HttpURI.from("http://localhost:" + connector.getLocalPort() + pushPath); + MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.build()); stream.push(new PushPromiseFrame(stream.getId(), 0, pushRequest), new Promise.Adapter<>() { @Override public void succeeded(Stream pushStream) { // Just send the normal response and wait for the reset. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } }, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java index 9b15717ea504..8640a4136ade 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java @@ -65,7 +65,7 @@ private void testEmptyTrailers(String content) throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -80,7 +80,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); request.trailers(() -> trailers); if (content != null) request.body(new StringRequestContent(content)); @@ -110,7 +110,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -120,7 +120,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); @@ -159,7 +159,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -169,7 +169,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java index 62c91f435a30..8e1210ad6598 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java @@ -87,7 +87,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r http2Client.connect(address, new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); - HttpURI uri = new HttpURI("http://" + host + ":" + port + "/"); + HttpURI uri = HttpURI.from("http://" + host + ":" + port + "/"); MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); HeadersFrame frame = new HeadersFrame(request, null, true); BlockingQueue headers = new LinkedBlockingQueue<>(); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java index 2915a1856579..458d1c02c2d0 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java @@ -356,7 +356,7 @@ public boolean upgrade(Request request, HttpFieldsBuilder responseFields) // This is the settings from the HTTP2-Settings header. upgradeFrames.add(settingsFrame); // Remember the request to send a response. - upgradeFrames.add(new HeadersFrame(1, new Request(request), null, true)); + upgradeFrames.add(new HeadersFrame(1, request, null, true)); } return true; } diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java index 9e2b64c69bb1..dbd24b4f127e 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java @@ -111,18 +111,6 @@ public Runnable onRequest(HeadersFrame frame) MetaData.Request request = (MetaData.Request)frame.getMetaData(); HttpFields fields = request.getFields(); - // HTTP/2 sends the Host header as the :authority - // pseudo-header, so we need to synthesize a Host header. - if (!fields.contains(HttpHeader.HOST)) - { - String authority = request.getURI().getAuthority(); - if (authority != null) - { - // Lower-case to be consistent with other HTTP/2 headers. - fields.put("host", authority); - } - } - _expect100Continue = fields.contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); HttpFieldsBuilder response = getResponse().getHttpFields(); @@ -300,7 +288,7 @@ public InvocationType getInvocationType() @Override public Runnable onTrailer(HeadersFrame frame) { - HttpFieldsBuilder trailers = frame.getMetaData().getFields(); + HttpFields trailers = frame.getMetaData().getFields(); if (trailers.size() > 0) onTrailers(trailers); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java index 7c1af0997028..47021765029c 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java @@ -23,6 +23,7 @@ import java.util.function.Supplier; import org.eclipse.jetty.http.BadMessageException; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; @@ -230,12 +231,12 @@ public void succeeded() } } - private HttpFieldsBuilder retrieveTrailers() + private HttpFields retrieveTrailers() { - Supplier supplier = metaData.getTrailerSupplier(); + Supplier supplier = metaData.getTrailerSupplier(); if (supplier == null) return null; - HttpFieldsBuilder trailers = supplier.get(); + HttpFields trailers = supplier.get(); if (trailers == null) return null; return trailers.size() == 0 ? null : trailers; diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java index bb11bb2bb161..27fec624cfe7 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java @@ -83,7 +83,7 @@ protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - return new MetaData.Request(method, HttpScheme.HTTP, new HostPortHttpField(authority), path, HttpVersion.HTTP_2, fields); + return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField(authority), path, HttpVersion.HTTP_2, fields, -1); } @AfterEach diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java index a814e6d8580f..006e602d67f7 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java @@ -65,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); // Reply with HEADERS. stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); closeLatch.await(5, TimeUnit.SECONDS); @@ -81,7 +81,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -133,7 +133,7 @@ public void testClientSendsGoAwayButDoesNotCloseConnectionServerCloses() throws public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -142,7 +142,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes("UTF-8"))); @@ -198,7 +198,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, "OK", Callback.NOOP); return null; @@ -209,7 +209,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java index 3ba86cc1f8aa..125d9a920977 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java @@ -195,7 +195,7 @@ public void onData(DataFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.build(), -1); generator.control(lease, new HeadersFrame(3, metaData, null, true)); for (ByteBuffer buffer : lease.getByteBuffers()) { @@ -233,7 +233,7 @@ public void testHTTP20Direct() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP, new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.build(), -1); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java index 119eae5fbdcb..fc2e8dcc4b09 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java @@ -82,7 +82,7 @@ public void testNoPrefaceBytes() throws Exception startServer(new HttpServlet() {}); // No preface bytes. - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new HeadersFrame(1, metaData, null, true)); @@ -127,7 +127,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -185,7 +185,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -361,7 +361,7 @@ public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateE ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector2.getLocalPort())) { @@ -399,7 +399,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -428,7 +428,7 @@ public void testRequestWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); return lease; }); @@ -443,7 +443,7 @@ public void testRequestWithPriorityWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); return lease; }); @@ -457,7 +457,7 @@ public void testRequestWithContinuationFramesWithEmptyHeadersFrame() throws Exce ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the HeadersFrame header and set the length to zero. List buffers = lease.getByteBuffers(); @@ -479,7 +479,7 @@ public void testRequestWithPriorityWithContinuationFramesWithEmptyHeadersFrame() ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); // Take the HeadersFrame header and set the length to just the priority frame. List buffers = lease.getByteBuffers(); @@ -500,7 +500,7 @@ public void testRequestWithContinuationFramesWithEmptyContinuationFrame() throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the ContinuationFrame header, duplicate it, and set the length to zero. List buffers = lease.getByteBuffers(); @@ -524,7 +524,7 @@ public void testRequestWithContinuationFramesWithEmptyLastContinuationFrame() th ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.empty()); + MetaData.Request metaData = newRequest("GET", HttpFields.build()); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the last CONTINUATION frame and reset the flag. List buffers = lease.getByteBuffers(); @@ -562,7 +562,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) serverLatch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.empty()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java index 19ce91ed7e16..27f74c2f2b26 100644 --- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java +++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java @@ -44,6 +44,8 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpScheme; @@ -468,7 +470,7 @@ protected boolean expects100Continue(HttpServletRequest request) protected void copyRequestHeaders(HttpServletRequest clientRequest, Request proxyRequest) { // First clear possibly existing headers, as we are going to copy those from the client request. - proxyRequest.getHeaders().clear(); + HttpFieldsBuilder newHeaders = HttpFields.build(); Set headersToRemove = findConnectionHeaders(clientRequest); @@ -490,13 +492,15 @@ protected void copyRequestHeaders(HttpServletRequest clientRequest, Request prox { String headerValue = headerValues.nextElement(); if (headerValue != null) - proxyRequest.header(headerName, headerValue); + newHeaders.add(headerName, headerValue); } } // Force the Host header if configured if (_hostHeader != null) - proxyRequest.header(HttpHeader.HOST, _hostHeader); + newHeaders.add(HttpHeader.HOST, _hostHeader); + + proxyRequest.set(newHeaders); } protected Set findConnectionHeaders(HttpServletRequest clientRequest) diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java index 5dc4a853e682..99e9e7523717 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/CompactPathRule.java @@ -43,7 +43,7 @@ public void applyURI(Request request, String oldURI, String newURI) throws IOExc String uri = request.getRequestURI(); if (uri.startsWith("/")) uri = URIUtil.compactPath(uri); - request.setHttpURI(HttpURI.from(request.getHttpURI(), uri).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI(), uri)); } @Override diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java index a21da99ffe5c..f27afd3c9d09 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRule.java @@ -48,7 +48,7 @@ public void setScheme(String scheme) protected String apply(String target, String value, HttpServletRequest request, HttpServletResponse response) { Request baseRequest = Request.getBaseRequest(request); - baseRequest.setHttpURI(HttpURI.from(baseRequest.getHttpURI()).scheme(_scheme).toHttpURI()); + baseRequest.setHttpURI(HttpURI.build(baseRequest.getHttpURI()).scheme(_scheme)); return target; } } diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java index 1fdab46b7f68..c7ae14b10fbb 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java @@ -93,7 +93,7 @@ public void applyURI(Request request, String oldURI, String newURI) throws IOExc { HttpURI baseURI = request.getHttpURI(); String query = URIUtil.addQueries(baseURI.getQuery(),_query); - request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), query).toHttpURI()); + request.setHttpURI(HttpURI.build(baseURI, newURI, baseURI.getParam(), query)); } /** diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java index a97fd55cb3fd..79246c18aeaa 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRule.java @@ -110,7 +110,7 @@ public void applyURI(Request request, String oldURI, String newURI) throws IOExc HttpURI baseURI = request.getHttpURI(); if (_query == null) { - request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), baseURI.getQuery()).toHttpURI()); + request.setHttpURI(HttpURI.build(baseURI, newURI, baseURI.getParam(), baseURI.getQuery())); } else { @@ -119,7 +119,7 @@ public void applyURI(Request request, String oldURI, String newURI) throws IOExc if (!_queryGroup) query = URIUtil.addQueries(baseURI.getQuery(), query); - request.setHttpURI(HttpURI.from(baseURI, newURI, baseURI.getParam(), query).toHttpURI()); + request.setHttpURI(HttpURI.build(baseURI, newURI, baseURI.getParam(), query)); } } diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java index 53ce4d7a08b9..c756c45222cb 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java @@ -188,8 +188,8 @@ protected String apply(String target, HttpServletRequest request, HttpServletRes else { HttpURI baseUri = baseRequest.getHttpURI(); - baseRequest.setHttpURI(HttpURI.from(baseUri,encoded) - .param(baseUri.getParam()).toHttpURI()); + baseRequest.setHttpURI(HttpURI.build(baseUri,encoded) + .param(baseUri.getParam())); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java index 1ce23f057e14..de836b7d0194 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java @@ -34,7 +34,7 @@ public void init() throws Exception { start(false); _rule = new ForwardedSchemeHeaderRule(); - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme((String)null).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null).asImmutable()); } @Test @@ -72,13 +72,13 @@ public void testHeaderValue() throws Exception _rule.matchAndApply("/", _request, _response); assertEquals("https", _request.getScheme()); - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme("other").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme("other").asImmutable()); // header value doesn't match rule's value setRequestHeader("Front-End-Https", "off"); _rule.matchAndApply("/", _request, _response); assertEquals("other", _request.getScheme()); - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).scheme((String)null).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null).asImmutable()); // header value can be any value setRequestHeader("Front-End-Https", "any"); _rule.setHeaderValue(null); @@ -88,6 +88,6 @@ public void testHeaderValue() throws Exception private void setRequestHeader(String header, String headerValue) { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()).put(header, headerValue)); + _request.setHttpFields(HttpFields.build(_request.getHttpFields()).put(header, headerValue)); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java index 57d888d0466f..8384d8eb7c71 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java @@ -43,7 +43,7 @@ public void init() throws Exception @Test public void testWin2kSP1WithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.01)"); _request.setHttpFields(fields); @@ -68,7 +68,7 @@ public void testWin2kSP1WithIE5() throws Exception @Test public void testWin2kSP1WithIE6() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.01)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -80,7 +80,7 @@ public void testWin2kSP1WithIE6() throws Exception @Test public void testWin2kSP1WithIE7() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.01)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -92,7 +92,7 @@ public void testWin2kSP1WithIE7() throws Exception @Test public void testWin2kWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"); _request.setHttpFields(fields); @@ -117,7 +117,7 @@ public void testWin2kWithIE5() throws Exception @Test public void testWin2kWithIE6() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)") .asImmutable()); @@ -130,7 +130,7 @@ public void testWin2kWithIE6() throws Exception @Test public void testWin2kWithIE7() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -142,7 +142,7 @@ public void testWin2kWithIE7() throws Exception @Test public void testWinVistaWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 6.0)"); _request.setHttpFields(fields); @@ -167,7 +167,7 @@ public void testWinVistaWithIE5() throws Exception @Test public void testWinVistaWithIE6() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 6.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -179,7 +179,7 @@ public void testWinVistaWithIE6() throws Exception @Test public void testWinVistaWithIE7() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -191,7 +191,7 @@ public void testWinVistaWithIE7() throws Exception @Test public void testWinXpWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.from(_request.getHttpFields()); + HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"); _request.setHttpFields(fields); @@ -216,7 +216,7 @@ public void testWinXpWithIE5() throws Exception @Test public void testWinXpWithIE6() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -228,7 +228,7 @@ public void testWinXpWithIE6() throws Exception @Test public void testWinXpWithIE7() throws Exception { - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -244,7 +244,7 @@ public void testWithoutSsl() throws Exception super.stop(); super.start(false); - _request.setHttpFields(HttpFields.from(_request.getHttpFields()) + _request.setHttpFields(HttpFields.build(_request.getHttpFields()) .add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java index dc86d701ed69..7b9cd51f5a72 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java @@ -141,7 +141,7 @@ private void assertMatch(boolean flag, String[] matchCase) throws IOException new Request(null, null) { { - setMetaData(new MetaData.Request("GET", new HttpURI(uri), HttpVersion.HTTP_1_0, HttpFields.empty())); + setMetaData(new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_1_0, HttpFields.build())); } }, null ); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java index 33a717c4bce0..e9b6dc9bc5c6 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java @@ -84,7 +84,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/xxx/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/bar").asImmutable()); _request.setPathInfo("/xxx/bar"); _handler.handle("/xxx/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -98,7 +98,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(false); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/foo/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/foo/bar").asImmutable()); _request.setPathInfo("/foo/bar"); _handler.handle("/foo/bar", _request, _request, _response); @@ -111,7 +111,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _handler.setOriginalPathAttribute(null); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -125,7 +125,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -137,7 +137,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _rule2.setTerminating(true); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -153,7 +153,7 @@ public void test() throws Exception _request.setAttribute("target", null); _request.setAttribute("URI", null); _request.setAttribute("info", null); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/aaa/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(200, _response.getStatus()); @@ -172,7 +172,7 @@ public void testEncodedPattern() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/ccc/x%20y").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/ccc/x%20y").asImmutable()); _request.setPathInfo("/ccc/x y"); _handler.handle("/ccc/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -189,7 +189,7 @@ public void testEncodedRegex() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/xxx/x%20y").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/x%20y").asImmutable()); _request.setPathInfo("/xxx/x y"); _handler.handle("/xxx/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java index 0d5a36586eaa..9579d8190b5e 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java @@ -88,7 +88,7 @@ public void testRequestWithQueryString() throws IOException { String replacement = "/replace"; String queryString = "request=parameter"; - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/old/context", null, queryString).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/old/context", null, queryString).asImmutable()); RewritePatternRule rewritePatternRule = new RewritePatternRule(); rewritePatternRule.setPattern("/old/context"); @@ -110,7 +110,7 @@ public void testRequestAndReplacementWithQueryString() throws IOException String[] split = replacement.split("\\?", 2); String path = split[0]; String queryString = split[1]; - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/old/context", null, queryString).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/old/context", null, queryString).asImmutable()); RewritePatternRule rewritePatternRule = new RewritePatternRule(); rewritePatternRule.setPattern("/old/context"); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java index 3bf4125ae5e7..4438abddd52d 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java @@ -63,12 +63,12 @@ public void testRequestUriEnabled(Scenario scenario) throws Exception RewriteRegexRule rule = new RewriteRegexRule(); reset(); - _request.setHttpURI(HttpURI.from(_request.getHttpURI()).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI()).asImmutable()); rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),scenario.uriPathQuery, null, scenario.queryString).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString).asImmutable()); String result = rule.matchAndApply(scenario.uriPathQuery, _request, _response); assertEquals(scenario.expectedRequestURI, result); @@ -107,7 +107,7 @@ public void testContainedRequestUriEnabled(Scenario scenario) throws Exception rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),scenario.uriPathQuery, null, scenario.queryString).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString).asImmutable()); _request.getAttributes().clearAttributes(); String result = container.apply(URIUtil.decodePath(scenario.uriPathQuery), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java index 2d22c62f744b..0fb43ab4412a 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java @@ -44,7 +44,7 @@ public void init() throws Exception public void testValidUrl() throws Exception { _rule.setCode("404"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/valid/uri.html").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/valid/uri.html").asImmutable()); _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -55,7 +55,7 @@ public void testValidUrl() throws Exception public void testInvalidUrl() throws Exception { _rule.setCode("404"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/invalid%0c/uri.html").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/invalid%0c/uri.html").asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -67,7 +67,7 @@ public void testInvalidUrlWithMessage() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(),"/%00/").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/%00/").asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -80,7 +80,7 @@ public void testInvalidJsp() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/bean1.jsp%00").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/bean1.jsp%00").asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -94,7 +94,7 @@ public void testInvalidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/shamrock-%00%E2%98%98.jsp").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%00%E2%98%98.jsp").asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -108,7 +108,7 @@ public void testValidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/jsp/shamrock-%E2%98%98.jsp").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%E2%98%98.jsp").asImmutable()); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java index 5a434ef108f0..a164a0d8444d 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java @@ -50,7 +50,7 @@ public void init() throws Exception _fooContainerRule.setRules(new Rule[]{_fooRule}); start(false); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _handler.setServer(_server); _handler.start(); @@ -59,7 +59,7 @@ public void init() throws Exception @Test public void testArbitraryHost() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("cheese.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0).asImmutable()); _handler.setRules(new Rule[]{_rule, _fooContainerRule}); handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule, Host: cheese.com}: applied _rule"); @@ -68,7 +68,7 @@ public void testArbitraryHost() throws Exception @Test public void testVirtualHost() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); _handler.setRules(new Rule[]{_fooContainerRule}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: foo.com}: applied _fooRule"); @@ -77,8 +77,8 @@ public void testVirtualHost() throws Exception @Test public void testCascadingRules() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _rule.setTerminating(false); _fooRule.setTerminating(false); @@ -88,17 +88,17 @@ public void testCascadingRules() throws Exception handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule}: applied _rule, didn't match _fooRule"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _handler.setRules(new Rule[]{_fooContainerRule, _rule}); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: applied _fooRule, _rule"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _fooRule.setTerminating(true); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: (_fooRule is terminating); applied _fooRule, _rule"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _fooRule.setTerminating(false); _fooContainerRule.setTerminating(true); handleRequest(); @@ -108,7 +108,7 @@ public void testCascadingRules() throws Exception @Test public void testCaseInsensitiveHostname() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("Foo.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("Foo.com", 0).asImmutable()); _fooContainerRule.setVirtualHosts(new String[]{"foo.com"}); _handler.setRules(new Rule[]{_fooContainerRule}); @@ -119,21 +119,21 @@ public void testCaseInsensitiveHostname() throws Exception @Test public void testEmptyVirtualHost() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("cheese.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0).asImmutable()); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(null); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is null, Host: cheese.com}: apply _fooRule"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _fooContainerRule.setVirtualHosts(new String[]{}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is empty, Host: cheese.com}: apply _fooRule"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _fooContainerRule.setVirtualHosts(new String[]{null}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual host is null, Host: cheese.com}: apply _fooRule"); @@ -142,14 +142,14 @@ public void testEmptyVirtualHost() throws Exception @Test public void testMultipleVirtualHosts() throws Exception { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority("foo.com", 0).toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(new String[]{"cheese.com"}); handleRequest(); assertEquals("/cheese/bar", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com], Host: foo.com}: no effect"); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); _fooContainerRule.addVirtualHost("foo.com"); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com, foo.com], Host: foo.com}: apply _fooRule"); @@ -186,8 +186,8 @@ private void checkWildcardHost(boolean succeed, String[] ruleHosts, String[] req for (String host : requestHosts) { - _request.setHttpURI(HttpURI.from(_request.getRequestURI()).authority(host, 0).toHttpURI()); - _request.setHttpURI(HttpURI.from(_request.getHttpURI(), "/cheese/bar").toHttpURI()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority(host, 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); handleRequest(); if (succeed) assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: " + host + "}: should apply _fooRule"); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java index 941a691e2f8f..37799f234f04 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java @@ -72,7 +72,7 @@ public void startServer() @Override public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { - request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS).asImmutable()); request.setSecure(true); } }); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java index 3873a32fb3cf..a1eb0ebc807f 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java @@ -77,7 +77,7 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - MetaData.Request metadata = new MetaData.Request(null, HttpURI.from("http://localhost").toHttpURI(), null, HttpFields.empty()); + MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, HttpFields.build()); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); @@ -115,8 +115,8 @@ public void flush() throws IOException {} // Create a bogus Authorization header. We don't care about the actual credentials. - MetaData.Request metadata = new MetaData.Request(null, HttpURI.from("http://localhost").toHttpURI(), null, - HttpFields.empty().add(HttpHeader.AUTHORIZATION, "Basic asdf")); + MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, + HttpFields.build().add(HttpHeader.AUTHORIZATION, "Basic asdf")); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index 197985cbd163..c7103d249269 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -193,10 +193,7 @@ protected void forward(ServletRequest request, ServletResponse response, Dispatc if (query == null) query = old_uri.getQuery(); - HttpURI uri = HttpURI.from(old_uri, _uri.getPath(), _uri.getParam(), query).toHttpURI(); - - baseRequest.setHttpURI(uri); - + baseRequest.setHttpURI(HttpURI.build(old_uri, _uri.getPath(), _uri.getParam(), query)); baseRequest.setContextPath(_contextHandler.getContextPath()); baseRequest.setServletPath(null); baseRequest.setPathInfo(_pathInContext); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index fd30b41becc7..31066f69e869 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -399,7 +399,7 @@ public void customize(Connector connector, HttpConfiguration config, Request req if (match) { - HttpURI.Builder builder = HttpURI.from(request.getHttpURI()); + HttpURI.Builder builder = HttpURI.build(request.getHttpURI()); if (forwarded._proto != null) { builder.scheme(forwarded._proto); @@ -409,18 +409,18 @@ public void customize(Connector connector, HttpConfiguration config, Request req if (forwarded._server != null && forwarded._host instanceof PortSetHostPort) { - request.setHttpFields(HttpFields.from(httpFields, + request.setHttpFields(HttpFields.build(httpFields, new HostPortHttpField(forwarded._server, forwarded._host.getPort()))); builder.host(forwarded._server).port(forwarded._host.getPort()); } else if (forwarded._host != null) { - request.setHttpFields(HttpFields.from(httpFields, new HostPortHttpField(forwarded._host))); + request.setHttpFields(HttpFields.build(httpFields, new HostPortHttpField(forwarded._host))); builder.host(forwarded._host.getHost()).port(forwarded._host.getPort()); } else if (forwarded._server != null) { - request.setHttpFields(HttpFields.from(httpFields, new HostPortHttpField(forwarded._server))); + request.setHttpFields(HttpFields.build(httpFields, new HostPortHttpField(forwarded._server))); builder.host(forwarded._server).port(0); } @@ -432,7 +432,7 @@ else if (forwarded._server != null) if (request.isSecure() && !wasSecure) builder.scheme(HttpScheme.HTTPS); - request.setHttpURI(builder.toHttpURI()); + request.setHttpURI(builder); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java index 2c8ca9a33be7..adf0d08f169b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java @@ -66,6 +66,6 @@ public void customize(Connector connector, HttpConfiguration channelConfig, Requ { if (request.getHeader("Host") == null) // TODO set the field as well? - request.setHttpURI(HttpURI.from(request.getHttpURI()).host(serverName).port(serverPort).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).host(serverName).port(serverPort)); } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 1dcf381a23cd..0df6d49fad4a 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -712,7 +712,7 @@ public boolean onContentComplete() return false; } - public void onTrailers(HttpFieldsBuilder trailers) + public void onTrailers(HttpFields trailers) { if (LOG.isDebugEnabled()) LOG.debug("onTrailers {} {}", this, trailers); @@ -792,7 +792,7 @@ public void onBadMessage(BadMessageException failure) if (action == Action.DISPATCH) { ByteBuffer content = null; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); ErrorHandler handler = getServer().getBean(ErrorHandler.class); if (handler != null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index e21bafa9914b..836d0581eacd 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -420,7 +420,7 @@ public void parsedHeader(HttpField field) public void parsedTrailer(HttpField field) { if (_trailers == null) - _trailers = HttpFields.empty(); + _trailers = HttpFields.build(); _trailers.add(field); } @@ -503,7 +503,7 @@ private boolean upgrade() throws BadMessageException } // Create new connection - HttpFieldsBuilder response101 = HttpFields.empty(); + HttpFieldsBuilder response101 = HttpFields.build(); Connection upgradeConnection = factory.upgradeConnection(getConnector(), getEndPoint(), _metadata, response101); if (upgradeConnection == null) { @@ -544,8 +544,8 @@ boolean onIdleTimeout(Throwable timeout) private static class RequestBuilder { - private final HttpFieldsBuilder _fieldBuilder = HttpFields.empty(); - private final HttpURI.Builder _uri = HttpURI.empty(); + private final HttpFieldsBuilder _fieldBuilder = HttpFields.build(); + private final HttpURI.Builder _uri = HttpURI.build(); private String _method; private HttpVersion _version; @@ -569,7 +569,7 @@ public HttpFieldsBuilder getFields() public MetaData.Request build() { - return new MetaData.Request(_method, _uri.toHttpURI(), _version, _fieldBuilder); + return new MetaData.Request(_method, _uri, _version, _fieldBuilder); } public HttpVersion version() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index e950a0018d19..2c8092143484 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -176,7 +176,7 @@ public void push() // _rawFields.add("Cookie","JSESSIONID="+_sessionId); } - HttpURI uri = HttpURI.from(_request.getHttpURI(), path, param, query).normalize().toHttpURI(); + HttpURI uri = HttpURI.build(_request.getHttpURI(), path, param, query).normalize(); MetaData.Request push = new MetaData.Request(_method, uri, _request.getHttpVersion(), _fields); if (LOG.isDebugEnabled()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 4043d79eb3c1..e5075002ac09 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -389,7 +389,7 @@ public PushBuilder newPushBuilder() if (!isPushSupported()) return null; - HttpFieldsBuilder fields = HttpFields.from(getHttpFields(), NOT_PUSHED_HEADERS); + HttpFieldsBuilder fields = HttpFields.build(getHttpFields(), NOT_PUSHED_HEADERS); String id; try @@ -1535,7 +1535,7 @@ public void setHttpURI(HttpURI uri) { if (_uri != null && !Objects.equals(_uri.getQuery(), uri.getQuery()) && _queryParameters != BAD_PARAMS) _parameters = _queryParameters = null; - _uri = uri; + _uri = uri.asImmutable(); } /** @@ -1677,7 +1677,7 @@ public void setMetaData(MetaData.Request request) _uri = uri; else { - HttpURI.Builder builder = HttpURI.from(uri); + HttpURI.Builder builder = HttpURI.build(uri); if (!uri.isAbsolute()) builder.scheme(HttpScheme.HTTP.asString()); @@ -1694,7 +1694,7 @@ public void setMetaData(MetaData.Request request) builder.host(findServerName()).port(findServerPort()); } } - _uri = builder.toHttpURI(); + _uri = builder.asImmutable(); } String encoded = uri.getPath(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 78592ec1e04d..69536359b853 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -85,7 +85,7 @@ public enum OutputType public static final String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include."; private final HttpChannel _channel; - private final HttpFieldsBuilder _fields = HttpFields.empty(); + private final HttpFieldsBuilder _fields = HttpFields.build(); private final AtomicBiInteger _errorSentAndIncludes = new AtomicBiInteger(); // hi is errorSent flag, lo is include count private final HttpOutput _out; private int _status = HttpStatus.OK_200; @@ -321,7 +321,7 @@ public String encodeURL(String url) HttpURI uri = null; if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url)) { - uri = new HttpURI(url); + uri = HttpURI.from(url); String path = uri.getPath(); path = (path == null ? "" : path); int port = uri.getPort(); @@ -375,7 +375,7 @@ public String encodeURL(String url) String id = sessionManager.getExtendedId(session); if (uri == null) - uri = new HttpURI(url); + uri = HttpURI.from(url); // Already encoded int prefix = url.indexOf(sessionURLPrefix); @@ -1431,7 +1431,7 @@ public HttpFields get() Map t = _supplier.get(); if (t == null) return null; - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); for (Map.Entry e : t.entrySet()) { fields.add(e.getKey(), e.getValue()); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java index 13d21319039a..397c4f8b7442 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java @@ -207,13 +207,13 @@ public void customize(Connector connector, HttpConfiguration channelConfig, Requ SSLEngine sslEngine = sslConnection.getSSLEngine(); customize(sslEngine, request); - request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS)); } else if (endp instanceof ProxyConnectionFactory.ProxyEndPoint) { ProxyConnectionFactory.ProxyEndPoint proxy = (ProxyConnectionFactory.ProxyEndPoint)endp; if (request.getHttpURI().getScheme() == null && proxy.getAttribute(ProxyConnectionFactory.TLS_VERSION) != null) - request.setHttpURI(HttpURI.from(request.getHttpURI()).scheme(HttpScheme.HTTPS).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS)); } if (HttpScheme.HTTPS.is(request.getScheme())) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index f4c58f70ecb9..11b9d0a1b672 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -606,12 +606,12 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio if (baseUri == null) baseUri = oldUri; - HttpURI.Builder builder = HttpURI.from(baseUri, encodedPathQuery); - if (StringUtil.isEmpty(builder.param())) + HttpURI.Builder builder = HttpURI.build(baseUri, encodedPathQuery); + if (StringUtil.isEmpty(builder.getParam())) builder.param(baseUri.getParam()); - if (StringUtil.isEmpty(builder.query())) + if (StringUtil.isEmpty(builder.getQuery())) builder.query(baseUri.getQuery()); - baseRequest.setHttpURI(builder.toHttpURI()); + baseRequest.setHttpURI(builder); if (baseUri.getQuery() != null && baseRequest.getQueryString() != null) // TODO why can't the old map be passed? diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 8a7b16d9da67..2ad22ff4456b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -2145,18 +2145,18 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) String pathInfo; if (StringUtil.isEmpty(contextPath)) { - uri = new HttpURI.Builder(null, null, 0, uriInContext).toHttpURI(); + uri = HttpURI.from(uriInContext); pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); if (StringUtil.isEmpty(pathInfo)) return null; } else { - HttpURI.Builder builder = new HttpURI.Builder(null, null, 0, uriInContext); - if (StringUtil.isEmpty(URIUtil.canonicalPath(builder.decodedPath()))) + HttpURI.Builder builder = HttpURI.build(uriInContext); + if (StringUtil.isEmpty(URIUtil.canonicalPath(builder.getDecodedPath()))) return null; - builder.path(URIUtil.addPaths(contextPath,builder.path())); - uri = builder.toHttpURI(); + builder.path(URIUtil.addPaths(contextPath,builder.getPath())); + uri = builder.asImmutable(); pathInfo = uri.getDecodedPath().substring(contextPath.length()); } return new Dispatcher(ContextHandler.this, uri, pathInfo); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index eb4052640b93..a8f5a9071ccf 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -620,7 +620,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques // Update headers for etags and inflation if (inflated || httpFields.contains(ETAG_HEADERS)) { - HttpFieldsBuilder newFields = HttpFields.empty(httpFields.size() + 1); + HttpFieldsBuilder newFields = HttpFields.build(httpFields.size() + 1); for (HttpField field : httpFields) { if (field.getHeader() == null) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java index f98782f7f1aa..6d8759390d73 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java @@ -83,7 +83,7 @@ public void test33() { try { - HttpFieldsBuilder fields = HttpFields.empty() + HttpFieldsBuilder fields = HttpFields.build() .put("D1", "Sun, 6 Nov 1994 08:49:37 GMT") .put("D2", "Sunday, 6-Nov-94 08:49:37 GMT") .put("D3", "Sun Nov 6 08:49:37 1994"); @@ -275,7 +275,7 @@ public void test36d() throws Exception @Test public void test39() throws Exception { - HttpFields fields = HttpFields.empty() + HttpFields fields = HttpFields.build() .put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7").asImmutable(); List list = fields.getQualityCSV("Q"); assertEquals("aaa", HttpField.valueParameters(list.get(0), null), "Quality parameters"); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 8b32af440a8d..2c9906eb35f6 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -861,7 +861,7 @@ public void testEncodeRedirect() { Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - request.setHttpURI(HttpURI.from(request.getHttpURI()).host("myhost").port(8888).toHttpURI()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).host("myhost").port(8888).asImmutable()); request.setContextPath("/path"); assertEquals("http://myhost:8888/path/info;param?query=0&more=1#target", response.encodeURL("http://myhost:8888/path/info;param?query=0&more=1#target")); @@ -950,12 +950,12 @@ public void testSendRedirect() Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - HttpURI.Builder builder = HttpURI.from(request.getHttpURI(), + HttpURI.Builder builder = HttpURI.build(request.getHttpURI(), "/path/info;param;jsessionid=12345?query=0&more=1#target"); builder.scheme("http"); if (host != null) builder.host(host).port(port); - request.setHttpURI(builder.toHttpURI()); + request.setHttpURI(builder.asImmutable()); request.setContextPath("/path"); request.setRequestedSessionId("12345"); request.setRequestedSessionIdFromCookie(i > 2); @@ -1331,7 +1331,7 @@ public void testFlushAfterFullContent() throws Exception private Response getResponse() { _channel.recycle(); - _channel.getRequest().setMetaData(new MetaData.Request("GET", new HttpURI("/path/info"), HttpVersion.HTTP_1_0, HttpFields.EMPTY)); + _channel.getRequest().setMetaData(new MetaData.Request("GET", HttpURI.from("/path/info"), HttpVersion.HTTP_1_0, HttpFields.EMPTY)); BufferUtil.clear(_content); return _channel.getResponse(); } diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java index 0f4c9eb714d3..1d40780698a8 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushCacheFilter.java @@ -160,7 +160,7 @@ else if (HttpHeader.REFERER.is(headerName)) path += "?" + query; if (referrer != null) { - HttpURI referrerURI = new HttpURI(referrer); + HttpURI referrerURI = HttpURI.from(referrer); String host = referrerURI.getHost(); int port = referrerURI.getPort(); if (port <= 0) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushSessionCacheFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushSessionCacheFilter.java index ecb6ed02144a..4384ee790a9d 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushSessionCacheFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/PushSessionCacheFilter.java @@ -83,7 +83,7 @@ public void requestDestroyed(ServletRequestEvent sre) if (referer != null) { // Is the referer from this contexts? - HttpURI refererUri = new HttpURI(referer); + HttpURI refererUri = HttpURI.from(referer); if (request.getServerName().equals(refererUri.getHost())) { Target refererTarget = _cache.get(refererUri.getPath()); diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java index 287e8fe157dc..e9a49a60fdec 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java @@ -72,7 +72,7 @@ public void startServer(WorkDir workDir, Class filter) throws _tester.getContext().getSessionHandler().setSessionCache(sessionCache); - HttpURI uri = new HttpURI(_tester.createConnector(true)); + HttpURI uri = HttpURI.from(_tester.createConnector(true)); _host = uri.getHost(); _port = uri.getPort(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java index 7748da0cac59..409dd5e775a4 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java @@ -89,7 +89,7 @@ protected Socket newClient(int port, String extensions) throws Exception protected static HttpFieldsBuilder newUpgradeRequest(String extensions) { - HttpFieldsBuilder fields = HttpFields.empty() + HttpFieldsBuilder fields = HttpFields.build() .add(HttpHeader.HOST, "127.0.0.1") .add(HttpHeader.UPGRADE, "websocket") .add(HttpHeader.CONNECTION, "Upgrade") diff --git a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java index 1e9124035dec..da6d8fe745b3 100644 --- a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java +++ b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java @@ -548,7 +548,7 @@ public void setURI(String uri) @Override public MetaData.Request getInfo() { - return new MetaData.Request(_method, new HttpURI(_uri), _version, this, _content == null ? 0 : _content.size()); + return new MetaData.Request(_method, HttpURI.from(_uri), _version, this, _content == null ? 0 : _content.size()); } @Override diff --git a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java index fca5ba44d91f..eb08da492c30 100644 --- a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java +++ b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java @@ -31,7 +31,7 @@ public class HttpFieldsMatchersTest @Test public void testContainsHeader() { - HttpFields fields = HttpFields.empty() + HttpFields fields = HttpFields.build() .put("a", "foo") .put("b", "bar") .put("c", "fizz") @@ -43,7 +43,7 @@ public void testContainsHeader() @Test public void testNotContainsHeader() { - HttpFieldsBuilder fields = HttpFields.empty() + HttpFieldsBuilder fields = HttpFields.build() .put("a", "foo") .put("b", "bar") .put("c", "fizz"); @@ -59,7 +59,7 @@ public void testNotContainsHeader() @Test public void testContainsHeaderMisMatch() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -75,7 +75,7 @@ public void testContainsHeaderMisMatch() @Test public void testContainsHeaderValueMisMatchNoSuchHeader() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -91,7 +91,7 @@ public void testContainsHeaderValueMisMatchNoSuchHeader() @Test public void testContainsHeaderValueMisMatchNoSuchValue() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -107,7 +107,7 @@ public void testContainsHeaderValueMisMatchNoSuchValue() @Test public void testContainsHeaderValue() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java index 30a24f855eb5..4acd875b3844 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java @@ -105,7 +105,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } }); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); trailers.put(trailerName, trailerValue); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); @@ -141,7 +141,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } }); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); request = request.trailers(() -> trailers); ContentResponse response = request.timeout(5, TimeUnit.SECONDS).send(); @@ -178,7 +178,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r if (once.compareAndSet(false, true)) { - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); trailers.put(trailerName, trailerValue); jettyResponse.setTrailers(() -> trailers); } @@ -241,7 +241,7 @@ public void testEmptyResponseTrailers(Transport transport) throws Exception @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); response.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); } @@ -283,7 +283,7 @@ public void testResponseTrailersWithLargeContent(Transport transport) throws Exc @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); trailers.put(trailerName, trailerValue); response.setTrailerFields(() -> @@ -334,7 +334,7 @@ public void testResponseResetAlsoResetsTrailers(Transport transport) throws Exce protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.empty(); + HttpFieldsBuilder trailers = HttpFields.build(); trailers.put("name", "value"); jettyResponse.setTrailers(() -> trailers); // Fill some other response field. diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java index 0d6c3e6b648a..dc6cc69bba1f 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java @@ -442,7 +442,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.empty(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.build(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); @@ -527,7 +527,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.empty(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.build(), null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java index c3a0e7546c48..850faecb9f12 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java @@ -138,7 +138,7 @@ public void test33() expected.set(Calendar.ZONE_OFFSET, 0); // Use GMT+0:00 expected.set(Calendar.DST_OFFSET, 0); // No Daylight Savings Offset - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); // RFC 822 Preferred Format fields.put("D1", "Sun, 6 Nov 1994 08:49:37 GMT"); @@ -335,7 +335,7 @@ public void test364() throws Throwable @Test public void test39() { - HttpFieldsBuilder fields = HttpFields.empty(); + HttpFieldsBuilder fields = HttpFields.build(); fields.put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7"); List list = fields.getQualityCSV("Q"); From 372455a6cae366b26502ec4a17b48aa0d85cb2da Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 12:56:46 +0200 Subject: [PATCH 15/38] Immutable MetaData WIP http2-server tests passed Signed-off-by: Greg Wilkins --- .../eclipse/jetty/http/HostPortHttpField.java | 6 ++++++ .../java/org/eclipse/jetty/http/MetaData.java | 8 ++++---- .../jetty/http2/hpack/MetaDataBuilder.java | 5 +---- .../http2/server/HttpTransportOverHTTP2.java | 20 ++++++++++++------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java index 1bda127bec34..bef4a99d0956 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java @@ -58,6 +58,12 @@ public HostPortHttpField(HostPort hostport) _hostPort = hostport; } + public HostPortHttpField(HttpHeader header, String headerString, HostPort hostport) + { + super(header, headerString, hostport.toString()); + _hostPort = hostport; + } + /** * Get the host. * diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 4eb3889e7720..69b0da71c4c8 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -238,22 +238,22 @@ public static class Response extends MetaData private final int _status; private final String _reason; - public Response(HttpVersion version, int status, HttpFieldsBuilder fields) + public Response(HttpVersion version, int status, HttpFields fields) { this(version, status, fields, Long.MIN_VALUE); } - public Response(HttpVersion version, int status, HttpFieldsBuilder fields, long contentLength) + public Response(HttpVersion version, int status, HttpFields fields, long contentLength) { this(version, status, null, fields, contentLength); } - public Response(HttpVersion version, int status, String reason, HttpFieldsBuilder fields, long contentLength) + public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength) { this(version, status, reason, fields, contentLength, null); } - public Response(HttpVersion version, int status, String reason, HttpFieldsBuilder fields, long contentLength, Supplier trailers) + public Response(HttpVersion version, int status, String reason, HttpFields fields, long contentLength, Supplier trailers) { super(version, fields, contentLength, trailers); _reason = reason; diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index 516778e809c9..2d367ef12019 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -141,7 +141,6 @@ else if (header != null) _authority = (HostPortHttpField)field; else if (value != null) _authority = new AuthorityHttpField(value); - _fields.add(_authority); // TODO does this need to be lowercase "host" } _request = true; @@ -165,9 +164,7 @@ else if (value != null) break; case HOST: - // if the :authority fields has come first then ignore the host header. - if (_authority == null) - _fields.add(field); + _fields.add(field); break; case CONTENT_LENGTH: diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java index 47021765029c..fe7e62dfae88 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpTransportOverHTTP2.java @@ -24,7 +24,6 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -115,7 +114,14 @@ public void send(MetaData.Request request, MetaData.Response response, ByteBuffe long contentLength = response.getContentLength(); if (contentLength < 0) { - response.setContentLength(realContentLength); + response = new MetaData.Response( + response.getHttpVersion(), + response.getStatus(), + response.getReason(), + response.getFields(), + realContentLength, + response.getTrailerSupplier() + ); } else if (hasContent && contentLength != realContentLength) { @@ -133,7 +139,7 @@ public void succeeded() { if (lastContent) { - HttpFieldsBuilder trailers = retrieveTrailers(); + HttpFields trailers = retrieveTrailers(); if (trailers != null) { if (transportCallback.start(new SendTrailers(getCallback(), trailers), false)) @@ -166,7 +172,7 @@ public void succeeded() } else { - HttpFieldsBuilder trailers = retrieveTrailers(); + HttpFields trailers = retrieveTrailers(); if (trailers != null) { if (transportCallback.start(new SendTrailers(callback, trailers), true)) @@ -198,7 +204,7 @@ public void succeeded() { if (lastContent) { - HttpFieldsBuilder trailers = retrieveTrailers(); + HttpFields trailers = retrieveTrailers(); if (trailers != null) { SendTrailers sendTrailers = new SendTrailers(callback, trailers); @@ -508,9 +514,9 @@ private enum State private class SendTrailers extends Callback.Nested { - private final HttpFieldsBuilder trailers; + private final HttpFields trailers; - private SendTrailers(Callback callback, HttpFieldsBuilder trailers) + private SendTrailers(Callback callback, HttpFields trailers) { super(callback); this.trailers = trailers; From 58e458c0139ed41660aa2b98cd6b063d93230413 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 13:22:02 +0200 Subject: [PATCH 16/38] Immutable MetaData WIP http2-client tests passed Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/http/HttpURI.java | 5 ++++ .../java/org/eclipse/jetty/http/MetaData.java | 4 +-- .../jetty/http2/client/AbstractTest.java | 6 ++--- .../jetty/http2/client/ConnectTunnelTest.java | 5 ++-- .../eclipse/jetty/http2/client/HTTP2Test.java | 2 +- .../http2/client/PushCacheFilterTest.java | 2 +- .../http2/client/SessionFailureTest.java | 3 ++- .../http2/client/SmallThreadPoolLoadTest.java | 7 +++--- .../jetty/http2/client/StreamResetTest.java | 2 +- .../jetty/http2/client/TrailersTest.java | 2 +- .../client/http/HttpReceiverOverHTTP2.java | 6 ++--- .../client/http/HttpSenderOverHTTP2.java | 25 +++++++++++-------- .../client/http/ResponseTrailerTest.java | 3 ++- 13 files changed, 43 insertions(+), 29 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index bab8baece50e..6606fe41d36b 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -95,6 +95,11 @@ static HttpURI from(String method, String uri) return new HttpURI.Builder(uri).asImmutable(); } + static HttpURI from(String scheme, String host, int port, String pathQuery) + { + return build(pathQuery).scheme(scheme).host(host).port(port).asImmutable(); + } + String getAuthority(); String getDecodedPath(); diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 69b0da71c4c8..c3f74f6a6d2f 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -215,12 +215,12 @@ public static class ConnectRequest extends Request { private final String _protocol; - public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String path, HttpFieldsBuilder fields, String protocol) + public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { this(scheme == null ? null : scheme.asString(), authority, path, fields, protocol); } - public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFieldsBuilder fields, String protocol) + public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { super(HttpMethod.CONNECT.asString(), scheme, authority, path, HttpVersion.HTTP_2, fields, Long.MIN_VALUE); _protocol = protocol; diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java index d05cdf85c011..cf8d3ddc135f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AbstractTest.java @@ -23,7 +23,7 @@ import javax.servlet.http.HttpServlet; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -109,12 +109,12 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, HttpFields fields) { return newRequest(method, "", fields); } - protected MetaData.Request newRequest(String method, String pathInfo, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, String pathInfo, HttpFields fields) { String host = "localhost"; int port = connector.getLocalPort(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java index 32205a9b6225..e03bbde57be4 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ConnectTunnelTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.http.HostPortHttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpURI; @@ -78,7 +79,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request request = new MetaData.Request(HttpMethod.CONNECT.asString(), null, new HostPortHttpField(authority), null, HttpVersion.HTTP_2, HttpFields.EMPTY, -1); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { @@ -130,7 +131,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) String host = "localhost"; int port = connector.getLocalPort(); String authority = host + ":" + port; - MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpFields.empty(), "websocket"); + MetaData.Request request = new MetaData.ConnectRequest(HttpScheme.HTTP, new HostPortHttpField(authority), "/", HttpFields.EMPTY, "websocket"); FuturePromise streamPromise = new FuturePromise<>(); client.newStream(new HeadersFrame(request, null, false), streamPromise, new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index c233f13fb559..1b1ca8822ced 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -339,7 +339,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { assertEquals(host, request.getServerName()); assertEquals(port, request.getServerPort()); - assertEquals(authority, request.getHeader("Host")); + // TODO is this needed ? assertEquals(authority, request.getHeader("Host")); } }); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 5f6ef4b361eb..00e554ed9a9f 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -69,7 +69,7 @@ protected void customizeContext(ServletContextHandler context) } @Override - protected MetaData.Request newRequest(String method, String pathInfo, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, String pathInfo, HttpFields fields) { return new MetaData.Request(method, HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), contextPath + servletPath + pathInfo, HttpVersion.HTTP_2, fields, -1); } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java index 0cb100d76e8c..d8724ee16089 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SessionFailureTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http2.HTTP2Session; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.api.Stream; @@ -113,7 +114,7 @@ public void onFailure(Session session, Throwable failure) clientFailureLatch.countDown(); } }); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.empty()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); Promise promise = new Promise.Adapter<>(); session.newStream(frame, promise, null); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java index ced4866c906f..b79d6f6e3323 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/SmallThreadPoolLoadTest.java @@ -149,9 +149,10 @@ private boolean test(Session session, CountDownLatch latch) throws Exception int contentLength = random.nextInt(maxContentLength) + 1; long requestId = requestIds.incrementAndGet(); - MetaData.Request request = newRequest(method.asString(), "/" + requestId, HttpFields.build()); - if (download) - request.getFields().put("X-Download", String.valueOf(contentLength)); + + MetaData.Request request = newRequest(method.asString(), "/" + requestId, + download ? HttpFields.build().put("X-Download", String.valueOf(contentLength)) : HttpFields.EMPTY); + HeadersFrame requestFrame = new HeadersFrame(request, null, download); FuturePromise promise = new FuturePromise<>(); CountDownLatch requestLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java index 3812067b4ba3..7e6b66be1395 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java @@ -1020,7 +1020,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) waitUntilTCPCongested(exchanger.exchange(null)); // Send a second request. - uri = new HttpURI("http", host, port, servletPath + "/2"); + uri = HttpURI.from("http", host, port, servletPath + "/2"); request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); int streamId = 5; headersFrame = new HeadersFrame(streamId, request, null, true); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 4669c1d9be67..9f278a32e96e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -133,7 +133,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) } // Now we have the trailers. - HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); + HttpFields trailers = jettyRequest.getTrailerHttpFields(); assertNotNull(trailers); assertNotNull(trailers.get("X-Trailer")); } diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java index d5b033f7d623..ea2e1f93a22c 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpReceiverOverHTTP2.java @@ -35,7 +35,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MetaData; @@ -94,7 +94,7 @@ void onHeaders(Stream stream, HeadersFrame frame) if (responseBegin(exchange)) { - HttpFieldsBuilder headers = response.getFields(); + HttpFields headers = response.getFields(); for (HttpField header : headers) { if (!responseHeader(exchange, header)) @@ -138,7 +138,7 @@ void onHeaders(Stream stream, HeadersFrame frame) } else // Response trailers. { - HttpFieldsBuilder trailers = metaData.getFields(); + HttpFields trailers = metaData.getFields(); trailers.forEach(httpResponse::trailer); // Previous DataFrames had endStream=false, so // add a poison pill to trigger response success diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java index 1a537b29e904..f51739514410 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java @@ -27,7 +27,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpSender; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -64,6 +64,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool MetaData.Request metaData; if (isTunnel) { + // TODO what to do with trailers ?? String upgradeProtocol = request.getUpgradeProtocol(); if (upgradeProtocol == null) { @@ -78,11 +79,14 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool else { String path = relativize(request.getPath()); - HttpURI uri = HttpURI.createHttpURI(request.getScheme(), request.getHost(), request.getPort(), path, null, request.getQuery(), null); - metaData = new MetaData.Request(request.getMethod(), uri, HttpVersion.HTTP_2, request.getHeaders()); + HttpURI uri = HttpURI.build() + .scheme(request.getScheme()) + .host(request.getHost()) + .port(request.getPort()) + .path(path) + .query(request.getQuery()); + metaData = new MetaData.Request(request.getMethod(), uri, HttpVersion.HTTP_2, request.getHeaders(), -1, request.getTrailers()); } - Supplier trailerSupplier = request.getTrailers(); - metaData.setTrailerSupplier(trailerSupplier); HeadersFrame headersFrame; Promise promise; @@ -93,9 +97,10 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool } else { + Supplier trailerSupplier = request.getTrailers(); if (BufferUtil.isEmpty(contentBuffer) && lastContent) { - HttpFieldsBuilder trailers = trailerSupplier == null ? null : trailerSupplier.get(); + HttpFields trailers = trailerSupplier == null ? null : trailerSupplier.get(); boolean endStream = trailers == null || trailers.size() == 0; headersFrame = new HeadersFrame(metaData, null, endStream); promise = new HeadersPromise(request, callback, stream -> @@ -140,17 +145,17 @@ private String relativize(String path) protected void sendContent(HttpExchange exchange, ByteBuffer contentBuffer, boolean lastContent, Callback callback) { Stream stream = getHttpChannel().getStream(); - Supplier trailerSupplier = exchange.getRequest().getTrailers(); + Supplier trailerSupplier = exchange.getRequest().getTrailers(); sendContent(stream, contentBuffer, lastContent, trailerSupplier, callback); } - private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, Supplier trailerSupplier, Callback callback) + private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, Supplier trailerSupplier, Callback callback) { boolean hasContent = buffer.hasRemaining(); if (lastContent) { // Call the trailers supplier as late as possible. - HttpFieldsBuilder trailers = trailerSupplier == null ? null : trailerSupplier.get(); + HttpFields trailers = trailerSupplier == null ? null : trailerSupplier.get(); boolean hasTrailers = trailers != null && trailers.size() > 0; if (hasContent) { @@ -188,7 +193,7 @@ private void sendContent(Stream stream, ByteBuffer buffer, boolean lastContent, } } - private void sendTrailers(Stream stream, HttpFieldsBuilder trailers, Callback callback) + private void sendTrailers(Stream stream, HttpFields trailers, Callback callback) { MetaData metaData = new MetaData(HttpVersion.HTTP_2, trailers); HeadersFrame trailersFrame = new HeadersFrame(stream.getId(), metaData, null, true); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java index 8e1210ad6598..fb73452ab8be 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ResponseTrailerTest.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -88,7 +89,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r Session session = sessionPromise.get(5, TimeUnit.SECONDS); HttpURI uri = HttpURI.from("http://" + host + ":" + port + "/"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); BlockingQueue headers = new LinkedBlockingQueue<>(); CountDownLatch latch = new CountDownLatch(1); From 0215268bc36e278ed7f2316a45efe0054f3e0466 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 14:56:10 +0200 Subject: [PATCH 17/38] Immutable MetaData WIP cleann build? Signed-off-by: Greg Wilkins --- .../jetty/embedded/FastFileServerTest.java | 4 +-- .../jetty/embedded/FileServerTest.java | 4 +-- .../jetty/embedded/FileServerXmlTest.java | 4 +-- .../java/client/ConscryptHTTP2ClientTest.java | 4 +-- .../jetty/client/HttpContentResponse.java | 4 +-- .../eclipse/jetty/client/HttpReceiver.java | 2 +- .../eclipse/jetty/client/HttpResponse.java | 7 ++++- .../eclipse/jetty/client/api/Response.java | 4 +-- .../client/http/HttpChannelOverHTTP.java | 4 +-- .../util/BufferingResponseListener.java | 4 +-- .../client/util/MultiPartContentProvider.java | 5 ++-- .../client/util/MultiPartRequestContent.java | 5 ++-- .../client/ClientConnectionCloseTest.java | 3 +- .../client/http/HttpReceiverOverHTTPTest.java | 6 ++-- .../fcgi/client/http/HttpChannelOverFCGI.java | 4 +-- .../client/http/HttpConnectionOverFCGI.java | 4 +-- .../jetty/fcgi/generator/ServerGenerator.java | 4 +-- .../java/org/eclipse/jetty/http/MetaData.java | 2 +- .../http2/client/http/ContentLengthTest.java | 8 +++--- .../eclipse/jetty/server/PushBuilderImpl.java | 5 ++-- .../jetty/server/handler/ErrorHandler.java | 3 +- .../core/client/HttpUpgraderOverHTTP.java | 6 ++-- .../client/internal/JsrUpgradeListener.java | 3 +- .../jetty/http/client/HttpTrailersTest.java | 28 ++++++++----------- .../jetty/test/webapp/HTTP1Servlet.java | 5 ++-- 25 files changed, 68 insertions(+), 64 deletions(-) diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java index b80dfbe308a4..683a1905776f 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FastFileServerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -79,7 +79,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java index ad4ed1ac9278..e16a401ca90d 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -80,7 +80,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java index 4421bc43b16a..51c996fdf3ff 100644 --- a/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java +++ b/examples/embedded/src/test/java/org/eclipse/jetty/embedded/FileServerXmlTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Server; @@ -79,7 +79,7 @@ public void testGetSimpleText() throws Exception // dumpResponseHeaders(response); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); assertThat("Content-Type", responseHeaders.get("Content-Type"), is("text/plain")); assertThat("Content-Length", responseHeaders.getLongField("Content-Length"), diff --git a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java index e3c8cd58e41d..d143e12bb225 100644 --- a/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-conscrypt-client/src/test/java/org/eclipse/jetty/alpn/java/client/ConscryptHTTP2ClientTest.java @@ -27,7 +27,6 @@ import org.conscrypt.Conscrypt; import org.conscrypt.OpenSSLProvider; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -75,8 +74,7 @@ public void testConscryptHTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.build(); - requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); + HttpFields requestFields = HttpFields.build().put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java index 74524d91dfc6..471f6e5f03eb 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContentResponse.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Response; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; public class HttpContentResponse implements ContentResponse @@ -75,7 +75,7 @@ public String getReason() } @Override - public HttpFieldsBuilder getHeaders() + public HttpFields getHeaders() { return response.getHeaders(); } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java index e8fba07cb92a..e75f421169eb 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java @@ -242,7 +242,7 @@ protected boolean responseHeader(HttpExchange exchange, HttpField field) boolean process = notifier.notifyHeader(exchange.getConversation().getResponseListeners(), response, field); if (process) { - response.getHeaders().add(field); + response.getHeadersBuilder().add(field); HttpHeader fieldHeader = field.getHeader(); if (fieldHeader != null) { diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index 1b337fd0b937..206225c78374 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -87,7 +87,12 @@ public HttpResponse reason(String reason) } @Override - public HttpFieldsBuilder getHeaders() + public HttpFields getHeaders() + { + return headers.asImmutable(); + } + + public HttpFieldsBuilder getHeadersBuilder() { return headers; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java index 14c91e1b5cb1..9c830cb1904e 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.util.Callback; @@ -72,7 +72,7 @@ public interface Response /** * @return the headers of this response */ - HttpFieldsBuilder getHeaders(); + HttpFields getHeaders(); /** * Attempts to abort the receive of this response. diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java index fd416cdc3d31..871c6d7f382f 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpChannelOverHTTP.java @@ -24,7 +24,7 @@ import org.eclipse.jetty.client.HttpExchange; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -99,7 +99,7 @@ public void exchangeTerminated(HttpExchange exchange, Result result) super.exchangeTerminated(exchange, result); Response response = result.getResponse(); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); String closeReason = null; if (result.isFailed()) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java index a8280c3ab470..9fb78deda460 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BufferingResponseListener.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response.Listener; import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.util.BufferUtil; @@ -74,7 +74,7 @@ public void onHeaders(Response response) super.onHeaders(response); Request request = response.getRequest(); - HttpFieldsBuilder headers = response.getHeaders(); + HttpFields headers = response.getHeaders(); long length = headers.getLongField(HttpHeader.CONTENT_LENGTH); if (HttpMethod.HEAD.is(request.getMethod())) length = 0; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java index 14cc3366e405..783a36961482 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.client.Synchronizable; import org.eclipse.jetty.client.api.ContentProvider; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; @@ -222,11 +223,11 @@ private static class Part private final String fileName; private final String contentType; private final ContentProvider content; - private final HttpFieldsBuilder fields; + private final HttpFields fields; private final ByteBuffer headers; private final long length; - private Part(String name, String fileName, String contentType, ContentProvider content, HttpFieldsBuilder fields) + private Part(String name, String fileName, String contentType, ContentProvider content, HttpFields fields) { this.name = name; this.fileName = fileName; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java index f720dfd31b38..24f7868959d3 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java @@ -30,6 +30,7 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; @@ -215,11 +216,11 @@ private static class Part private final String name; private final String fileName; private final Request.Content content; - private final HttpFieldsBuilder fields; + private final HttpFields fields; private final ByteBuffer headers; private final long length; - private Part(String name, String fileName, Request.Content content, HttpFieldsBuilder fields) + private Part(String name, String fileName, Request.Content content, HttpFields fields) { this.name = name; this.fileName = fileName; diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java index fab10cb6b6c3..d99ef74e51d2 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java @@ -250,7 +250,8 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques HttpConnectionOverHTTP connection = (HttpConnectionOverHTTP)connectionPool.getActiveConnections().iterator().next(); assertFalse(connection.getEndPoint().isOutputShutdown()); }) - .onResponseHeaders(r -> r.getHeaders().remove(HttpHeader.CONNECTION)); + // TODO ??? .onResponseHeaders(r -> r.getHeaders().remove(HttpHeader.CONNECTION)); + ; ContentResponse response = request.send(); assertEquals(HttpStatus.OK_200, response.getStatus()); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java index 067572af8f8d..551f1e61c737 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java @@ -37,7 +37,7 @@ import org.eclipse.jetty.client.util.FutureResponseListener; import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpCompliance; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.ByteArrayEndPoint; @@ -122,7 +122,7 @@ public void testReceiveNoResponseContent(HttpCompliance compliance) throws Excep assertEquals(200, response.getStatus()); assertEquals("OK", response.getReason()); assertSame(HttpVersion.HTTP_1_1, response.getVersion()); - HttpFieldsBuilder headers = response.getHeaders(); + HttpFields headers = response.getHeaders(); assertNotNull(headers); assertEquals(1, headers.size()); assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH)); @@ -148,7 +148,7 @@ public void testReceiveResponseContent(HttpCompliance compliance) throws Excepti assertEquals(200, response.getStatus()); assertEquals("OK", response.getReason()); assertSame(HttpVersion.HTTP_1_1, response.getVersion()); - HttpFieldsBuilder headers = response.getHeaders(); + HttpFields headers = response.getHeaders(); assertNotNull(headers); assertEquals(1, headers.size()); assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH)); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java index 702003c00332..61c8cd250332 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpChannelOverFCGI.java @@ -29,7 +29,7 @@ import org.eclipse.jetty.fcgi.generator.Flusher; import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.IdleTimeout; import org.eclipse.jetty.util.Callback; @@ -150,7 +150,7 @@ public void exchangeTerminated(HttpExchange exchange, Result result) { super.exchangeTerminated(exchange, result); idle.onClose(); - HttpFieldsBuilder responseHeaders = result.getResponse().getHeaders(); + HttpFields responseHeaders = result.getResponse().getHeaders(); if (result.isFailed()) connection.close(result.getFailure()); else if (!connection.closeByHTTP(responseHeaders)) diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java index 2d6980ab3df3..c4720e323187 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java @@ -43,7 +43,7 @@ import org.eclipse.jetty.fcgi.generator.Flusher; import org.eclipse.jetty.fcgi.parser.ClientParser; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.io.AbstractConnection; @@ -264,7 +264,7 @@ public boolean isClosed() return closed.get(); } - protected boolean closeByHTTP(HttpFieldsBuilder fields) + protected boolean closeByHTTP(HttpFields fields) { if (!fields.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString())) return false; diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java index fd5a50b0d518..59562fa2cc90 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ServerGenerator.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.BufferUtil; @@ -51,7 +51,7 @@ public ServerGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffe this.sendStatus200 = sendStatus200; } - public Result generateResponseHeaders(int request, int code, String reason, HttpFieldsBuilder fields, Callback callback) + public Result generateResponseHeaders(int request, int code, String reason, HttpFields fields, Callback callback) { request &= 0xFF_FF; diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index c3f74f6a6d2f..aabd48bbb9a8 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -160,7 +160,7 @@ public Request(String method, String scheme, HostPortHttpField authority, String version, fields, contentLength); } - public Request(String method, HttpURI uri, HttpVersion version, HttpFieldsBuilder fields, long contentLength, Supplier trailers) + public Request(String method, HttpURI uri, HttpVersion version, HttpFields fields, long contentLength, Supplier trailers) { super(version, fields, contentLength, trailers); _method = method; diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java index 15387fcf512a..461476937a6e 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/ContentLengthTest.java @@ -23,7 +23,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.client.api.ContentResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.gzip.GzipHandler; @@ -45,7 +45,7 @@ public void testZeroContentLengthAddedByServer(String method) throws Exception .method(method) .send(); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertEquals(0, contentLength); } @@ -68,7 +68,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r .method(method) .send(); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertEquals(data.length, contentLength); } @@ -98,7 +98,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r .method(method) .send(); - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); long contentLength = responseHeaders.getLongField(HttpHeader.CONTENT_LENGTH.asString()); assertTrue(0 < contentLength && contentLength < data.length); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index 2c8092143484..354a4ad3ebb3 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -22,6 +22,7 @@ import javax.servlet.http.PushBuilder; import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; @@ -48,11 +49,11 @@ public class PushBuilderImpl implements PushBuilder private String _path; private String _lastModified; - public PushBuilderImpl(Request request, HttpFieldsBuilder fields, String method, String queryString, String sessionId) + public PushBuilderImpl(Request request, HttpFields fields, String method, String queryString, String sessionId) { super(); _request = request; - _fields = fields; + _fields = HttpFields.build(fields); _method = method; _queryString = queryString; _sessionId = sessionId; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index 684f15cd4dd6..e5458c87a45b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -525,7 +525,8 @@ public ByteBuffer badMessageError(int status, String reason, HttpFieldsBuilder f { if (reason == null) reason = HttpStatus.getMessage(status); - // TODO only if a status allows a body! + if (HttpStatus.hasNoBody(status)) + return BufferUtil.EMPTY_BUFFER; fields.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.TEXT_HTML_8859_1.asString()); return BufferUtil.toBuffer("

Bad Message " + status + "

reason: " + reason + "
"); } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java index 046e83b8785f..9d3f3e4145ec 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.HttpResponse; import org.eclipse.jetty.client.HttpResponseException; import org.eclipse.jetty.client.HttpUpgrader; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -81,10 +81,10 @@ private String generateRandomKey() public void upgrade(HttpResponse response, EndPoint endPoint, Callback callback) { HttpRequest request = (HttpRequest)response.getRequest(); - HttpFieldsBuilder requestHeaders = request.getHeaders(); + HttpFields requestHeaders = request.getHeaders(); if (requestHeaders.contains(HttpHeader.UPGRADE, "websocket")) { - HttpFieldsBuilder responseHeaders = response.getHeaders(); + HttpFields responseHeaders = response.getHeaders(); if (responseHeaders.contains(HttpHeader.CONNECTION, "upgrade")) { // Check the Accept hash diff --git a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java index ec5e72667aa6..55c4fd18e826 100644 --- a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java +++ b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java @@ -28,6 +28,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.websocket.core.client.UpgradeListener; @@ -76,7 +77,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) HandshakeResponse handshakeResponse = () -> { - HttpFieldsBuilder fields = response.getHeaders(); + HttpFields fields = response.getHeaders(); Map> ret = new HashMap<>(); fields.forEach((field) -> { diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java index 4acd875b3844..f625fac0ca58 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/HttpTrailersTest.java @@ -39,7 +39,6 @@ import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Request; @@ -99,14 +98,13 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } // Now the trailers can be accessed. - HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); + HttpFields trailers = jettyRequest.getTrailerHttpFields(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); } }); - HttpFieldsBuilder trailers = HttpFields.build(); - trailers.put(trailerName, trailerValue); + HttpFields trailers = HttpFields.build().put(trailerName, trailerValue).asImmutable(); HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); request = request.trailers(() -> trailers); @@ -136,12 +134,12 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r } // Now the trailers can be accessed. - HttpFieldsBuilder trailers = jettyRequest.getTrailerHttpFields(); + HttpFields trailers = jettyRequest.getTrailerHttpFields(); assertNull(trailers); } }); - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields trailers = HttpFields.EMPTY; HttpRequest request = (HttpRequest)scenario.client.newRequest(scenario.newURI()); request = request.trailers(() -> trailers); ContentResponse response = request.timeout(5, TimeUnit.SECONDS).send(); @@ -178,8 +176,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r if (once.compareAndSet(false, true)) { - HttpFieldsBuilder trailers = HttpFields.build(); - trailers.put(trailerName, trailerValue); + HttpFields trailers = HttpFields.build().put(trailerName, trailerValue); jettyResponse.setTrailers(() -> trailers); } @@ -195,7 +192,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r try { HttpResponse httpResponse = (HttpResponse)r; - HttpFieldsBuilder trailers = httpResponse.getTrailers(); + HttpFields trailers = httpResponse.getTrailers(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); failure.set(null); @@ -241,7 +238,7 @@ public void testEmptyResponseTrailers(Transport transport) throws Exception @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) { - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields trailers = HttpFields.build(); response.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); } @@ -254,7 +251,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r try { HttpResponse httpResponse = (HttpResponse)r; - HttpFieldsBuilder trailers = httpResponse.getTrailers(); + HttpFields trailers = httpResponse.getTrailers(); assertNull(trailers); failure.set(null); } @@ -283,9 +280,7 @@ public void testResponseTrailersWithLargeContent(Transport transport) throws Exc @Override protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { - HttpFieldsBuilder trailers = HttpFields.build(); - trailers.put(trailerName, trailerValue); - + HttpFields trailers = HttpFields.build().put(trailerName, trailerValue); response.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); @@ -318,7 +313,7 @@ protected void service(String target, Request jettyRequest, HttpServletRequest r listener.await(5, TimeUnit.SECONDS); HttpResponse httpResponse = (HttpResponse)response; - HttpFieldsBuilder trailers = httpResponse.getTrailers(); + HttpFields trailers = httpResponse.getTrailers(); assertNotNull(trailers); assertEquals(trailerValue, trailers.get(trailerName)); } @@ -334,8 +329,7 @@ public void testResponseResetAlsoResetsTrailers(Transport transport) throws Exce protected void service(String target, Request jettyRequest, HttpServletRequest request, HttpServletResponse response) throws IOException { Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.build(); - trailers.put("name", "value"); + HttpFields trailers = HttpFields.build().put("name", "value"); jettyResponse.setTrailers(() -> trailers); // Fill some other response field. response.setHeader("name", "value"); diff --git a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java index 0bd57b868c69..d36bb88ac62e 100644 --- a/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java +++ b/tests/test-webapps/test-http2-webapp/src/main/java/org/eclipse/jetty/test/webapp/HTTP1Servlet.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; @@ -89,8 +90,8 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t @Override public void succeeded(Session session) { - HttpURI uri = new HttpURI(request.getScheme(), host, port, contextPath + "/h2"); - MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.empty()); + HttpURI uri = HttpURI.from(request.getScheme(), host, port, contextPath + "/h2"); + MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter() { From c23ea622b5c803d7f85027c84ad1e1e654bc6465 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 15:34:00 +0200 Subject: [PATCH 18/38] Immutable MetaData WIP fix Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/http/HttpURI.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 6606fe41d36b..ab0891437ea4 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -92,12 +92,14 @@ static HttpURI from(String method, String uri) { if (HttpMethod.CONNECT.is(method)) return new Immutable(uri, null, null, null, -1, uri, null, null, null, null); - return new HttpURI.Builder(uri).asImmutable(); + if (uri.startsWith("/")) + return HttpURI.build().pathQuery(uri).asImmutable(); + return HttpURI.from(uri); } static HttpURI from(String scheme, String host, int port, String pathQuery) { - return build(pathQuery).scheme(scheme).host(host).port(port).asImmutable(); + return build(pathQuery).scheme(scheme).host(host).port(port).pathQuery(pathQuery).asImmutable(); } String getAuthority(); From cf6df85cf92d312203f0f78c23ae54fac18e2d19 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 18:33:16 +0200 Subject: [PATCH 19/38] Immutable MetaData WIP more test fixes Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/http/HttpURI.java | 18 ++++++++++++++++++ .../handler/RewritePatternRuleTest.java | 2 +- .../jetty/server/HttpChannelOverHttp.java | 2 +- .../java/org/eclipse/jetty/server/Request.java | 14 ++++++++++++-- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index ab0891437ea4..14a273b83f63 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -754,6 +754,24 @@ public Builder uri(String uri) return this; } + public Builder uri(String method, String uri) + { + if (HttpMethod.CONNECT.is(method)) + { + clear(); + _uri = uri; + _path = uri; + } + else if (uri.startsWith("/")) + { + clear(); + pathQuery(uri); + } + else + uri(uri); + return this; + } + public Builder uri(String uri, int offset, int length) { clear(); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java index 9579d8190b5e..f0c035f96603 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewritePatternRuleTest.java @@ -110,7 +110,7 @@ public void testRequestAndReplacementWithQueryString() throws IOException String[] split = replacement.split("\\?", 2); String path = split[0]; String queryString = split[1]; - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/old/context", null, queryString).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/old/context", null, requestQueryString).asImmutable()); RewritePatternRule rewritePatternRule = new RewritePatternRule(); rewritePatternRule.setPattern("/old/context"); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index 836d0581eacd..fd32b17d1fe2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -557,7 +557,7 @@ public String method() public void request(String method, String uri, HttpVersion version) { _method = method; - _uri.uri(uri); + _uri.uri(method, uri); _version = version; _fieldBuilder.clear(); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e5075002ac09..4d469017a687 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1673,13 +1673,21 @@ public void setMetaData(MetaData.Request request) _httpFields = request.getFields(); final HttpURI uri = request.getURI(); - if (uri.isAbsolute() && uri.hasAuthority()) + if (uri.isAbsolute() && uri.hasAuthority() && uri.getPath() != null) _uri = uri; else { HttpURI.Builder builder = HttpURI.build(uri); - if (!uri.isAbsolute()) + + if (uri.isAbsolute()) + { + if (uri.getPath() == null) + builder.path("/"); + } + else + { builder.scheme(HttpScheme.HTTP.asString()); + } if (!uri.hasAuthority()) { @@ -1694,6 +1702,8 @@ public void setMetaData(MetaData.Request request) builder.host(findServerName()).port(findServerPort()); } } + + _uri = builder.asImmutable(); } From e8617da0f1ce5f06dacd446299568d6d231a750c Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 19:28:57 +0200 Subject: [PATCH 20/38] Immutable MetaData WIP Cleanups, mostly using EMPTY when appropriate. Signed-off-by: Greg Wilkins --- .../server/http2/HTTP2ServerDocs.java | 6 +- .../jetty/fcgi/generator/ClientGenerator.java | 4 +- .../fcgi/parser/ResponseContentParser.java | 2 +- .../jetty/fcgi/parser/ClientParserTest.java | 4 +- .../jetty/http2/client/AsyncIOTest.java | 13 ++-- .../jetty/http2/client/AsyncServletTest.java | 16 ++--- .../jetty/http2/client/DataDemandTest.java | 18 ++--- .../http2/client/FlowControlStalledTest.java | 15 ++--- .../http2/client/FlowControlStrategyTest.java | 48 +++++++------ .../http2/client/FlowControlWindowsTest.java | 4 +- .../eclipse/jetty/http2/client/HTTP2Test.java | 67 +++++++++---------- .../jetty/http2/client/IdleTimeoutTest.java | 36 +++++----- .../jetty/http2/client/InterleavingTest.java | 8 +-- .../http2/client/MaxPushedStreamsTest.java | 8 +-- .../jetty/http2/client/PrefaceTest.java | 6 +- .../jetty/http2/client/PriorityTest.java | 14 ++-- .../jetty/http2/client/ProxyProtocolTest.java | 7 +- .../eclipse/jetty/http2/client/ProxyTest.java | 5 +- .../http2/client/PushCacheFilterTest.java | 31 +++++---- .../jetty/http2/client/RawHTTP2ProxyTest.java | 8 +-- .../jetty/http2/client/StreamCloseTest.java | 26 +++---- .../jetty/http2/client/StreamCountTest.java | 13 ++-- .../jetty/http2/client/StreamResetTest.java | 36 +++++----- .../jetty/http2/client/TrailersTest.java | 8 +-- .../http2/frames/ContinuationParseTest.java | 7 +- .../frames/HeadersGenerateParseTest.java | 12 ++-- .../frames/PushPromiseGenerateParseTest.java | 12 ++-- .../jetty/http2/hpack/HpackEncoderTest.java | 6 +- .../eclipse/jetty/http2/hpack/HpackTest.java | 16 ++--- .../HttpClientTransportOverHTTP2Test.java | 13 ++-- .../client/http/PushedResourcesTest.java | 4 +- .../client/http/RequestTrailersTest.java | 6 +- .../http2/server/AbstractServerTest.java | 4 +- .../eclipse/jetty/http2/server/CloseTest.java | 12 ++-- .../jetty/http2/server/HTTP2ServerTest.java | 24 +++---- .../rewrite/handler/PatternRuleTest.java | 2 +- .../SpnegoAuthenticatorTest.java | 2 +- 37 files changed, 246 insertions(+), 277 deletions(-) diff --git a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java index 483e8f942035..9869011b4c34 100644 --- a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java @@ -202,7 +202,7 @@ private void respond(Stream stream, MetaData.Request request) // Prepare the response HEADERS frame. // The response HTTP status and HTTP headers. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); if (HttpMethod.GET.is(request.getMethod())) { @@ -295,13 +295,13 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { // Push the favicon. HttpURI pushedURI = HttpURI.build(request.getURI()).path("/favicon.ico").asImmutable(); - MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.build()); + MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.EMPTY); PushPromiseFrame promiseFrame = new PushPromiseFrame(stream.getId(), 0, pushedRequest); stream.push(promiseFrame, new Stream.Listener.Adapter()) .thenCompose(pushedStream -> { // Send the favicon "response". - MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response pushedResponse = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); return pushedStream.headers(new HeadersFrame(pushedStream.getId(), pushedResponse, null, false)) .thenCompose(pushed -> pushed.data(new DataFrame(pushed.getId(), faviconBuffer, true))); }); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java index e80c63349150..1bddc5aba68e 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/generator/ClientGenerator.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; @@ -48,7 +48,7 @@ public ClientGenerator(ByteBufferPool byteBufferPool, boolean useDirectByteBuffe super(byteBufferPool, useDirectByteBuffers); } - public Result generateRequestHeaders(int request, HttpFieldsBuilder fields, Callback callback) + public Result generateRequestHeaders(int request, HttpFields fields, Callback callback) { request &= 0xFF_FF; diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index a5a66335c45b..cf1534a5c057 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -228,7 +228,7 @@ private void notifyHeader(HttpField httpField) } } - private void notifyHeaders(HttpFieldsBuilder fields) + private void notifyHeaders(HttpFields fields) { if (fields != null) { diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java index 672164d78d44..fdbb2588c27a 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java @@ -113,8 +113,8 @@ public boolean onHeaders(int request) public void testParseNoResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Content-Length", "0"); + HttpFields fields = HttpFields.build() + .put("Content-Length", "0"); ByteBufferPool byteBufferPool = new MappedByteBufferPool(); ServerGenerator generator = new ServerGenerator(byteBufferPool); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java index 051aecc576df..9e1a50a36ed5 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncIOTest.java @@ -36,7 +36,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.api.Session; import org.eclipse.jetty.http2.api.Stream; @@ -87,8 +86,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); FuturePromise promise = new FuturePromise<>(); @@ -138,8 +136,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); FuturePromise promise = new FuturePromise<>(); @@ -194,8 +191,7 @@ public void onDataAvailable() throws IOException Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); final CountDownLatch latch = new CountDownLatch(1); FuturePromise promise = new FuturePromise<>(); @@ -267,8 +263,7 @@ public Map onPreface(Session session) } }); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); FuturePromise promise = new FuturePromise<>(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java index 3214fd1e20a8..c1a8856507a3 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/AsyncServletTest.java @@ -35,7 +35,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.ErrorCode; @@ -95,8 +94,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); CountDownLatch latch = new CountDownLatch(1); @@ -132,8 +130,7 @@ public void testStartAsyncThenClientSessionIdleTimeout() throws Exception client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); @@ -169,8 +166,7 @@ public void testStartAsyncThenClientStreamIdleTimeout() throws Exception client.setIdleTimeout(10 * idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch clientLatch = new CountDownLatch(1); @@ -218,8 +214,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) prepareClient(); client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -329,8 +324,7 @@ public void onStartAsync(AsyncEvent event) throws IOException client.start(); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch clientLatch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java index 484ae412832e..195ae1bccb0c 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/DataDemandTest.java @@ -79,7 +79,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.build()); + MetaData.Request post = newRequest("POST", HttpFields.EMPTY); FuturePromise promise = new FuturePromise<>(); Queue clientQueue = new ConcurrentLinkedQueue<>(); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() @@ -177,7 +177,7 @@ public void testOnBeforeData() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -189,7 +189,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.build()); + MetaData.Request post = newRequest("GET", HttpFields.EMPTY); FuturePromise promise = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); CountDownLatch beforeDataLatch = new CountDownLatch(1); @@ -237,7 +237,7 @@ public void testDemandFromOnHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -249,7 +249,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.build()); + MetaData.Request post = newRequest("GET", HttpFields.EMPTY); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -284,7 +284,7 @@ public void testOnBeforeDataDoesNotReenter() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, false), Callback.from(() -> sendData(stream), x -> {})); return null; } @@ -296,7 +296,7 @@ private void sendData(Stream stream) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("GET", HttpFields.build()); + MetaData.Request post = newRequest("GET", HttpFields.EMPTY); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,7 +339,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) stream.demand(1); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -348,7 +348,7 @@ public void onDataDemanded(Stream stream, DataFrame frame, Callback callback) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request post = newRequest("POST", HttpFields.build()); + MetaData.Request post = newRequest("POST", HttpFields.EMPTY); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); client.newStream(new HeadersFrame(post, null, false), promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java index 764be0d435fe..985cbc9198c9 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStalledTest.java @@ -30,7 +30,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -98,7 +97,7 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, String target, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, String target, HttpFields fields) { String host = "localhost"; int port = connector.getLocalPort(); @@ -141,7 +140,7 @@ protected void onStreamUnstalled(IStream stream) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); if (request.getURIString().endsWith("/stall")) { @@ -171,7 +170,7 @@ public void succeeded() CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.build()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.EMPTY); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -189,7 +188,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the first be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.build()); + request = newRequest("GET", "/", HttpFields.EMPTY); client.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); @@ -232,7 +231,7 @@ protected void onSessionUnstalled(ISession session) public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { MetaData.Request request = (MetaData.Request)frame.getMetaData(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); if (request.getURIString().endsWith("/stall")) { @@ -271,7 +270,7 @@ public Map onPreface(Session session) CountDownLatch latch = new CountDownLatch(1); Queue callbacks = new ArrayDeque<>(); - MetaData.Request request = newRequest("GET", "/stall", HttpFields.build()); + MetaData.Request request = newRequest("GET", "/stall", HttpFields.EMPTY); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -289,7 +288,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // does not result in the session be notified again of being stalled. stallLatch.set(new CountDownLatch(1)); - request = newRequest("GET", "/", HttpFields.build()); + request = newRequest("GET", "/", HttpFields.EMPTY); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertFalse(stallLatch.get().await(1, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java index e084678af8fa..4c1867008e84 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlStrategyTest.java @@ -35,7 +35,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -118,7 +117,7 @@ protected Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, HttpFields fields) { String host = "localhost"; int port = connector.getLocalPort(); @@ -193,7 +192,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(FlowControlStrategy.DEFAULT_WINDOW_SIZE, clientSession.getRecvWindow()); assertTrue(prefaceLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.build()); + MetaData.Request request1 = newRequest("GET", HttpFields.EMPTY); FuturePromise promise1 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request1, null, true), promise1, new Stream.Listener.Adapter()); HTTP2Stream clientStream1 = (HTTP2Stream)promise1.get(5, TimeUnit.SECONDS); @@ -217,7 +216,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) settingsLatch.await(5, TimeUnit.SECONDS); // Now create a new stream, it must pick up the new value. - MetaData.Request request2 = newRequest("POST", HttpFields.build()); + MetaData.Request request2 = newRequest("POST", HttpFields.EMPTY); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(new HeadersFrame(request2, null, true), promise2, new Stream.Listener.Adapter()); HTTP2Stream clientStream2 = (HTTP2Stream)promise2.get(5, TimeUnit.SECONDS); @@ -244,8 +243,7 @@ public void testFlowControlWithConcurrentSettings() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); @@ -287,7 +285,7 @@ public void onSettings(Session session, SettingsFrame frame) } }); - MetaData.Request request = newRequest("POST", HttpFields.build()); + MetaData.Request request = newRequest("POST", HttpFields.EMPTY); FuturePromise promise = new FuturePromise<>(); session.newStream(new HeadersFrame(request, null, false), promise, new Stream.Listener.Adapter()); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -328,7 +326,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); stream.headers(responseFrame, Callback.from(completable)); @@ -353,7 +351,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) final CountDownLatch dataLatch = new CountDownLatch(1); final Exchanger exchanger = new Exchanger<>(); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -425,7 +423,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -476,7 +474,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, null); @@ -528,7 +526,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) else { // For every stream, send down half the window size of data. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -547,7 +545,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) // First request is just to consume most of the session window. final List callbacks1 = new ArrayList<>(); final CountDownLatch prepareLatch = new CountDownLatch(1); - MetaData.Request request1 = newRequest("POST", HttpFields.build()); + MetaData.Request request1 = newRequest("POST", HttpFields.EMPTY); session.newStream(new HeadersFrame(request1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -562,7 +560,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(prepareLatch.await(5, TimeUnit.SECONDS)); // Second request will consume half of the remaining the session window. - MetaData.Request request2 = newRequest("GET", HttpFields.build()); + MetaData.Request request2 = newRequest("GET", HttpFields.EMPTY); session.newStream(new HeadersFrame(request2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -574,7 +572,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Third request will consume the whole session window, which is now stalled. // A fourth request will not be able to receive data. - MetaData.Request request3 = newRequest("GET", HttpFields.build()); + MetaData.Request request3 = newRequest("GET", HttpFields.EMPTY); session.newStream(new HeadersFrame(request3, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -586,7 +584,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Fourth request is now stalled. final CountDownLatch latch = new CountDownLatch(1); - MetaData.Request request4 = newRequest("GET", HttpFields.build()); + MetaData.Request request4 = newRequest("GET", HttpFields.EMPTY); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -622,7 +620,7 @@ public void testServerSendsBigContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -636,7 +634,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); final byte[] bytes = new byte[data.length]; final CountDownLatch latch = new CountDownLatch(1); @@ -668,7 +666,7 @@ public void testClientSendingInitialSmallWindow() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -700,7 +698,7 @@ public Map onPreface(Session session) byte[] responseData = new byte[requestData.length]; final ByteBuffer responseContent = ByteBuffer.wrap(responseData); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); final CountDownLatch latch = new CountDownLatch(1); @@ -760,7 +758,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole session and stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); CompletableFuture completable = new CompletableFuture<>(); session.newStream(requestFrame, Promise.from(completable), new Stream.Listener.Adapter()); @@ -844,7 +842,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // Consume the whole stream window. - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); session.newStream(requestFrame, streamPromise, new Stream.Listener.Adapter()); @@ -915,7 +913,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); final CountDownLatch resetLatch = new CountDownLatch(1); @@ -970,7 +968,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Succeed the callbacks when the stream is already remotely closed. callbacks.forEach(Callback::succeeded); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -994,7 +992,7 @@ public void onWindowUpdate(ISession session, IStream stream, WindowUpdateFrame f }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java index 3a87e6a10804..4ebf5b396e92 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/FlowControlWindowsTest.java @@ -113,7 +113,7 @@ public void testClientFlowControlWindows() throws Exception assertEquals(clientSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.EMPTY, -1); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); clientSession.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -163,7 +163,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(serverSessionRecvWindow, sessionRecvWindow); HostPortHttpField hostPort = new HostPortHttpField("localhost:" + connector.getLocalPort()); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), HttpScheme.HTTP.asString(), hostPort, "/", HttpVersion.HTTP_2, HttpFields.EMPTY, -1); HeadersFrame frame = new HeadersFrame(request, null, true); clientSession.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter()); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index 1b1ca8822ced..b7cc35b2edd2 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -84,8 +84,7 @@ public void testRequestNoContentResponseNoContent() throws Exception Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -116,7 +115,7 @@ public void testRequestNoContentResponseEmptyContent() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, false), new Callback() { @Override @@ -131,8 +130,7 @@ public void succeeded() Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -173,8 +171,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(2); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -222,7 +219,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable streamCompletable = new Promise.Completable<>(); session.newStream(frame, streamCompletable, new Stream.Listener.Adapter() @@ -270,9 +267,9 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFieldsBuilder fields = HttpFields.build(); - fields.putLongField(downloadBytes, random.nextInt(128 * 1024)); - fields.put("User-Agent", "HTTP2Client/" + Jetty.VERSION); + HttpFieldsBuilder fields = HttpFields.build() + .putLongField(downloadBytes, random.nextInt(128 * 1024)) + .put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(requests); @@ -307,8 +304,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -339,13 +335,12 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { assertEquals(host, request.getServerName()); assertEquals(port, request.getServerPort()); - // TODO is this needed ? assertEquals(authority, request.getHeader("Host")); } }); Session session = newClient(new Session.Listener.Adapter()); HostPortHttpField hostHeader = new HostPortHttpField(authority); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), hostHeader, servletPath, HttpVersion.HTTP_2, HttpFields.EMPTY, -1); HeadersFrame frame = new HeadersFrame(metaData, null, true); final CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -424,7 +419,7 @@ public Map onPreface(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build(), 0); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY, 0); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -441,7 +436,7 @@ public void onSettings(Session session, SettingsFrame frame) }); assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request1 = newRequest("GET", HttpFields.build()); + MetaData.Request request1 = newRequest("GET", HttpFields.EMPTY); FuturePromise promise1 = new FuturePromise<>(); CountDownLatch exchangeLatch1 = new CountDownLatch(2); session.newStream(new HeadersFrame(request1, null, false), promise1, new Stream.Listener.Adapter() @@ -455,7 +450,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData.Request request2 = newRequest("GET", HttpFields.build()); + MetaData.Request request2 = newRequest("GET", HttpFields.EMPTY); FuturePromise promise2 = new FuturePromise<>(); CountDownLatch exchangeLatch2 = new CountDownLatch(2); session.newStream(new HeadersFrame(request2, null, false), promise2, new Stream.Listener.Adapter() @@ -470,7 +465,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream2 = promise2.get(5, TimeUnit.SECONDS); // The third stream must not be created. - MetaData.Request request3 = newRequest("GET", HttpFields.build()); + MetaData.Request request3 = newRequest("GET", HttpFields.EMPTY); CountDownLatch maxStreamsLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request3, null, false), new Promise.Adapter<>() { @@ -498,7 +493,7 @@ public void succeeded() assertEquals(1, session.getStreams().size()); // Create a fourth stream. - MetaData.Request request4 = newRequest("GET", HttpFields.build()); + MetaData.Request request4 = newRequest("GET", HttpFields.EMPTY); CountDownLatch exchangeLatch4 = new CountDownLatch(2); session.newStream(new HeadersFrame(request4, null, true), new Promise.Adapter<>() { @@ -541,7 +536,7 @@ public void testInvalidAPIUsageOnClient() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { Callback.Completable completable = new Callback.Completable(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, false), completable); return new Stream.Listener.Adapter() { @@ -564,7 +559,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, false); Promise.Completable completable = new Promise.Completable<>(); CountDownLatch completeLatch = new CountDownLatch(2); @@ -636,7 +631,7 @@ public void testInvalidAPIUsageOnServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); DataFrame dataFrame = new DataFrame(stream.getId(), BufferUtil.EMPTY_BUFFER, true); // The call to headers() is legal, but slow. new Thread(() -> @@ -683,7 +678,7 @@ public void failed(Throwable x) Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -707,7 +702,7 @@ public void testCleanGoAwayDoesNotTriggerFailureNotification() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); // Close cleanly. @@ -732,7 +727,7 @@ public void onFailure(Session session, Throwable failure) failureLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame request = new HeadersFrame(metaData, null, true); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter()); @@ -749,7 +744,7 @@ public void testGoAwayRespondedWithGoAway() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, null, Callback.NOOP); @@ -788,7 +783,7 @@ public void onClose(Session session, GoAwayFrame frame) closeLatch.countDown(); } }); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame request = new HeadersFrame(metaData, null, true); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(request, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -812,8 +807,8 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.build(); - requestFields.put(":custom", "special"); + HttpFieldsBuilder requestFields = HttpFields.build() + .put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); @@ -836,7 +831,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -879,7 +874,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Good request with bad header in the response. Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", "/flush", HttpFields.EMPTY); HeadersFrame request = new HeadersFrame(metaData, null, true); FuturePromise promise = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); @@ -926,7 +921,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) dataLatch.countDown(); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } } @@ -950,7 +945,7 @@ public void onClose(Session session, GoAwayFrame frame) // Start 2 requests without completing them yet. CountDownLatch responseLatch = new CountDownLatch(2); - MetaData.Request metaData1 = newRequest("GET", HttpFields.build()); + MetaData.Request metaData1 = newRequest("GET", HttpFields.EMPTY); HeadersFrame request1 = new HeadersFrame(metaData1, null, false); FuturePromise promise1 = new FuturePromise<>(); Stream.Listener.Adapter listener = new Stream.Listener.Adapter() @@ -970,7 +965,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); stream1.data(new DataFrame(stream1.getId(), ByteBuffer.allocate(1), false), Callback.NOOP); - MetaData.Request metaData2 = newRequest("GET", HttpFields.build()); + MetaData.Request metaData2 = newRequest("GET", HttpFields.EMPTY); HeadersFrame request2 = new HeadersFrame(metaData2, null, false); FuturePromise promise2 = new FuturePromise<>(); clientSession.newStream(request2, promise2, listener); @@ -988,7 +983,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // New requests should be immediately rejected. HostPortHttpField authority3 = new HostPortHttpField("localhost" + ":" + port); - MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP.asString(), authority3, servletPath, HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request metaData3 = new MetaData.Request("GET", HttpScheme.HTTP.asString(), authority3, servletPath, HttpVersion.HTTP_2, HttpFields.EMPTY, -1); HeadersFrame request3 = new HeadersFrame(metaData3, null, false); FuturePromise promise3 = new FuturePromise<>(); CountDownLatch resetLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java index 02a4d14a9f58..22c9b3517bc1 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/IdleTimeoutTest.java @@ -76,7 +76,7 @@ public void testServerEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -94,7 +94,7 @@ public void onClose(Session session, GoAwayFrame frame) } }); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -133,7 +133,7 @@ public void onClose(Session session, GoAwayFrame frame) }); // The request is not replied, and the server should idle timeout. - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -161,7 +161,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // to avoid a race where the idle timeout fires // again before we can send the headers to the client. sleep(idleTimeout + idleTimeout / 2); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -180,7 +180,7 @@ public void onClose(Session session, GoAwayFrame frame) }); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -214,7 +214,7 @@ public void testClientEnforcingIdleTimeout() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -229,7 +229,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -266,7 +266,7 @@ public void onClose(Session session, GoAwayFrame frame) client.setIdleTimeout(idleTimeout); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -290,7 +290,7 @@ public void testClientNotEnforcingIdleTimeoutWithinCallback() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -307,7 +307,7 @@ public void onClose(Session session, GoAwayFrame frame) Session session = newClient(new Session.Listener.Adapter()); final CountDownLatch replyLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -350,7 +350,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se final CountDownLatch dataLatch = new CountDownLatch(1); final CountDownLatch timeoutLatch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter() { @@ -411,7 +411,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) final CountDownLatch resetLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); // Stream does not end here, but we won't send any DATA frame. HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -455,7 +455,7 @@ public boolean onIdleTimeout(Stream stream, Throwable x) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -505,7 +505,7 @@ public void testClientStreamIdleTimeoutIsNotEnforcedWhenSending() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -518,7 +518,7 @@ public void onReset(Session session, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise() { @@ -575,7 +575,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) connector.setIdleTimeout(2 * delay); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("POST", HttpFields.build()); + MetaData.Request metaData = newRequest("POST", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, false); FuturePromise promise = new FuturePromise<>(); CountDownLatch latch = new CountDownLatch(1); @@ -641,7 +641,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -655,7 +655,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) // Send one more request to consume the whole session flow control window. CountDownLatch resetLatch = new CountDownLatch(1); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java index 22d9c887fca6..203c7165c766 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/InterleavingTest.java @@ -95,12 +95,12 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }; - HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame headersFrame1 = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); FuturePromise streamPromise1 = new FuturePromise<>(); session.newStream(headersFrame1, streamPromise1, streamListener); streamPromise1.get(5, TimeUnit.SECONDS); - HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame headersFrame2 = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); FuturePromise streamPromise2 = new FuturePromise<>(); session.newStream(headersFrame2, streamPromise2, streamListener); streamPromise2.get(5, TimeUnit.SECONDS); @@ -111,7 +111,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream serverStream1 = serverStreams.get(0); Stream serverStream2 = serverStreams.get(1); - MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response1 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); serverStream1.headers(new HeadersFrame(serverStream1.getId(), response1, null, false), Callback.NOOP); Random random = new Random(); @@ -120,7 +120,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) byte[] content2 = new byte[2 * ((ISession)serverStream2.getSession()).updateSendWindow(0)]; random.nextBytes(content2); - MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response2 = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); serverStream2.headers(new HeadersFrame(serverStream2.getId(), response2, null, false), new Callback() { @Override diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java index 0e0f2df207e5..bd0f38b1ccf9 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/MaxPushedStreamsTest.java @@ -78,7 +78,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) CompletableFuture> result = CompletableFuture.completedFuture(new ArrayList<>()); // Push maxPushed resources... IntStream.range(0, maxPushed) - .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.build()))) + .mapToObj(i -> new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_" + i, HttpFields.EMPTY))) .map(pushFrame -> { Promise.Completable promise = new Promise.Completable<>(); @@ -91,7 +91,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // ... then push one extra stream, the client must reject it... .thenApply(streams -> { - PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.build())); + PushPromiseFrame extraPushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", "/push_extra", HttpFields.EMPTY)); FuturePromise extraPromise = new FuturePromise<>(); stream.push(extraPushFrame, extraPromise, new Stream.Listener.Adapter() { @@ -113,7 +113,7 @@ public void onReset(Stream stream, ResetFrame frame) // ... then send the response. .thenRun(() -> { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); }); return null; @@ -122,7 +122,7 @@ public void onReset(Stream stream, ResetFrame frame) client.setMaxConcurrentPushedStreams(maxPushed); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); CountDownLatch responseLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(request, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java index 83f84fa35fa9..6f50fb13b99b 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PrefaceTest.java @@ -82,7 +82,7 @@ public void onAccept(Session session) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -110,7 +110,7 @@ public Map onPreface(Session session) }); CountDownLatch latch = new CountDownLatch(1); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(metaData, null, true); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -224,7 +224,7 @@ public void onSettings(Session session, SettingsFrame frame) @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java index 637fa6479566..398725a6f143 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PriorityTest.java @@ -48,7 +48,7 @@ public void testPriorityBeforeHeaders() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -60,7 +60,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertTrue(streamId > 0); CountDownLatch latch = new CountDownLatch(2); - MetaData metaData = newRequest("GET", HttpFields.build()); + MetaData metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame headersFrame = new HeadersFrame(streamId, metaData, null, true); session.newStream(headersFrame, new Promise.Adapter() { @@ -96,7 +96,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { beforeRequests.await(5, TimeUnit.SECONDS); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); afterRequests.countDown(); @@ -122,13 +122,13 @@ public void onHeaders(Stream stream, HeadersFrame frame) }; Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData1 = newRequest("GET", "/one", HttpFields.build()); + MetaData metaData1 = newRequest("GET", "/one", HttpFields.EMPTY); HeadersFrame headersFrame1 = new HeadersFrame(metaData1, null, true); FuturePromise promise1 = new FuturePromise<>(); session.newStream(headersFrame1, promise1, listener); Stream stream1 = promise1.get(5, TimeUnit.SECONDS); - MetaData metaData2 = newRequest("GET", "/two", HttpFields.build()); + MetaData metaData2 = newRequest("GET", "/two", HttpFields.EMPTY); HeadersFrame headersFrame2 = new HeadersFrame(metaData2, null, true); FuturePromise promise2 = new FuturePromise<>(); session.newStream(headersFrame2, promise2, listener); @@ -162,7 +162,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) assertEquals(priorityFrame.isExclusive(), priority.isExclusive()); latch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; @@ -170,7 +170,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData metaData = newRequest("GET", "/one", HttpFields.build()); + MetaData metaData = newRequest("GET", "/one", HttpFields.EMPTY); HeadersFrame headersFrame = new HeadersFrame(metaData, priorityFrame, true); session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java index 3183afb3e721..3c2b57f9e2a1 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyProtocolTest.java @@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -120,9 +119,8 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.build(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; - MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -178,9 +176,8 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques client.accept(null, channel, new Session.Listener.Adapter(), promise); Session session = promise.get(5, TimeUnit.SECONDS); - HttpFieldsBuilder fields = HttpFields.build(); String uri = "http://localhost:" + connector.getLocalPort() + "/"; - MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, fields); + MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java index 9e837695e135..f9dbe1da486e 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/ProxyTest.java @@ -32,7 +32,6 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -121,7 +120,7 @@ private Session newClient(Session.Listener listener) throws Exception return promise.get(5, TimeUnit.SECONDS); } - private MetaData.Request newRequest(String method, String path, HttpFieldsBuilder fields) + private MetaData.Request newRequest(String method, String path, HttpFields fields) { String host = "localhost"; int port = proxyConnector.getLocalPort(); @@ -166,7 +165,7 @@ protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletRes final CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request metaData = newRequest("GET", "/", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", "/", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(metaData, null, true); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 00e554ed9a9f..1040aadd00da 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -103,8 +103,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); - MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); + MetaData.Request primaryRequest = newRequest("GET", primaryResource, HttpFields.EMPTY); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -115,8 +114,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); - secondaryFields.put(HttpHeader.REFERER, referrerURI); + HttpFieldsBuilder secondaryFields = HttpFields.build() + .put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -133,7 +132,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(warmupLatch.await(5, TimeUnit.SECONDS)); // Request again the primary resource, we should get the secondary resource pushed. - primaryRequest = newRequest("GET", primaryResource, primaryFields); + primaryRequest = newRequest("GET", primaryResource, HttpFields.EMPTY); final CountDownLatch primaryResponseLatch = new CountDownLatch(2); final CountDownLatch pushLatch = new CountDownLatch(2); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -219,8 +218,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); - secondaryFields.put(HttpHeader.REFERER, referrerURI); + HttpFieldsBuilder secondaryFields = HttpFields.build() + .put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -305,8 +304,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); - secondaryFields.put(HttpHeader.REFERER, primaryURI); + HttpFieldsBuilder secondaryFields = HttpFields.build() + .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -500,8 +499,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Request for the secondary resources. String secondaryURI1 = newURI(secondaryResource1); - HttpFieldsBuilder secondaryFields1 = HttpFields.build(); - secondaryFields1.put(HttpHeader.REFERER, primaryURI); + HttpFieldsBuilder secondaryFields1 = HttpFields.build() + .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest1 = newRequest("GET", secondaryResource1, secondaryFields1); session.newStream(new HeadersFrame(secondaryRequest1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -512,8 +511,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the tertiary resource. - HttpFieldsBuilder tertiaryFields = HttpFields.build(); - tertiaryFields.put(HttpHeader.REFERER, secondaryURI1); + HttpFieldsBuilder tertiaryFields = HttpFields.build() + .put(HttpHeader.REFERER, secondaryURI1); MetaData.Request tertiaryRequest = newRequest("GET", tertiaryResource, tertiaryFields); session.newStream(new HeadersFrame(tertiaryRequest, null, true), new Promise.Adapter<>(), new Adapter() { @@ -529,8 +528,8 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); - HttpFieldsBuilder secondaryFields2 = HttpFields.build(); - secondaryFields2.put(HttpHeader.REFERER, primaryURI); + HttpFieldsBuilder secondaryFields2 = HttpFields.build() + .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest2 = newRequest("GET", secondaryResource2, secondaryFields2); session.newStream(new HeadersFrame(secondaryRequest2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -605,7 +604,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) // Make sure that explicitly requesting a secondary resource, we get the tertiary pushed. CountDownLatch secondaryResponseLatch = new CountDownLatch(1); CountDownLatch secondaryPushLatch = new CountDownLatch(1); - MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.build()); + MetaData.Request secondaryRequest = newRequest("GET", secondaryResource1, HttpFields.EMPTY); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java index 065f76a4092a..7394d67cff74 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java @@ -132,7 +132,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) LOGGER.debug("SERVER1 received {}", frame); if (frame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER1 sending {}", reply); @@ -168,7 +168,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 received {}", frame); callback.succeeded(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); Callback.Completable completable1 = new Callback.Completable(); HeadersFrame reply = new HeadersFrame(stream.getId(), response, null, false); if (LOGGER.isDebugEnabled()) @@ -184,7 +184,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) return completable2; }).thenRun(() -> { - MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.build()); + MetaData trailer = new MetaData(HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame end = new HeadersFrame(stream.getId(), trailer, null, true); if (LOGGER.isDebugEnabled()) LOGGER.debug("SERVER2 sending {}", end); @@ -231,7 +231,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); Stream stream1 = streamPromise1.get(5, TimeUnit.SECONDS); - stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.build()), null, true), Callback.NOOP); + stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.EMPTY), null, true), Callback.NOOP); // Send a request for server2. HttpFieldsBuilder fields2 = HttpFields.build(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java index fdeb4fbaeac6..1b0423db1f3c 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCloseTest.java @@ -65,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, null); Stream stream = promise.get(5, TimeUnit.SECONDS); @@ -82,7 +82,7 @@ public void testRequestClosedResponseClosedClosesStream() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(response, new Callback() { @@ -99,7 +99,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -124,7 +124,7 @@ public void testRequestDataClosedResponseDataClosedClosesStream() throws Excepti @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame response = new HeadersFrame(stream.getId(), metaData, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(response, completable); @@ -153,7 +153,7 @@ public void succeeded() final CountDownLatch completeLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, false); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(frame, promise, new Stream.Listener.Adapter() { @@ -196,7 +196,7 @@ public void testPushedStreamIsClosed() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.build())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.EMPTY)); stream.push(pushFrame, new Promise.Adapter() { @Override @@ -216,14 +216,14 @@ public void succeeded() }); } }, new Stream.Listener.Adapter()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY), null, true); stream.headers(response, Callback.NOOP); return null; } }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); final CountDownLatch clientLatch = new CountDownLatch(1); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -257,7 +257,7 @@ public void testPushedStreamResetIsClosed() throws Exception @Override public Stream.Listener onNewStream(final Stream stream, HeadersFrame frame) { - PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.build())); + PushPromiseFrame pushFrame = new PushPromiseFrame(stream.getId(), 0, newRequest("GET", HttpFields.EMPTY)); stream.push(pushFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @Override @@ -265,7 +265,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) { assertTrue(pushedStream.isReset()); assertTrue(pushedStream.isClosed()); - HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()), null, true); + HeadersFrame response = new HeadersFrame(stream.getId(), new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY), null, true); stream.headers(response, Callback.NOOP); serverLatch.countDown(); } @@ -275,7 +275,7 @@ public void onReset(Stream pushedStream, ResetFrame frame) }); Session session = newClient(new Session.Listener.Adapter()); - HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame frame = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); final CountDownLatch clientLatch = new CountDownLatch(2); session.newStream(frame, new Promise.Adapter<>(), new Stream.Listener.Adapter() { @@ -339,11 +339,11 @@ public void onFailure(Session session, Throwable failure) Session session = newClient(new Session.Listener.Adapter()); // First stream will be idle on server. - HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.build()), null, true); + HeadersFrame request1 = new HeadersFrame(newRequest("HEAD", HttpFields.EMPTY), null, true); session.newStream(request1, new Promise.Adapter<>(), new Stream.Listener.Adapter()); // Second stream will fail on server. - HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.build()), null, true); + HeadersFrame request2 = new HeadersFrame(newRequest("GET", HttpFields.EMPTY), null, true); session.newStream(request2, new Promise.Adapter<>(), new Stream.Listener.Adapter()); assertTrue(latch.await(5, TimeUnit.SECONDS)); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java index aed40e923547..08a24cf2bf41 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamCountTest.java @@ -27,7 +27,6 @@ import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.http2.HTTP2Session; @@ -74,8 +73,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } else @@ -99,8 +97,7 @@ public void onSettings(Session session, SettingsFrame frame) assertTrue(settingsLatch.await(5, TimeUnit.SECONDS)); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); @@ -144,8 +141,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { if (frame.isEndStream()) { - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, fields); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), metaData, null, true), callback); } else @@ -167,8 +163,7 @@ public void onReset(Session session, ResetFrame frame) } }); - HttpFieldsBuilder fields = HttpFields.build(); - MetaData.Request metaData = newRequest("GET", fields); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame1 = new HeadersFrame(metaData, null, false); FuturePromise streamPromise1 = new FuturePromise<>(); CountDownLatch responseLatch = new CountDownLatch(1); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java index 7e6b66be1395..2ac6077a9888 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/StreamResetTest.java @@ -104,7 +104,7 @@ public void testStreamSendingResetIsRemoved() throws Exception start(new ServerSessionListener.Adapter()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -142,7 +142,7 @@ public void onReset(Stream stream, ResetFrame frame) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -170,7 +170,7 @@ public void testStreamResetDoesNotCloseConnection() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame requestFrame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); Callback.Completable completable = new Callback.Completable(); stream.headers(responseFrame, completable); @@ -210,7 +210,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request1 = newRequest("GET", HttpFields.build()); + MetaData.Request request1 = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame1 = new HeadersFrame(request1, null, false); FuturePromise promise1 = new FuturePromise<>(); final CountDownLatch stream1HeadersLatch = new CountDownLatch(1); @@ -233,7 +233,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Stream stream1 = promise1.get(5, TimeUnit.SECONDS); assertTrue(stream1HeadersLatch.await(5, TimeUnit.SECONDS)); - MetaData.Request request2 = newRequest("GET", HttpFields.build()); + MetaData.Request request2 = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame2 = new HeadersFrame(request2, null, false); FuturePromise promise2 = new FuturePromise<>(); final CountDownLatch stream2DataLatch = new CountDownLatch(1); @@ -317,7 +317,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -404,7 +404,7 @@ public void failed(Throwable x) }); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); client.newStream(frame, new FuturePromise<>(), new Stream.Listener.Adapter() { @@ -434,7 +434,7 @@ public void testClientResetConsumesQueuedData() throws Exception start(new EmptyHttpServlet()); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -501,7 +501,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { phaser.set(new CountDownLatch(1)); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -532,7 +532,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } // Send one more request to consume the whole session flow control window, then reset it. - MetaData.Request request = newRequest("GET", "/x", HttpFields.build()); + MetaData.Request request = newRequest("GET", "/x", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); // This request will get no event from the server since it's reset by the client. @@ -585,7 +585,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -648,7 +648,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -697,7 +697,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -774,7 +774,7 @@ public void onError(Throwable t) AtomicLong received = new AtomicLong(); CountDownLatch latch = new CountDownLatch(1); Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, true); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter() @@ -830,7 +830,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session client = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame frame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); client.newStream(frame, promise, new Stream.Listener.Adapter()); @@ -907,7 +907,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = HttpURI.from("http", host, port, servletPath); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY); int streamId = 3; HeadersFrame headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); @@ -1010,7 +1010,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) generator.control(lease, new WindowUpdateFrame(0, Integer.MAX_VALUE - FlowControlStrategy.DEFAULT_WINDOW_SIZE)); HttpURI uri = HttpURI.from("http", host, port, servletPath + "/1"); - MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); + MetaData.Request request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY); HeadersFrame headersFrame = new HeadersFrame(3, request, null, true); generator.control(lease, headersFrame); @@ -1021,7 +1021,7 @@ private void service2(HttpServletRequest request, HttpServletResponse response) // Send a second request. uri = HttpURI.from("http", host, port, servletPath + "/2"); - request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.build()); + request = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, HttpFields.EMPTY); int streamId = 5; headersFrame = new HeadersFrame(streamId, request, null, true); generator.control(lease, headersFrame); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index 9f278a32e96e..bfec3429992d 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -208,7 +208,7 @@ public void succeeded() }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); session.newStream(requestFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -263,7 +263,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) }); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("GET", HttpFields.build()); + MetaData.Request request = newRequest("GET", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, true); CountDownLatch latch = new CountDownLatch(1); List frames = new ArrayList<>(); @@ -305,7 +305,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception start(new EmptyHttpServlet()); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.build()); + MetaData.Request request = newRequest("POST", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter()); @@ -356,7 +356,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) CountDownLatch clientLatch = new CountDownLatch(1); Session session = newClient(new Session.Listener.Adapter()); - MetaData.Request request = newRequest("POST", HttpFields.build()); + MetaData.Request request = newRequest("POST", HttpFields.EMPTY); HeadersFrame requestFrame = new HeadersFrame(request, null, false); FuturePromise promise = new FuturePromise<>(); session.newStream(requestFrame, promise, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java index 70c5c405d80b..7a45290e17b5 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/ContinuationParseTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -72,9 +71,9 @@ public void onConnectionFailure(int error, String reason) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Accept", "text/html"); - fields.put("User-Agent", "Jetty"); + HttpFields fields = HttpFields.build() + .put("Accept", "text/html") + .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java index e757574604e6..02bc966b2adb 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java @@ -52,9 +52,9 @@ public void testGenerateParse() throws Exception HeadersGenerator generator = new HeadersGenerator(new HeaderGenerator(), new HpackEncoder()); int streamId = 13; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Accept", "text/html"); - fields.put("User-Agent", "Jetty"); + HttpFields fields = HttpFields.build() + .put("Accept", "text/html") + .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); final List frames = new ArrayList<>(); @@ -125,9 +125,9 @@ public void onHeaders(HeadersFrame frame) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Accept", "text/html"); - fields.put("User-Agent", "Jetty"); + HttpFieldsBuilder fields = HttpFields.build() + .put("Accept", "text/html") + .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java index 9213c7f21fe3..9e571b933eee 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java @@ -63,9 +63,9 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Accept", "text/html"); - fields.put("User-Agent", "Jetty"); + HttpFieldsBuilder fields = HttpFields.build() + .put("Accept", "text/html") + .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); // Iterate a few times to be sure generator and parser are properly reset. @@ -116,9 +116,9 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.build(); - fields.put("Accept", "text/html"); - fields.put("User-Agent", "Jetty"); + HttpFieldsBuilder fields = HttpFields.build() + .put("Accept", "text/html") + .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); // Iterate a few times to be sure generator and parser are properly reset. diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java index ad3eb3641202..a56e31b63b89 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java @@ -245,9 +245,9 @@ public void testFieldLargerThanTable() throws Exception @Test public void testResize() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); - fields.add("host", "localhost0"); - fields.add("cookie", "abcdefghij"); + HttpFields fields = HttpFields.build() + .add("host", "localhost0") + .add("cookie", "abcdefghij"); HpackEncoder encoder = new HpackEncoder(4096); diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java index 2bce2880e2db..78daa873bac5 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java @@ -108,7 +108,7 @@ public void encodeDecodeTooLargeTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 164); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.build() + HttpFields fields0 = HttpFields.build() .add("1234567890", "1234567890123456789012345678901234567890") .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); @@ -120,7 +120,7 @@ public void encodeDecodeTooLargeTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFieldsBuilder fields1 = HttpFields.build() + HttpFields fields1 = HttpFields.build() .add("1234567890", "1234567890123456789012345678901234567890") .add("Cookie", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR") .add("x", "y"); @@ -147,7 +147,7 @@ public void encodeDecodeNonAscii() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocate(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.build() + HttpFields fields0 = HttpFields.build() // @checkstyle-disable-check : AvoidEscapedUnicodeCharactersCheck .add("Cookie", "[\uD842\uDF9F]") .add("custom-key", "[\uD842\uDF9F]"); @@ -170,7 +170,7 @@ public void evictReferencedFieldTest() throws Exception String longEnoughToBeEvicted = "012345678901234567890123456789012345678901234567890"; - HttpFieldsBuilder fields0 = HttpFields.build() + HttpFields fields0 = HttpFields.build() .add(longEnoughToBeEvicted, "value") .add("foo", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); MetaData original0 = new MetaData(HttpVersion.HTTP_2, fields0); @@ -187,7 +187,7 @@ public void evictReferencedFieldTest() throws Exception assertMetaDataSame(original0, decoded0); - HttpFieldsBuilder fields1 = HttpFields.build() + HttpFields fields1 = HttpFields.build() .add(longEnoughToBeEvicted, "other_value") .add("x", "y"); MetaData original1 = new MetaData(HttpVersion.HTTP_2, fields1); @@ -210,7 +210,7 @@ public void testHopHeadersAreRemoved() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFieldsBuilder input = HttpFields.build() + HttpFields input = HttpFields.build() .add(HttpHeader.ACCEPT, "*") .add(HttpHeader.CONNECTION, "TE, Upgrade, Custom") .add("Custom", "Pizza") @@ -239,7 +239,7 @@ public void testTETrailers() throws Exception String teValue = "trailers"; String trailerValue = "Custom"; - HttpFieldsBuilder input = HttpFields.build() + HttpFields input = HttpFields.build() .add(HttpHeader.CONNECTION, "TE") .add(HttpHeader.TE, teValue) .add(HttpHeader.TRAILER, trailerValue); @@ -262,7 +262,7 @@ public void testColonHeaders() throws Exception HpackEncoder encoder = new HpackEncoder(); HpackDecoder decoder = new HpackDecoder(4096, 16384); - HttpFieldsBuilder input = HttpFields.build() + HttpFields input = HttpFields.build() .add(":status", "200") .add(":custom", "special"); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java index f1ca05758b47..43ab806d6226 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/HttpClientTransportOverHTTP2Test.java @@ -46,7 +46,6 @@ import org.eclipse.jetty.client.Origin; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -156,7 +155,7 @@ public void testResponseAbortSendsResetFrame() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), metaData, null, false), new Callback() { @Override @@ -233,7 +232,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) } else { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } return null; @@ -490,7 +489,7 @@ public void onHeaders(HeadersFrame request) try { // Response. - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame response = new HeadersFrame(request.getStreamId(), metaData, null, true); generator.control(lease, response); writeFrames(); @@ -564,7 +563,7 @@ public void test204WithContent() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { int streamId = stream.getId(); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.NO_CONTENT_204, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(streamId, response, null, false); Callback.Completable callback = new Callback.Completable(); stream.headers(responseFrame, callback); @@ -593,8 +592,8 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) // Disable checks for invalid headers. ((HTTP2Session)stream.getSession()).getGenerator().setValidateHpackEncoding(false); // Produce an invalid HPACK block by adding a request pseudo-header to the response. - HttpFieldsBuilder fields = HttpFields.build(); - fields.put(":method", "get"); + HttpFields fields = HttpFields.build() + .put(":method", "get"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, fields, 0); int streamId = stream.getId(); HeadersFrame responseFrame = new HeadersFrame(streamId, response, null, false); diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java index 3e43015be6d9..d5bd31e27265 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/PushedResourcesTest.java @@ -63,14 +63,14 @@ public void testPushedResourceCancelled() throws Exception public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { HttpURI pushURI = HttpURI.from("http://localhost:" + connector.getLocalPort() + pushPath); - MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.build()); + MetaData.Request pushRequest = new MetaData.Request(HttpMethod.GET.asString(), pushURI, HttpVersion.HTTP_2, HttpFields.EMPTY); stream.push(new PushPromiseFrame(stream.getId(), 0, pushRequest), new Promise.Adapter<>() { @Override public void succeeded(Stream pushStream) { // Just send the normal response and wait for the reset. - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); } }, new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java index 8640a4136ade..3b0b118ea083 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java @@ -65,7 +65,7 @@ private void testEmptyTrailers(String content) throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); return new Stream.Listener.Adapter() @@ -110,7 +110,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } @@ -159,7 +159,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) // trailers, but instead a DATA frame with endStream=true. if (dataFrame.isEndStream()) { - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true); stream.headers(responseFrame, Callback.NOOP); } diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java index 27fec624cfe7..a1f464fc5ed6 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/AbstractServerTest.java @@ -26,7 +26,7 @@ import javax.servlet.http.HttpServlet; import org.eclipse.jetty.http.HostPortHttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -78,7 +78,7 @@ private void prepareServer(ConnectionFactory connectionFactory) generator = new Generator(byteBufferPool); } - protected MetaData.Request newRequest(String method, HttpFieldsBuilder fields) + protected MetaData.Request newRequest(String method, HttpFields fields) { String host = "localhost"; int port = connector.getLocalPort(); diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java index 006e602d67f7..4b740038d3c6 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/CloseTest.java @@ -65,7 +65,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) try { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); // Reply with HEADERS. stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); closeLatch.await(5, TimeUnit.SECONDS); @@ -81,7 +81,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -133,7 +133,7 @@ public void testClientSendsGoAwayButDoesNotCloseConnectionServerCloses() throws public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); return null; } @@ -142,7 +142,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); generator.control(lease, new GoAwayFrame(1, ErrorCode.NO_ERROR.code, "OK".getBytes("UTF-8"))); @@ -198,7 +198,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { stream.setIdleTimeout(10 * idleTimeout); sessionRef.set(stream.getSession()); - MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); stream.headers(new HeadersFrame(stream.getId(), response, null, true), Callback.NOOP); stream.getSession().close(ErrorCode.NO_ERROR.code, "OK", Callback.NOOP); return null; @@ -209,7 +209,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java index fc2e8dcc4b09..3d67bed20477 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2ServerTest.java @@ -82,7 +82,7 @@ public void testNoPrefaceBytes() throws Exception startServer(new HttpServlet() {}); // No preface bytes. - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new HeadersFrame(1, metaData, null, true)); @@ -127,7 +127,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -185,7 +185,7 @@ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -361,7 +361,7 @@ public void write(Callback callback, ByteBuffer... buffers) throws IllegalStateE ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector2.getLocalPort())) { @@ -399,7 +399,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) @@ -428,7 +428,7 @@ public void testRequestWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); return lease; }); @@ -443,7 +443,7 @@ public void testRequestWithPriorityWithContinuationFrames() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); return lease; }); @@ -457,7 +457,7 @@ public void testRequestWithContinuationFramesWithEmptyHeadersFrame() throws Exce ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the HeadersFrame header and set the length to zero. List buffers = lease.getByteBuffers(); @@ -479,7 +479,7 @@ public void testRequestWithPriorityWithContinuationFramesWithEmptyHeadersFrame() ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, priority, true)); // Take the HeadersFrame header and set the length to just the priority frame. List buffers = lease.getByteBuffers(); @@ -500,7 +500,7 @@ public void testRequestWithContinuationFramesWithEmptyContinuationFrame() throws ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the ContinuationFrame header, duplicate it, and set the length to zero. List buffers = lease.getByteBuffers(); @@ -524,7 +524,7 @@ public void testRequestWithContinuationFramesWithEmptyLastContinuationFrame() th ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = newRequest("GET", HttpFields.build()); + MetaData.Request metaData = newRequest("GET", HttpFields.EMPTY); generator.control(lease, new HeadersFrame(1, metaData, null, true)); // Take the last CONTINUATION frame and reset the flag. List buffers = lease.getByteBuffers(); @@ -562,7 +562,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) serverLatch.countDown(); - MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.build()); + MetaData.Response metaData = new MetaData.Response(HttpVersion.HTTP_2, 200, HttpFields.EMPTY); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), metaData, null, true); stream.headers(responseFrame, Callback.NOOP); return null; diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java index 7b9cd51f5a72..13c201cc03b0 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/PatternRuleTest.java @@ -141,7 +141,7 @@ private void assertMatch(boolean flag, String[] matchCase) throws IOException new Request(null, null) { { - setMetaData(new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_1_0, HttpFields.build())); + setMetaData(new MetaData.Request("GET", HttpURI.from(uri), HttpVersion.HTTP_1_0, HttpFields.EMPTY)); } }, null ); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java index a1eb0ebc807f..ac20c661ac95 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java @@ -77,7 +77,7 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, HttpFields.build()); + MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, HttpFields.EMPTY); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); From a2d05a17214cccc1aa88fb9b685ee1f068bc9267 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 20 Apr 2020 19:33:33 +0200 Subject: [PATCH 21/38] Immutable MetaData WIP Cleanups, use immutable Signed-off-by: Greg Wilkins --- .../eclipse/jetty/client/util/MultiPartContentProvider.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java index 783a36961482..8f40c1217ad0 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartContentProvider.java @@ -35,7 +35,6 @@ import org.eclipse.jetty.client.api.ContentProvider; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.util.Callback; @@ -130,7 +129,7 @@ private static String makeBoundary() * @param content the part content * @param fields the headers associated with this part */ - public void addFieldPart(String name, ContentProvider content, HttpFieldsBuilder fields) + public void addFieldPart(String name, ContentProvider content, HttpFields fields) { addPart(new Part(name, null, "text/plain", content, fields)); } @@ -151,7 +150,7 @@ public void addFieldPart(String name, ContentProvider content, HttpFieldsBuilder * @param content the part content * @param fields the headers associated with this part */ - public void addFilePart(String name, String fileName, ContentProvider content, HttpFieldsBuilder fields) + public void addFilePart(String name, String fileName, ContentProvider content, HttpFields fields) { addPart(new Part(name, fileName, "application/octet-stream", content, fields)); } From f6387a0ec329564d0d07997337600e92d4ca9247 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2020 12:43:13 +0200 Subject: [PATCH 22/38] Immutable MetaData WIP No trailers for connect Signed-off-by: Greg Wilkins --- .../main/java/org/eclipse/jetty/http/MetaData.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index aabd48bbb9a8..5fd5a581fb74 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -42,18 +42,18 @@ public MetaData(HttpVersion version, HttpFields fields, long contentLength) this(version, fields, contentLength, SELF_SUPPLIED_TRAILORS); } - public MetaData(HttpVersion version, HttpFields fields, long contentLength, Supplier trailers) + public MetaData(HttpVersion version, HttpFields fields, long contentLength, Supplier trailerSupplier) { _httpVersion = version; _fields = fields == null ? null : fields.asImmutable(); _contentLength = contentLength >= 0 ? contentLength : _fields == null ? -1 : _fields.getLongField(HttpHeader.CONTENT_LENGTH); - if (trailers == SELF_SUPPLIED_TRAILORS) + if (trailerSupplier == SELF_SUPPLIED_TRAILORS) _trailerSupplier = () -> _trailers; else { - _trailerSupplier = trailers; - if (trailers != null) + _trailerSupplier = trailerSupplier; + if (trailerSupplier != null) _trailers = SUPPLIED_TRAILERS; } } @@ -222,7 +222,9 @@ public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String pat public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { - super(HttpMethod.CONNECT.asString(), scheme, authority, path, HttpVersion.HTTP_2, fields, Long.MIN_VALUE); + super(HttpMethod.CONNECT.asString(), + HttpURI.build().scheme(scheme).host(authority == null ? null : authority.getHost()).port(authority == null ? -1 : authority.getPort()).pathQuery(path), + HttpVersion.HTTP_2, fields, Long.MIN_VALUE, null); _protocol = protocol; } From d1b62c71753f13ab8f6fad0860d478d8f7781d7b Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2020 13:26:20 +0200 Subject: [PATCH 23/38] Immutable MetaData WIP Fix CONNECT path handling Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/http/MetaData.java | 1 + .../jetty/http2/client/http/HttpSenderOverHTTP2.java | 1 + .../eclipse/jetty/http2/server/HttpChannelOverHTTP2.java | 2 ++ .../src/main/java/org/eclipse/jetty/server/Request.java | 7 +++---- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 5fd5a581fb74..eb86992b1013 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -222,6 +222,7 @@ public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String pat public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { + // TODO should connect requests have paths? super(HttpMethod.CONNECT.asString(), HttpURI.build().scheme(scheme).host(authority == null ? null : authority.getHost()).port(authority == null ? -1 : authority.getPort()).pathQuery(path), HttpVersion.HTTP_2, fields, Long.MIN_VALUE, null); diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java index f51739514410..e62973e55c6a 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java @@ -65,6 +65,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool if (isTunnel) { // TODO what to do with trailers ?? + // TODO should connect requests have paths??? String upgradeProtocol = request.getUpgradeProtocol(); if (upgradeProtocol == null) { diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java index dbd24b4f127e..47bd11ef7d2b 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java @@ -150,6 +150,8 @@ public Runnable onRequest(HeadersFrame frame) } catch (BadMessageException x) { + if (LOG.isDebugEnabled()) + LOG.debug("onRequest", x); onBadMessage(x); return null; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 4d469017a687..6e0a9f5227af 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1702,15 +1702,14 @@ public void setMetaData(MetaData.Request request) builder.host(findServerName()).port(findServerPort()); } } - - _uri = builder.asImmutable(); } - String encoded = uri.getPath(); + String encoded = _uri.getPath(); String path; if (encoded == null) - path = uri.isAbsolute() ? "/" : null; + // TODO this is not really right for CONNECT + path = _uri.isAbsolute() ? "/" : null; else if (encoded.startsWith("/")) path = (encoded.length() == 1) ? "/" : URIUtil.canonicalPath(URIUtil.decodePath(encoded)); else if ("*".equals(encoded) || HttpMethod.CONNECT.is(getMethod())) From 79c453b171168f50e787ec079373e84655b8003d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2020 15:29:18 +0200 Subject: [PATCH 24/38] Immutable MetaData WIP fixed rewrite query handling Signed-off-by: Greg Wilkins --- .../jetty/rewrite/handler/RuleContainer.java | 3 +- .../handler/CookiePatternRuleTest.java | 35 +++++++++++++++++++ .../java/org/eclipse/jetty/server/Server.java | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java index c756c45222cb..860eb0a05cf8 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java @@ -189,7 +189,8 @@ protected String apply(String target, HttpServletRequest request, HttpServletRes { HttpURI baseUri = baseRequest.getHttpURI(); baseRequest.setHttpURI(HttpURI.build(baseUri,encoded) - .param(baseUri.getParam())); + .param(baseUri.getParam()) + .query(baseUri.getQuery())); } } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java index 9fd364b8627c..8e0f50eeb035 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/CookiePatternRuleTest.java @@ -72,6 +72,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques out.printf("baseRequest.requestUri=%s%n", baseRequest.getRequestURI()); out.printf("baseRequest.originalUri=%s%n", baseRequest.getOriginalURI()); out.printf("request.requestUri=%s%n", request.getRequestURI()); + out.printf("request.queryString=%s%n", request.getQueryString()); baseRequest.setHandled(true); } }; @@ -143,6 +144,40 @@ public void testSetAlready() throws Exception assertThat("response should not have Set-Cookie", response.getField(HttpHeader.SET_COOKIE), nullValue()); } + @Test + public void testUrlQuery() throws Exception + { + CookiePatternRule rule = new CookiePatternRule(); + rule.setPattern("*"); + rule.setName("fruit"); + rule.setValue("banana"); + + startServer(rule); + + StringBuilder rawRequest = new StringBuilder(); + rawRequest.append("GET /other?fruit=apple HTTP/1.1\r\n"); + rawRequest.append("Host: local\r\n"); + rawRequest.append("Connection: close\r\n"); + rawRequest.append("\r\n"); + + String rawResponse = localConnector.getResponse(rawRequest.toString()); + HttpTester.Response response = HttpTester.parseResponse(rawResponse); + + String responseContent = response.getContent(); + assertResponseContentLine(responseContent, "baseRequest.requestUri=", "/other"); + assertResponseContentLine(responseContent, "request.queryString=", "fruit=apple"); + + // verify + HttpField setCookieField = response.getField(HttpHeader.SET_COOKIE); + assertThat("response should have Set-Cookie", setCookieField, notNullValue()); + for (String value : setCookieField.getValues()) + { + String[] result = value.split("="); + assertThat(result[0], is("fruit")); + assertThat(result[1], is("banana")); + } + } + @Test public void testUrlParameter() throws Exception { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 11b9d0a1b672..e175561c304c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -528,7 +528,7 @@ public void handle(HttpChannel channel) throws IOException, ServletException final Response response = channel.getResponse(); if (LOG.isDebugEnabled()) - LOG.debug("{} {} {} on {}", request.getDispatcherType(), request.getMethod(), target, channel); + LOG.debug("{} {} {} ?{} on {}", request.getDispatcherType(), request.getMethod(), target, request.getQueryString(), channel); if (HttpMethod.OPTIONS.is(request.getMethod()) || "*".equals(target)) { From 8943b9b80618ea0e5a6ed7d05b7eecb2a6b188af Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2020 17:14:51 +0200 Subject: [PATCH 25/38] Immutable MetaData WIP rename Builders to Muttables Signed-off-by: Greg Wilkins --- .../alpn/java/client/JDK9HTTP2ClientTest.java | 3 +- .../org/eclipse/jetty/client/HttpRequest.java | 5 +- .../eclipse/jetty/client/HttpResponse.java | 9 +- .../client/util/MultiPartRequestContent.java | 5 +- .../client/util/MultiPartContentTest.java | 7 +- .../src/main/java/embedded/HTTP2Docs.java | 3 +- .../client/http2/HTTP2ClientDocs.java | 7 +- .../http/HttpClientTransportOverFCGI.java | 4 +- .../fcgi/client/http/HttpSenderOverFCGI.java | 5 +- .../fcgi/parser/ResponseContentParser.java | 3 +- .../fcgi/generator/ClientGeneratorTest.java | 3 +- .../jetty/fcgi/parser/ClientParserTest.java | 7 +- .../fcgi/server/HttpChannelOverFCGI.java | 3 +- .../server/proxy/FastCGIProxyServlet.java | 6 +- .../org/eclipse/jetty/http/HttpFields.java | 638 +++++++++++++++++- .../eclipse/jetty/http/HttpFieldsBuilder.java | 629 ----------------- .../org/eclipse/jetty/http/HttpGenerator.java | 2 +- .../org/eclipse/jetty/http/HttpParser.java | 2 +- .../java/org/eclipse/jetty/http/HttpURI.java | 295 ++++---- .../eclipse/jetty/http/HttpFieldsTest.java | 76 +-- .../jetty/http/HttpGeneratorClientTest.java | 14 +- .../http/HttpGeneratorServerHTTPTest.java | 4 +- .../jetty/http/HttpGeneratorServerTest.java | 42 +- .../org/eclipse/jetty/http/HttpURITest.java | 6 +- .../eclipse/jetty/http2/client/HTTP2Test.java | 5 +- .../http2/client/PushCacheFilterTest.java | 41 +- .../jetty/http2/client/RawHTTP2ProxyTest.java | 5 +- .../jetty/http2/client/TrailersTest.java | 19 +- .../frames/HeadersGenerateParseTest.java | 3 +- .../frames/PushPromiseGenerateParseTest.java | 5 +- .../jetty/http2/hpack/MetaDataBuilder.java | 5 +- .../jetty/http2/hpack/HpackEncoderTest.java | 7 +- .../jetty/http2/hpack/HpackPerfTest.java | 3 +- .../eclipse/jetty/http2/hpack/HpackTest.java | 5 +- .../client/http/RequestTrailersTest.java | 7 +- .../server/HTTP2CServerConnectionFactory.java | 4 +- .../http2/server/HTTP2ServerConnection.java | 4 +- .../http2/server/HttpChannelOverHTTP2.java | 3 +- .../jetty/proxy/AbstractProxyServlet.java | 3 +- .../rewrite/handler/MsieSslRuleTest.java | 9 +- .../jetty/server/ConnectionFactory.java | 4 +- .../server/ForwardedRequestCustomizer.java | 2 +- .../org/eclipse/jetty/server/HttpChannel.java | 5 +- .../jetty/server/HttpChannelOverHttp.java | 11 +- .../eclipse/jetty/server/PushBuilderImpl.java | 3 +- .../org/eclipse/jetty/server/Request.java | 5 +- .../eclipse/jetty/server/ResourceService.java | 4 +- .../org/eclipse/jetty/server/Response.java | 7 +- .../java/org/eclipse/jetty/server/Server.java | 2 +- .../jetty/server/handler/ContextHandler.java | 2 +- .../jetty/server/handler/ErrorHandler.java | 6 +- .../server/handler/gzip/GzipHandler.java | 3 +- .../gzip/GzipHttpOutputInterceptor.java | 4 +- .../jetty/server/PartialRFC2616Test.java | 3 +- .../eclipse/jetty/server/ResponseTest.java | 2 +- .../core/client/ClientUpgradeRequest.java | 6 +- .../server/internal/RFC6455Handshaker.java | 4 +- .../core/WebSocketNegotiationTest.java | 8 +- .../jetty/websocket/core/WebSocketTester.java | 5 +- .../PerMessageDeflaterBufferSizeTest.java | 18 +- .../client/internal/JsrUpgradeListener.java | 3 +- .../websocket/javax/tests/NetworkFuzzer.java | 4 +- .../impl/JettyClientUpgradeRequest.java | 6 +- .../eclipse/jetty/http/tools/HttpTester.java | 4 +- .../matchers/HttpFieldsMatchersTest.java | 11 +- .../jetty/test/rfcs/RFC2616BaseTest.java | 5 +- 66 files changed, 989 insertions(+), 1054 deletions(-) delete mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java diff --git a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java index e1d6aea8f543..29b0afbd6d3a 100644 --- a/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java +++ b/jetty-alpn/jetty-alpn-java-client/src/test/java/org/eclipse/jetty/alpn/java/client/JDK9HTTP2ClientTest.java @@ -24,7 +24,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -64,7 +63,7 @@ public void testJDK9HTTP2Client() throws Exception client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(15, TimeUnit.SECONDS); - HttpFieldsBuilder requestFields = HttpFields.build(); + HttpFields.Mutable requestFields = HttpFields.build(); requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION); MetaData.Request metaData = new MetaData.Request("GET", HttpURI.from("https://" + host + ":" + port + "/"), HttpVersion.HTTP_2, requestFields); HeadersFrame headersFrame = new HeadersFrame(metaData, null, true); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java index f3d04a0b61e2..ce0a100ab6cd 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java @@ -54,7 +54,6 @@ import org.eclipse.jetty.client.util.PathRequestContent; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -65,7 +64,7 @@ public class HttpRequest implements Request { private static final URI NULL_URI = URI.create("null:0"); - private final HttpFieldsBuilder headers = HttpFields.build(); + private final HttpFields.Mutable headers = HttpFields.build(); private final Fields params = new Fields(true); private final List responseListeners = new ArrayList<>(); private final AtomicReference aborted = new AtomicReference<>(); @@ -382,7 +381,7 @@ public Map getAttributes() } @Override - public HttpFieldsBuilder getHeaders() + public HttpFields.Mutable getHeaders() { return headers; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index 206225c78374..36b730a79c49 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -25,18 +25,17 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; public class HttpResponse implements Response { - private final HttpFieldsBuilder headers = HttpFields.build(); + private final HttpFields.Mutable headers = HttpFields.build(); private final Request request; private final List listeners; private HttpVersion version; private int status; private String reason; - private HttpFieldsBuilder trailers; + private HttpFields.Mutable trailers; public HttpResponse(Request request, List listeners) { @@ -92,7 +91,7 @@ public HttpFields getHeaders() return headers.asImmutable(); } - public HttpFieldsBuilder getHeadersBuilder() + public HttpFields.Mutable getHeadersBuilder() { return headers; } @@ -109,7 +108,7 @@ public List getListeners(Class type) return result; } - public HttpFieldsBuilder getTrailers() + public HttpFields.Mutable getTrailers() { return trailers; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java index 24f7868959d3..aebce8664903 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java @@ -31,7 +31,6 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.util.Callback; @@ -146,7 +145,7 @@ public void fail(Throwable failure) * @param content the part content * @param fields the headers associated with this part */ - public void addFieldPart(String name, Request.Content content, HttpFieldsBuilder fields) + public void addFieldPart(String name, Request.Content content, HttpFields.Mutable fields) { addPart(new Part(name, null, content, fields)); } @@ -165,7 +164,7 @@ public void addFieldPart(String name, Request.Content content, HttpFieldsBuilder * @param content the part content * @param fields the headers associated with this part */ - public void addFilePart(String name, String fileName, Request.Content content, HttpFieldsBuilder fields) + public void addFilePart(String name, String fileName, Request.Content content, HttpFields.Mutable fields) { addPart(new Part(name, fileName, content, fields)); } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java index 293ace217ad2..f138a1b5d3bf 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/util/MultiPartContentTest.java @@ -44,7 +44,6 @@ import org.eclipse.jetty.client.AbstractHttpClientServerTest; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.server.Request; @@ -145,7 +144,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put(HttpHeader.CONTENT_TYPE, "text/plain;charset=" + encoding.name()); BytesRequestContent content = new BytesRequestContent(value.getBytes(encoding)); multiPart.addFieldPart(name, content, fields); @@ -241,7 +240,7 @@ public void close() throws IOException closeLatch.countDown(); } }); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put(HttpHeader.CONTENT_TYPE, contentType); multiPart.addFilePart(name, fileName, content, fields); multiPart.close(); @@ -355,7 +354,7 @@ protected void handle(HttpServletRequest request, HttpServletResponse response) }); MultiPartRequestContent multiPart = new MultiPartRequestContent(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put(headerName, headerValue); multiPart.addFieldPart(field, new StringRequestContent(value, encoding), fields); multiPart.addFilePart(fileField, tmpPath.getFileName().toString(), new PathRequestContent(tmpPath), null); diff --git a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java index c4750932325b..b38addd1a4a3 100644 --- a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java +++ b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java @@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -49,7 +48,7 @@ public void dataDemanded() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.build() + HttpFields.Mutable requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index 7b65374eba6e..884f33058f05 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -27,7 +27,6 @@ import java.util.concurrent.CompletableFuture; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -173,7 +172,7 @@ public void newStreamWithData() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFieldsBuilder requestHeaders = HttpFields.build() + HttpFields.Mutable requestHeaders = HttpFields.build() .put(HttpHeader.CONTENT_TYPE, "application/json"); // The request metadata with method, URI and headers. @@ -214,7 +213,7 @@ public void responseListener() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.build() + HttpFields.Mutable requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -359,7 +358,7 @@ public void pushReset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFieldsBuilder requestHeaders = HttpFields.build() + HttpFields.Mutable requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java index 1d5c920ea3f9..338c646504a2 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpClientTransportOverFCGI.java @@ -32,7 +32,7 @@ import org.eclipse.jetty.client.api.Connection; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.fcgi.FCGI; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.io.ClientConnector; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.ProcessorUtils; @@ -103,7 +103,7 @@ protected HttpConnectionOverFCGI newHttpConnection(EndPoint endPoint, HttpDestin return new HttpConnectionOverFCGI(endPoint, destination, promise); } - protected void customize(Request request, HttpFieldsBuilder fastCGIHeaders) + protected void customize(Request request, HttpFields.Mutable fastCGIHeaders) { fastCGIHeaders.put(FCGI.Headers.DOCUMENT_ROOT, getScriptRoot()); } diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index d04f83ef8fde..8de4ae4e3bf1 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -32,7 +32,6 @@ import org.eclipse.jetty.fcgi.generator.Generator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Jetty; @@ -60,8 +59,8 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { Request request = exchange.getRequest(); // Copy the request headers to be able to convert them properly - HttpFieldsBuilder headers = HttpFields.build(request.getHeaders()); - HttpFieldsBuilder fcgiHeaders = HttpFields.build(); + HttpFields.Mutable headers = HttpFields.build(request.getHeaders()); + HttpFields.Mutable fcgiHeaders = HttpFields.build(); // FastCGI headers based on the URI URI uri = request.getURI(); diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java index cf1534a5c057..107116c6a5d4 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; @@ -85,7 +84,7 @@ protected void end(int request) private static class ResponseParser implements HttpParser.ResponseHandler { - private final HttpFieldsBuilder fields = HttpFields.build(); + private final HttpFields.Mutable fields = HttpFields.build(); private ClientParser.Listener listener; private final int request; private final FCGIHttpParser httpParser; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java index 8ae2501d0a58..4bd299858b08 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/generator/ClientGeneratorTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.fcgi.parser.ServerParser; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.junit.jupiter.api.Test; @@ -39,7 +38,7 @@ public class ClientGeneratorTest @Test public void testGenerateRequestHeaders() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); // Short name, short value final String shortShortName = "REQUEST_METHOD"; diff --git a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java index fdbb2588c27a..77b02530c98f 100644 --- a/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java +++ b/jetty-fcgi/fcgi-client/src/test/java/org/eclipse/jetty/fcgi/parser/ClientParserTest.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.fcgi.generator.ServerGenerator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.junit.jupiter.api.Test; @@ -43,7 +42,7 @@ public class ClientParserTest public void testParseResponseHeaders() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); final int statusCode = 200; final String statusMessage = "OK"; @@ -158,7 +157,7 @@ public void onEnd(int request) public void testParseSmallResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); ByteBuffer content = ByteBuffer.wrap(new byte[1024]); final int contentLength = content.remaining(); @@ -211,7 +210,7 @@ public void onEnd(int request) public void testParseLargeResponseContent() throws Exception { final int id = 13; - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); ByteBuffer content = ByteBuffer.wrap(new byte[128 * 1024]); final int contentLength = content.remaining(); diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java index d85b36ea2e05..0c7b168604b0 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/HttpChannelOverFCGI.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; @@ -44,7 +43,7 @@ public class HttpChannelOverFCGI extends HttpChannel { private static final Logger LOG = LoggerFactory.getLogger(HttpChannelOverFCGI.class); - private final HttpFieldsBuilder fields = HttpFields.build(); + private final HttpFields.Mutable fields = HttpFields.build(); private final Dispatcher dispatcher; private String method; private String path; diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java index fcf9ecfd1c0a..5869f2c44961 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java @@ -38,7 +38,7 @@ import org.eclipse.jetty.fcgi.FCGI; import org.eclipse.jetty.fcgi.client.http.HttpClientTransportOverFCGI; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.proxy.AsyncProxyServlet; @@ -209,7 +209,7 @@ protected void sendProxyRequest(HttpServletRequest request, HttpServletResponse super.sendProxyRequest(request, proxyResponse, proxyRequest); } - protected void customizeFastCGIHeaders(Request proxyRequest, HttpFieldsBuilder fastCGIHeaders) + protected void customizeFastCGIHeaders(Request proxyRequest, HttpFields.Mutable fastCGIHeaders) { for (String envName : fcgiEnvNames) { @@ -271,7 +271,7 @@ private ProxyHttpClientTransportOverFCGI(int selectors, String scriptRoot) } @Override - protected void customize(Request request, HttpFieldsBuilder fastCGIHeaders) + protected void customize(Request request, HttpFields.Mutable fastCGIHeaders) { super.customize(request, fastCGIHeaders); customizeFastCGIHeaders(request, fastCGIHeaders); 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 893e145ecc95..305ab8a4e056 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 @@ -19,11 +19,13 @@ package org.eclipse.jetty.http; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.Enumeration; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Set; import java.util.function.ToIntFunction; @@ -37,29 +39,34 @@ public interface HttpFields extends Iterable { HttpFields EMPTY = build().asImmutable(); - static HttpFieldsBuilder build() + static Mutable build() { - return new HttpFieldsBuilder(); + return new Mutable(); } - static HttpFieldsBuilder build(int capacity) + static Mutable build(int capacity) { - return new HttpFieldsBuilder(capacity); + return new Mutable(capacity); } - static HttpFieldsBuilder build(HttpFields fields) + static Mutable build(HttpFields fields) { - return new HttpFieldsBuilder(fields); + return new Mutable(fields); } - static HttpFieldsBuilder build(HttpFields fields, HttpField replaceField) + static Mutable build(HttpFields fields, HttpField replaceField) { - return new HttpFieldsBuilder(fields, replaceField); + return new Mutable(fields, replaceField); } - static HttpFieldsBuilder build(HttpFields fields, EnumSet removeFields) + static Mutable build(HttpFields fields, EnumSet removeFields) { - return new HttpFieldsBuilder(fields, removeFields); + return new Mutable(fields, removeFields); + } + + static Immutable from(HttpField... fields) + { + return new Immutable(fields); } default int asHashCode() @@ -70,12 +77,7 @@ default int asHashCode() return hash; } - HttpFields asImmutable(); - - default HttpFieldsBuilder asMutable() - { - return build(this); - } + Immutable asImmutable(); default String asString() { @@ -499,4 +501,608 @@ default boolean isEqualTo(HttpFields that) int size(); Stream stream(); + + /** + * HTTP Fields. A collection of HTTP header and or Trailer fields. + * + *

This class is not synchronized as it is expected that modifications will only be performed by a + * single thread. + * + *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + */ + class Mutable implements Iterable, HttpFields + { + ArrayList _fields; + + /** + * Initialize an empty HttpFields. + */ + protected Mutable() + { + this(16); // Based on small sample of Chrome requests. + } + + /** + * Initialize an empty HttpFields. + * + * @param capacity the capacity of the http fields + */ + Mutable(int capacity) + { + _fields = new ArrayList<>(capacity); + } + + /** + * Initialize HttpFields from another. + * + * @param fields the fields to copy data from + */ + Mutable(HttpFields fields) + { + if (fields instanceof Immutable) + _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); + else if (fields instanceof Mutable) + _fields = new ArrayList<>(((Mutable)fields)._fields); + else + { + _fields = new ArrayList<>(fields.size() + 4); + for (HttpField f : fields) + { + _fields.add(f); + } + } + } + + /** + * Initialize HttpFields from another and replace a field + * + * @param fields the fields to copy data from + * @param replaceField the replacement field + */ + Mutable(HttpFields fields, HttpField replaceField) + { + _fields = new ArrayList<>(fields.size() + 4); + boolean put = false; + for (HttpField f : fields) + { + if (replaceField.isSameName(f)) + { + if (!put) + _fields.add(replaceField); + put = true; + } + else + { + _fields.add(f); + } + } + if (!put) + _fields.add(replaceField); + } + + /** + * Initialize HttpFields from another and remove fields + * + * @param fields the fields to copy data from + * @param removeFields the the fields to remove + */ + Mutable(HttpFields fields, EnumSet removeFields) + { + _fields = new ArrayList<>(Math.max(fields.size() + 4, 16)); + for (HttpField f : fields) + { + if (f.getHeader() == null || removeFields.contains(f.getHeader())) + _fields.add(f); + } + } + + /** + * 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. + * @return this builder + */ + public Mutable add(String name, String value) + { + if (value != null) + return add(new HttpField(name, value)); + return this; + } + + public Mutable add(HttpHeader header, HttpHeaderValue value) + { + return add(header, value.toString()); + } + + /** + * 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 header the header + * @param value the value of the field. + * @return this builder + */ + public Mutable add(HttpHeader header, String value) + { + if (value == null) + throw new IllegalArgumentException("null value"); + + HttpField field = new HttpField(header, value); + return add(field); + } + + public Mutable add(HttpField field) + { + if (field != null) + _fields.add(field); + return this; + } + + /** + * Add fields from another HttpFields instance. Single valued fields are replaced, while all + * others are added. + * + * @param fields the fields to add + * @return this builder + */ + public Mutable add(HttpFields fields) + { + // TODO is this any different to addAll? + + if (fields == null) + return this; + + _fields.ensureCapacity(size() + fields.size() + 4); + Enumeration e = fields.getFieldNames(); + while (e.hasMoreElements()) + { + String name = e.nextElement(); + Enumeration values = fields.getValues(name); + while (values.hasMoreElements()) + { + add(name, values.nextElement()); + } + } + return this; + } + + public Mutable addAll(HttpFields fields) + { + _fields.ensureCapacity(size() + fields.size() + 4); + for (HttpField f : fields) + { + _fields.add(f); + } + return this; + } + + /** + * Add comma separated values, but only if not already + * present. + * + * @param header The header to add the value(s) to + * @param values The value(s) to add + * @return this builder + */ + public Mutable addCSV(HttpHeader header, String... values) + { + // TODO is the javadoc right ? + QuotedCSV existing = null; + for (HttpField f : this) + { + if (f.getHeader() == header) + { + if (existing == null) + existing = new QuotedCSV(false); + existing.addValue(f.getValue()); + } + } + String value = addCSV(existing, values); + if (value != null) + add(header, value); + return this; + } + + /** + * Add comma separated values, but only if not already + * present. + * + * @param name The header to add the value(s) to + * @param values The value(s) to add + * @return this builder + */ + public Mutable addCSV(String name, String... values) + { + // TODO is the javadoc right ? + QuotedCSV existing = null; + for (HttpField f : this) + { + if (f.getName().equalsIgnoreCase(name)) + { + if (existing == null) + existing = new QuotedCSV(false); + existing.addValue(f.getValue()); + } + } + String value = addCSV(existing, values); + if (value != null) + add(name, value); + return this; + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public Mutable addDateField(String name, long date) + { + add(name, DateGenerator.formatDate(date)); + return this; + } + + @Override + public Immutable asImmutable() + { + return new Immutable(_fields.toArray(new HttpField[0])); + } + + public Mutable clear() + { + _fields.clear(); + return this; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof Mutable)) + return false; + + return isEqualTo((HttpFields)o); + } + + /** + * Remove the first instance of a header and return previous value + * + * @param name the field to remove + * @return the header that was removed + */ + public HttpField getAndRemove(HttpHeader name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getHeader() == name) + { + i.remove(); + return f; + } + } + return null; + } + + /** + * Get a Field by index. + * + * @param index the field index + * @return A Field value or null if the Field value has not been set + */ + @Override + public HttpField getField(int index) + { + if (index >= size()) + throw new NoSuchElementException(); + return _fields.get(index); + } + + @Override + public int hashCode() + { + return asHashCode(); + } + + @Override + public Iterator iterator() + { + return _fields.iterator(); + } + + public ListIterator listIterator() + { + return _fields.listIterator(); + } + + public Mutable put(HttpField field) + { + boolean put = false; + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.isSameName(field)) + { + if (put) + i.remove(); + else + { + i.set(field); + put = true; + } + } + } + if (!put) + add(field); + return this; + } + + /** + * Set a field. + * + * @param name the name of the field + * @param value the value of the field. If null the field is cleared. + * @return this builder + */ + public Mutable put(String name, String value) + { + return (value == null) + ? remove(name) + : put(new HttpField(name, value)); + } + + public Mutable put(HttpHeader header, HttpHeaderValue value) + { + return put(header, value.toString()); + } + + /** + * Set a field. + * + * @param header the header name of the field + * @param value the value of the field. If null the field is cleared. + * @return this builder + */ + public Mutable put(HttpHeader header, String value) + { + return (value == null) + ? remove(header) + : put(new HttpField(header, value)); + } + + /** + * Set a field. + * + * @param name the name of the field + * @param list the List value of the field. If null the field is cleared. + * @return this builder + */ + public Mutable put(String name, List list) + { + remove(name); + for (String v : list) + { + if (v != null) + add(name, v); + } + return this; + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public Mutable putDateField(HttpHeader name, long date) + { + return put(name, DateGenerator.formatDate(date)); + } + + /** + * Sets the value of a date field. + * + * @param name the field name + * @param date the field date value + * @return this builder + */ + public Mutable putDateField(String name, long date) + { + return put(name, DateGenerator.formatDate(date)); + } + + /** + * Sets the value of an long field. + * + * @param name the field name + * @param value the field long value + * @return this builder + */ + public Mutable putLongField(HttpHeader name, long value) + { + return put(name, Long.toString(value)); + } + + /** + * Sets the value of an long field. + * + * @param name the field name + * @param value the field long value + * @return this builder + */ + public Mutable putLongField(String name, long value) + { + return put(name, Long.toString(value)); + } + + /** + * Remove a field. + * + * @param name the field to remove + * @return this builder + */ + public Mutable remove(HttpHeader name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getHeader() == name) + i.remove(); + } + return this; + } + + /** + * Remove a field. + * + * @param name the field to remove + * @return this builder + */ + public Mutable remove(String name) + { + for (ListIterator i = listIterator(); i.hasNext(); ) + { + HttpField f = i.next(); + if (f.getName().equalsIgnoreCase(name)) + i.remove(); + } + return this; + } + + public int size() + { + return _fields.size(); + } + + @Override + public Stream stream() + { + return _fields.stream(); + } + + @Override + public String toString() + { + return asString(); + } + + private String addCSV(QuotedCSV existing, String... values) + { + // remove any existing values from the new values + boolean add = true; + if (existing != null && !existing.isEmpty()) + { + add = false; + + for (int i = values.length; i-- > 0; ) + { + String unquoted = QuotedCSV.unquote(values[i]); + if (existing.getValues().contains(unquoted)) + values[i] = null; + else + add = true; + } + } + + if (add) + { + StringBuilder value = new StringBuilder(); + for (String v : values) + { + if (v == null) + continue; + if (value.length() > 0) + value.append(", "); + value.append(v); + } + if (value.length() > 0) + return value.toString(); + } + + return null; + } + } + + /** + * HTTP Fields. A collection of HTTP header and or Trailer fields. + * + *

This class is not synchronized as it is expected that modifications will only be performed by a + * single thread. + * + *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. + */ + class Immutable implements HttpFields + { + final HttpField[] _fields; + + /** + * Initialize HttpFields from copy. + * + * @param fields the fields to copy data from + */ + Immutable(HttpField[] fields) + { + _fields = fields; + } + + @Override + public Immutable asImmutable() + { + return this; + } + + @Override + public boolean equals(Object o) + { + if (this == o) + return true; + if (!(o instanceof Immutable)) + return false; + + return isEqualTo((HttpFields)o); + } + + @Override + public HttpField getField(int index) + { + if (index >= _fields.length) + throw new NoSuchElementException(); + return _fields[index]; + } + + @Override + public int hashCode() + { + return asHashCode(); + } + + @Override + public Iterator iterator() + { + return Arrays.stream(_fields).iterator(); + } + + @Override + public int size() + { + return _fields.length; + } + + @Override + public Stream stream() + { + return Arrays.stream(_fields); + } + + @Override + public String toString() + { + return asString(); + } + } } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java deleted file mode 100644 index 9821ee5ed58e..000000000000 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFieldsBuilder.java +++ /dev/null @@ -1,629 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. -// -// This program and the accompanying materials are made available under -// the terms of the Eclipse Public License 2.0 which is available at -// https://www.eclipse.org/legal/epl-2.0 -// -// This Source Code may also be made available under the following -// Secondary Licenses when the conditions for such availability set -// forth in the Eclipse Public License, v. 2.0 are satisfied: -// the Apache License v2.0 which is available at -// https://www.apache.org/licenses/LICENSE-2.0 -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// ======================================================================== -// - -package org.eclipse.jetty.http; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Enumeration; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.NoSuchElementException; -import java.util.stream.Stream; - -/** - * HTTP Fields. A collection of HTTP header and or Trailer fields. - * - *

This class is not synchronized as it is expected that modifications will only be performed by a - * single thread. - * - *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. - */ -public class HttpFieldsBuilder implements Iterable, HttpFields -{ - ArrayList _fields; - - /** - * Initialize an empty HttpFields. - */ - protected HttpFieldsBuilder() - { - this(16); // Based on small sample of Chrome requests. - } - - /** - * Initialize an empty HttpFields. - * - * @param capacity the capacity of the http fields - */ - HttpFieldsBuilder(int capacity) - { - _fields = new ArrayList<>(capacity); - } - - /** - * Initialize HttpFields from another. - * - * @param fields the fields to copy data from - */ - HttpFieldsBuilder(HttpFields fields) - { - if (fields instanceof Immutable) - _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); - else if (fields instanceof HttpFieldsBuilder) - _fields = new ArrayList<>(((HttpFieldsBuilder)fields)._fields); - else - { - _fields = new ArrayList<>(fields.size() + 4); - for (HttpField f : fields) - _fields.add(f); - } - } - - /** - * Initialize HttpFields from another and replace a field - * - * @param fields the fields to copy data from - * @param replaceField the replacement field - */ - HttpFieldsBuilder(HttpFields fields, HttpField replaceField) - { - _fields = new ArrayList<>(fields.size() + 4); - boolean put = false; - for (HttpField f : fields) - { - if (replaceField.isSameName(f)) - { - if (!put) - _fields.add(replaceField); - put = true; - } - else - { - _fields.add(f); - } - } - if (!put) - _fields.add(replaceField); - } - - /** - * Initialize HttpFields from another and remove fields - * - * @param fields the fields to copy data from - * @param removeFields the the fields to remove - */ - HttpFieldsBuilder(HttpFields fields, EnumSet removeFields) - { - _fields = new ArrayList<>(Math.max(fields.size() + 4, 16)); - for (HttpField f : fields) - { - if (f.getHeader() == null || removeFields.contains(f.getHeader())) - _fields.add(f); - } - } - - /** - * 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. - * @return this builder - */ - public HttpFieldsBuilder add(String name, String value) - { - if (value != null) - return add(new HttpField(name, value)); - return this; - } - - public HttpFieldsBuilder add(HttpHeader header, HttpHeaderValue value) - { - return add(header, value.toString()); - } - - /** - * 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 header the header - * @param value the value of the field. - * @return this builder - */ - public HttpFieldsBuilder add(HttpHeader header, String value) - { - if (value == null) - throw new IllegalArgumentException("null value"); - - HttpField field = new HttpField(header, value); - return add(field); - } - - public HttpFieldsBuilder add(HttpField field) - { - if (field != null) - _fields.add(field); - return this; - } - - /** - * Add fields from another HttpFields instance. Single valued fields are replaced, while all - * others are added. - * - * @param fields the fields to add - * @return this builder - */ - public HttpFieldsBuilder add(HttpFields fields) - { - // TODO is this any different to addAll? - - if (fields == null) - return this; - - _fields.ensureCapacity(size() + fields.size() + 4); - Enumeration e = fields.getFieldNames(); - while (e.hasMoreElements()) - { - String name = e.nextElement(); - Enumeration values = fields.getValues(name); - while (values.hasMoreElements()) - { - add(name, values.nextElement()); - } - } - return this; - } - - public HttpFieldsBuilder addAll(HttpFields fields) - { - _fields.ensureCapacity(size() + fields.size() + 4); - for (HttpField f : fields) - _fields.add(f); - return this; - } - - /** - * Add comma separated values, but only if not already - * present. - * - * @param header The header to add the value(s) to - * @param values The value(s) to add - * @return this builder - */ - public HttpFieldsBuilder addCSV(HttpHeader header, String... values) - { - // TODO is the javadoc right ? - QuotedCSV existing = null; - for (HttpField f : this) - { - if (f.getHeader() == header) - { - if (existing == null) - existing = new QuotedCSV(false); - existing.addValue(f.getValue()); - } - } - String value = addCSV(existing, values); - if (value != null) - add(header, value); - return this; - } - - /** - * Add comma separated values, but only if not already - * present. - * - * @param name The header to add the value(s) to - * @param values The value(s) to add - * @return this builder - */ - public HttpFieldsBuilder addCSV(String name, String... values) - { - // TODO is the javadoc right ? - QuotedCSV existing = null; - for (HttpField f : this) - { - if (f.getName().equalsIgnoreCase(name)) - { - if (existing == null) - existing = new QuotedCSV(false); - existing.addValue(f.getValue()); - } - } - String value = addCSV(existing, values); - if (value != null) - add(name, value); - return this; - } - - /** - * Sets the value of a date field. - * - * @param name the field name - * @param date the field date value - * @return this builder - */ - public HttpFieldsBuilder addDateField(String name, long date) - { - add(name, DateGenerator.formatDate(date)); - return this; - } - - @Override - public HttpFields asImmutable() - { - return new Immutable(_fields.toArray(new HttpField[0])); - } - - public HttpFieldsBuilder clear() - { - _fields.clear(); - return this; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof HttpFieldsBuilder)) - return false; - - return isEqualTo((HttpFields)o); - } - - /** - * Remove the first instance of a header and return previous value - * - * @param name the field to remove - * @return the header that was removed - */ - public HttpField getAndRemove(HttpHeader name) - { - for (ListIterator i = listIterator(); i.hasNext(); ) - { - HttpField f = i.next(); - if (f.getHeader() == name) - { - i.remove(); - return f; - } - } - return null; - } - - /** - * Get a Field by index. - * - * @param index the field index - * @return A Field value or null if the Field value has not been set - */ - @Override - public HttpField getField(int index) - { - if (index >= size()) - throw new NoSuchElementException(); - return _fields.get(index); - } - - @Override - public int hashCode() - { - return asHashCode(); - } - - @Override - public Iterator iterator() - { - return _fields.iterator(); - } - - public ListIterator listIterator() - { - return _fields.listIterator(); - } - - public HttpFieldsBuilder put(HttpField field) - { - boolean put = false; - for (ListIterator i = listIterator(); i.hasNext(); ) - { - HttpField f = i.next(); - if (f.isSameName(field)) - { - if (put) - i.remove(); - else - { - i.set(field); - put = true; - } - } - } - if (!put) - add(field); - return this; - } - - /** - * Set a field. - * - * @param name the name of the field - * @param value the value of the field. If null the field is cleared. - * @return this builder - */ - public HttpFieldsBuilder put(String name, String value) - { - return (value == null) - ? remove(name) - : put(new HttpField(name, value)); - } - - public HttpFieldsBuilder put(HttpHeader header, HttpHeaderValue value) - { - return put(header, value.toString()); - } - - /** - * Set a field. - * - * @param header the header name of the field - * @param value the value of the field. If null the field is cleared. - * @return this builder - */ - public HttpFieldsBuilder put(HttpHeader header, String value) - { - return (value == null) - ? remove(header) - : put(new HttpField(header, value)); - } - - /** - * Set a field. - * - * @param name the name of the field - * @param list the List value of the field. If null the field is cleared. - * @return this builder - */ - public HttpFieldsBuilder put(String name, List list) - { - remove(name); - for (String v : list) - { - if (v != null) - add(name, v); - } - return this; - } - - /** - * Sets the value of a date field. - * - * @param name the field name - * @param date the field date value - * @return this builder - */ - public HttpFieldsBuilder putDateField(HttpHeader name, long date) - { - return put(name, DateGenerator.formatDate(date)); - } - - /** - * Sets the value of a date field. - * - * @param name the field name - * @param date the field date value - * @return this builder - */ - public HttpFieldsBuilder putDateField(String name, long date) - { - return put(name, DateGenerator.formatDate(date)); - } - - /** - * Sets the value of an long field. - * - * @param name the field name - * @param value the field long value - * @return this builder - */ - public HttpFieldsBuilder putLongField(HttpHeader name, long value) - { - return put(name, Long.toString(value)); - } - - /** - * Sets the value of an long field. - * - * @param name the field name - * @param value the field long value - * @return this builder - */ - public HttpFieldsBuilder putLongField(String name, long value) - { - return put(name, Long.toString(value)); - } - - /** - * Remove a field. - * - * @param name the field to remove - * @return this builder - */ - public HttpFieldsBuilder remove(HttpHeader name) - { - for (ListIterator i = listIterator(); i.hasNext(); ) - { - HttpField f = i.next(); - if (f.getHeader() == name) - i.remove(); - } - return this; - } - - /** - * Remove a field. - * - * @param name the field to remove - * @return this builder - */ - public HttpFieldsBuilder remove(String name) - { - for (ListIterator i = listIterator(); i.hasNext(); ) - { - HttpField f = i.next(); - if (f.getName().equalsIgnoreCase(name)) - i.remove(); - } - return this; - } - - public int size() - { - return _fields.size(); - } - - @Override - public Stream stream() - { - return _fields.stream(); - } - - @Override - public String toString() - { - return asString(); - } - - private String addCSV(QuotedCSV existing, String... values) - { - // remove any existing values from the new values - boolean add = true; - if (existing != null && !existing.isEmpty()) - { - add = false; - - for (int i = values.length; i-- > 0; ) - { - String unquoted = QuotedCSV.unquote(values[i]); - if (existing.getValues().contains(unquoted)) - values[i] = null; - else - add = true; - } - } - - if (add) - { - StringBuilder value = new StringBuilder(); - for (String v : values) - { - if (v == null) - continue; - if (value.length() > 0) - value.append(", "); - value.append(v); - } - if (value.length() > 0) - return value.toString(); - } - - return null; - } - - /** - * HTTP Fields. A collection of HTTP header and or Trailer fields. - * - *

This class is not synchronized as it is expected that modifications will only be performed by a - * single thread. - * - *

The cookie handling provided by this class is guided by the Servlet specification and RFC6265. - */ - private static class Immutable implements HttpFields - { - final HttpField[] _fields; - - /** - * Initialize HttpFields from copy. - * - * @param fields the fields to copy data from - */ - Immutable(HttpField[] fields) - { - _fields = fields; - } - - @Override - public HttpFields asImmutable() - { - return this; - } - - @Override - public boolean equals(Object o) - { - if (this == o) - return true; - if (!(o instanceof Immutable)) - return false; - - return isEqualTo((HttpFields)o); - } - - @Override - public HttpField getField(int index) - { - if (index >= _fields.length) - throw new NoSuchElementException(); - return _fields[index]; - } - - @Override - public int hashCode() - { - return asHashCode(); - } - - @Override - public Iterator iterator() - { - return Arrays.stream(_fields).iterator(); - } - - @Override - public int size() - { - return _fields.length; - } - - @Override - public Stream stream() - { - return Arrays.stream(_fields); - } - - @Override - public String toString() - { - return asString(); - } - } -} 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 9a084a12695e..8a92bef3d3ec 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 @@ -921,7 +921,7 @@ public static void putTo(HttpField field, ByteBuffer bufferInFillMode) } } - public static void putTo(HttpFieldsBuilder fields, ByteBuffer bufferInFillMode) + public static void putTo(HttpFields.Mutable fields, ByteBuffer bufferInFillMode) { for (HttpField field : fields) { 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 d6563065651b..9efc1be10228 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 @@ -72,7 +72,7 @@ * is used to lookup common combinations of headers and values * (eg. "Connection: close"), or just header names (eg. "Connection:" ). * For headers who's value is not known statically (eg. Host, COOKIE) then a - * per parser dynamic Trie of {@link HttpFieldsBuilder} from previous parsed messages + * per parser dynamic Trie of {@link HttpFields.Mutable} from previous parsed messages * is used to help the parsing of subsequent messages. *

*

diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 14a273b83f63..0ebebc2362c3 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -48,47 +48,47 @@ */ public interface HttpURI { - static HttpURI.Builder build() + static Mutable build() { - return new HttpURI.Builder(); + return new Mutable(); } - static HttpURI.Builder build(HttpURI uri) + static Mutable build(HttpURI uri) { - return new HttpURI.Builder(uri); + return new Mutable(uri); } - static HttpURI.Builder build(HttpURI uri, String pathQuery) + static Mutable build(HttpURI uri, String pathQuery) { - return new HttpURI.Builder(uri, pathQuery); + return new Mutable(uri, pathQuery); } - static HttpURI.Builder build(HttpURI uri, String path, String param, String query) + static Mutable build(HttpURI uri, String path, String param, String query) { - return new HttpURI.Builder(uri, path, param, query); + return new Mutable(uri, path, param, query); } - static HttpURI.Builder build(URI uri) + static Mutable build(URI uri) { - return new HttpURI.Builder(uri); + return new Mutable(uri); } - static HttpURI.Builder build(String uri) + static Mutable build(String uri) { - return new HttpURI.Builder(uri); + return new Mutable(uri); } - static HttpURI from(URI uri) + static Immutable from(URI uri) { return new HttpURI.Immutable(uri); } - static HttpURI from(String uri) + static Immutable from(String uri) { return new HttpURI.Immutable(uri); } - static HttpURI from(String method, String uri) + static Immutable from(String method, String uri) { if (HttpMethod.CONNECT.is(method)) return new Immutable(uri, null, null, null, -1, uri, null, null, null, null); @@ -97,11 +97,13 @@ static HttpURI from(String method, String uri) return HttpURI.from(uri); } - static HttpURI from(String scheme, String host, int port, String pathQuery) + static Immutable from(String scheme, String host, int port, String pathQuery) { - return build(pathQuery).scheme(scheme).host(host).port(port).pathQuery(pathQuery).asImmutable(); + return new Immutable(scheme, host, port, pathQuery); } + Immutable asImmutable(); + String getAuthority(); String getDecodedPath(); @@ -135,10 +137,6 @@ static HttpURI from(String scheme, String host, int port, String pathQuery) boolean isAbsolute(); - HttpURI asImmutable(); - - HttpURI.Builder asMutable(); - default URI toURI() { try @@ -167,7 +165,7 @@ class Immutable implements HttpURI private Immutable(String uri) { - Builder builder = new Builder(uri); + Mutable builder = new Mutable(uri); _uri = builder._uri; _scheme = builder._scheme; _user = builder._user; @@ -182,7 +180,7 @@ private Immutable(String uri) private Immutable(URI uri) { - Builder builder = new Builder(uri); + Mutable builder = new Mutable(uri); _uri = builder._uri; _scheme = builder._scheme; _user = builder._user; @@ -195,6 +193,21 @@ private Immutable(URI uri) _fragment = builder._fragment; } + private Immutable(String scheme, String host, int port, String pathQuery) + { + Mutable builder = build().scheme(scheme).host(host).port(port).pathQuery(pathQuery); + _uri = null; + _scheme = builder._scheme; + _user = builder._user; + _host = builder._host; + _port = builder._port; + _path = builder._path; + _decodedPath = builder._decodedPath; + _param = builder._param; + _query = builder._query; + _fragment = builder._fragment; + } + private Immutable(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) { _uri = uri; @@ -209,6 +222,12 @@ private Immutable(String uri, String scheme, String user, String host, int port, _fragment = fragment; } + @Override + public Immutable asImmutable() + { + return this; + } + @Override public boolean equals(Object o) { @@ -317,31 +336,6 @@ public boolean isAbsolute() return !StringUtil.isEmpty(_scheme); } - @Override - public URI toURI() - { - try - { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); - } - catch (URISyntaxException x) - { - throw new RuntimeException(x); - } - } - - @Override - public HttpURI asImmutable() - { - return this; - } - - @Override - public HttpURI.Builder asMutable() - { - return build(this); - } - @Override public String toString() { @@ -379,9 +373,22 @@ public String toString() } return _uri; } + + @Override + public URI toURI() + { + try + { + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + } + catch (URISyntaxException x) + { + throw new RuntimeException(x); + } + } } - class Builder implements HttpURI + class Mutable implements HttpURI { private enum State { @@ -409,16 +416,16 @@ private enum State private String _query; private String _fragment; - private Builder() + private Mutable() { } - private Builder(HttpURI uri) + private Mutable(HttpURI uri) { uri(uri); } - private Builder(HttpURI baseURI, String pathQuery) + private Mutable(HttpURI baseURI, String pathQuery) { _uri = null; _scheme = baseURI.getScheme(); @@ -429,7 +436,7 @@ private Builder(HttpURI baseURI, String pathQuery) parse(State.PATH, pathQuery); } - private Builder(HttpURI baseURI, String path, String param, String query) + private Mutable(HttpURI baseURI, String path, String param, String query) { _uri = null; _scheme = baseURI.getScheme(); @@ -442,13 +449,13 @@ private Builder(HttpURI baseURI, String path, String param, String query) _fragment = null; } - private Builder(String uri) + private Mutable(String uri) { _port = -1; parse(State.START, uri); } - private Builder(URI uri) + private Mutable(URI uri) { _uri = null; @@ -473,7 +480,7 @@ private Builder(URI uri) _fragment = uri.getFragment(); } - private Builder(String scheme, String host, int port, String pathQuery) + private Mutable(String scheme, String host, int port, String pathQuery) { _uri = null; @@ -486,30 +493,16 @@ private Builder(String scheme, String host, int port, String pathQuery) } @Override - public HttpURI asImmutable() + public Immutable asImmutable() { return new Immutable(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); } - @Override - public HttpURI.Builder asMutable() - { - return this; - } - - @Override - public String getAuthority() - { - if (_port > 0) - return _host + ":" + _port; - return _host; - } - /** * @param host the host * @param port the port */ - public Builder authority(String host, int port) + public Mutable authority(String host, int port) { _user = null; _host = host; @@ -521,7 +514,7 @@ public Builder authority(String host, int port) /** * @param hostport the host and port combined */ - public Builder authority(String hostport) + public Mutable authority(String hostport) { HostPort hp = new HostPort(hostport); _user = null; @@ -545,6 +538,29 @@ public void clear() _user = null; } + public Mutable decodedPath(String path) + { + _uri = null; + _path = URIUtil.encodePath(path); + _decodedPath = path; + return this; + } + + public Mutable fragment(String fragment) + { + _fragment = fragment; + _uri = null; + return this; + } + + @Override + public String getAuthority() + { + if (_port > 0) + return _host + ":" + _port; + return _host; + } + @Override public String getDecodedPath() { @@ -553,46 +569,74 @@ public String getDecodedPath() return _decodedPath; } - public Builder decodedPath(String path) + @Override + public String getFragment() { - _uri = null; - _path = URIUtil.encodePath(path); - _decodedPath = path; - return this; + return _fragment; } @Override - public String getFragment() + public String getHost() { - return _fragment; + return _host; } - public Builder fragment(String fragment) + @Override + public String getParam() { - _fragment = fragment; - _uri = null; - return this; + return _param; } @Override - public boolean hasAuthority() + public String getPath() { - return _host != null; + return _path; } @Override - public boolean hasQuery() + public String getPathQuery() { - return _query != null && !_query.isEmpty(); + if (_query == null) + return _path; + return _path + "?" + _query; } @Override - public String getHost() + public int getPort() { - return _host; + return _port; + } + + @Override + public String getQuery() + { + return _query; + } + + @Override + public String getScheme() + { + return _scheme; + } + + public String getUser() + { + return _user; + } + + @Override + public boolean hasAuthority() + { + return _host != null; + } + + @Override + public boolean hasQuery() + { + return _query != null && !_query.isEmpty(); } - public Builder host(String host) + public Mutable host(String host) { _host = host; _uri = null; @@ -605,7 +649,7 @@ public boolean isAbsolute() return _scheme != null && !_scheme.isEmpty(); } - public Builder normalize() + public Mutable normalize() { if (_port == 80 && HttpScheme.HTTP.is(_scheme)) _port = 0; @@ -615,13 +659,7 @@ public Builder normalize() return this; } - @Override - public String getParam() - { - return _param; - } - - public Builder param(String param) + public Mutable param(String param) { _param = param; if (_path != null && _param != null && !_path.contains(_param)) @@ -632,16 +670,10 @@ public Builder param(String param) return this; } - @Override - public String getPath() - { - return _path; - } - /** * @param path the path */ - public Builder path(String path) + public Mutable path(String path) { _uri = null; _path = path; @@ -649,15 +681,7 @@ public Builder path(String path) return this; } - @Override - public String getPathQuery() - { - if (_query == null) - return _path; - return _path + "?" + _query; - } - - public Builder pathQuery(String pathQuery) + public Mutable pathQuery(String pathQuery) { _uri = null; _path = null; @@ -669,44 +693,26 @@ public Builder pathQuery(String pathQuery) return this; } - @Override - public int getPort() - { - return _port; - } - - public Builder port(int port) + public Mutable port(int port) { _port = port; _uri = null; return this; } - @Override - public String getQuery() - { - return _query; - } - - public Builder query(String query) + public Mutable query(String query) { _query = query; _uri = null; return this; } - @Override - public String getScheme() - { - return _scheme; - } - - public Builder scheme(HttpScheme scheme) + public Mutable scheme(HttpScheme scheme) { return scheme(scheme.asString()); } - public Builder scheme(String scheme) + public Mutable scheme(String scheme) { _scheme = scheme; _uri = null; @@ -731,7 +737,7 @@ public URI toURI() } } - public Builder uri(HttpURI uri) + public Mutable uri(HttpURI uri) { _uri = null; _scheme = uri.getScheme(); @@ -746,7 +752,7 @@ public Builder uri(HttpURI uri) return this; } - public Builder uri(String uri) + public Mutable uri(String uri) { clear(); _uri = uri; @@ -754,7 +760,7 @@ public Builder uri(String uri) return this; } - public Builder uri(String method, String uri) + public Mutable uri(String method, String uri) { if (HttpMethod.CONNECT.is(method)) { @@ -772,7 +778,7 @@ else if (uri.startsWith("/")) return this; } - public Builder uri(String uri, int offset, int length) + public Mutable uri(String uri, int offset, int length) { clear(); int end = offset + length; @@ -781,12 +787,7 @@ public Builder uri(String uri, int offset, int length) return this; } - public String getUser() - { - return _user; - } - - public Builder user(String user) + public Mutable user(String user) { _user = user; _uri = null; 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 81f95407060b..465c97cca4ec 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 @@ -47,10 +47,9 @@ public class HttpFieldsTest @Test public void testPut() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); - - header.put("name0", "value:0"); - header.put("name1", "value1"); + HttpFields.Mutable header = HttpFields.build() + .put("name0", "value:0") + .put("name1", "value1"); assertEquals(2, header.size()); assertEquals("value:0", header.get("name0")); @@ -78,12 +77,11 @@ public void testPut() throws Exception @Test public void testPutTo() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); - - header.put("name0", "value0"); - header.put("name1", "value:A"); - header.add("name1", "value:B"); - header.add("name2", ""); + HttpFields.Mutable header = HttpFields.build() + .put("name0", "value0") + .put("name1", "value:A") + .add("name1", "value:B") + .add("name2", ""); ByteBuffer buffer = BufferUtil.allocate(1024); BufferUtil.flipToFill(buffer); @@ -99,12 +97,9 @@ public void testPutTo() throws Exception @Test public void testImmutable() throws Exception { - HttpFieldsBuilder builder = HttpFields.build(); - - builder.put("name0", "value0"); - builder.put("name1", "value1"); - - HttpFields header = builder.asImmutable(); + HttpFields header = HttpFields.build() + .put("name0", "value0") + .put("name1", "value1").asImmutable(); assertEquals("value0", header.get("name0")); assertEquals("value0", header.get("Name0")); @@ -129,10 +124,9 @@ public void testImmutable() throws Exception @Test public void testGet() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); - - header.put("name0", "value0"); - header.put("name1", "value1"); + HttpFields header = HttpFields.build() + .put("name0", "value0") + .put("name1", "value1"); assertEquals("value0", header.get("name0")); assertEquals("value0", header.get("Name0")); @@ -157,7 +151,7 @@ public void testGet() throws Exception @Test public void testGetKnown() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.put("Connection", "value0"); header.put(HttpHeader.ACCEPT, "value1"); @@ -175,7 +169,7 @@ public void testGetKnown() throws Exception @Test public void testCRLF() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.put("name0", "value\r\n0"); header.put("name\r\n1", "value1"); @@ -194,7 +188,7 @@ public void testCRLF() throws Exception @Test public void testCachedPut() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.put("Connection", "Keep-Alive"); header.put("tRansfer-EncOding", "CHUNKED"); @@ -214,7 +208,7 @@ public void testCachedPut() throws Exception @Test public void testRePut() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.put("name0", "value0"); header.put("name1", "xxxxxx"); @@ -254,7 +248,7 @@ public void testRePut() throws Exception @Test public void testRemovePut() throws Exception { - HttpFieldsBuilder header = HttpFields.build(1); + HttpFields.Mutable header = HttpFields.build(1); header.put("name0", "value0"); header.put("name1", "value1"); @@ -292,7 +286,7 @@ public void testRemovePut() throws Exception @Test public void testAdd() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("name0", "value0"); fields.add("name1", "valueA"); @@ -354,7 +348,7 @@ public void testAddPreEncodedField() { final PreEncodedHttpField X_XSS_PROTECTION_FIELD = new PreEncodedHttpField("X-XSS-Protection", "1; mode=block"); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -365,7 +359,7 @@ public void testAddFinalHttpField() { final HttpField X_XSS_PROTECTION_FIELD = new HttpField("X-XSS-Protection", "1; mode=block"); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add(X_XSS_PROTECTION_FIELD); assertThat("Fields output", fields.toString(), containsString("X-XSS-Protection: 1; mode=block")); @@ -374,7 +368,7 @@ public void testAddFinalHttpField() @Test public void testGetValues() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -414,7 +408,7 @@ public void testGetValues() throws Exception @Test public void testGetCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("name0", "value0A,value0B"); fields.add("name0", "value0C,value0D"); @@ -454,7 +448,7 @@ public void testGetCSV() throws Exception @Test public void testAddQuotedCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("some", "value"); fields.add("name", "\"zero\""); @@ -502,7 +496,7 @@ public void testAddQuotedCSV() throws Exception @Test public void testGetQualityCSV() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("some", "value"); fields.add("name", "zero;q=0.9,four;q=0.1"); @@ -524,7 +518,7 @@ public void testGetQualityCSV() throws Exception @Test public void testGetQualityCSVHeader() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("some", "value"); fields.add("Accept", "zero;q=0.9,four;q=0.1"); @@ -546,7 +540,7 @@ public void testGetQualityCSVHeader() throws Exception @Test public void testDateFields() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("D0", "Wed, 31 Dec 1969 23:59:59 GMT"); fields.put("D1", "Fri, 31 Dec 1999 23:59:59 GMT"); @@ -588,7 +582,7 @@ public void testDateFields() throws Exception @Test public void testNegDateFields() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.putDateField("Dzero", 0); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT", fields.get("Dzero")); @@ -606,7 +600,7 @@ public void testNegDateFields() throws Exception @Test public void testLongFields() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.put("I1", "42"); header.put("I2", " 43 99"); @@ -670,7 +664,7 @@ public void testLongFields() throws Exception @Test public void testContains() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); header.add("n0", ""); header.add("n1", ","); @@ -708,7 +702,7 @@ public void testContains() throws Exception @ValueSource(strings = {"Host", "host", "HOST", "HoSt", "Connection", "CONNECTION", "connection", "CoNnEcTiOn"}) public void testContainsKeyTrue(String keyName) { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -720,7 +714,7 @@ public void testContainsKeyTrue(String keyName) @ValueSource(strings = {"Content-Type", "Content-Length", "X-Bogus", ""}) public void testContainsKeyFalse(String keyName) { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "localhost"); HttpField namelessField = new HttpField(HttpHeader.CONNECTION, null, "bogus"); fields.put(namelessField); @@ -731,7 +725,7 @@ public void testContainsKeyFalse(String keyName) @Test public void testPreventNullField() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); assertThrows(NullPointerException.class, () -> { HttpField nullNullField = new HttpField(null, null, "bogus"); @@ -742,7 +736,7 @@ public void testPreventNullField() @Test public void testIteration() throws Exception { - HttpFieldsBuilder header = HttpFields.build(); + HttpFields.Mutable header = HttpFields.build(); Iterator i = header.iterator(); assertThat(i.hasNext(), is(false)); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java index 660c204ed7ed..fc5dc37f6da2 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java @@ -62,7 +62,7 @@ public void testGETRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("GET", "/index.html", fields); @@ -100,7 +100,7 @@ public void testEmptyHeaders() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("Null", null); fields.add("Empty", ""); @@ -136,7 +136,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "localhost"); fields.add("Field", "SomeWhatLongValue"); RequestInfo info = new RequestInfo("GET", "/index.html", HttpVersion.HTTP_1_0, fields); @@ -178,7 +178,7 @@ public void testPOSTRequestNoContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -218,7 +218,7 @@ public void testRequestWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -264,7 +264,7 @@ public void testRequestWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", fields); @@ -336,7 +336,7 @@ public void testRequestWithKnownContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Host", "something"); fields.add("User-Agent", "test"); RequestInfo info = new RequestInfo("POST", "/index.html", 58, fields); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java index bd4377c29382..902c56a96602 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerHTTPTest.java @@ -78,7 +78,7 @@ public void testHTTP(Run run) throws Exception private static class Result { - private HttpFieldsBuilder _fields = HttpFields.build(); + private HttpFields.Mutable _fields = HttpFields.build(); private final String _body; private final int _code; private String _connection; @@ -207,7 +207,7 @@ public String toString() return "[" + _code + "," + _contentType + "," + _contentLength + "," + (_body == null ? "null" : "content") + "]"; } - public HttpFieldsBuilder getHttpFields() + public HttpFields.Mutable getHttpFields() { return _fields; } 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 8a5b05177cfc..0d7c88d41675 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 @@ -46,7 +46,7 @@ public void test09() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_0_9, 200, null, fields, 10); @@ -83,7 +83,7 @@ public void testSimple() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -116,7 +116,7 @@ public void testHeaderOverflow() throws Exception { HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Location", "http://somewhere/else"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 302, null, fields, 0); @@ -152,7 +152,7 @@ public void test204() throws Exception HttpGenerator gen = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Content-Type", "test/data"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 204, "Foo", fields, 10); @@ -189,7 +189,7 @@ public void testComplexChars() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Content-Type", "test/data;\r\nextra=value"); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", fields, 10); @@ -222,9 +222,9 @@ public void testComplexChars() throws Exception public void testSendServerXPoweredBy() throws Exception { ByteBuffer header = BufferUtil.allocate(8096); - HttpFieldsBuilder fields1 = HttpFields.build(); + HttpFields.Mutable fields1 = HttpFields.build(); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields1, -1); - HttpFieldsBuilder fields2 = HttpFields.build(); + HttpFields.Mutable fields2 = HttpFields.build(); fields2.add(HttpHeader.SERVER, "SomeServer"); fields2.add(HttpHeader.X_POWERED_BY, "SomePower"); MetaData.Response infoF = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields2, -1); @@ -278,7 +278,7 @@ public void testResponseIncorrectContentLength() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "11"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 10); @@ -304,7 +304,7 @@ public void testResponseNoContentPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -338,7 +338,7 @@ public void testResponseKnownNoContentNotPersistent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Connection", "close"); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 0); @@ -373,7 +373,7 @@ public void testResponseUpgrade() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Upgrade", "WebSocket"); fields.add("Connection", "Upgrade"); fields.add("Sec-WebSocket-Accept", "123456789=="); @@ -409,7 +409,7 @@ public void testResponseWithChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); result = gen.generateResponse(info, false, null, null, content0, false); @@ -475,7 +475,7 @@ public void testResponseWithHintedChunkedContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -546,13 +546,13 @@ public void testResponseWithContentAndTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFieldsBuilder trailer1 = HttpFields.build(); + HttpFields.Mutable trailer1 = HttpFields.build(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -633,13 +633,13 @@ public void testResponseWithTrailer() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1, () -> { - HttpFieldsBuilder trailer1 = HttpFields.build(); + HttpFields.Mutable trailer1 = HttpFields.build(); trailer1.add("T-Name0", "T-ValueA"); trailer1.add("T-Name0", "T-ValueB"); trailer1.add("T-Name1", "T-ValueC"); @@ -702,7 +702,7 @@ public void testResponseWithKnownContentLengthFromMetaData() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, 59); result = gen.generateResponse(info, false, null, null, content0, false); @@ -751,7 +751,7 @@ public void testResponseWithKnownContentLengthFromHeader() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); fields.add("Content-Length", "" + (content0.remaining() + content1.remaining())); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, -1); @@ -816,7 +816,7 @@ public void test100ThenResponseWithContent() throws Exception assertEquals(HttpGenerator.Result.NEED_INFO, result); assertEquals(HttpGenerator.State.START, gen.getState()); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.add("Last-Modified", DateGenerator.__01Jan1970); MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, fields, BufferUtil.length(content0) + BufferUtil.length(content1)); result = gen.generateResponse(info, false, null, null, content0, false); @@ -858,7 +858,7 @@ public void testConnectionKeepAliveWithAdditionalCustomValue() throws Exception { HttpGenerator generator = new HttpGenerator(); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE); String customValue = "test"; fields.add(HttpHeader.CONNECTION, customValue); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index de1e1b3b283d..2e581cbb168b 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -119,7 +119,7 @@ private void assertInvalidURI(String invalidURI, String message) @Test public void testParse() { - HttpURI.Builder builder = HttpURI.build(); + HttpURI.Mutable builder = HttpURI.build(); HttpURI uri; builder.uri("*"); @@ -204,7 +204,7 @@ public void testParams() throws Exception @Test public void testMutableURIBuilder() { - HttpURI.Builder builder = HttpURI.build("/foo/bar"); + HttpURI.Mutable builder = HttpURI.build("/foo/bar"); HttpURI uri = builder.asImmutable(); assertEquals("/foo/bar", uri.toString()); assertEquals("/foo/bar", uri.getPath()); @@ -250,7 +250,7 @@ public void testMutableURIBuilder() @Test public void testSchemeAndOrAuthority() throws Exception { - HttpURI.Builder builder = HttpURI.build("/path/info"); + HttpURI.Mutable builder = HttpURI.build("/path/info"); HttpURI uri = builder.asImmutable(); assertEquals("/path/info", uri.toString()); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index b7cc35b2edd2..235f13360f72 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -36,7 +36,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -267,7 +266,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .putLongField(downloadBytes, random.nextInt(128 * 1024)) .put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); @@ -807,7 +806,7 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.build() + HttpFields.Mutable requestFields = HttpFields.build() .put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java index 1040aadd00da..0b85ff51211d 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/PushCacheFilterTest.java @@ -33,7 +33,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -114,7 +113,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build() + HttpFields.Mutable secondaryFields = HttpFields.build() .put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -206,7 +205,7 @@ else if (requestURI.endsWith(secondaryResource)) // The referrerURI does not point to the primary resource, so there will be no // resource association with the primary resource and therefore won't be pushed. final String referrerURI = "http://localhost:" + connector.getLocalPort(); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -218,7 +217,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build() + HttpFields.Mutable secondaryFields = HttpFields.build() .put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -292,7 +291,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -304,7 +303,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build() + HttpFields.Mutable secondaryFields = HttpFields.build() .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -357,7 +356,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS)); // Make sure the session is sane by requesting the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); + HttpFields.Mutable secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); final CountDownLatch secondaryResponseLatch = new CountDownLatch(1); @@ -395,7 +394,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -406,7 +405,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); + HttpFields.Mutable secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -486,7 +485,7 @@ else if (requestURI.endsWith(secondaryResource2)) // Request for the primary, secondary and tertiary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(2); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -499,7 +498,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) { // Request for the secondary resources. String secondaryURI1 = newURI(secondaryResource1); - HttpFieldsBuilder secondaryFields1 = HttpFields.build() + HttpFields.Mutable secondaryFields1 = HttpFields.build() .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest1 = newRequest("GET", secondaryResource1, secondaryFields1); session.newStream(new HeadersFrame(secondaryRequest1, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -511,7 +510,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the tertiary resource. - HttpFieldsBuilder tertiaryFields = HttpFields.build() + HttpFields.Mutable tertiaryFields = HttpFields.build() .put(HttpHeader.REFERER, secondaryURI1); MetaData.Request tertiaryRequest = newRequest("GET", tertiaryResource, tertiaryFields); session.newStream(new HeadersFrame(tertiaryRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -528,7 +527,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) } }); - HttpFieldsBuilder secondaryFields2 = HttpFields.build() + HttpFields.Mutable secondaryFields2 = HttpFields.build() .put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest2 = newRequest("GET", secondaryResource2, secondaryFields2); session.newStream(new HeadersFrame(secondaryRequest2, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -675,7 +674,7 @@ else if ("secret".equals(credentials)) final Session session = newClient(new Session.Listener.Adapter()); // Login with the wrong credentials, causing a redirect to self. - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource + "?credentials=wrong", primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -690,7 +689,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) { // Follow the redirect. String location = response.getFields().get(HttpHeader.LOCATION); - HttpFieldsBuilder redirectFields = HttpFields.build(); + HttpFields.Mutable redirectFields = HttpFields.build(); redirectFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request redirectRequest = newRequest("GET", location, redirectFields); session.newStream(new HeadersFrame(redirectRequest, null, true), new Promise.Adapter<>(), new Adapter() @@ -768,7 +767,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String primaryURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -779,7 +778,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); + HttpFields.Mutable secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, primaryURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -861,7 +860,7 @@ else if (requestURI.endsWith(secondaryResource)) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -873,7 +872,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); + HttpFields.Mutable secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -956,7 +955,7 @@ public Map onPreface(Session session) // Request for the primary and secondary resource to build the cache. final String referrerURI = newURI(primaryResource); - HttpFieldsBuilder primaryFields = HttpFields.build(); + HttpFields.Mutable primaryFields = HttpFields.build(); MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields); final CountDownLatch warmupLatch = new CountDownLatch(1); session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() @@ -968,7 +967,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) if (frame.isEndStream()) { // Request for the secondary resource. - HttpFieldsBuilder secondaryFields = HttpFields.build(); + HttpFields.Mutable secondaryFields = HttpFields.build(); secondaryFields.put(HttpHeader.REFERER, referrerURI); MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields); session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter() diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java index 7394d67cff74..3ebfc00e5571 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/RawHTTP2ProxyTest.java @@ -32,7 +32,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersion; @@ -206,7 +205,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) Session clientSession = clientPromise.get(5, TimeUnit.SECONDS); // Send a request with trailers for server1. - HttpFieldsBuilder fields1 = HttpFields.build(); + HttpFields.Mutable fields1 = HttpFields.build(); fields1.put("X-Target", String.valueOf(connector1.getLocalPort())); MetaData.Request request1 = new MetaData.Request("GET", HttpURI.from("http://localhost/server1"), HttpVersion.HTTP_2, fields1); FuturePromise streamPromise1 = new FuturePromise<>(); @@ -234,7 +233,7 @@ public void onData(Stream stream, DataFrame frame, Callback callback) stream1.headers(new HeadersFrame(stream1.getId(), new MetaData(HttpVersion.HTTP_2, HttpFields.EMPTY), null, true), Callback.NOOP); // Send a request for server2. - HttpFieldsBuilder fields2 = HttpFields.build(); + HttpFields.Mutable fields2 = HttpFields.build(); fields2.put("X-Target", String.valueOf(connector2.getLocalPort())); MetaData.Request request2 = new MetaData.Request("GET", HttpURI.from("http://localhost/server1"), HttpVersion.HTTP_2, fields2); FuturePromise streamPromise2 = new FuturePromise<>(); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java index bfec3429992d..9086ab270b35 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/TrailersTest.java @@ -33,7 +33,6 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; @@ -90,7 +89,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.build(); + HttpFields.Mutable requestFields = HttpFields.build(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -99,7 +98,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) Stream stream = streamPromise.get(5, TimeUnit.SECONDS); // Send the trailers. - HttpFieldsBuilder trailerFields = HttpFields.build(); + HttpFields.Mutable trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -141,7 +140,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); - HttpFieldsBuilder requestFields = HttpFields.build(); + HttpFields.Mutable requestFields = HttpFields.build(); requestFields.put("X-Request", "true"); MetaData.Request request = newRequest("GET", requestFields); HeadersFrame requestFrame = new HeadersFrame(request, null, false); @@ -169,7 +168,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) // Send the trailers. callback.thenRun(() -> { - HttpFieldsBuilder trailerFields = HttpFields.build(); + HttpFields.Mutable trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailers = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailers, null, true); @@ -187,7 +186,7 @@ public void testTrailersSentByServer() throws Exception @Override public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) { - HttpFieldsBuilder responseFields = HttpFields.build(); + HttpFields.Mutable responseFields = HttpFields.build(); responseFields.put("X-Response", "true"); MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, responseFields); HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, false); @@ -196,7 +195,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) @Override public void succeeded() { - HttpFieldsBuilder trailerFields = HttpFields.build(); + HttpFields.Mutable trailerFields = HttpFields.build(); trailerFields.put("X-Trailer", "true"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -251,7 +250,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) { Request jettyRequest = (Request)request; Response jettyResponse = jettyRequest.getResponse(); - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields.Mutable trailers = HttpFields.build(); jettyResponse.setTrailerFields(() -> trailers.stream().collect(Collectors.toMap(HttpField::getName, HttpField::getValue))); @@ -317,7 +316,7 @@ public void testRequestTrailerInvalidHpackSent() throws Exception completable.thenRun(() -> { // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.build(); + HttpFields.Mutable trailerFields = HttpFields.build(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); @@ -376,7 +375,7 @@ public void onReset(Stream stream, ResetFrame frame) // Disable checks for invalid headers. ((HTTP2Session)session).getGenerator().setValidateHpackEncoding(false); // Invalid trailer: cannot contain pseudo headers. - HttpFieldsBuilder trailerFields = HttpFields.build(); + HttpFields.Mutable trailerFields = HttpFields.build(); trailerFields.put(HttpHeader.C_METHOD, "GET"); MetaData trailer = new MetaData(HttpVersion.HTTP_2, trailerFields); HeadersFrame trailerFrame = new HeadersFrame(stream.getId(), trailer, null, true); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java index 02bc966b2adb..6df768cdf29d 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/HeadersGenerateParseTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -125,7 +124,7 @@ public void onHeaders(HeadersFrame frame) for (int i = 0; i < 2; ++i) { int streamId = 13; - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("Accept", "text/html") .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); diff --git a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java index 9e571b933eee..c94f783ffd50 100644 --- a/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java +++ b/jetty-http2/http2-common/src/test/java/org/eclipse/jetty/http2/frames/PushPromiseGenerateParseTest.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -63,7 +62,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("Accept", "text/html") .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); @@ -116,7 +115,7 @@ public void onPushPromise(PushPromiseFrame frame) int streamId = 13; int promisedStreamId = 17; - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("Accept", "text/html") .put("User-Agent", "Jetty"); MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:8080"), "/path", HttpVersion.HTTP_2, fields, -1); diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index 2d367ef12019..2a00686edd48 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -21,7 +21,6 @@ import org.eclipse.jetty.http.HostPortHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpScheme; @@ -32,7 +31,7 @@ public class MetaDataBuilder { private final int _maxSize; - private final HttpFieldsBuilder _fields = HttpFields.build(); + private final HttpFields.Mutable _fields = HttpFields.build(); private int _size; private Integer _status; private String _method; @@ -236,7 +235,7 @@ public MetaData build() throws HpackException.StreamException if (_request && _response) throw new HpackException.StreamException("Request and Response headers"); - HttpFieldsBuilder fields = _fields; + HttpFields.Mutable fields = _fields; try { if (_request) diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java index a56e31b63b89..cfd0178abd13 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackEncoderTest.java @@ -22,7 +22,6 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.util.BufferUtil; @@ -39,7 +38,7 @@ public class HpackEncoderTest public void testUnknownFieldsContextManagement() throws Exception { HpackEncoder encoder = new HpackEncoder(38 * 5); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); HttpField[] field = { @@ -152,7 +151,7 @@ public void testNeverIndexSetCookie() throws Exception HpackEncoder encoder = new HpackEncoder(38 * 5); ByteBuffer buffer = BufferUtil.allocate(4096); - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("set-cookie", "some cookie value"); // encode @@ -181,7 +180,7 @@ public void testNeverIndexSetCookie() throws Exception @Test public void testFieldLargerThanTable() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); HpackEncoder encoder = new HpackEncoder(128); ByteBuffer buffer0 = BufferUtil.allocate(4096); diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java index ace537223ca2..5d4d8588f724 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackPerfTest.java @@ -24,7 +24,6 @@ import java.util.Map; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; @@ -108,7 +107,7 @@ private void encodeStories(ByteBuffer buffer, Map[] stories, Str var kase = (Map)c; Object[] headers = (Object[])kase.get("headers"); // System.err.println(" "+headers); - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); for (Object header : headers) { @SuppressWarnings("unchecked") diff --git a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java index 78daa873bac5..b1f631712469 100644 --- a/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java +++ b/jetty-http2/http2-hpack/src/test/java/org/eclipse/jetty/http2/hpack/HpackTest.java @@ -24,7 +24,6 @@ import org.eclipse.jetty.http.DateGenerator; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -53,7 +52,7 @@ public void encodeDecodeResponseTest() throws Exception HpackDecoder decoder = new HpackDecoder(4096, 8192); ByteBuffer buffer = BufferUtil.allocateDirect(16 * 1024); - HttpFieldsBuilder fields0 = HttpFields.build() + HttpFields.Mutable fields0 = HttpFields.build() .add(HttpHeader.CONTENT_TYPE, "text/html") .add(HttpHeader.CONTENT_LENGTH, "1024") .add(new HttpField(HttpHeader.CONTENT_ENCODING, (String)null)) @@ -81,7 +80,7 @@ public void encodeDecodeResponseTest() throws Exception assertMetaDataResponseSame(nullToEmpty, decoded0b); - HttpFieldsBuilder fields1 = HttpFields.build() + HttpFields.Mutable fields1 = HttpFields.build() .add(HttpHeader.CONTENT_TYPE, "text/plain") .add(HttpHeader.CONTENT_LENGTH, "1234") .add(HttpHeader.CONTENT_ENCODING, " ") diff --git a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java index 3b0b118ea083..776894af24b9 100644 --- a/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java +++ b/jetty-http2/http2-http-client-transport/src/test/java/org/eclipse/jetty/http2/client/http/RequestTrailersTest.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.client.util.AsyncRequestContent; import org.eclipse.jetty.client.util.StringRequestContent; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -80,7 +79,7 @@ public void onHeaders(Stream stream, HeadersFrame frame) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields.Mutable trailers = HttpFields.build(); request.trailers(() -> trailers); if (content != null) request.body(new StringRequestContent(content)); @@ -120,7 +119,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields.Mutable trailers = HttpFields.build(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); @@ -169,7 +168,7 @@ public void onData(Stream stream, DataFrame dataFrame, Callback callback) }); HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort()); - HttpFieldsBuilder trailers = HttpFields.build(); + HttpFields.Mutable trailers = HttpFields.build(); request.trailers(() -> trailers); AsyncRequestContent content = new AsyncRequestContent(); request.body(content); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java index 6a431f8823d5..91817919dcbd 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2CServerConnectionFactory.java @@ -19,7 +19,7 @@ package org.eclipse.jetty.http2.server; import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.MetaData.Request; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -71,7 +71,7 @@ public boolean isAcceptable(String protocol, String tlsProtocol, String tlsCiphe } @Override - public Connection upgradeConnection(Connector connector, EndPoint endPoint, Request request, HttpFieldsBuilder response101) throws BadMessageException + public Connection upgradeConnection(Connector connector, EndPoint endPoint, Request request, HttpFields.Mutable response101) throws BadMessageException { if (LOG.isDebugEnabled()) LOG.debug("{} upgrading {}{}{}", this, request, System.lineSeparator(), request.getFields()); diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java index 458d1c02c2d0..6c0de97c0f4f 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HTTP2ServerConnection.java @@ -32,7 +32,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; @@ -320,7 +320,7 @@ private HttpChannelOverHTTP2 pollHttpChannel() } } - public boolean upgrade(Request request, HttpFieldsBuilder responseFields) + public boolean upgrade(Request request, HttpFields.Mutable responseFields) { if (HttpMethod.PRI.is(request.getMethod())) { diff --git a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java index 47bd11ef7d2b..a54e6769c556 100644 --- a/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java +++ b/jetty-http2/http2-server/src/main/java/org/eclipse/jetty/http2/server/HttpChannelOverHTTP2.java @@ -26,7 +26,6 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -113,7 +112,7 @@ public Runnable onRequest(HeadersFrame frame) _expect100Continue = fields.contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); - HttpFieldsBuilder response = getResponse().getHttpFields(); + HttpFields.Mutable response = getResponse().getHttpFields(); if (getHttpConfiguration().getSendServerVersion()) response.add(SERVER_VERSION); if (getHttpConfiguration().getSendXPoweredBy()) diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java index 27f74c2f2b26..d29dbad3b267 100644 --- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java +++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AbstractProxyServlet.java @@ -45,7 +45,6 @@ import org.eclipse.jetty.client.dynamic.HttpClientTransportDynamic; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpScheme; @@ -470,7 +469,7 @@ protected boolean expects100Continue(HttpServletRequest request) protected void copyRequestHeaders(HttpServletRequest clientRequest, Request proxyRequest) { // First clear possibly existing headers, as we are going to copy those from the client request. - HttpFieldsBuilder newHeaders = HttpFields.build(); + HttpFields.Mutable newHeaders = HttpFields.build(); Set headersToRemove = findConnectionHeaders(clientRequest); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java index 8384d8eb7c71..312109ae5997 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/MsieSslRuleTest.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.rewrite.handler; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.junit.jupiter.api.BeforeEach; @@ -43,7 +42,7 @@ public void init() throws Exception @Test public void testWin2kSP1WithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); + HttpFields.Mutable fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.01)"); _request.setHttpFields(fields); @@ -92,7 +91,7 @@ public void testWin2kSP1WithIE7() throws Exception @Test public void testWin2kWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); + HttpFields.Mutable fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0)"); _request.setHttpFields(fields); @@ -142,7 +141,7 @@ public void testWin2kWithIE7() throws Exception @Test public void testWinVistaWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); + HttpFields.Mutable fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 6.0)"); _request.setHttpFields(fields); @@ -191,7 +190,7 @@ public void testWinVistaWithIE7() throws Exception @Test public void testWinXpWithIE5() throws Exception { - HttpFieldsBuilder fields = HttpFields.build(_request.getHttpFields()); + HttpFields.Mutable fields = HttpFields.build(_request.getHttpFields()); fields.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.1)"); _request.setHttpFields(fields); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java index 800b2642bc5a..62d14f37732e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ConnectionFactory.java @@ -22,7 +22,7 @@ import java.util.List; import org.eclipse.jetty.http.BadMessageException; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.MetaData; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; @@ -84,7 +84,7 @@ public interface Upgrading extends ConnectionFactory * indicate that the upgrade should proceed. * @throws BadMessageException Thrown to indicate the upgrade attempt was illegal and that a bad message response should be sent. */ - public Connection upgradeConnection(Connector connector, EndPoint endPoint, MetaData.Request upgradeRequest, HttpFieldsBuilder responseFields) throws BadMessageException; + public Connection upgradeConnection(Connector connector, EndPoint endPoint, MetaData.Request upgradeRequest, HttpFields.Mutable responseFields) throws BadMessageException; } /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java index 31066f69e869..39ce7e89c0e5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java @@ -399,7 +399,7 @@ public void customize(Connector connector, HttpConfiguration config, Request req if (match) { - HttpURI.Builder builder = HttpURI.build(request.getHttpURI()); + HttpURI.Mutable builder = HttpURI.build(request.getHttpURI()); if (forwarded._proto != null) { builder.scheme(forwarded._proto); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 0df6d49fad4a..48d8871cf678 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -36,7 +36,6 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; @@ -675,7 +674,7 @@ public void onRequest(MetaData.Request request) { _requests.incrementAndGet(); _request.setTimeStamp(System.currentTimeMillis()); - HttpFieldsBuilder fields = _response.getHttpFields(); + HttpFields.Mutable fields = _response.getHttpFields(); if (_configuration.getSendDateHeader() && !fields.contains(HttpHeader.DATE)) fields.put(_connector.getServer().getDateField()); @@ -792,7 +791,7 @@ public void onBadMessage(BadMessageException failure) if (action == Action.DISPATCH) { ByteBuffer content = null; - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); ErrorHandler handler = getServer().getBean(ErrorHandler.class); if (handler != null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index fd32b17d1fe2..c6ec24f0a871 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.http.HttpCompliance; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -61,7 +60,7 @@ public class HttpChannelOverHttp extends HttpChannel implements HttpParser.Reque private boolean _expect100Continue = false; private boolean _expect102Processing = false; private List _complianceViolations; - private HttpFieldsBuilder _trailers; + private HttpFields.Mutable _trailers; public HttpChannelOverHttp(HttpConnection httpConnection, Connector connector, HttpConfiguration config, EndPoint endPoint, HttpTransport transport) { @@ -503,7 +502,7 @@ private boolean upgrade() throws BadMessageException } // Create new connection - HttpFieldsBuilder response101 = HttpFields.build(); + HttpFields.Mutable response101 = HttpFields.build(); Connection upgradeConnection = factory.upgradeConnection(getConnector(), getEndPoint(), _metadata, response101); if (upgradeConnection == null) { @@ -544,8 +543,8 @@ boolean onIdleTimeout(Throwable timeout) private static class RequestBuilder { - private final HttpFieldsBuilder _fieldBuilder = HttpFields.build(); - private final HttpURI.Builder _uri = HttpURI.build(); + private final HttpFields.Mutable _fieldBuilder = HttpFields.build(); + private final HttpURI.Mutable _uri = HttpURI.build(); private String _method; private HttpVersion _version; @@ -562,7 +561,7 @@ public void request(String method, String uri, HttpVersion version) _fieldBuilder.clear(); } - public HttpFieldsBuilder getFields() + public HttpFields.Mutable getFields() { return _fieldBuilder; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java index 354a4ad3ebb3..ab745646d884 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/PushBuilderImpl.java @@ -23,7 +23,6 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpURI; @@ -42,7 +41,7 @@ public class PushBuilderImpl implements PushBuilder private static final HttpField JettyPush = new HttpField("x-http2-push", "PushBuilder"); private final Request _request; - private final HttpFieldsBuilder _fields; + private final HttpFields.Mutable _fields; private String _method; private String _queryString; private String _sessionId; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 6e0a9f5227af..e76659d2fdc9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -74,7 +74,6 @@ import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -389,7 +388,7 @@ public PushBuilder newPushBuilder() if (!isPushSupported()) return null; - HttpFieldsBuilder fields = HttpFields.build(getHttpFields(), NOT_PUSHED_HEADERS); + HttpFields.Mutable fields = HttpFields.build(getHttpFields(), NOT_PUSHED_HEADERS); String id; try @@ -1677,7 +1676,7 @@ public void setMetaData(MetaData.Request request) _uri = uri; else { - HttpURI.Builder builder = HttpURI.build(uri); + HttpURI.Mutable builder = HttpURI.build(uri); if (uri.isAbsolute()) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 82f19fe7843f..93909ade0a03 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -40,7 +40,7 @@ import org.eclipse.jetty.http.DateParser; import org.eclipse.jetty.http.HttpContent; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http.QuotedCSV; @@ -846,7 +846,7 @@ protected void putHeaders(HttpServletResponse response, HttpContent content, lon { Response r = (Response)response; r.putHeaders(content, contentLength, _etags); - HttpFieldsBuilder f = r.getHttpFields(); + HttpFields.Mutable f = r.getHttpFields(); if (_acceptRanges) f.put(ACCEPT_RANGES); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 69536359b853..6d5919d7d063 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -45,7 +45,6 @@ import org.eclipse.jetty.http.HttpCookie.SetCookieHttpField; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; @@ -85,7 +84,7 @@ public enum OutputType public static final String SET_INCLUDE_HEADER_PREFIX = "org.eclipse.jetty.server.include."; private final HttpChannel _channel; - private final HttpFieldsBuilder _fields = HttpFields.build(); + private final HttpFields.Mutable _fields = HttpFields.build(); private final AtomicBiInteger _errorSentAndIncludes = new AtomicBiInteger(); // hi is errorSent flag, lo is include count private final HttpOutput _out; private int _status = HttpStatus.OK_200; @@ -1307,7 +1306,7 @@ public String getReason() return _reason; } - public HttpFieldsBuilder getHttpFields() + public HttpFields.Mutable getHttpFields() { return _fields; } @@ -1431,7 +1430,7 @@ public HttpFields get() Map t = _supplier.get(); if (t == null) return null; - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); for (Map.Entry e : t.entrySet()) { fields.add(e.getKey(), e.getValue()); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index e175561c304c..d118bdc7c896 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -606,7 +606,7 @@ public void handleAsync(HttpChannel channel) throws IOException, ServletExceptio if (baseUri == null) baseUri = oldUri; - HttpURI.Builder builder = HttpURI.build(baseUri, encodedPathQuery); + HttpURI.Mutable builder = HttpURI.build(baseUri, encodedPathQuery); if (StringUtil.isEmpty(builder.getParam())) builder.param(baseUri.getParam()); if (StringUtil.isEmpty(builder.getQuery())) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 2ad22ff4456b..271b2488ad57 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -2152,7 +2152,7 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) } else { - HttpURI.Builder builder = HttpURI.build(uriInContext); + HttpURI.Mutable builder = HttpURI.build(uriInContext); if (StringUtil.isEmpty(URIUtil.canonicalPath(builder.getDecodedPath()))) return null; builder.path(URIUtil.addPaths(contextPath,builder.getPath())); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java index e5458c87a45b..87af9e2a345e 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java @@ -36,7 +36,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.MimeTypes; @@ -56,7 +56,7 @@ * An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or * {@link Server#setErrorHandler(ErrorHandler)}. * It is called by the HttpResponse.sendError method to write an error page via {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} - * or via {@link #badMessageError(int, String, HttpFieldsBuilder)} for bad requests for which a dispatch cannot be done. + * or via {@link #badMessageError(int, String, HttpFields.Mutable)} for bad requests for which a dispatch cannot be done. */ public class ErrorHandler extends AbstractHandler { @@ -521,7 +521,7 @@ protected void writeErrorPageStacks(HttpServletRequest request, Writer writer) * @param fields The header fields that will be sent with the response. * @return The content as a ByteBuffer, or null for no body. */ - public ByteBuffer badMessageError(int status, String reason, HttpFieldsBuilder fields) + public ByteBuffer badMessageError(int status, String reason, HttpFields.Mutable fields) { if (reason == null) reason = HttpStatus.getMessage(status); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java index a8f5a9071ccf..8f678f31dd00 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHandler.java @@ -33,7 +33,6 @@ import org.eclipse.jetty.http.CompressedContentFormat; import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpMethod; @@ -620,7 +619,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques // Update headers for etags and inflation if (inflated || httpFields.contains(ETAG_HEADERS)) { - HttpFieldsBuilder newFields = HttpFields.build(httpFields.size() + 1); + HttpFields.Mutable newFields = HttpFields.build(httpFields.size() + 1); for (HttpField field : httpFields) { if (field.getHeader() == null) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java index e2da22561c56..8b1a16d9c8c1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/gzip/GzipHttpOutputInterceptor.java @@ -25,7 +25,7 @@ import java.util.zip.Deflater; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.http.PreEncodedHttpField; @@ -175,7 +175,7 @@ protected void commit(ByteBuffer content, boolean complete, Callback callback) } // Has the Content-Encoding header already been set? - HttpFieldsBuilder fields = response.getHttpFields(); + HttpFields.Mutable fields = response.getHttpFields(); String ce = fields.get(HttpHeader.CONTENT_ENCODING); if (ce != null) { diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java index 6d8759390d73..8010e7e13331 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java @@ -24,7 +24,6 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.LocalConnector.LocalEndPoint; @@ -83,7 +82,7 @@ public void test33() { try { - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("D1", "Sun, 6 Nov 1994 08:49:37 GMT") .put("D2", "Sunday, 6-Nov-94 08:49:37 GMT") .put("D3", "Sun Nov 6 08:49:37 1994"); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 2c9906eb35f6..e134fb338c83 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -950,7 +950,7 @@ public void testSendRedirect() Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - HttpURI.Builder builder = HttpURI.build(request.getHttpURI(), + HttpURI.Mutable builder = HttpURI.build(request.getHttpURI(), "/path/info;param;jsessionid=12345?query=0&more=1#target"); builder.scheme("http"); if (host != null) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java index 8eb6e6a9a61a..c5afed2d7b7a 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/ClientUpgradeRequest.java @@ -38,7 +38,7 @@ import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; @@ -154,7 +154,7 @@ public List getSubProtocols() public void setSubProtocols(String... protocols) { - HttpFieldsBuilder headers = getHeaders(); + HttpFields.Mutable headers = getHeaders(); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); for (String protocol : protocols) { @@ -164,7 +164,7 @@ public void setSubProtocols(String... protocols) public void setSubProtocols(List protocols) { - HttpFieldsBuilder headers = getHeaders(); + HttpFields.Mutable headers = getHeaders(); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); for (String protocol : protocols) { diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java index cf8ed3d497fd..2c4df763b0bb 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/server/internal/RFC6455Handshaker.java @@ -23,7 +23,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpVersion; @@ -106,7 +106,7 @@ protected WebSocketConnection createWebSocketConnection(Request baseRequest, Web protected void prepareResponse(Response response, Negotiation negotiation) { response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); - HttpFieldsBuilder responseFields = response.getHttpFields(); + HttpFields.Mutable responseFields = response.getHttpFields(); responseFields.put(UPGRADE_WEBSOCKET); responseFields.put(CONNECTION_UPGRADE); responseFields.put(HttpHeader.SEC_WEBSOCKET_ACCEPT, WebSocketCore.hashKey(((RFC6455Negotiation)negotiation).getKey())); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java index 3492c9c19f88..313c968cac7c 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketNegotiationTest.java @@ -31,7 +31,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.logging.StacklessLogging; import org.eclipse.jetty.server.HttpChannel; @@ -255,7 +255,7 @@ public void testExtensionThatDoesNotExist() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFieldsBuilder httpFields = newUpgradeRequest("nonExistentExtensionName"); + HttpFields.Mutable httpFields = newUpgradeRequest("nonExistentExtensionName"); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1)); String response = getUpgradeResponse(client.getInputStream()); @@ -336,7 +336,7 @@ public void testValidUpgradeRequest() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFieldsBuilder httpFields = newUpgradeRequest(null); + HttpFields.Mutable httpFields = newUpgradeRequest(null); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; client.getOutputStream().write(upgradeRequest.getBytes(StandardCharsets.ISO_8859_1)); String response = getUpgradeResponse(client.getInputStream()); @@ -352,7 +352,7 @@ public void testInvalidUpgradeRequestNoKey() throws Exception Socket client = new Socket(); client.connect(new InetSocketAddress("127.0.0.1", server.getLocalPort())); - HttpFieldsBuilder httpFields = newUpgradeRequest(null); + HttpFields.Mutable httpFields = newUpgradeRequest(null); httpFields.remove(HttpHeader.SEC_WEBSOCKET_KEY); String upgradeRequest = "GET / HTTP/1.1\r\n" + httpFields; diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java index 409dd5e775a4..8ea7da37f895 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/WebSocketTester.java @@ -28,7 +28,6 @@ import java.util.Base64; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.io.ArrayByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool; @@ -87,9 +86,9 @@ protected Socket newClient(int port, String extensions) throws Exception return newClient(port, false, extensions); } - protected static HttpFieldsBuilder newUpgradeRequest(String extensions) + protected static HttpFields.Mutable newUpgradeRequest(String extensions) { - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .add(HttpHeader.HOST, "127.0.0.1") .add(HttpHeader.UPGRADE, "websocket") .add(HttpHeader.CONNECTION, "Upgrade") diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java index d8e0b1f1c2fe..9dc1edbfdeb6 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java @@ -26,7 +26,7 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.websocket.core.CoreSession; import org.eclipse.jetty.websocket.core.ExtensionConfig; @@ -106,7 +106,7 @@ public void testClientDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @deflate_buffer_size=" + deflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -121,7 +121,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFieldsBuilder requestHeaders = futureRequestHeaders.get(); + HttpFields.Mutable requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -160,7 +160,7 @@ public void testClientInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @inflate_buffer_size=" + inflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -175,7 +175,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFieldsBuilder requestHeaders = futureRequestHeaders.get(); + HttpFields.Mutable requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -215,7 +215,7 @@ public void testServerDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -230,7 +230,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFieldsBuilder responseHeaders = futureResponseHeaders.get(); + HttpFields.Mutable responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -270,7 +270,7 @@ public void testServerInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -285,7 +285,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFieldsBuilder responseHeaders = futureResponseHeaders.get(); + HttpFields.Mutable responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); diff --git a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java index 55c4fd18e826..0df4048e05f2 100644 --- a/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java +++ b/jetty-websocket/websocket-javax-client/src/main/java/org/eclipse/jetty/websocket/javax/client/internal/JsrUpgradeListener.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.client.HttpRequest; import org.eclipse.jetty.client.HttpResponse; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.websocket.core.client.UpgradeListener; public class JsrUpgradeListener implements UpgradeListener @@ -49,7 +48,7 @@ public void onHandshakeRequest(HttpRequest request) return; } - HttpFieldsBuilder fields = request.getHeaders(); + HttpFields.Mutable fields = request.getHeaders(); Map> originalHeaders = new HashMap<>(); fields.forEach((field) -> diff --git a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java index 02a6bd0b9e4d..b0ac7588cf44 100644 --- a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java +++ b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/NetworkFuzzer.java @@ -30,7 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; @@ -72,7 +72,7 @@ public NetworkFuzzer(LocalServer server, URI wsURI, Map requestH this.upgradeRequest = new RawUpgradeRequest(client, wsURI); if (requestHeaders != null) { - HttpFieldsBuilder fields = this.upgradeRequest.getHeaders(); + HttpFields.Mutable fields = this.upgradeRequest.getHeaders(); requestHeaders.forEach((name, value) -> { fields.remove(name); diff --git a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java index 25211c92ec86..52938a7b9e6a 100644 --- a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java +++ b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java @@ -24,7 +24,7 @@ import java.util.stream.Collectors; import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; @@ -49,14 +49,14 @@ public JettyClientUpgradeRequest(WebSocketCoreClient coreClient, UpgradeRequest if (request != null) { // Copy request details into actual request - HttpFieldsBuilder fields = getHeaders(); + HttpFields.Mutable fields = getHeaders(); request.getHeaders().forEach(fields::put); // Copy manually created Cookies into place List cookies = request.getCookies(); if (cookies != null) { - HttpFieldsBuilder headers = getHeaders(); + HttpFields.Mutable headers = getHeaders(); // TODO: remove existing Cookie header (if set)? for (HttpCookie cookie : cookies) { diff --git a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java index da6d8fe745b3..0d9f1cb136da 100644 --- a/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java +++ b/tests/jetty-http-tools/src/main/java/org/eclipse/jetty/http/tools/HttpTester.java @@ -28,7 +28,7 @@ import org.eclipse.jetty.http.BadMessageException; import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFieldsBuilder; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpMethod; @@ -289,7 +289,7 @@ private static void parseResponse(Input in, HttpParser parser, Response r) throw } } - public abstract static class Message extends HttpFieldsBuilder implements HttpParser.HttpHandler + public abstract static class Message extends HttpFields.Mutable implements HttpParser.HttpHandler { boolean _earlyEOF; boolean _complete = false; diff --git a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java index eb08da492c30..3732ceccdd67 100644 --- a/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java +++ b/tests/jetty-http-tools/src/test/java/org/eclipse/jetty/http/tools/matchers/HttpFieldsMatchersTest.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.http.tools.matchers; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; @@ -43,7 +42,7 @@ public void testContainsHeader() @Test public void testNotContainsHeader() { - HttpFieldsBuilder fields = HttpFields.build() + HttpFields.Mutable fields = HttpFields.build() .put("a", "foo") .put("b", "bar") .put("c", "fizz"); @@ -59,7 +58,7 @@ public void testNotContainsHeader() @Test public void testContainsHeaderMisMatch() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -75,7 +74,7 @@ public void testContainsHeaderMisMatch() @Test public void testContainsHeaderValueMisMatchNoSuchHeader() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -91,7 +90,7 @@ public void testContainsHeaderValueMisMatchNoSuchHeader() @Test public void testContainsHeaderValueMisMatchNoSuchValue() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); @@ -107,7 +106,7 @@ public void testContainsHeaderValueMisMatchNoSuchValue() @Test public void testContainsHeaderValue() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("a", "foo"); fields.put("b", "bar"); fields.put("c", "fizz"); diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java index 850faecb9f12..6848225b62d6 100644 --- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java +++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpFieldsBuilder; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; @@ -138,7 +137,7 @@ public void test33() expected.set(Calendar.ZONE_OFFSET, 0); // Use GMT+0:00 expected.set(Calendar.DST_OFFSET, 0); // No Daylight Savings Offset - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); // RFC 822 Preferred Format fields.put("D1", "Sun, 6 Nov 1994 08:49:37 GMT"); @@ -335,7 +334,7 @@ public void test364() throws Throwable @Test public void test39() { - HttpFieldsBuilder fields = HttpFields.build(); + HttpFields.Mutable fields = HttpFields.build(); fields.put("Q", "bbb;q=0.5,aaa,ccc;q=0.002,d;q=0,e;q=0.0001,ddd;q=0.001,aa2,abb;q=0.7"); List list = fields.getQualityCSV("Q"); From 89aa96902e9d1ee67165552fc5a8da1fb3ac32c9 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2020 17:51:26 +0200 Subject: [PATCH 26/38] Immutable MetaData WIP misc cleanups Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpFields.java | 4 +- .../java/org/eclipse/jetty/http/HttpURI.java | 155 ++++-------------- .../eclipse/jetty/http/HttpURIParseTest.java | 18 +- .../org/eclipse/jetty/http/HttpURITest.java | 7 +- .../org/eclipse/jetty/server/Response.java | 8 +- 5 files changed, 58 insertions(+), 134 deletions(-) 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 305ab8a4e056..6b2e67e028d8 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 @@ -33,7 +33,9 @@ import java.util.stream.Stream; /** - * Interface that represents readonly list of {@link HttpField}s. + * Interface that represents on ordered collection of {@link HttpField}s. + * Both {@link Mutable} and {@link Immutable} implementations are available + * via the static methods such as {@link #build()} and {@link #from(HttpField...)}. */ public interface HttpFields extends Iterable { diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index 0ebebc2362c3..f7887c30bb43 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -29,9 +29,13 @@ /** * Http URI. - * Parse an HTTP URI from a string or byte array. Given a URI - * http://user@host:port/path/info;param?query#fragment - * this class will split it into the following undecoded optional elements:

    + * + * Both {@link HttpFields.Mutable} and {@link HttpFields.Immutable} implementations are available + * via the static methods such as {@link #build()} and {@link #from(String)}. + * + * A URI such as + * http://user@host:port/path;ignored/info;param?query#ignored + * is split into the following undecoded elements:
      *
    • {@link #getScheme()} - http:
    • *
    • {@link #getAuthority()} - //name@host:port
    • *
    • {@link #getHost()} - host
    • @@ -39,12 +43,10 @@ *
    • {@link #getPath()} - /path/info
    • *
    • {@link #getParam()} - param
    • *
    • {@link #getQuery()} - query
    • - *
    • {@link #getFragment()} - fragment
    • *
    - * *

    Any parameters will be returned from {@link #getPath()}, but are excluded from the * return value of {@link #getDecodedPath()}. If there are multiple parameters, the - * {@link #getParam()} method returns only the last one. + * {@link #getParam()} method returns only the last one. Fragments are ignored. */ public interface HttpURI { @@ -80,18 +82,18 @@ static Mutable build(String uri) static Immutable from(URI uri) { - return new HttpURI.Immutable(uri); + return new HttpURI.Mutable(uri).asImmutable(); } static Immutable from(String uri) { - return new HttpURI.Immutable(uri); + return new HttpURI.Mutable(uri).asImmutable(); } static Immutable from(String method, String uri) { if (HttpMethod.CONNECT.is(method)) - return new Immutable(uri, null, null, null, -1, uri, null, null, null, null); + return new Immutable(uri); if (uri.startsWith("/")) return HttpURI.build().pathQuery(uri).asImmutable(); return HttpURI.from(uri); @@ -99,7 +101,7 @@ static Immutable from(String method, String uri) static Immutable from(String scheme, String host, int port, String pathQuery) { - return new Immutable(scheme, host, port, pathQuery); + return new Mutable(scheme, host, port, pathQuery).asImmutable(); } Immutable asImmutable(); @@ -108,17 +110,10 @@ static Immutable from(String scheme, String host, int port, String pathQuery) String getDecodedPath(); - String getFragment(); - String getHost(); String getParam(); - /** - * The parsed Path. - * - * @return the path as parsed on valid URI. null for invalid URI. - */ String getPath(); String getPathQuery(); @@ -133,8 +128,6 @@ static Immutable from(String scheme, String host, int port, String pathQuery) boolean hasAuthority(); - boolean hasQuery(); - boolean isAbsolute(); default URI toURI() @@ -142,7 +135,7 @@ default URI toURI() try { String query = getQuery(); - return new URI(getScheme(), null, getHost(), getPort(), getPath(), query == null ? null : UrlEncoded.decodeString(query), getFragment()); + return new URI(getScheme(), null, getHost(), getPort(), getPath(), query == null ? null : UrlEncoded.decodeString(query), null); } catch (URISyntaxException x) { @@ -159,28 +152,11 @@ class Immutable implements HttpURI private final String _path; private final String _param; private final String _query; - private final String _fragment; private String _uri; private String _decodedPath; - private Immutable(String uri) - { - Mutable builder = new Mutable(uri); - _uri = builder._uri; - _scheme = builder._scheme; - _user = builder._user; - _host = builder._host; - _port = builder._port; - _path = builder._path; - _decodedPath = builder._decodedPath; - _param = builder._param; - _query = builder._query; - _fragment = builder._fragment; - } - - private Immutable(URI uri) + private Immutable(Mutable builder) { - Mutable builder = new Mutable(uri); _uri = builder._uri; _scheme = builder._scheme; _user = builder._user; @@ -190,36 +166,19 @@ private Immutable(URI uri) _decodedPath = builder._decodedPath; _param = builder._param; _query = builder._query; - _fragment = builder._fragment; - } - - private Immutable(String scheme, String host, int port, String pathQuery) - { - Mutable builder = build().scheme(scheme).host(host).port(port).pathQuery(pathQuery); - _uri = null; - _scheme = builder._scheme; - _user = builder._user; - _host = builder._host; - _port = builder._port; - _path = builder._path; - _decodedPath = builder._decodedPath; - _param = builder._param; - _query = builder._query; - _fragment = builder._fragment; } - private Immutable(String uri, String scheme, String user, String host, int port, String path, String decodedPath, String param, String query, String fragment) + private Immutable(String uri) { _uri = uri; - _scheme = scheme; - _user = user; - _host = host; - _port = port; - _path = path; - _decodedPath = decodedPath; - _param = param; - _query = query; - _fragment = fragment; + _scheme = null; + _user = null; + _host = null; + _port = -1; + _path = uri; + _decodedPath = null; + _param = null; + _query = null; } @Override @@ -254,12 +213,6 @@ public String getDecodedPath() return _decodedPath; } - @Override - public String getFragment() - { - return _fragment; - } - @Override public String getHost() { @@ -275,11 +228,6 @@ public String getParam() return _param; } - /** - * The parsed Path. - * - * @return the path as parsed on valid URI. null for invalid URI. - */ @Override public String getPath() { @@ -324,12 +272,6 @@ public boolean hasAuthority() return _host != null; } - @Override - public boolean hasQuery() - { - return _query != null && !_query.isEmpty(); - } - @Override public boolean isAbsolute() { @@ -363,9 +305,6 @@ public String toString() if (_query != null) out.append('?').append(_query); - if (_fragment != null) - out.append('#').append(_fragment); - if (out.length() > 0) _uri = out.toString(); else @@ -379,7 +318,7 @@ public URI toURI() { try { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), null); } catch (URISyntaxException x) { @@ -414,7 +353,6 @@ private enum State private String _path; private String _param; private String _query; - private String _fragment; private Mutable() { @@ -446,7 +384,6 @@ private Mutable(HttpURI baseURI, String path, String param, String query) _path = path; _param = param; _query = query; - _fragment = null; } private Mutable(String uri) @@ -477,7 +414,6 @@ private Mutable(URI uri) _decodedPath = pathParam; } _query = uri.getRawQuery(); - _fragment = uri.getFragment(); } private Mutable(String scheme, String host, int port, String pathQuery) @@ -495,12 +431,13 @@ private Mutable(String scheme, String host, int port, String pathQuery) @Override public Immutable asImmutable() { - return new Immutable(_uri, _scheme, _user, _host, _port, _path, _decodedPath, _param, _query, _fragment); + return new Immutable(this); } /** * @param host the host * @param port the port + * @return this mutable */ public Mutable authority(String host, int port) { @@ -513,6 +450,7 @@ public Mutable authority(String host, int port) /** * @param hostport the host and port combined + * @return this mutable */ public Mutable authority(String hostport) { @@ -524,7 +462,7 @@ public Mutable authority(String hostport) return this; } - public void clear() + public Mutable clear() { _uri = null; _scheme = null; @@ -533,9 +471,9 @@ public void clear() _path = null; _param = null; _query = null; - _fragment = null; _decodedPath = null; _user = null; + return this; } public Mutable decodedPath(String path) @@ -546,13 +484,6 @@ public Mutable decodedPath(String path) return this; } - public Mutable fragment(String fragment) - { - _fragment = fragment; - _uri = null; - return this; - } - @Override public String getAuthority() { @@ -569,12 +500,6 @@ public String getDecodedPath() return _decodedPath; } - @Override - public String getFragment() - { - return _fragment; - } - @Override public String getHost() { @@ -630,12 +555,6 @@ public boolean hasAuthority() return _host != null; } - @Override - public boolean hasQuery() - { - return _query != null && !_query.isEmpty(); - } - public Mutable host(String host) { _host = host; @@ -672,6 +591,7 @@ public Mutable param(String param) /** * @param path the path + * @return this Mutuble */ public Mutable path(String path) { @@ -687,7 +607,6 @@ public Mutable pathQuery(String pathQuery) _path = null; _decodedPath = null; _param = null; - _fragment = null; if (pathQuery != null) parse(State.PATH, pathQuery); return this; @@ -729,7 +648,7 @@ public URI toURI() { try { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), null); } catch (URISyntaxException x) { @@ -748,7 +667,6 @@ public Mutable uri(HttpURI uri) _decodedPath = uri.getDecodedPath(); _param = uri.getParam(); _query = uri.getQuery(); - _fragment = uri.getFragment(); return this; } @@ -1097,7 +1015,6 @@ else if (c == '/') case FRAGMENT: { - _fragment = uri.substring(mark, end); i = end; break; } @@ -1111,7 +1028,10 @@ else if (c == '/') switch (state) { case START: + case ASTERISK: + case FRAGMENT: break; + case SCHEME_OR_PATH: _path = uri.substring(mark, end); break; @@ -1132,13 +1052,6 @@ else if (c == '/') _port = TypeUtil.parseInt(uri, mark, end - mark, 10); break; - case ASTERISK: - break; - - case FRAGMENT: - _fragment = uri.substring(mark, end); - break; - case PARAM: _path = uri.substring(pathMark, end); _param = uri.substring(mark, end); diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java index 7b20da955632..d56d3e96191e 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java @@ -179,7 +179,10 @@ public void testParseString(String input, String scheme, String host, Integer po assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); - assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); + + // We don't retain the fragment + if (input.indexOf('#') >= 0) + input = input.substring(0, input.indexOf('#')); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } catch (URISyntaxException e) @@ -191,7 +194,6 @@ public void testParseString(String input, String scheme, String host, Integer po assertThat("[" + input + "] .path", httpUri.getPath(), is(nullValue())); assertThat("[" + input + "] .param", httpUri.getParam(), is(nullValue())); assertThat("[" + input + "] .query", httpUri.getQuery(), is(nullValue())); - assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(nullValue())); } } @@ -218,8 +220,10 @@ public void testParseURI(String input, String scheme, String host, Integer port, assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); - assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); + // We don't retain the fragment + if (input.indexOf('#') >= 0) + input = input.substring(0, input.indexOf('#')); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } @@ -246,7 +250,11 @@ public void testCompareToJavaNetURI(String input, String scheme, String host, In assertThat("[" + input + "] .path", httpUri.getPath(), is(javaUri.getRawPath())); // Not Relevant for java.net.URI -- assertThat("["+input+"] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(javaUri.getRawQuery())); - assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(javaUri.getFragment())); - assertThat("[" + input + "] .toString", httpUri.toString(), is(javaUri.toASCIIString())); + + // We don't retain the fragment + String javaString = javaUri.toASCIIString(); + if (javaString.indexOf('#') >= 0) + javaString = javaString.substring(0, javaString.indexOf('#')); + assertThat("[" + input + "] .toString", httpUri.toString(), is(javaString)); } } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index 2e581cbb168b..aaa0d0a5b7ea 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -40,7 +40,6 @@ public void testBuilder() throws Exception .path("/ignored/../p%61th;ignored/info") .param("param") .query("query=value") - .fragment("fragment") .asImmutable(); assertThat(uri.getScheme(), is("http")); @@ -51,9 +50,8 @@ public void testBuilder() throws Exception assertThat(uri.getDecodedPath(), is("/path/info")); assertThat(uri.getParam(), is("param")); assertThat(uri.getQuery(), is("query=value")); - assertThat(uri.getFragment(), is("fragment")); assertThat(uri.getAuthority(), is("host:8888")); - assertThat(uri.toString(), is("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value#fragment")); + assertThat(uri.toString(), is("http://user:password@host:8888/ignored/../p%61th;ignored/info;param?query=value")); uri = HttpURI.build(uri) .scheme("https") @@ -62,7 +60,6 @@ public void testBuilder() throws Exception .decodedPath("/some encoded/evening") .param("id=12345") .query(null) - .fragment(null) .asImmutable(); assertThat(uri.getScheme(), is("https")); @@ -73,7 +70,6 @@ public void testBuilder() throws Exception assertThat(uri.getDecodedPath(), is("/some encoded/evening")); assertThat(uri.getParam(), is("id=12345")); assertThat(uri.getQuery(), nullValue()); - assertThat(uri.getFragment(), nullValue()); assertThat(uri.getAuthority(), is("[::1]:8080")); assertThat(uri.toString(), is("https://[::1]:8080/some%20encoded/evening;id=12345")); } @@ -91,7 +87,6 @@ public void testExample() throws Exception assertThat(uri.getDecodedPath(), is("/path/info")); assertThat(uri.getParam(), is("param")); assertThat(uri.getQuery(), is("query=value")); - assertThat(uri.getFragment(), is("fragment")); assertThat(uri.getAuthority(), is("host:8888")); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index 6d5919d7d063..95e10a2e17e9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -540,7 +540,13 @@ public void sendRedirect(String location) throws IOException public void setDateHeader(String name, long date) { if (isMutable()) - _fields.putDateField(name, date); + { + HttpHeader header = HttpHeader.CACHE.get(name); + if (header == null) + _fields.putDateField(name, date); + else + _fields.putDateField(header, date); + } } @Override From 915f324b581df316a8ed997c7e2a4bf62b13d43a Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 22 Apr 2020 16:30:56 +0200 Subject: [PATCH 27/38] Immutable MetaData WIP Revert to using arrays due to garbage generated by streams and iterators (12% of a simple benchmark!). Even if this garbage is an artifact of the JIT being disabled by observation, it can hide other allocations, so best to just use simple arrays! Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/http/HttpFields.java | 227 +++++++++++++----- 1 file changed, 162 insertions(+), 65 deletions(-) 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 6b2e67e028d8..898d2a3ce3d6 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 @@ -514,7 +514,8 @@ default boolean isEqualTo(HttpFields that) */ class Mutable implements Iterable, HttpFields { - ArrayList _fields; + private HttpField[] _fields; + private int _size; /** * Initialize an empty HttpFields. @@ -531,7 +532,7 @@ protected Mutable() */ Mutable(int capacity) { - _fields = new ArrayList<>(capacity); + _fields = new HttpField[capacity]; } /** @@ -541,18 +542,7 @@ protected Mutable() */ Mutable(HttpFields fields) { - if (fields instanceof Immutable) - _fields = new ArrayList<>(Arrays.asList(((Immutable)fields)._fields)); - else if (fields instanceof Mutable) - _fields = new ArrayList<>(((Mutable)fields)._fields); - else - { - _fields = new ArrayList<>(fields.size() + 4); - for (HttpField f : fields) - { - _fields.add(f); - } - } + add(fields); } /** @@ -563,23 +553,24 @@ else if (fields instanceof Mutable) */ Mutable(HttpFields fields, HttpField replaceField) { - _fields = new ArrayList<>(fields.size() + 4); + _fields = new HttpField[fields.size() + 4]; + _size = 0; boolean put = false; for (HttpField f : fields) { if (replaceField.isSameName(f)) { if (!put) - _fields.add(replaceField); + _fields[_size++] = replaceField; put = true; } else { - _fields.add(f); + _fields[_size++] = f; } } if (!put) - _fields.add(replaceField); + _fields[_size++] = replaceField; } /** @@ -590,11 +581,12 @@ else if (fields instanceof Mutable) */ Mutable(HttpFields fields, EnumSet removeFields) { - _fields = new ArrayList<>(Math.max(fields.size() + 4, 16)); + _fields = new HttpField[fields.size() + 4]; + _size = 0; for (HttpField f : fields) { - if (f.getHeader() == null || removeFields.contains(f.getHeader())) - _fields.add(f); + if (f.getHeader() == null || !removeFields.contains(f.getHeader())) + _fields[_size++] = f; } } @@ -638,44 +630,34 @@ public Mutable add(HttpHeader header, String value) public Mutable add(HttpField field) { if (field != null) - _fields.add(field); + { + if (_size == _fields.length) + _fields = Arrays.copyOf(_fields, _size * 2); + _fields[_size++] = field; + } return this; } - /** - * Add fields from another HttpFields instance. Single valued fields are replaced, while all - * others are added. - * - * @param fields the fields to add - * @return this builder - */ public Mutable add(HttpFields fields) { - // TODO is this any different to addAll? - - if (fields == null) - return this; - - _fields.ensureCapacity(size() + fields.size() + 4); - Enumeration e = fields.getFieldNames(); - while (e.hasMoreElements()) + if (fields instanceof Immutable) { - String name = e.nextElement(); - Enumeration values = fields.getValues(name); - while (values.hasMoreElements()) - { - add(name, values.nextElement()); - } + Immutable b = (Immutable)fields; + _fields = Arrays.copyOf(b._fields, b._fields.length + 4); + _size = b._fields.length; } - return this; - } - - public Mutable addAll(HttpFields fields) - { - _fields.ensureCapacity(size() + fields.size() + 4); - for (HttpField f : fields) + else if (fields instanceof Mutable) { - _fields.add(f); + Mutable b = (Mutable)fields; + _fields = Arrays.copyOf(b._fields, b._fields.length); + _size = b._size; + } + else + { + _fields = new HttpField[fields.size() + 4]; + _size = 0; + for (HttpField f : fields) + _fields[_size++] = f; } return this; } @@ -690,7 +672,6 @@ public Mutable addAll(HttpFields fields) */ public Mutable addCSV(HttpHeader header, String... values) { - // TODO is the javadoc right ? QuotedCSV existing = null; for (HttpField f : this) { @@ -701,7 +682,7 @@ public Mutable addCSV(HttpHeader header, String... values) existing.addValue(f.getValue()); } } - String value = addCSV(existing, values); + String value = formatCsvExcludingExisting(existing, values); if (value != null) add(header, value); return this; @@ -717,7 +698,6 @@ public Mutable addCSV(HttpHeader header, String... values) */ public Mutable addCSV(String name, String... values) { - // TODO is the javadoc right ? QuotedCSV existing = null; for (HttpField f : this) { @@ -728,7 +708,7 @@ public Mutable addCSV(String name, String... values) existing.addValue(f.getValue()); } } - String value = addCSV(existing, values); + String value = formatCsvExcludingExisting(existing, values); if (value != null) add(name, value); return this; @@ -750,12 +730,12 @@ public Mutable addDateField(String name, long date) @Override public Immutable asImmutable() { - return new Immutable(_fields.toArray(new HttpField[0])); + return new Immutable(Arrays.copyOf(_fields, _size)); } public Mutable clear() { - _fields.clear(); + _size = 0; return this; } @@ -799,9 +779,9 @@ public HttpField getAndRemove(HttpHeader name) @Override public HttpField getField(int index) { - if (index >= size()) + if (index >= _size || index < 0) throw new NoSuchElementException(); - return _fields.get(index); + return _fields[index]; } @Override @@ -813,12 +793,37 @@ public int hashCode() @Override public Iterator iterator() { - return _fields.iterator(); + return new Iterator<>() + { + int _index = 0; + + @Override + public boolean hasNext() + { + return _index < _size; + } + + @Override + public HttpField next() + { + return _fields[_index++]; + } + + @Override + public void remove() + { + if (_size == 0) + throw new IllegalStateException(); + System.arraycopy(_fields, _index, _fields, _index - 1, _size - _index); + _index--; + _size--; + } + }; } public ListIterator listIterator() { - return _fields.listIterator(); + return new ListItr(); } public Mutable put(HttpField field) @@ -978,13 +983,13 @@ public Mutable remove(String name) public int size() { - return _fields.size(); + return _size; } @Override public Stream stream() { - return _fields.stream(); + return Arrays.stream(_fields, 0, _size); } @Override @@ -993,7 +998,7 @@ public String toString() return asString(); } - private String addCSV(QuotedCSV existing, String... values) + private String formatCsvExcludingExisting(QuotedCSV existing, String... values) { // remove any existing values from the new values boolean add = true; @@ -1028,6 +1033,83 @@ private String addCSV(QuotedCSV existing, String... values) return null; } + + private class ListItr implements ListIterator + { + int _cursor; // index of next element to return + int _current = -1; + + @Override + public boolean hasNext() + { + return _cursor != _size; + } + + @Override + public HttpField next() + { + if (_cursor == _size) + throw new NoSuchElementException(); + _current = _cursor++; + return _fields[_current]; + } + + @Override + public void remove() + { + if (_current < 0) + throw new IllegalStateException(); + _size--; + System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); + _fields[_size] = null; + _cursor = _current; + _current = -1; + } + + @Override + public boolean hasPrevious() + { + return _cursor > 0; + } + + @Override + public HttpField previous() + { + if (_cursor == 0) + throw new NoSuchElementException(); + _current = --_cursor; + return _fields[_current]; + } + + @Override + public int nextIndex() + { + return _cursor + 1; + } + + @Override + public int previousIndex() + { + return _cursor - 1; + } + + @Override + public void set(HttpField field) + { + if (_current < 0) + throw new IllegalStateException(); + _fields[_current] = field; + } + + @Override + public void add(HttpField field) + { + _fields = Arrays.copyOf(_fields, _fields.length + 1); + System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); + _fields[_cursor++] = field; + _current = -1; + } + } } /** @@ -1086,7 +1168,22 @@ public int hashCode() @Override public Iterator iterator() { - return Arrays.stream(_fields).iterator(); + return new Iterator<>() + { + int _index = 0; + + @Override + public boolean hasNext() + { + return _index < _fields.length; + } + + @Override + public HttpField next() + { + return _fields[_index++]; + } + }; } @Override From 3de51af3fcc2e58bec8af6671856bded1726f495 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 22 Apr 2020 19:37:46 +0200 Subject: [PATCH 28/38] Immutable MetaData WIP More optimizations and better test coverage. Signed-off-by: Greg Wilkins --- .../fcgi/client/http/HttpSenderOverFCGI.java | 8 +- .../org/eclipse/jetty/http/HttpFields.java | 168 ++++++++++-------- .../eclipse/jetty/http/HttpFieldsTest.java | 76 +++++++- 3 files changed, 170 insertions(+), 82 deletions(-) diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index 8de4ae4e3bf1..0c654a43d77c 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -20,6 +20,7 @@ import java.net.URI; import java.nio.ByteBuffer; +import java.util.EnumSet; import java.util.Locale; import org.eclipse.jetty.client.HttpChannel; @@ -70,13 +71,14 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool fcgiHeaders.put(FCGI.Headers.QUERY_STRING, query == null ? "" : query); // FastCGI headers based on HTTP headers - HttpField httpField = headers.getAndRemove(HttpHeader.AUTHORIZATION); + HttpField httpField = headers.getField(HttpHeader.AUTHORIZATION); if (httpField != null) fcgiHeaders.put(FCGI.Headers.AUTH_TYPE, httpField.getValue()); - httpField = headers.getAndRemove(HttpHeader.CONTENT_LENGTH); + httpField = headers.getField(HttpHeader.CONTENT_LENGTH); fcgiHeaders.put(FCGI.Headers.CONTENT_LENGTH, httpField == null ? "" : httpField.getValue()); - httpField = headers.getAndRemove(HttpHeader.CONTENT_TYPE); + httpField = headers.getField(HttpHeader.CONTENT_TYPE); fcgiHeaders.put(FCGI.Headers.CONTENT_TYPE, httpField == null ? "" : httpField.getValue()); + headers.remove(EnumSet.of(HttpHeader.AUTHORIZATION, HttpHeader.CONTENT_LENGTH, HttpHeader.CONTENT_TYPE)); // FastCGI headers that are not based on HTTP headers nor URI fcgiHeaders.put(FCGI.Headers.REQUEST_METHOD, request.getMethod()); 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 898d2a3ce3d6..49b4efd2742c 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 @@ -71,14 +71,6 @@ static Immutable from(HttpField... fields) return new Immutable(fields); } - default int asHashCode() - { - int hash = 0; - for (HttpField f : this) - hash ^= f.hashCode(); - return hash; - } - Immutable asImmutable(); default String asString() @@ -750,26 +742,6 @@ public boolean equals(Object o) return isEqualTo((HttpFields)o); } - /** - * Remove the first instance of a header and return previous value - * - * @param name the field to remove - * @return the header that was removed - */ - public HttpField getAndRemove(HttpHeader name) - { - for (ListIterator i = listIterator(); i.hasNext(); ) - { - HttpField f = i.next(); - if (f.getHeader() == name) - { - i.remove(); - return f; - } - } - return null; - } - /** * Get a Field by index. * @@ -787,7 +759,10 @@ public HttpField getField(int index) @Override public int hashCode() { - return asHashCode(); + int hash = 0; + for (int i = _fields.length; i-- > 0; ) + hash ^= _fields[i].hashCode(); + return hash; } @Override @@ -814,9 +789,7 @@ public void remove() { if (_size == 0) throw new IllegalStateException(); - System.arraycopy(_fields, _index, _fields, _index - 1, _size - _index); - _index--; - _size--; + System.arraycopy(_fields, _index, _fields, _index - 1, _size-- - _index--); } }; } @@ -829,16 +802,17 @@ public ListIterator listIterator() public Mutable put(HttpField field) { boolean put = false; - for (ListIterator i = listIterator(); i.hasNext(); ) + + for (int i = 0; i < _size; i++) { - HttpField f = i.next(); + HttpField f = _fields[i]; if (f.isSameName(field)) { if (put) - i.remove(); + System.arraycopy(_fields, i + 1, _fields, i, _size-- - i-- - 1); else { - i.set(field); + _fields[i] = field; put = true; } } @@ -955,11 +929,22 @@ public Mutable putLongField(String name, long value) */ public Mutable remove(HttpHeader name) { - for (ListIterator i = listIterator(); i.hasNext(); ) + for (int i = 0; i < _size; i++) { - HttpField f = i.next(); + HttpField f = _fields[i]; if (f.getHeader() == name) - i.remove(); + System.arraycopy(_fields, i + 1, _fields, i, _size-- - i-- - 1); + } + return this; + } + + public Mutable remove(EnumSet fields) + { + for (int i = 0; i < _size; i++) + { + HttpField f = _fields[i]; + if (fields.contains(f.getHeader())) + System.arraycopy(_fields, i + 1, _fields, i, _size-- - i-- - 1); } return this; } @@ -972,11 +957,11 @@ public Mutable remove(HttpHeader name) */ public Mutable remove(String name) { - for (ListIterator i = listIterator(); i.hasNext(); ) + for (int i = 0; i < _size; i++) { - HttpField f = i.next(); + HttpField f = _fields[i]; if (f.getName().equalsIgnoreCase(name)) - i.remove(); + System.arraycopy(_fields, i + 1, _fields, i, _size-- - i-- - 1); } return this; } @@ -1039,12 +1024,27 @@ private class ListItr implements ListIterator int _cursor; // index of next element to return int _current = -1; + @Override + public void add(HttpField field) + { + _fields = Arrays.copyOf(_fields, _fields.length + 1); + System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); + _fields[_cursor++] = field; + _current = -1; + } + @Override public boolean hasNext() { return _cursor != _size; } + @Override + public boolean hasPrevious() + { + return _cursor > 0; + } + @Override public HttpField next() { @@ -1055,21 +1055,9 @@ public HttpField next() } @Override - public void remove() - { - if (_current < 0) - throw new IllegalStateException(); - _size--; - System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); - _fields[_size] = null; - _cursor = _current; - _current = -1; - } - - @Override - public boolean hasPrevious() + public int nextIndex() { - return _cursor > 0; + return _cursor + 1; } @Override @@ -1081,12 +1069,6 @@ public HttpField previous() return _fields[_current]; } - @Override - public int nextIndex() - { - return _cursor + 1; - } - @Override public int previousIndex() { @@ -1094,20 +1076,23 @@ public int previousIndex() } @Override - public void set(HttpField field) + public void remove() { if (_current < 0) throw new IllegalStateException(); - _fields[_current] = field; + _size--; + System.arraycopy(_fields, _current + 1, _fields, _current, _size - _current); + _fields[_size] = null; + _cursor = _current; + _current = -1; } @Override - public void add(HttpField field) + public void set(HttpField field) { - _fields = Arrays.copyOf(_fields, _fields.length + 1); - System.arraycopy(_fields, _cursor, _fields, _cursor + 1, _size++); - _fields[_cursor++] = field; - _current = -1; + if (_current < 0) + throw new IllegalStateException(); + _fields[_current] = field; } } } @@ -1151,6 +1136,46 @@ public boolean equals(Object o) return isEqualTo((HttpFields)o); } + @Override + public String get(String header) + { + // default impl overridden for efficiency + for (HttpField f : _fields) + if (f.getName().equalsIgnoreCase(header)) + return f.getValue(); + return null; + } + + @Override + public String get(HttpHeader header) + { + // default impl overridden for efficiency + for (HttpField f : _fields) + if (f.getHeader() == header) + return f.getValue(); + return null; + } + + @Override + public HttpField getField(HttpHeader header) + { + // default impl overridden for efficiency + for (HttpField f : _fields) + if (f.getHeader() == header) + return f; + return null; + } + + @Override + public HttpField getField(String name) + { + // default impl overridden for efficiency + for (HttpField f : _fields) + if (f.getName().equalsIgnoreCase(name)) + return f; + return null; + } + @Override public HttpField getField(int index) { @@ -1162,7 +1187,10 @@ public HttpField getField(int index) @Override public int hashCode() { - return asHashCode(); + int hash = 0; + for (int i = _fields.length; i-- > 0; ) + hash ^= _fields[i].hashCode(); + return hash; } @Override 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 465c97cca4ec..d9b9b39008dc 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 @@ -20,11 +20,14 @@ import java.nio.ByteBuffer; import java.util.Collections; +import java.util.EnumSet; import java.util.Enumeration; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Locale; +import java.util.Map; import java.util.NoSuchElementException; import org.eclipse.jetty.util.BufferUtil; @@ -36,6 +39,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -121,6 +125,40 @@ public void testImmutable() throws Exception }); } + @Test + public void testMutable() throws Exception + { + HttpFields headers = HttpFields.build() + .add(HttpHeader.ETAG, "tag") + .add("name0", "value0") + .add("name1", "value1").asImmutable(); + + headers = HttpFields.build(headers, EnumSet.of(HttpHeader.ETAG, HttpHeader.CONTENT_RANGE)) + .add(new PreEncodedHttpField(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString())) + .addDateField("name2", System.currentTimeMillis()).asImmutable(); + + headers = HttpFields.build(headers, new HttpField(HttpHeader.CONNECTION, "open")); + + assertThat(headers.size(), is(4)); + assertThat(headers.getField(0).getValue(), is("value0")); + assertThat(headers.getField(1).getValue(), is("value1")); + assertThat(headers.getField(2).getValue(), is("open")); + assertThat(headers.getField(3).getName(), is("name2")); + } + + @Test + public void testMap() throws Exception + { + Map map = new HashMap<>(); + map.put(HttpFields.build().add("X","1").add(HttpHeader.ETAG,"tag").asImmutable(),"1"); + map.put(HttpFields.build().add("X","2").add(HttpHeader.ETAG,"other").asImmutable(),"2"); + + assertThat(map.get(HttpFields.build().add("X","1").add(HttpHeader.ETAG,"tag").asImmutable()), is("1")); + assertThat(map.get(HttpFields.build().add("X","2").add(HttpHeader.ETAG,"other").asImmutable()), is("2")); + assertThat(map.get(HttpFields.build().add("X","2").asImmutable()), nullValue()); + assertThat(map.get(HttpFields.build().add("X","2").add(HttpHeader.ETAG,"tag").asImmutable()), nullValue()); + } + @Test public void testGet() throws Exception { @@ -246,19 +284,27 @@ public void testRePut() throws Exception } @Test - public void testRemovePut() throws Exception + public void testRemove() throws Exception { - HttpFields.Mutable header = HttpFields.build(1); - - header.put("name0", "value0"); - header.put("name1", "value1"); - header.put("name2", "value2"); + HttpFields.Mutable header = HttpFields.build(1) + .put("name0", "value0") + .add(HttpHeader.CONTENT_TYPE, "text") + .add("name1", "WRONG") + .add(HttpHeader.EXPECT, "spanish inquisition") + .put("name1", "value1") + .add(HttpHeader.ETAG, "tag") + .put("name2", "value2"); assertEquals("value0", header.get("name0")); + assertEquals("text", header.get(HttpHeader.CONTENT_TYPE)); assertEquals("value1", header.get("name1")); + assertEquals("spanish inquisition", header.get(HttpHeader.EXPECT)); + assertEquals("tag", header.get(HttpHeader.ETAG)); assertEquals("value2", header.get("name2")); header.remove("name1"); + header.remove(HttpHeader.ETAG); + header.remove(EnumSet.of(HttpHeader.CONTENT_TYPE, HttpHeader.EXPECT, HttpHeader.EXPIRES)); assertEquals("value0", header.get("name0")); assertNull(header.get("name1")); @@ -740,11 +786,17 @@ public void testIteration() throws Exception Iterator i = header.iterator(); assertThat(i.hasNext(), is(false)); - header.put("name1", "valueA"); - header.put("name2", "valueB"); - header.add("name3", "valueC"); + header.add("REMOVE", "ME") + .add("name1", "valueA") + .add("name2", "valueB") + .add("name3", "valueC"); i = header.iterator(); + + assertThat(i.hasNext(), is(true)); + assertThat(i.next().getName(), is("REMOVE")); + i.remove(); + assertThat(i.hasNext(), is(true)); assertThat(i.next().getName(), is("name1")); assertThat(i.next().getName(), is("name2")); @@ -758,6 +810,7 @@ public void testIteration() throws Exception assertThat(i.next().getName(), is("name3")); assertThat(i.hasNext(), is(false)); + header.add("REMOVE", "ME"); ListIterator l = header.listIterator(); assertThat(l.hasNext(), is(true)); l.add(new HttpField("name0", "value")); @@ -778,6 +831,11 @@ public void testIteration() throws Exception assertThat(l.next().getName(), is("NAME1")); l.add(new HttpField("name2", "value")); assertThat(l.next().getName(), is("name3")); + + assertThat(l.hasNext(), is(true)); + assertThat(l.next().getName(), is("REMOVE")); + l.remove(); + assertThat(l.hasNext(), is(false)); assertThat(l.hasPrevious(), is(true)); l.add(new HttpField("name4", "value")); From dd154dd9a92b7841b8adea5e6b9197d4ed5bb7c3 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 22 Apr 2020 22:53:05 +0200 Subject: [PATCH 29/38] Immutable Metadata various cleanups Signed-off-by: Greg Wilkins --- .../client/ClientConnectionCloseTest.java | 4 +-- .../org/eclipse/jetty/http/HttpFields.java | 17 ++++------ .../java/org/eclipse/jetty/http/MetaData.java | 1 - .../org/eclipse/jetty/server/Request.java | 3 -- .../jetty/server/handler/ContextHandler.java | 2 +- .../core/client/HttpUpgraderOverHTTP.java | 33 +++++++++---------- 6 files changed, 25 insertions(+), 35 deletions(-) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java index d99ef74e51d2..2415f568a86b 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java @@ -249,9 +249,7 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool(); HttpConnectionOverHTTP connection = (HttpConnectionOverHTTP)connectionPool.getActiveConnections().iterator().next(); assertFalse(connection.getEndPoint().isOutputShutdown()); - }) - // TODO ??? .onResponseHeaders(r -> r.getHeaders().remove(HttpHeader.CONNECTION)); - ; + }); ContentResponse response = request.send(); assertEquals(HttpStatus.OK_200, response.getStatus()); 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 49b4efd2742c..45d721818292 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 @@ -478,18 +478,15 @@ default boolean isEqualTo(HttpFields that) if (size() != that.size()) return false; - // Order is not important, so we cannot rely on List.equals(). // TODO is this true? - loop: - for (HttpField fi : this) + Iterator i = that.iterator(); + for (HttpField f : this) { - for (HttpField fa : that) - { - if (fi.equals(fa)) - continue loop; - } - return false; + if (!i.hasNext()) + return false; + if (!f.equals(i.next())) + return false; } - return true; + return !i.hasNext(); } int size(); diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index eb86992b1013..9f27909476e5 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -154,7 +154,6 @@ public Request(String method, HttpURI uri, HttpVersion version, HttpFields field public Request(String method, String scheme, HostPortHttpField authority, String uri, HttpVersion version, HttpFields fields, long contentLength) { - // TODO review this constructor this(method, HttpURI.build().scheme(scheme).host(authority == null ? null : authority.getHost()).port(authority == null ? -1 : authority.getPort()).pathQuery(uri), version, fields, contentLength); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e76659d2fdc9..e9215ff33e70 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -769,10 +769,7 @@ public long getContentLengthLong() if (_httpFields == null) return -1; - // TODO should we cache this? return _httpFields.getLongField(HttpHeader.CONTENT_LENGTH); - - // TODO should we return metaData.getContentLength() if field is not found? } public long getContentRead() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 271b2488ad57..d1b63779f5a0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1208,7 +1208,7 @@ else if (_contextPath.length() == 1) if (_contextPath.length() == 1) baseRequest.setContextPath(""); else - baseRequest.setContextPath(getContextPathEncoded()); // TODO shouldn't this be decoded context path??? + baseRequest.setContextPath(getContextPathEncoded()); baseRequest.setServletPath(null); baseRequest.setPathInfo(pathInfo); } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java index 9d3f3e4145ec..dbe61eb8ea8e 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java @@ -38,11 +38,11 @@ public class HttpUpgraderOverHTTP implements HttpUpgrader { - public static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); - public static final PreEncodedHttpField WS_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "websocket"); - public static final PreEncodedHttpField WS_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade"); - public static final PreEncodedHttpField PRAGMA_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.PRAGMA, "no-cache"); - public static final PreEncodedHttpField CACHE_CONTROL_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, "no-cache"); + private static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + private static final PreEncodedHttpField WS_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "websocket"); + private static final PreEncodedHttpField WS_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade"); + private static final PreEncodedHttpField PRAGMA_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.PRAGMA, "no-cache"); + private static final PreEncodedHttpField CACHE_CONTROL_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.CACHE_CONTROL, "no-cache"); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP(ClientUpgradeRequest clientUpgradeRequest) @@ -53,18 +53,17 @@ public HttpUpgraderOverHTTP(ClientUpgradeRequest clientUpgradeRequest) @Override public void prepare(HttpRequest request) { - request.method(HttpMethod.GET).version(HttpVersion.HTTP_1_1); - request.add(WS_VERSIONS_FIELD); - request.add(WS_UPGRADE_FIELD); - request.add(WS_CONNECTION_FIELD); - request.header(HttpHeader.SEC_WEBSOCKET_KEY, generateRandomKey()); - - // Per the hybi list: Add no-cache headers to avoid compatibility issue. - // There are some proxies that rewrite "Connection: upgrade" to - // "Connection: close" in the response if a request doesn't contain - // these headers. - request.add(PRAGMA_NO_CACHE_FIELD); - request.add(CACHE_CONTROL_NO_CACHE_FIELD); + request.method(HttpMethod.GET).version(HttpVersion.HTTP_1_1) + .add(WS_VERSIONS_FIELD) + .add(WS_UPGRADE_FIELD) + .add(WS_CONNECTION_FIELD) + .header(HttpHeader.SEC_WEBSOCKET_KEY, generateRandomKey()) + // Per the hybi list: Add no-cache headers to avoid compatibility issue. + // There are some proxies that rewrite "Connection: upgrade" to + // "Connection: close" in the response if a request doesn't contain + // these headers. + .add(PRAGMA_NO_CACHE_FIELD) + .add(CACHE_CONTROL_NO_CACHE_FIELD); // Notify the UpgradeListeners now the headers are set. clientUpgradeRequest.requestComplete(); From 3749a5ca5526d8526fc4e4320f158e8a34e097b4 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Wed, 22 Apr 2020 23:39:28 +0200 Subject: [PATCH 30/38] Immutable MetaData WIP More optimizations Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/client/HttpConnection.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index f18df06dc16b..187a4f133e15 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -152,7 +152,7 @@ protected void normalizeRequest(Request request) HttpFields headers = request.getHeaders(); if (version.getVersion() <= 11) { - if (!headers.contains(HttpHeader.HOST.asString())) + if (!headers.contains(HttpHeader.HOST)) request.put(getHttpDestination().getHostField()); } @@ -164,7 +164,7 @@ protected void normalizeRequest(Request request) } else { - if (!headers.contains(HttpHeader.CONTENT_TYPE.asString())) + if (!headers.contains(HttpHeader.CONTENT_TYPE)) { String contentType = content.getContentType(); if (contentType != null) @@ -181,7 +181,7 @@ protected void normalizeRequest(Request request) long contentLength = content.getLength(); if (contentLength >= 0) { - if (!headers.contains(HttpHeader.CONTENT_LENGTH.asString())) + if (!headers.contains(HttpHeader.CONTENT_LENGTH)) request.put(new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH, contentLength)); } } @@ -195,7 +195,7 @@ protected void normalizeRequest(Request request) cookies = convertCookies(HttpCookieStore.matchPath(uri, cookieStore.get(uri)), null); cookies = convertCookies(request.getCookies(), cookies); if (cookies != null) - request.header(HttpHeader.COOKIE.asString(), cookies.toString()); + request.header(HttpHeader.COOKIE, cookies.toString()); } // Authentication From fa86645a99b52390456f0c04bea50f94b890daf5 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 23 Apr 2020 10:18:15 +0200 Subject: [PATCH 31/38] Immutable MetaData WIP review changes Signed-off-by: Greg Wilkins --- .../main/java/org/eclipse/jetty/http/HttpFields.java | 8 +------- .../eclipse/jetty/server/HttpChannelOverHttp.java | 12 ++++++------ 2 files changed, 7 insertions(+), 13 deletions(-) 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 45d721818292..f8390b79a237 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 @@ -154,12 +154,6 @@ default boolean contains(String name) return false; } - @Deprecated - default boolean containsKey(String name) - { - return contains(name); - } - default String get(HttpHeader header) { for (HttpField f : this) @@ -478,7 +472,7 @@ default boolean isEqualTo(HttpFields that) if (size() != that.size()) return false; - Iterator i = that.iterator(); + Iterator i = that.iterator(); for (HttpField f : this) { if (!i.hasNext()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java index c6ec24f0a871..3dfd130306d9 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelOverHttp.java @@ -543,8 +543,8 @@ boolean onIdleTimeout(Throwable timeout) private static class RequestBuilder { - private final HttpFields.Mutable _fieldBuilder = HttpFields.build(); - private final HttpURI.Mutable _uri = HttpURI.build(); + private final HttpFields.Mutable _fieldsBuilder = HttpFields.build(); + private final HttpURI.Mutable _uriBuilder = HttpURI.build(); private String _method; private HttpVersion _version; @@ -556,19 +556,19 @@ public String method() public void request(String method, String uri, HttpVersion version) { _method = method; - _uri.uri(method, uri); + _uriBuilder.uri(method, uri); _version = version; - _fieldBuilder.clear(); + _fieldsBuilder.clear(); } public HttpFields.Mutable getFields() { - return _fieldBuilder; + return _fieldsBuilder; } public MetaData.Request build() { - return new MetaData.Request(_method, _uri, _version, _fieldBuilder); + return new MetaData.Request(_method, _uriBuilder, _version, _fieldsBuilder); } public HttpVersion version() From c71cb54a13f9ca2a72a3ba8e4bb7c64ba359b635 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 23 Apr 2020 19:10:02 +0200 Subject: [PATCH 32/38] Immutable MetaData WIP changes after review: + less usage of Mutable + more usage of EMPTY + restored fragment handling Signed-off-by: Greg Wilkins --- .../eclipse/jetty/client/HttpResponse.java | 2 +- .../client/util/MultiPartRequestContent.java | 4 +- .../jetty/client/HttpClientRedirectTest.java | 24 ++++++------ .../src/main/java/embedded/HTTP2Docs.java | 2 +- .../embedded/client/http/HTTPClientDocs.java | 12 ++---- .../client/http2/HTTP2ClientDocs.java | 6 +-- .../embedded/server/http/HTTPServerDocs.java | 3 +- .../server/http2/HTTP2ServerDocs.java | 2 +- .../server/proxy/FastCGIProxyServlet.java | 2 +- .../org/eclipse/jetty/http/HttpGenerator.java | 10 ++--- .../org/eclipse/jetty/http/HttpParser.java | 2 +- .../java/org/eclipse/jetty/http/HttpURI.java | 38 ++++++++++++++++++- .../java/org/eclipse/jetty/http/MetaData.java | 31 +-------------- .../eclipse/jetty/http/HttpURIParseTest.java | 18 +++------ .../org/eclipse/jetty/http/HttpURITest.java | 1 + .../jetty/http2/server/HTTP2CServerTest.java | 4 +- .../org/eclipse/jetty/server/HttpChannel.java | 4 +- .../org/eclipse/jetty/server/Request.java | 12 ++++-- .../eclipse/jetty/server/ResponseTest.java | 10 ++--- .../core/client/HttpUpgraderOverHTTP.java | 4 +- .../core/client/HttpUpgraderOverHTTP2.java | 4 +- .../PerMessageDeflaterBufferSizeTest.java | 16 ++++---- .../impl/JettyClientUpgradeRequest.java | 5 +-- .../client/ProxyWithDynamicTransportTest.java | 4 +- 24 files changed, 107 insertions(+), 113 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index 36b730a79c49..30e01c5a5d33 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -108,7 +108,7 @@ public List getListeners(Class type) return result; } - public HttpFields.Mutable getTrailers() + public HttpFields getTrailers() { return trailers; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java index aebce8664903..7acfdb20c895 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/MultiPartRequestContent.java @@ -145,7 +145,7 @@ public void fail(Throwable failure) * @param content the part content * @param fields the headers associated with this part */ - public void addFieldPart(String name, Request.Content content, HttpFields.Mutable fields) + public void addFieldPart(String name, Request.Content content, HttpFields fields) { addPart(new Part(name, null, content, fields)); } @@ -164,7 +164,7 @@ public void addFieldPart(String name, Request.Content content, HttpFields.Mutabl * @param content the part content * @param fields the headers associated with this part */ - public void addFilePart(String name, String fileName, Request.Content content, HttpFields.Mutable fields) + public void addFilePart(String name, String fileName, Request.Content content, HttpFields fields) { addPart(new Part(name, fileName, content, fields)); } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java index 83f5e4ca0767..581fcafbcb6e 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientRedirectTest.java @@ -70,7 +70,7 @@ public void test303(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -86,7 +86,7 @@ public void test303302(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -102,7 +102,7 @@ public void test303302OnDifferentDestinations(Scenario scenario) throws Exceptio .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -119,7 +119,7 @@ public void test301(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -139,7 +139,7 @@ public void test301WithWrongMethod(Scenario scenario) throws Exception Response response = xx.getResponse(); assertNotNull(response); assertEquals(301, response.getStatus()); - assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -158,7 +158,7 @@ public void test307WithRequestContent(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); assertArrayEquals(data, response.getContent()); } @@ -179,7 +179,7 @@ public void testMaxRedirections(Scenario scenario) throws Exception Response response = xx.getResponse(); assertNotNull(response); assertEquals(302, response.getStatus()); - assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -195,7 +195,7 @@ public void test303WithConnectionCloseWithBigRequest(Scenario scenario) throws E .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -212,7 +212,7 @@ public void testDontFollowRedirects(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(303, response.getStatus()); - assertTrue(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertTrue(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -228,7 +228,7 @@ public void testRelativeLocation(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -244,7 +244,7 @@ public void testAbsoluteURIPathWithSpaces(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest @@ -260,7 +260,7 @@ public void testRelativeURIPathWithSpaces(Scenario scenario) throws Exception .send(); assertNotNull(response); assertEquals(200, response.getStatus()); - assertFalse(response.getHeaders().contains(HttpHeader.LOCATION.asString())); + assertFalse(response.getHeaders().contains(HttpHeader.LOCATION)); } @ParameterizedTest diff --git a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java index b38addd1a4a3..2a4bb6c10fd2 100644 --- a/jetty-documentation/src/main/java/embedded/HTTP2Docs.java +++ b/jetty-documentation/src/main/java/embedded/HTTP2Docs.java @@ -48,7 +48,7 @@ public void dataDemanded() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields.Mutable requestHeaders = HttpFields.build() + HttpFields requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java index b9ff3e81078d..60161cf3c218 100644 --- a/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http/HTTPClientDocs.java @@ -63,7 +63,6 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.http.PreEncodedHttpField; import org.eclipse.jetty.http2.client.HTTP2Client; import org.eclipse.jetty.http2.client.http.ClientConnectionFactoryOverHTTP2; import org.eclipse.jetty.http2.client.http.HttpClientTransportOverHTTP2; @@ -79,11 +78,6 @@ @SuppressWarnings("unused") public class HTTPClientDocs { - - public static final PreEncodedHttpField H2C_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "h2c"); - public static final PreEncodedHttpField H2_SETTINGS_FIELD = new PreEncodedHttpField(HttpHeader.HTTP2_SETTINGS, ""); - public static final PreEncodedHttpField H2_UPGRADE_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade, HTTP2-Settings"); - public void start() throws Exception { // tag::start[] @@ -804,9 +798,9 @@ public void dynamicClearText() throws Exception // Make a clear-text upgrade request from HTTP/1.1 to HTTP/2. // The request will start as HTTP/1.1, but the response will be HTTP/2. ContentResponse upgradedResponse = client.newRequest("host", 8080) - .add(H2C_UPGRADE_FIELD) - .add(H2_SETTINGS_FIELD) - .add(H2_UPGRADE_CONNECTION_FIELD) + .header(HttpHeader.UPGRADE, "h2c") + .header(HttpHeader.HTTP2_SETTINGS, "") + .header(HttpHeader.CONNECTION, "Upgrade, HTTP2-Settings") .send(); // end::dynamicClearText[] } diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index 884f33058f05..1a7b64ab8b19 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -172,7 +172,7 @@ public void newStreamWithData() throws Exception Session session = sessionCF.get(); // Configure the request headers. - HttpFields.Mutable requestHeaders = HttpFields.build() + HttpFields requestHeaders = HttpFields.build() .put(HttpHeader.CONTENT_TYPE, "application/json"); // The request metadata with method, URI and headers. @@ -213,7 +213,7 @@ public void responseListener() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields.Mutable requestHeaders = HttpFields.build() + HttpFields requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -358,7 +358,7 @@ public void pushReset() throws Exception CompletableFuture sessionCF = http2Client.connect(serverAddress, new Session.Listener.Adapter()); Session session = sessionCF.get(); - HttpFields.Mutable requestHeaders = HttpFields.build() + HttpFields requestHeaders = HttpFields.build() .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java index 0519c58d3ecf..143643c5c9d3 100644 --- a/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http/HTTPServerDocs.java @@ -464,7 +464,8 @@ public void handle(String target, Request jettyRequest, HttpServletRequest reque { // Rewrite old paths to new paths. HttpURI uri = jettyRequest.getHttpURI(); - HttpURI newURI = HttpURI.build(uri).path("/new_path/" + path.substring("/old_path/".length())); + String newPath = "/new_path/" + path.substring("/old_path/".length()); + HttpURI newURI = HttpURI.build(uri).path(newPath); // Modify the request object. jettyRequest.setHttpURI(newURI); } diff --git a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java index 9869011b4c34..9833c0958eb4 100644 --- a/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java +++ b/jetty-documentation/src/main/java/embedded/server/http2/HTTP2ServerDocs.java @@ -294,7 +294,7 @@ public Stream.Listener onNewStream(Stream stream, HeadersFrame frame) if (pushEnabled && request.getURIString().endsWith("/index.html")) { // Push the favicon. - HttpURI pushedURI = HttpURI.build(request.getURI()).path("/favicon.ico").asImmutable(); + HttpURI pushedURI = HttpURI.build(request.getURI()).path("/favicon.ico"); MetaData.Request pushedRequest = new MetaData.Request("GET", pushedURI, HttpVersion.HTTP_2, HttpFields.EMPTY); PushPromiseFrame promiseFrame = new PushPromiseFrame(stream.getId(), 0, pushedRequest); stream.push(promiseFrame, new Stream.Listener.Adapter()) diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java index 5869f2c44961..c04580d4f8b2 100644 --- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java +++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/proxy/FastCGIProxyServlet.java @@ -180,7 +180,7 @@ protected void sendProxyRequest(HttpServletRequest request, HttpServletResponse proxyRequest.attribute(REQUEST_QUERY_ATTRIBUTE, originalQuery); // If the Host header is missing, add it. - if (!proxyRequest.getHeaders().contains(HttpHeader.HOST.asString())) + if (!proxyRequest.getHeaders().contains(HttpHeader.HOST)) { String host = request.getServerName(); int port = request.getServerPort(); 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 8a92bef3d3ec..962f4e80a290 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 @@ -22,7 +22,6 @@ import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.util.Arrays; -import java.util.function.Supplier; import org.eclipse.jetty.http.HttpTokens.EndOfContent; import org.eclipse.jetty.util.ArrayTrie; @@ -321,14 +320,13 @@ private Result completing(ByteBuffer chunk, ByteBuffer content) if (isChunking()) { - Supplier trailerSupplier = _info.getTrailerSupplier(); - if (_info.mayHaveTrailers()) + if (_info.getTrailerSupplier() != null) { // Do we need a chunk buffer? if (chunk == null || chunk.capacity() <= CHUNK_SIZE) return Result.NEED_CHUNK_TRAILER; - HttpFields trailers = trailerSupplier.get(); + HttpFields trailers = _info.getTrailerSupplier().get(); if (trailers != null) { @@ -588,7 +586,7 @@ private void generateHeaders(ByteBuffer header, ByteBuffer content, boolean last HttpField transferEncoding = null; boolean http11 = _info.getHttpVersion() == HttpVersion.HTTP_1_1; boolean close = false; - boolean chunkedHint = _info.hasTrailerSupplier(); + boolean chunkedHint = _info.getTrailerSupplier() != null; boolean contentType = false; long contentLength = _info.getContentLength(); boolean contentLengthField = false; @@ -667,7 +665,7 @@ else if (contentLength != field.getLongValue()) } // Can we work out the content length? - if (last && contentLength < 0 && !_info.mayHaveTrailers()) + if (last && contentLength < 0 && _info.getTrailerSupplier() == null) contentLength = _contentPrepared + BufferUtil.length(content); // Calculate how to end _content and connection, _content length and transfer encoding 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 9efc1be10228..1d6db1f0cf9b 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 @@ -72,7 +72,7 @@ * is used to lookup common combinations of headers and values * (eg. "Connection: close"), or just header names (eg. "Connection:" ). * For headers who's value is not known statically (eg. Host, COOKIE) then a - * per parser dynamic Trie of {@link HttpFields.Mutable} from previous parsed messages + * per parser dynamic Trie of {@link HttpFields} from previous parsed messages * is used to help the parsing of subsequent messages. *

    *

    diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index f7887c30bb43..e9f2480dde44 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -43,6 +43,7 @@ *

  • {@link #getPath()} - /path/info
  • *
  • {@link #getParam()} - param
  • *
  • {@link #getQuery()} - query
  • + *
  • {@link #getFragment()} - fragment
  • *
*

Any parameters will be returned from {@link #getPath()}, but are excluded from the * return value of {@link #getDecodedPath()}. If there are multiple parameters, the @@ -110,6 +111,8 @@ static Immutable from(String scheme, String host, int port, String pathQuery) String getDecodedPath(); + String getFragment(); + String getHost(); String getParam(); @@ -152,6 +155,7 @@ class Immutable implements HttpURI private final String _path; private final String _param; private final String _query; + private final String _fragment; private String _uri; private String _decodedPath; @@ -166,6 +170,7 @@ private Immutable(Mutable builder) _decodedPath = builder._decodedPath; _param = builder._param; _query = builder._query; + _fragment = builder._fragment; } private Immutable(String uri) @@ -179,6 +184,7 @@ private Immutable(String uri) _decodedPath = null; _param = null; _query = null; + _fragment = null; } @Override @@ -213,6 +219,12 @@ public String getDecodedPath() return _decodedPath; } + @Override + public String getFragment() + { + return _fragment; + } + @Override public String getHost() { @@ -305,6 +317,9 @@ public String toString() if (_query != null) out.append('?').append(_query); + if (_fragment != null) + out.append('#').append(_fragment); + if (out.length() > 0) _uri = out.toString(); else @@ -318,7 +333,7 @@ public URI toURI() { try { - return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), null); + return new URI(_scheme, null, _host, _port, _path, _query == null ? null : UrlEncoded.decodeString(_query), _fragment); } catch (URISyntaxException x) { @@ -353,6 +368,7 @@ private enum State private String _path; private String _param; private String _query; + private String _fragment; private Mutable() { @@ -384,6 +400,7 @@ private Mutable(HttpURI baseURI, String path, String param, String query) _path = path; _param = param; _query = query; + _fragment = null; } private Mutable(String uri) @@ -414,6 +431,7 @@ private Mutable(URI uri) _decodedPath = pathParam; } _query = uri.getRawQuery(); + _fragment = uri.getRawFragment(); } private Mutable(String scheme, String host, int port, String pathQuery) @@ -471,6 +489,7 @@ public Mutable clear() _path = null; _param = null; _query = null; + _fragment = null; _decodedPath = null; _user = null; return this; @@ -484,6 +503,12 @@ public Mutable decodedPath(String path) return this; } + public Mutable fragment(String fragment) + { + _fragment = fragment; + return this; + } + @Override public String getAuthority() { @@ -500,6 +525,12 @@ public String getDecodedPath() return _decodedPath; } + @Override + public String getFragment() + { + return _fragment; + } + @Override public String getHost() { @@ -1029,7 +1060,6 @@ else if (c == '/') { case START: case ASTERISK: - case FRAGMENT: break; case SCHEME_OR_PATH: @@ -1065,6 +1095,10 @@ else if (c == '/') _query = uri.substring(mark, end); break; + case FRAGMENT: + _fragment = uri.substring(mark, end); + break; + default: throw new IllegalStateException(state.toString()); } diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 9f27909476e5..1732b717f725 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -24,13 +24,10 @@ public class MetaData implements Iterable { - private static final Supplier SELF_SUPPLIED_TRAILORS = () -> null; - private static final HttpFields SUPPLIED_TRAILERS = HttpFields.build(HttpFields.EMPTY).asImmutable(); private final HttpVersion _httpVersion; private final HttpFields _fields; private final long _contentLength; private final Supplier _trailerSupplier; - private HttpFields _trailers; public MetaData(HttpVersion version, HttpFields fields) { @@ -39,7 +36,7 @@ public MetaData(HttpVersion version, HttpFields fields) public MetaData(HttpVersion version, HttpFields fields, long contentLength) { - this(version, fields, contentLength, SELF_SUPPLIED_TRAILORS); + this(version, fields, contentLength, null); } public MetaData(HttpVersion version, HttpFields fields, long contentLength, Supplier trailerSupplier) @@ -48,14 +45,7 @@ public MetaData(HttpVersion version, HttpFields fields, long contentLength, Supp _fields = fields == null ? null : fields.asImmutable(); _contentLength = contentLength >= 0 ? contentLength : _fields == null ? -1 : _fields.getLongField(HttpHeader.CONTENT_LENGTH); - if (trailerSupplier == SELF_SUPPLIED_TRAILORS) - _trailerSupplier = () -> _trailers; - else - { - _trailerSupplier = trailerSupplier; - if (trailerSupplier != null) - _trailers = SUPPLIED_TRAILERS; - } + _trailerSupplier = trailerSupplier; } public boolean isRequest() @@ -84,28 +74,11 @@ public HttpFields getFields() return _fields; } - public boolean mayHaveTrailers() - { - return _trailers != null; - } - - public boolean hasTrailerSupplier() - { - return _trailers == SUPPLIED_TRAILERS; - } - public Supplier getTrailerSupplier() { return _trailerSupplier; } - public void setTrailers(HttpFields trailers) - { - if (_trailers != null) - throw new IllegalStateException(); - _trailers = trailers; - } - public long getContentLength() { return _contentLength; diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java index d56d3e96191e..7b20da955632 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURIParseTest.java @@ -179,10 +179,7 @@ public void testParseString(String input, String scheme, String host, Integer po assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); - - // We don't retain the fragment - if (input.indexOf('#') >= 0) - input = input.substring(0, input.indexOf('#')); + assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } catch (URISyntaxException e) @@ -194,6 +191,7 @@ public void testParseString(String input, String scheme, String host, Integer po assertThat("[" + input + "] .path", httpUri.getPath(), is(nullValue())); assertThat("[" + input + "] .param", httpUri.getParam(), is(nullValue())); assertThat("[" + input + "] .query", httpUri.getQuery(), is(nullValue())); + assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(nullValue())); } } @@ -220,10 +218,8 @@ public void testParseURI(String input, String scheme, String host, Integer port, assertThat("[" + input + "] .path", httpUri.getPath(), is(path)); assertThat("[" + input + "] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(query)); + assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(fragment)); - // We don't retain the fragment - if (input.indexOf('#') >= 0) - input = input.substring(0, input.indexOf('#')); assertThat("[" + input + "] .toString", httpUri.toString(), is(input)); } @@ -250,11 +246,7 @@ public void testCompareToJavaNetURI(String input, String scheme, String host, In assertThat("[" + input + "] .path", httpUri.getPath(), is(javaUri.getRawPath())); // Not Relevant for java.net.URI -- assertThat("["+input+"] .param", httpUri.getParam(), is(param)); assertThat("[" + input + "] .query", httpUri.getQuery(), is(javaUri.getRawQuery())); - - // We don't retain the fragment - String javaString = javaUri.toASCIIString(); - if (javaString.indexOf('#') >= 0) - javaString = javaString.substring(0, javaString.indexOf('#')); - assertThat("[" + input + "] .toString", httpUri.toString(), is(javaString)); + assertThat("[" + input + "] .fragment", httpUri.getFragment(), is(javaUri.getFragment())); + assertThat("[" + input + "] .toString", httpUri.toString(), is(javaUri.toASCIIString())); } } diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java index aaa0d0a5b7ea..8027b1c09195 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java @@ -87,6 +87,7 @@ public void testExample() throws Exception assertThat(uri.getDecodedPath(), is("/path/info")); assertThat(uri.getParam(), is("param")); assertThat(uri.getQuery(), is("query=value")); + assertThat(uri.getFragment(), is("fragment")); assertThat(uri.getAuthority(), is("host:8888")); } diff --git a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java index 125d9a920977..00ff189804d0 100644 --- a/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java +++ b/jetty-http2/http2-server/src/test/java/org/eclipse/jetty/http2/server/HTTP2CServerTest.java @@ -195,7 +195,7 @@ public void onData(DataFrame frame) ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/two", HttpVersion.HTTP_2, HttpFields.EMPTY, -1); generator.control(lease, new HeadersFrame(3, metaData, null, true)); for (ByteBuffer buffer : lease.getByteBuffers()) { @@ -233,7 +233,7 @@ public void testHTTP20Direct() throws Exception ByteBufferPool.Lease lease = new ByteBufferPool.Lease(byteBufferPool); generator.control(lease, new PrefaceFrame()); generator.control(lease, new SettingsFrame(new HashMap<>(), false)); - MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.build(), -1); + MetaData.Request metaData = new MetaData.Request("GET", HttpScheme.HTTP.asString(), new HostPortHttpField("localhost:" + connector.getLocalPort()), "/test", HttpVersion.HTTP_2, HttpFields.EMPTY, -1); generator.control(lease, new HeadersFrame(1, metaData, null, true)); try (Socket client = new Socket("localhost", connector.getLocalPort())) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 48d8871cf678..431835c85626 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -685,7 +685,7 @@ public void onRequest(MetaData.Request request) _request.setMetaData(request); - _request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme())); + _request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme())); // TODO move to setMetaData _combinedListener.onRequestBegin(_request); @@ -715,7 +715,7 @@ public void onTrailers(HttpFields trailers) { if (LOG.isDebugEnabled()) LOG.debug("onTrailers {} {}", this, trailers); - _request.getMetaData().setTrailers(trailers.asImmutable()); + _request.setTrailerHttpFields(trailers); _combinedListener.onRequestTrailers(_request); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index e9215ff33e70..465f4f524e9f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -42,7 +42,6 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.function.Supplier; import java.util.stream.Collectors; import javax.servlet.AsyncContext; import javax.servlet.AsyncListener; @@ -277,6 +276,7 @@ public String toString() private final HttpInput _input; private MetaData.Request _metaData; private HttpFields _httpFields; + private HttpFields _trailers; private HttpURI _uri; private String _method; private String _contextPath; @@ -347,11 +347,14 @@ public Map getTrailerFields() return trailers; } + public void setTrailerHttpFields(HttpFields trailers) + { + _trailers = trailers == null ? null : trailers.asImmutable(); + } + public HttpFields getTrailerHttpFields() { - MetaData.Request metadata = _metaData; - Supplier trailers = metadata == null ? null : metadata.getTrailerSupplier(); - return trailers == null ? null : trailers.get(); + return _trailers; } public HttpInput getHttpInput() @@ -1735,6 +1738,7 @@ protected void recycle() { _metaData = null; _httpFields = null; + _trailers = null; _method = null; _uri = null; diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index e134fb338c83..a567c6814920 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -861,7 +861,7 @@ public void testEncodeRedirect() { Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - request.setHttpURI(HttpURI.build(request.getHttpURI()).host("myhost").port(8888).asImmutable()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).host("myhost").port(8888)); request.setContextPath("/path"); assertEquals("http://myhost:8888/path/info;param?query=0&more=1#target", response.encodeURL("http://myhost:8888/path/info;param?query=0&more=1#target")); @@ -950,12 +950,12 @@ public void testSendRedirect() Response response = getResponse(); Request request = response.getHttpChannel().getRequest(); - HttpURI.Mutable builder = HttpURI.build(request.getHttpURI(), + HttpURI.Mutable uri = HttpURI.build(request.getHttpURI(), "/path/info;param;jsessionid=12345?query=0&more=1#target"); - builder.scheme("http"); + uri.scheme("http"); if (host != null) - builder.host(host).port(port); - request.setHttpURI(builder.asImmutable()); + uri.host(host).port(port); + request.setHttpURI(uri); request.setContextPath("/path"); request.setRequestedSessionId("12345"); request.setRequestedSessionIdFromCookie(i > 2); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java index dbe61eb8ea8e..0e21f6104a29 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP.java @@ -38,7 +38,7 @@ public class HttpUpgraderOverHTTP implements HttpUpgrader { - private static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + private static final PreEncodedHttpField WS_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); private static final PreEncodedHttpField WS_UPGRADE_FIELD = new PreEncodedHttpField(HttpHeader.UPGRADE, "websocket"); private static final PreEncodedHttpField WS_CONNECTION_FIELD = new PreEncodedHttpField(HttpHeader.CONNECTION, "Upgrade"); private static final PreEncodedHttpField PRAGMA_NO_CACHE_FIELD = new PreEncodedHttpField(HttpHeader.PRAGMA, "no-cache"); @@ -54,7 +54,7 @@ public HttpUpgraderOverHTTP(ClientUpgradeRequest clientUpgradeRequest) public void prepare(HttpRequest request) { request.method(HttpMethod.GET).version(HttpVersion.HTTP_1_1) - .add(WS_VERSIONS_FIELD) + .add(WS_VERSION_FIELD) .add(WS_UPGRADE_FIELD) .add(WS_CONNECTION_FIELD) .header(HttpHeader.SEC_WEBSOCKET_KEY, generateRandomKey()) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java index 1fbba0f11023..865fc73860cd 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java @@ -30,7 +30,7 @@ public class HttpUpgraderOverHTTP2 implements HttpUpgrader { - public static final PreEncodedHttpField SPEC_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + public static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP2(ClientUpgradeRequest clientUpgradeRequest) @@ -43,7 +43,7 @@ public void prepare(HttpRequest request) { request.method(HttpMethod.CONNECT); request.upgradeProtocol("websocket"); - request.add(SPEC_VERSION_FIELD); + request.add(WS_VERSIONS_FIELD); // Notify the UpgradeListeners now the headers are set. clientUpgradeRequest.requestComplete(); diff --git a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java index 9dc1edbfdeb6..8d3a40bae68e 100644 --- a/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java +++ b/jetty-websocket/websocket-core/src/test/java/org/eclipse/jetty/websocket/core/extensions/PerMessageDeflaterBufferSizeTest.java @@ -106,7 +106,7 @@ public void testClientDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @deflate_buffer_size=" + deflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -121,7 +121,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFields.Mutable requestHeaders = futureRequestHeaders.get(); + HttpFields requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -160,7 +160,7 @@ public void testClientInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate; @inflate_buffer_size=" + inflateBufferSize); - CompletableFuture futureRequestHeaders = new CompletableFuture<>(); + CompletableFuture futureRequestHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -175,7 +175,7 @@ public void onHandshakeRequest(HttpRequest request) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent to the server. - HttpFields.Mutable requestHeaders = futureRequestHeaders.get(); + HttpFields requestHeaders = futureRequestHeaders.get(); assertThat(requestHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(requestHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -215,7 +215,7 @@ public void testServerDeflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -230,7 +230,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFields.Mutable responseHeaders = futureResponseHeaders.get(); + HttpFields responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); @@ -270,7 +270,7 @@ public void testServerInflateBufferSize() throws Exception ClientUpgradeRequest upgradeRequest = ClientUpgradeRequest.from(client, serverUri, clientHandler); upgradeRequest.addExtensions("permessage-deflate"); - CompletableFuture futureResponseHeaders = new CompletableFuture<>(); + CompletableFuture futureResponseHeaders = new CompletableFuture<>(); upgradeRequest.addListener(new UpgradeListener() { @Override @@ -285,7 +285,7 @@ public void onHandshakeResponse(HttpRequest request, HttpResponse response) connect.get(5, TimeUnit.SECONDS); // Make sure the internal parameter was not sent from the server. - HttpFields.Mutable responseHeaders = futureResponseHeaders.get(); + HttpFields responseHeaders = futureResponseHeaders.get(); assertThat(responseHeaders.getFields(HttpHeader.SEC_WEBSOCKET_EXTENSIONS).size(), is(1)); assertThat(responseHeaders.get(HttpHeader.SEC_WEBSOCKET_EXTENSIONS), is("permessage-deflate")); diff --git a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java index 52938a7b9e6a..b8d35e2342a2 100644 --- a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java +++ b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java @@ -56,12 +56,9 @@ public JettyClientUpgradeRequest(WebSocketCoreClient coreClient, UpgradeRequest List cookies = request.getCookies(); if (cookies != null) { - HttpFields.Mutable headers = getHeaders(); // TODO: remove existing Cookie header (if set)? for (HttpCookie cookie : cookies) - { - headers.add(HttpHeader.COOKIE, cookie.toString()); - } + fields.add(HttpHeader.COOKIE, cookie.toString()); } // Copy sub-protocols diff --git a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java index dc6cc69bba1f..fa10fea698f4 100644 --- a/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java +++ b/tests/test-http-client-transport/src/test/java/org/eclipse/jetty/http/client/ProxyWithDynamicTransportTest.java @@ -442,7 +442,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.build(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.EMPTY, null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); @@ -527,7 +527,7 @@ protected void close(Throwable failure) http2Client.connect(new InetSocketAddress("localhost", proxyConnector.getLocalPort()), new Session.Listener.Adapter(), sessionPromise); Session session = sessionPromise.get(5, TimeUnit.SECONDS); String serverAddress = "localhost:" + serverConnector.getLocalPort(); - MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.build(), null); + MetaData.ConnectRequest connect = new MetaData.ConnectRequest(HttpScheme.HTTP, new AuthorityHttpField(serverAddress), null, HttpFields.EMPTY, null); HeadersFrame frame = new HeadersFrame(connect, null, false); FuturePromise streamPromise = new FuturePromise<>(); CountDownLatch tunnelLatch = new CountDownLatch(1); From 1fe41691011c6434ee6c1a894f676fcc83a42739 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 23 Apr 2020 19:43:23 +0200 Subject: [PATCH 33/38] Immutable MetaData WIP changes after review: + less usage of Mutable + less usage of asImmutable Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/http/HttpURI.java | 133 +++++++++++------- .../java/org/eclipse/jetty/http/MetaData.java | 1 - .../eclipse/jetty/http2/client/HTTP2Test.java | 4 +- .../client/http/HttpSenderOverHTTP2.java | 2 - .../rewrite/handler/RewritePatternRule.java | 2 +- .../ForwardedSchemeHeaderRuleTest.java | 6 +- .../rewrite/handler/RewriteHandlerTest.java | 16 +-- .../rewrite/handler/RewriteRegexRuleTest.java | 6 +- .../rewrite/handler/ValidUrlRuleTest.java | 12 +- .../handler/VirtualHostRuleContainerTest.java | 36 ++--- .../jetty/security/DataConstraintsTest.java | 2 +- .../SpnegoAuthenticatorTest.java | 4 +- .../org/eclipse/jetty/server/Request.java | 2 +- .../eclipse/jetty/server/ResourceService.java | 2 +- 14 files changed, 131 insertions(+), 97 deletions(-) diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java index e9f2480dde44..f740a2086a02 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java @@ -30,7 +30,7 @@ /** * Http URI. * - * Both {@link HttpFields.Mutable} and {@link HttpFields.Immutable} implementations are available + * Both {@link Mutable} and {@link Immutable} implementations are available * via the static methods such as {@link #build()} and {@link #from(String)}. * * A URI such as @@ -47,7 +47,7 @@ * *

Any parameters will be returned from {@link #getPath()}, but are excluded from the * return value of {@link #getDecodedPath()}. If there are multiple parameters, the - * {@link #getParam()} method returns only the last one. Fragments are ignored. + * {@link #getParam()} method returns only the last one. */ public interface HttpURI { @@ -107,6 +107,8 @@ static Immutable from(String scheme, String host, int port, String pathQuery) Immutable asImmutable(); + String asString(); + String getAuthority(); String getDecodedPath(); @@ -161,30 +163,30 @@ class Immutable implements HttpURI private Immutable(Mutable builder) { - _uri = builder._uri; _scheme = builder._scheme; _user = builder._user; _host = builder._host; _port = builder._port; _path = builder._path; - _decodedPath = builder._decodedPath; _param = builder._param; _query = builder._query; _fragment = builder._fragment; + _uri = builder._uri; + _decodedPath = builder._decodedPath; } private Immutable(String uri) { - _uri = uri; _scheme = null; _user = null; _host = null; _port = -1; _path = uri; - _decodedPath = null; _param = null; _query = null; _fragment = null; + _uri = uri; + _decodedPath = null; } @Override @@ -193,6 +195,44 @@ public Immutable asImmutable() return this; } + @Override + public String asString() + { + if (_uri == null) + { + StringBuilder out = new StringBuilder(); + + if (_scheme != null) + out.append(_scheme).append(':'); + + if (_host != null) + { + out.append("//"); + if (_user != null) + out.append(_user).append('@'); + out.append(_host); + } + + if (_port > 0) + out.append(':').append(_port); + + if (_path != null) + out.append(_path); + + if (_query != null) + out.append('?').append(_query); + + if (_fragment != null) + out.append('#').append(_fragment); + + if (out.length() > 0) + _uri = out.toString(); + else + _uri = ""; + } + return _uri; + } + @Override public boolean equals(Object o) { @@ -200,7 +240,7 @@ public boolean equals(Object o) return true; if (!(o instanceof HttpURI)) return false; - return toString().equals(o.toString()); + return asString().equals(((HttpURI)o).asString()); } @Override @@ -284,6 +324,12 @@ public boolean hasAuthority() return _host != null; } + @Override + public int hashCode() + { + return asString().hashCode(); + } + @Override public boolean isAbsolute() { @@ -293,39 +339,7 @@ public boolean isAbsolute() @Override public String toString() { - if (_uri == null) - { - StringBuilder out = new StringBuilder(); - - if (_scheme != null) - out.append(_scheme).append(':'); - - if (_host != null) - { - out.append("//"); - if (_user != null) - out.append(_user).append('@'); - out.append(_host); - } - - if (_port > 0) - out.append(':').append(_port); - - if (_path != null) - out.append(_path); - - if (_query != null) - out.append('?').append(_query); - - if (_fragment != null) - out.append('#').append(_fragment); - - if (out.length() > 0) - _uri = out.toString(); - else - _uri = ""; - } - return _uri; + return asString(); } @Override @@ -359,8 +373,6 @@ private enum State ASTERISK } - private String _uri; - private String _decodedPath; private String _scheme; private String _user; private String _host; @@ -369,6 +381,8 @@ private enum State private String _param; private String _query; private String _fragment; + private String _uri; + private String _decodedPath; private Mutable() { @@ -452,6 +466,12 @@ public Immutable asImmutable() return new Immutable(this); } + @Override + public String asString() + { + return asImmutable().toString(); + } + /** * @param host the host * @param port the port @@ -482,16 +502,17 @@ public Mutable authority(String hostport) public Mutable clear() { - _uri = null; _scheme = null; + _user = null; _host = null; _port = -1; _path = null; _param = null; _query = null; _fragment = null; + _uri = null; _decodedPath = null; - _user = null; + return this; } @@ -503,6 +524,16 @@ public Mutable decodedPath(String path) return this; } + @Override + public boolean equals(Object o) + { + if (o == this) + return true; + if (!(o instanceof HttpURI)) + return false; + return asString().equals(((HttpURI)o).asString()); + } + public Mutable fragment(String fragment) { _fragment = fragment; @@ -586,6 +617,12 @@ public boolean hasAuthority() return _host != null; } + @Override + public int hashCode() + { + return asString().hashCode(); + } + public Mutable host(String host) { _host = host; @@ -672,7 +709,7 @@ public Mutable scheme(String scheme) @Override public String toString() { - return asImmutable().toString(); + return asString(); } public URI toURI() @@ -689,15 +726,15 @@ public URI toURI() public Mutable uri(HttpURI uri) { - _uri = null; _scheme = uri.getScheme(); _user = uri.getUser(); _host = uri.getHost(); _port = uri.getPort(); _path = uri.getPath(); - _decodedPath = uri.getDecodedPath(); _param = uri.getParam(); _query = uri.getQuery(); + _uri = null; + _decodedPath = uri.getDecodedPath(); return this; } @@ -1096,7 +1133,7 @@ else if (c == '/') break; case FRAGMENT: - _fragment = uri.substring(mark, end); + _fragment = uri.substring(mark, end); break; default: diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java index 1732b717f725..bc65f686b7ce 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MetaData.java @@ -194,7 +194,6 @@ public ConnectRequest(HttpScheme scheme, HostPortHttpField authority, String pat public ConnectRequest(String scheme, HostPortHttpField authority, String path, HttpFields fields, String protocol) { - // TODO should connect requests have paths? super(HttpMethod.CONNECT.asString(), HttpURI.build().scheme(scheme).host(authority == null ? null : authority.getHost()).port(authority == null ? -1 : authority.getPort()).pathQuery(path), HttpVersion.HTTP_2, fields, Long.MIN_VALUE, null); diff --git a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java index 235f13360f72..a49cfe134884 100644 --- a/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java +++ b/jetty-http2/http2-client/src/test/java/org/eclipse/jetty/http2/client/HTTP2Test.java @@ -266,7 +266,7 @@ protected void service(HttpServletRequest request, HttpServletResponse response) Session session = newClient(new Session.Listener.Adapter()); Random random = new Random(); - HttpFields.Mutable fields = HttpFields.build() + HttpFields fields = HttpFields.build() .putLongField(downloadBytes, random.nextInt(128 * 1024)) .put("User-Agent", "HTTP2Client/" + Jetty.VERSION); MetaData.Request metaData = newRequest("GET", fields); @@ -806,7 +806,7 @@ public void testClientInvalidHeader() throws Exception // A bad header in the request should fail on the client. Session session = newClient(new Session.Listener.Adapter()); - HttpFields.Mutable requestFields = HttpFields.build() + HttpFields requestFields = HttpFields.build() .put(":custom", "special"); MetaData.Request metaData = newRequest("GET", requestFields); HeadersFrame request = new HeadersFrame(metaData, null, true); diff --git a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java index e62973e55c6a..a666a7f68e65 100644 --- a/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java +++ b/jetty-http2/http2-http-client-transport/src/main/java/org/eclipse/jetty/http2/client/http/HttpSenderOverHTTP2.java @@ -64,8 +64,6 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool MetaData.Request metaData; if (isTunnel) { - // TODO what to do with trailers ?? - // TODO should connect requests have paths??? String upgradeProtocol = request.getUpgradeProtocol(); if (upgradeProtocol == null) { diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java index c7ae14b10fbb..e72440b76087 100644 --- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java +++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RewritePatternRule.java @@ -92,7 +92,7 @@ public String apply(String target, HttpServletRequest request, HttpServletRespon public void applyURI(Request request, String oldURI, String newURI) throws IOException { HttpURI baseURI = request.getHttpURI(); - String query = URIUtil.addQueries(baseURI.getQuery(),_query); + String query = URIUtil.addQueries(baseURI.getQuery(), _query); request.setHttpURI(HttpURI.build(baseURI, newURI, baseURI.getParam(), query)); } diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java index de836b7d0194..8700e1eb4fbd 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ForwardedSchemeHeaderRuleTest.java @@ -34,7 +34,7 @@ public void init() throws Exception { start(false); _rule = new ForwardedSchemeHeaderRule(); - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null)); } @Test @@ -72,13 +72,13 @@ public void testHeaderValue() throws Exception _rule.matchAndApply("/", _request, _response); assertEquals("https", _request.getScheme()); - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme("other").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme("other")); // header value doesn't match rule's value setRequestHeader("Front-End-Https", "off"); _rule.matchAndApply("/", _request, _response); assertEquals("other", _request.getScheme()); - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).scheme((String)null)); // header value can be any value setRequestHeader("Front-End-Https", "any"); _rule.setHeaderValue(null); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java index e9b6dc9bc5c6..ab5da55f4bcb 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteHandlerTest.java @@ -84,7 +84,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/bar")); _request.setPathInfo("/xxx/bar"); _handler.handle("/xxx/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -98,7 +98,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(false); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/foo/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/foo/bar")); _request.setPathInfo("/foo/bar"); _handler.handle("/foo/bar", _request, _request, _response); @@ -111,7 +111,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _handler.setOriginalPathAttribute(null); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar")); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -125,7 +125,7 @@ public void test() throws Exception _handler.setOriginalPathAttribute("before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(true); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar")); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -137,7 +137,7 @@ public void test() throws Exception _response.setStatus(200); _request.setHandled(false); _rule2.setTerminating(true); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar")); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -153,7 +153,7 @@ public void test() throws Exception _request.setAttribute("target", null); _request.setAttribute("URI", null); _request.setAttribute("info", null); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/aaa/bar")); _request.setPathInfo("/aaa/bar"); _handler.handle("/aaa/bar", _request, _request, _response); assertEquals(200, _response.getStatus()); @@ -172,7 +172,7 @@ public void testEncodedPattern() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/ccc/x%20y").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/ccc/x%20y")); _request.setPathInfo("/ccc/x y"); _handler.handle("/ccc/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); @@ -189,7 +189,7 @@ public void testEncodedRegex() throws Exception _handler.setOriginalPathAttribute("/before"); _handler.setRewriteRequestURI(true); _handler.setRewritePathInfo(false); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/x%20y").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/xxx/x%20y")); _request.setPathInfo("/xxx/x y"); _handler.handle("/xxx/x y", _request, _request, _response); assertEquals(201, _response.getStatus()); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java index 4438abddd52d..80f84a71146e 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/RewriteRegexRuleTest.java @@ -63,12 +63,12 @@ public void testRequestUriEnabled(Scenario scenario) throws Exception RewriteRegexRule rule = new RewriteRegexRule(); reset(); - _request.setHttpURI(HttpURI.build(_request.getHttpURI()).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI())); rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString)); String result = rule.matchAndApply(scenario.uriPathQuery, _request, _response); assertEquals(scenario.expectedRequestURI, result); @@ -107,7 +107,7 @@ public void testContainedRequestUriEnabled(Scenario scenario) throws Exception rule.setRegex(scenario.regex); rule.setReplacement(scenario.replacement); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), scenario.uriPathQuery, null, scenario.queryString)); _request.getAttributes().clearAttributes(); String result = container.apply(URIUtil.decodePath(scenario.uriPathQuery), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java index 0fb43ab4412a..3aa4d6869c42 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java @@ -44,7 +44,7 @@ public void init() throws Exception public void testValidUrl() throws Exception { _rule.setCode("404"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/valid/uri.html").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/valid/uri.html")); _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -55,7 +55,7 @@ public void testValidUrl() throws Exception public void testInvalidUrl() throws Exception { _rule.setCode("404"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/invalid%0c/uri.html").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/invalid%0c/uri.html")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -67,7 +67,7 @@ public void testInvalidUrlWithMessage() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/%00/").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/%00/")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -80,7 +80,7 @@ public void testInvalidJsp() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/bean1.jsp%00").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/bean1.jsp%00")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -94,7 +94,7 @@ public void testInvalidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%00%E2%98%98.jsp").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%00%E2%98%98.jsp")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); @@ -108,7 +108,7 @@ public void testValidShamrock() throws Exception { _rule.setCode("405"); _rule.setMessage("foo"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%E2%98%98.jsp").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/jsp/shamrock-%E2%98%98.jsp")); String result = _rule.matchAndApply(_request.getRequestURI(), _request, _response); diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java index a164a0d8444d..6e9e812c6bd7 100644 --- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java +++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/VirtualHostRuleContainerTest.java @@ -50,7 +50,7 @@ public void init() throws Exception _fooContainerRule.setRules(new Rule[]{_fooRule}); start(false); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _handler.setServer(_server); _handler.start(); @@ -59,7 +59,7 @@ public void init() throws Exception @Test public void testArbitraryHost() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0)); _handler.setRules(new Rule[]{_rule, _fooContainerRule}); handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule, Host: cheese.com}: applied _rule"); @@ -68,7 +68,7 @@ public void testArbitraryHost() throws Exception @Test public void testVirtualHost() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0)); _handler.setRules(new Rule[]{_fooContainerRule}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: foo.com}: applied _fooRule"); @@ -77,8 +77,8 @@ public void testVirtualHost() throws Exception @Test public void testCascadingRules() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0)); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _rule.setTerminating(false); _fooRule.setTerminating(false); @@ -88,17 +88,17 @@ public void testCascadingRules() throws Exception handleRequest(); assertEquals("/rule/bar", _request.getRequestURI(), "{_rule, _fooContainerRule}: applied _rule, didn't match _fooRule"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _handler.setRules(new Rule[]{_fooContainerRule, _rule}); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: applied _fooRule, _rule"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _fooRule.setTerminating(true); handleRequest(); assertEquals("/rule/fooRule", _request.getRequestURI(), "{_fooContainerRule, _rule}: (_fooRule is terminating); applied _fooRule, _rule"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _fooRule.setTerminating(false); _fooContainerRule.setTerminating(true); handleRequest(); @@ -108,7 +108,7 @@ public void testCascadingRules() throws Exception @Test public void testCaseInsensitiveHostname() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("Foo.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("Foo.com", 0)); _fooContainerRule.setVirtualHosts(new String[]{"foo.com"}); _handler.setRules(new Rule[]{_fooContainerRule}); @@ -119,21 +119,21 @@ public void testCaseInsensitiveHostname() throws Exception @Test public void testEmptyVirtualHost() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("cheese.com", 0)); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(null); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is null, Host: cheese.com}: apply _fooRule"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _fooContainerRule.setVirtualHosts(new String[]{}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual hosts array is empty, Host: cheese.com}: apply _fooRule"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _fooContainerRule.setVirtualHosts(new String[]{null}); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: virtual host is null, Host: cheese.com}: apply _fooRule"); @@ -142,14 +142,14 @@ public void testEmptyVirtualHost() throws Exception @Test public void testMultipleVirtualHosts() throws Exception { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0).asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority("foo.com", 0)); _handler.setRules(new Rule[]{_fooContainerRule}); _fooContainerRule.setVirtualHosts(new String[]{"cheese.com"}); handleRequest(); assertEquals("/cheese/bar", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com], Host: foo.com}: no effect"); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); _fooContainerRule.addVirtualHost("foo.com"); handleRequest(); assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule: vhosts[cheese.com, foo.com], Host: foo.com}: apply _fooRule"); @@ -186,8 +186,8 @@ private void checkWildcardHost(boolean succeed, String[] ruleHosts, String[] req for (String host : requestHosts) { - _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority(host, 0).asImmutable()); - _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar").asImmutable()); + _request.setHttpURI(HttpURI.build(_request.getRequestURI()).authority(host, 0)); + _request.setHttpURI(HttpURI.build(_request.getHttpURI(), "/cheese/bar")); handleRequest(); if (succeed) assertEquals("/cheese/fooRule", _request.getRequestURI(), "{_fooContainerRule, Host: " + host + "}: should apply _fooRule"); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java index 37799f234f04..aa7fce9ca8be 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/DataConstraintsTest.java @@ -72,7 +72,7 @@ public void startServer() @Override public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { - request.setHttpURI(HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS).asImmutable()); + request.setHttpURI(HttpURI.build(request.getHttpURI()).scheme(HttpScheme.HTTPS)); request.setSecure(true); } }); diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java index ac20c661ac95..5740c2da2904 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticatorTest.java @@ -77,7 +77,7 @@ public void flush() throws IOException {} }; Request req = channel.getRequest(); Response res = channel.getResponse(); - MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, HttpFields.EMPTY); + MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost"), null, HttpFields.EMPTY); req.setMetaData(metadata); assertThat(channel.getState().handling(), is(HttpChannelState.Action.DISPATCH)); @@ -115,7 +115,7 @@ public void flush() throws IOException {} // Create a bogus Authorization header. We don't care about the actual credentials. - MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost").asImmutable(), null, + MetaData.Request metadata = new MetaData.Request(null, HttpURI.build("http://localhost"), null, HttpFields.build().add(HttpHeader.AUTHORIZATION, "Basic asdf")); req.setMetaData(metadata); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 465f4f524e9f..0ed051bf9089 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1123,7 +1123,7 @@ public HttpVersion getHttpVersion() public String getQueryEncoding() { - return _queryEncoding == null ? null : _queryEncoding.toString(); + return _queryEncoding == null ? null : _queryEncoding.name(); } Charset getQueryCharset() diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 93909ade0a03..10d1759a4cf2 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -488,7 +488,7 @@ protected boolean passConditionalHeaders(HttpServletRequest request, HttpServlet if (request instanceof Request) { // Find multiple fields by iteration as an optimization - for (HttpField field : ((Request)request).getHttpFields()) + for (HttpField field : ((Request)request).getHttpFields()) { if (field.getHeader() != null) { From 9e9274fece8b9f952e5b5c91c548c7c962ebd7b8 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 24 Apr 2020 09:52:24 +0200 Subject: [PATCH 34/38] Immutable MetaData WIP changes after review: + less usage of Mutable Signed-off-by: Greg Wilkins --- .../jetty/fcgi/client/http/HttpSenderOverFCGI.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java index 0c654a43d77c..3e3fa2285a66 100644 --- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java +++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpSenderOverFCGI.java @@ -60,7 +60,7 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool { Request request = exchange.getRequest(); // Copy the request headers to be able to convert them properly - HttpFields.Mutable headers = HttpFields.build(request.getHeaders()); + HttpFields headers = request.getHeaders(); HttpFields.Mutable fcgiHeaders = HttpFields.build(); // FastCGI headers based on the URI @@ -72,13 +72,15 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool // FastCGI headers based on HTTP headers HttpField httpField = headers.getField(HttpHeader.AUTHORIZATION); + EnumSet toRemove = EnumSet.of(HttpHeader.AUTHORIZATION); if (httpField != null) fcgiHeaders.put(FCGI.Headers.AUTH_TYPE, httpField.getValue()); httpField = headers.getField(HttpHeader.CONTENT_LENGTH); + toRemove.add(HttpHeader.CONTENT_LENGTH); fcgiHeaders.put(FCGI.Headers.CONTENT_LENGTH, httpField == null ? "" : httpField.getValue()); httpField = headers.getField(HttpHeader.CONTENT_TYPE); + toRemove.add(HttpHeader.CONTENT_TYPE); fcgiHeaders.put(FCGI.Headers.CONTENT_TYPE, httpField == null ? "" : httpField.getValue()); - headers.remove(EnumSet.of(HttpHeader.AUTHORIZATION, HttpHeader.CONTENT_LENGTH, HttpHeader.CONTENT_TYPE)); // FastCGI headers that are not based on HTTP headers nor URI fcgiHeaders.put(FCGI.Headers.REQUEST_METHOD, request.getMethod()); @@ -89,6 +91,8 @@ protected void sendHeaders(HttpExchange exchange, ByteBuffer contentBuffer, bool // Translate remaining HTTP header into the HTTP_* format for (HttpField field : headers) { + if (toRemove.contains(field.getHeader())) + continue; String name = field.getName(); String fcgiName = "HTTP_" + StringUtil.replace(name, '-', '_').toUpperCase(Locale.ENGLISH); fcgiHeaders.add(fcgiName, field.getValue()); From 1abe2c79f8b3ab0257b105b095ee67f90b2fb3c3 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 24 Apr 2020 10:11:25 +0200 Subject: [PATCH 35/38] Immutable MetaData changes after review: + better handling of URI in ContextHandler Signed-off-by: Greg Wilkins --- .../jetty/http2/hpack/MetaDataBuilder.java | 1 - .../org/eclipse/jetty/server/Dispatcher.java | 2 +- .../org/eclipse/jetty/server/HttpChannel.java | 3 --- .../org/eclipse/jetty/server/Request.java | 1 + .../jetty/server/handler/ContextHandler.java | 22 +++++++------------ 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java index 2a00686edd48..03d2c1088cf5 100644 --- a/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java +++ b/jetty-http2/http2-hpack/src/main/java/org/eclipse/jetty/http2/hpack/MetaDataBuilder.java @@ -141,7 +141,6 @@ else if (header != null) else if (value != null) _authority = new AuthorityHttpField(value); } - _request = true; break; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java index c7103d249269..771e4b90cbf1 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java @@ -61,7 +61,7 @@ public class Dispatcher implements RequestDispatcher public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext) { _contextHandler = contextHandler; - _uri = uri; + _uri = uri.asImmutable(); _pathInContext = pathInContext; _named = null; } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 431835c85626..d920751f7f8f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -38,7 +38,6 @@ import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.MetaData; @@ -685,8 +684,6 @@ public void onRequest(MetaData.Request request) _request.setMetaData(request); - _request.setSecure(HttpScheme.HTTPS.is(request.getURI().getScheme())); // TODO move to setMetaData - _combinedListener.onRequestBegin(_request); if (LOG.isDebugEnabled()) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 0ed051bf9089..beee4c16082f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -1682,6 +1682,7 @@ public void setMetaData(MetaData.Request request) { if (uri.getPath() == null) builder.path("/"); + setSecure(HttpScheme.HTTPS.is(uri.getScheme())); } else { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index d1b63779f5a0..39bf1802caa8 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -2141,22 +2141,16 @@ public RequestDispatcher getRequestDispatcher(String uriInContext) try { String contextPath = getContextPath(); - HttpURI uri; String pathInfo; - if (StringUtil.isEmpty(contextPath)) - { - uri = HttpURI.from(uriInContext); - pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); - if (StringUtil.isEmpty(pathInfo)) - return null; - } - else + + HttpURI.Mutable uri = HttpURI.build(uriInContext); + pathInfo = URIUtil.canonicalPath(uri.getDecodedPath()); + if (StringUtil.isEmpty(pathInfo)) + return null; + + if (!StringUtil.isEmpty(contextPath)) { - HttpURI.Mutable builder = HttpURI.build(uriInContext); - if (StringUtil.isEmpty(URIUtil.canonicalPath(builder.getDecodedPath()))) - return null; - builder.path(URIUtil.addPaths(contextPath,builder.getPath())); - uri = builder.asImmutable(); + uri.path(URIUtil.addPaths(contextPath,uri.getPath())); pathInfo = uri.getDecodedPath().substring(contextPath.length()); } return new Dispatcher(ContextHandler.this, uri, pathInfo); From ad82672e233254cb6e49b7bfe8cc431b2a7a8f5f Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 24 Apr 2020 10:46:38 +0200 Subject: [PATCH 36/38] Immutable MetaData changes after review: + downcast in test to access mutable response headers. Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/client/HttpReceiver.java | 2 +- .../src/main/java/org/eclipse/jetty/client/HttpResponse.java | 2 +- .../org/eclipse/jetty/client/ClientConnectionCloseTest.java | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java index e75f421169eb..c39d75b17170 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java @@ -242,7 +242,7 @@ protected boolean responseHeader(HttpExchange exchange, HttpField field) boolean process = notifier.notifyHeader(exchange.getConversation().getResponseListeners(), response, field); if (process) { - response.getHeadersBuilder().add(field); + response.getHeaderFieldsMutable().add(field); HttpHeader fieldHeader = field.getHeader(); if (fieldHeader != null) { diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java index 30e01c5a5d33..3d941c928277 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpResponse.java @@ -91,7 +91,7 @@ public HttpFields getHeaders() return headers.asImmutable(); } - public HttpFields.Mutable getHeadersBuilder() + public HttpFields.Mutable getHeaderFieldsMutable() { return headers; } diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java index 2415f568a86b..70cb83e408ff 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ClientConnectionCloseTest.java @@ -249,6 +249,10 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques DuplexConnectionPool connectionPool = (DuplexConnectionPool)destination.getConnectionPool(); HttpConnectionOverHTTP connection = (HttpConnectionOverHTTP)connectionPool.getActiveConnections().iterator().next(); assertFalse(connection.getEndPoint().isOutputShutdown()); + }) + .onResponseHeaders(r -> + { + ((HttpResponse)r).getHeaderFieldsMutable().remove(HttpHeader.CONNECTION); }); ContentResponse response = request.send(); From ec9224d2191468dde347ac2d5e625d01ea4919e4 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 24 Apr 2020 18:32:10 +0200 Subject: [PATCH 37/38] Immutable MetaData changes after review: + use put instead of add for one time headers Signed-off-by: Greg Wilkins --- .../src/main/java/embedded/client/http2/HTTP2ClientDocs.java | 4 ++-- .../jetty/websocket/core/client/HttpUpgraderOverHTTP2.java | 4 ++-- .../websocket/client/impl/JettyClientUpgradeRequest.java | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java index 1a7b64ab8b19..0e59f95648aa 100644 --- a/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java +++ b/jetty-documentation/src/main/java/embedded/client/http2/HTTP2ClientDocs.java @@ -267,7 +267,7 @@ public void reset() throws Exception Session session = sessionCF.get(); HttpFields requestHeaders = HttpFields.build() - .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); @@ -297,7 +297,7 @@ public void push() throws Exception Session session = sessionCF.get(); HttpFields requestHeaders = HttpFields.build() - .add(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); + .put(HttpHeader.USER_AGENT, "Jetty HTTP2Client {version}"); MetaData.Request request = new MetaData.Request("GET", HttpURI.from("http://localhost:8080/path"), HttpVersion.HTTP_2, requestHeaders); HeadersFrame headersFrame = new HeadersFrame(request, null, true); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java index 865fc73860cd..ba2c0e642605 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java @@ -30,7 +30,7 @@ public class HttpUpgraderOverHTTP2 implements HttpUpgrader { - public static final PreEncodedHttpField WS_VERSIONS_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + public static final PreEncodedHttpField WS_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP2(ClientUpgradeRequest clientUpgradeRequest) @@ -43,7 +43,7 @@ public void prepare(HttpRequest request) { request.method(HttpMethod.CONNECT); request.upgradeProtocol("websocket"); - request.add(WS_VERSIONS_FIELD); + request.add(WS_VERSION_FIELD); // Notify the UpgradeListeners now the headers are set. clientUpgradeRequest.requestComplete(); diff --git a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java index b8d35e2342a2..0f6ddeeef99e 100644 --- a/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java +++ b/jetty-websocket/websocket-jetty-client/src/main/java/org/eclipse/jetty/websocket/client/impl/JettyClientUpgradeRequest.java @@ -58,7 +58,9 @@ public JettyClientUpgradeRequest(WebSocketCoreClient coreClient, UpgradeRequest { // TODO: remove existing Cookie header (if set)? for (HttpCookie cookie : cookies) + { fields.add(HttpHeader.COOKIE, cookie.toString()); + } } // Copy sub-protocols From 5817a1ab489dfc5d4f5eb1de93e2a4f7d98416a3 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 27 Apr 2020 12:56:34 +0200 Subject: [PATCH 38/38] private Signed-off-by: Greg Wilkins --- .../jetty/websocket/core/client/HttpUpgraderOverHTTP2.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java index ba2c0e642605..e1904a0b4197 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/HttpUpgraderOverHTTP2.java @@ -30,7 +30,7 @@ public class HttpUpgraderOverHTTP2 implements HttpUpgrader { - public static final PreEncodedHttpField WS_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); + private static final PreEncodedHttpField WS_VERSION_FIELD = new PreEncodedHttpField(HttpHeader.SEC_WEBSOCKET_VERSION, WebSocketConstants.SPEC_VERSION_STRING); private final ClientUpgradeRequest clientUpgradeRequest; public HttpUpgraderOverHTTP2(ClientUpgradeRequest clientUpgradeRequest)