diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/CombinedHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/CombinedHttpHeaders.java
new file mode 100644
index 0000000000..ba8588a402
--- /dev/null
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/CombinedHttpHeaders.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.codec.http;
+
+import io.netty.util.internal.StringUtil;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import static io.netty.util.internal.StringUtil.COMMA;
+
+/**
+ * Will add multiple values for the same header as single header with a comma separated list of values.
+ *
+ * Please refer to section RFC 7230, 3.2.2 .
+ */
+public class CombinedHttpHeaders extends DefaultHttpHeaders {
+ /**
+ * An estimate of the size of a header value.
+ */
+ private static final int VALUE_LENGTH_ESTIMATE = 10;
+ private CsvValueEscaper objectEscaper;
+ private CsvValueEscaper charSequenceEscaper;
+
+ public CombinedHttpHeaders(boolean validate) {
+ super(validate);
+ }
+
+ private CsvValueEscaper objectEscaper() {
+ if (objectEscaper == null) {
+ objectEscaper = new CsvValueEscaper() {
+ @Override
+ public CharSequence escape(Object value) {
+ return StringUtil.escapeCsv(valueConverter().convertObject(value));
+ }
+ };
+ }
+ return objectEscaper;
+ }
+
+ private CsvValueEscaper charSequenceEscaper() {
+ if (charSequenceEscaper == null) {
+ charSequenceEscaper = new CsvValueEscaper() {
+ @Override
+ public CharSequence escape(CharSequence value) {
+ return StringUtil.escapeCsv(value);
+ }
+ };
+ }
+ return charSequenceEscaper;
+ }
+
+ @Override
+ public CombinedHttpHeaders add(CharSequence name, CharSequence value) {
+ return addEscapedValue(name, StringUtil.escapeCsv(value));
+ }
+
+ @Override
+ public CombinedHttpHeaders add(CharSequence name, CharSequence... values) {
+ return addEscapedValue(name, commaSeparate(charSequenceEscaper(), values));
+ }
+
+ @Override
+ public CombinedHttpHeaders add(CharSequence name, Iterable extends CharSequence> values) {
+ return addEscapedValue(name, commaSeparate(charSequenceEscaper(), values));
+ }
+
+ @Override
+ public CombinedHttpHeaders addObject(CharSequence name, Iterable> values) {
+ return addEscapedValue(name, commaSeparate(objectEscaper(), values));
+ }
+
+ @Override
+ public CombinedHttpHeaders addObject(CharSequence name, Object... values) {
+ return addEscapedValue(name, commaSeparate(objectEscaper(), values));
+ }
+
+ @Override
+ public CombinedHttpHeaders set(CharSequence name, CharSequence... values) {
+ super.set(name, commaSeparate(charSequenceEscaper(), values));
+ return this;
+ }
+
+ @Override
+ public CombinedHttpHeaders set(CharSequence name, Iterable extends CharSequence> values) {
+ super.set(name, commaSeparate(charSequenceEscaper(), values));
+ return this;
+ }
+
+ @Override
+ public CombinedHttpHeaders setObject(CharSequence name, Object... values) {
+ super.set(name, commaSeparate(objectEscaper(), values));
+ return this;
+ }
+
+ @Override
+ public CombinedHttpHeaders setObject(CharSequence name, Iterable> values) {
+ super.set(name, commaSeparate(objectEscaper(), values));
+ return this;
+ }
+
+ private CombinedHttpHeaders addEscapedValue(CharSequence name, CharSequence escapedValue) {
+ CharSequence currentValue = super.get(name);
+ if (currentValue == null) {
+ super.add(name, escapedValue);
+ } else {
+ super.set(name, commaSeparateEscapedValues(currentValue, escapedValue));
+ }
+ return this;
+ }
+
+ private static CharSequence commaSeparate(CsvValueEscaper escaper, T... values) {
+ StringBuilder sb = new StringBuilder(values.length * VALUE_LENGTH_ESTIMATE);
+ if (values.length > 0) {
+ int end = values.length - 1;
+ for (int i = 0; i < end; i++) {
+ sb.append(escaper.escape(values[i])).append(COMMA);
+ }
+ sb.append(escaper.escape(values[end]));
+ }
+ return sb;
+ }
+
+ private static CharSequence commaSeparate(CsvValueEscaper escaper, Iterable extends T> values) {
+ @SuppressWarnings("rawtypes")
+ final StringBuilder sb = values instanceof Collection
+ ? new StringBuilder(((Collection) values).size() * VALUE_LENGTH_ESTIMATE) : new StringBuilder();
+ Iterator extends T> iterator = values.iterator();
+ if (iterator.hasNext()) {
+ T next = iterator.next();
+ while (iterator.hasNext()) {
+ sb.append(escaper.escape(next)).append(COMMA);
+ next = iterator.next();
+ }
+ sb.append(escaper.escape(next));
+ }
+ return sb;
+ }
+
+ private CharSequence commaSeparateEscapedValues(CharSequence currentValue, CharSequence value) {
+ return new StringBuilder(currentValue.length() + 1 + value.length())
+ .append(currentValue)
+ .append(COMMA)
+ .append(value);
+ }
+
+ /**
+ * Escapes comma separated values (CSV).
+ *
+ * @param The type that a concrete implementation handles
+ */
+ private interface CsvValueEscaper {
+ /**
+ * Appends the value to the specified {@link StringBuilder}, escaping if necessary.
+ *
+ * @param value the value to be appended, escaped if necessary
+ */
+ CharSequence escape(T value);
+ }
+}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultFullHttpResponse.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultFullHttpResponse.java
index 29d4495bd9..6db955d248 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultFullHttpResponse.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultFullHttpResponse.java
@@ -15,10 +15,10 @@
*/
package io.netty.handler.codec.http;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-
/**
* Default implementation of a {@link FullHttpResponse}.
*/
@@ -33,7 +33,7 @@ public class DefaultFullHttpResponse extends DefaultHttpResponse implements Full
}
public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, ByteBuf content) {
- this(version, status, content, false);
+ this(version, status, content, true);
}
public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders) {
@@ -46,18 +46,16 @@ public class DefaultFullHttpResponse extends DefaultHttpResponse implements Full
}
public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
- ByteBuf content, boolean singleFieldHeaders) {
- this(version, status, content, true, singleFieldHeaders);
+ ByteBuf content, boolean validateHeaders) {
+ this(version, status, content, validateHeaders, false);
}
public DefaultFullHttpResponse(HttpVersion version, HttpResponseStatus status,
ByteBuf content, boolean validateHeaders, boolean singleFieldHeaders) {
super(version, status, validateHeaders, singleFieldHeaders);
- if (content == null) {
- throw new NullPointerException("content");
- }
- this.content = content;
- trailingHeaders = new DefaultHttpHeaders(validateHeaders, singleFieldHeaders);
+ this.content = checkNotNull(content, "content");
+ this.trailingHeaders = singleFieldHeaders ? new CombinedHttpHeaders(validateHeaders)
+ : new DefaultHttpHeaders(validateHeaders);
this.validateHeaders = validateHeaders;
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
index ab384e43cc..e1fd297314 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
@@ -15,60 +15,65 @@
*/
package io.netty.handler.codec.http;
+import io.netty.handler.codec.CharSequenceValueConverter;
import io.netty.handler.codec.DefaultHeaders;
-import io.netty.handler.codec.DefaultTextHeaders;
-import io.netty.handler.codec.TextHeaders;
+import io.netty.handler.codec.Headers;
+import io.netty.handler.codec.HeadersUtils;
+import io.netty.handler.codec.ValueConverter;
import io.netty.util.AsciiString;
+import io.netty.util.ByteProcessor;
+import io.netty.util.internal.PlatformDependent;
import java.util.Calendar;
-import java.util.Comparator;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
-import java.util.TreeMap;
+import java.util.Map.Entry;
+import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
+import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
-public class DefaultHttpHeaders extends DefaultTextHeaders implements HttpHeaders {
-
- private static final int HIGHEST_INVALID_NAME_CHAR_MASK = ~63;
+public class DefaultHttpHeaders extends DefaultHeaders implements HttpHeaders {
private static final int HIGHEST_INVALID_VALUE_CHAR_MASK = ~15;
-
- /**
- * A look-up table used for checking if a character in a header name is prohibited.
- */
- private static final byte[] LOOKUP_TABLE = new byte[~HIGHEST_INVALID_NAME_CHAR_MASK + 1];
-
- static {
- LOOKUP_TABLE['\t'] = -1;
- LOOKUP_TABLE['\n'] = -1;
- LOOKUP_TABLE[0x0b] = -1;
- LOOKUP_TABLE['\f'] = -1;
- LOOKUP_TABLE[' '] = -1;
- LOOKUP_TABLE[','] = -1;
- LOOKUP_TABLE[':'] = -1;
- LOOKUP_TABLE[';'] = -1;
- LOOKUP_TABLE['='] = -1;
- }
+ private static final ByteProcessor HEADER_NAME_VALIDATOR = new ByteProcessor() {
+ @Override
+ public boolean process(byte value) throws Exception {
+ validateChar((char) (value & 0xFF));
+ return true;
+ }
+ };
+ static final NameValidator HttpNameValidator = new NameValidator() {
+ @Override
+ public void validateName(CharSequence name) {
+ if (name instanceof AsciiString) {
+ try {
+ ((AsciiString) name).forEachByte(HEADER_NAME_VALIDATOR);
+ } catch (Exception e) {
+ PlatformDependent.throwException(e);
+ }
+ } else {
+ checkNotNull(name, "name");
+ // Go through each character in the name
+ for (int index = 0; index < name.length(); ++index) {
+ validateChar(name.charAt(index));
+ }
+ }
+ }
+ };
public DefaultHttpHeaders() {
this(true);
}
+ @SuppressWarnings("unchecked")
public DefaultHttpHeaders(boolean validate) {
- this(validate, false);
+ super(CASE_INSENSITIVE_HASHER, valueConverter(validate),
+ validate ? HttpNameValidator : NameValidator.NOT_NULL);
}
- protected DefaultHttpHeaders(boolean validate, boolean singleHeaderFields) {
- this(true, validate ? HeaderNameValidator.INSTANCE : NO_NAME_VALIDATOR, singleHeaderFields);
- }
-
- protected DefaultHttpHeaders(boolean validate,
- DefaultHeaders.NameValidator nameValidator,
- boolean singleHeaderFields) {
- super(new TreeMap(AsciiString.CHARSEQUENCE_CASE_INSENSITIVE_ORDER),
- nameValidator,
- validate ? HeaderValueConverterAndValidator.INSTANCE : HeaderValueConverter.INSTANCE,
- singleHeaderFields);
+ protected DefaultHttpHeaders(boolean validateValue, NameValidator nameValidator) {
+ super(CASE_INSENSITIVE_HASHER, valueConverter(validateValue), nameValidator);
}
@Override
@@ -162,7 +167,7 @@ public class DefaultHttpHeaders extends DefaultTextHeaders implements HttpHeader
}
@Override
- public HttpHeaders add(TextHeaders headers) {
+ public HttpHeaders add(Headers extends CharSequence> headers) {
super.add(headers);
return this;
}
@@ -258,13 +263,13 @@ public class DefaultHttpHeaders extends DefaultTextHeaders implements HttpHeader
}
@Override
- public HttpHeaders set(TextHeaders headers) {
+ public HttpHeaders set(Headers extends CharSequence> headers) {
super.set(headers);
return this;
}
@Override
- public HttpHeaders setAll(TextHeaders headers) {
+ public HttpHeaders setAll(Headers extends CharSequence> headers) {
super.setAll(headers);
return this;
}
@@ -276,73 +281,96 @@ public class DefaultHttpHeaders extends DefaultTextHeaders implements HttpHeader
}
@Override
- public int hashCode() {
- return size();
+ public boolean equals(Object o) {
+ if (!(o instanceof HttpHeaders)) {
+ return false;
+ }
+ return equals((HttpHeaders) o, CASE_SENSITIVE_HASHER);
}
@Override
- public boolean equals(Object other) {
- if (!(other instanceof HttpHeaders)) {
- return false;
- }
- HttpHeaders headers = (HttpHeaders) other;
- return DefaultHeaders.comparatorEquals(this, headers, AsciiString.CHARSEQUENCE_CASE_SENSITIVE_ORDER);
+ public int hashCode() {
+ return hashCode(CASE_SENSITIVE_HASHER);
}
- static final class HeaderNameValidator implements DefaultHeaders.NameValidator {
+ @Override
+ public String getAsString(CharSequence name) {
+ return HeadersUtils.getAsString(this, name);
+ }
- public static final HeaderNameValidator INSTANCE = new HeaderNameValidator();
+ @Override
+ public List getAllAsString(CharSequence name) {
+ return HeadersUtils.getAllAsString(this, name);
+ }
- private HeaderNameValidator() {
- }
+ @Override
+ public Iterator> iteratorAsString() {
+ return HeadersUtils.iteratorAsString(this);
+ }
- @Override
- public void validate(CharSequence name) {
- // Go through each character in the name
- for (int index = 0; index < name.length(); index++) {
- char character = name.charAt(index);
+ @Override
+ public boolean contains(CharSequence name, CharSequence value) {
+ return contains(name, value, false);
+ }
- // Check to see if the character is not an ASCII character
- if (character > 127) {
- throw new IllegalArgumentException("a header name cannot contain non-ASCII characters: " + name);
- }
+ @Override
+ public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
+ return contains(name, value,
+ ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
+ }
- // Check for prohibited characters.
- if ((character & HIGHEST_INVALID_NAME_CHAR_MASK) == 0 && LOOKUP_TABLE[character] != 0) {
- throw new IllegalArgumentException(
- "a header name cannot contain the following prohibited characters: =,;: \\t\\r\\n\\v\\f: " +
- name);
- }
+ private static void validateChar(char character) {
+ switch (character) {
+ case '\t':
+ case '\n':
+ case 0x0b:
+ case '\f':
+ case '\r':
+ case ' ':
+ case ',':
+ case ':':
+ case ';':
+ case '=':
+ throw new IllegalArgumentException(
+ "a header name cannot contain the following prohibited characters: =,;: \\t\\r\\n\\v\\f: " +
+ character);
+ default:
+ // Check to see if the character is not an ASCII character, or invalid
+ if (character > 127) {
+ throw new IllegalArgumentException("a header name cannot contain non-ASCII character: " +
+ character);
}
}
}
- private static class HeaderValueConverter extends CharSequenceConverter {
+ private static ValueConverter valueConverter(boolean validate) {
+ return validate ? HeaderValueConverterAndValidator.INSTANCE : HeaderValueConverter.INSTANCE;
+ }
- public static final HeaderValueConverter INSTANCE = new HeaderValueConverter();
+ private static class HeaderValueConverter extends CharSequenceValueConverter {
+ static final HeaderValueConverter INSTANCE = new HeaderValueConverter();
@Override
public CharSequence convertObject(Object value) {
checkNotNull(value, "value");
- CharSequence seq;
if (value instanceof CharSequence) {
- seq = (CharSequence) value;
- } else if (value instanceof Number) {
- seq = value.toString();
- } else if (value instanceof Date) {
- seq = HttpHeaderDateFormat.get().format((Date) value);
- } else if (value instanceof Calendar) {
- seq = HttpHeaderDateFormat.get().format(((Calendar) value).getTime());
- } else {
- seq = value.toString();
+ return (CharSequence) value;
}
- return seq;
+ if (value instanceof Number) {
+ return value.toString();
+ }
+ if (value instanceof Date) {
+ return HttpHeaderDateFormat.get().format((Date) value);
+ }
+ if (value instanceof Calendar) {
+ return HttpHeaderDateFormat.get().format(((Calendar) value).getTime());
+ }
+ return value.toString();
}
}
private static final class HeaderValueConverterAndValidator extends HeaderValueConverter {
-
- public static final HeaderValueConverterAndValidator INSTANCE = new HeaderValueConverterAndValidator();
+ static final HeaderValueConverterAndValidator INSTANCE = new HeaderValueConverterAndValidator();
@Override
public CharSequence convertObject(Object value) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpMessage.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpMessage.java
index efb6e0bd4a..b92619035d 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpMessage.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpMessage.java
@@ -15,6 +15,8 @@
*/
package io.netty.handler.codec.http;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
/**
* The default {@link HttpMessage} implementation.
*/
@@ -33,12 +35,10 @@ public abstract class DefaultHttpMessage extends DefaultHttpObject implements Ht
/**
* Creates a new instance.
*/
- protected DefaultHttpMessage(final HttpVersion version, boolean validateHeaders, boolean singleHeaderFields) {
- if (version == null) {
- throw new NullPointerException("version");
- }
- this.version = version;
- headers = new DefaultHttpHeaders(validateHeaders, singleHeaderFields);
+ protected DefaultHttpMessage(final HttpVersion version, boolean validateHeaders, boolean singleFieldHeaders) {
+ this.version = checkNotNull(version, "version");
+ headers = singleFieldHeaders ? new CombinedHttpHeaders(validateHeaders)
+ : new DefaultHttpHeaders(validateHeaders);
}
@Override
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpRequest.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpRequest.java
index 2a0a7ccd6d..5d075a4234 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpRequest.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpRequest.java
@@ -15,6 +15,8 @@
*/
package io.netty.handler.codec.http;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
+
/**
* The default {@link HttpRequest} implementation.
*/
@@ -44,14 +46,8 @@ public class DefaultHttpRequest extends DefaultHttpMessage implements HttpReques
*/
public DefaultHttpRequest(HttpVersion httpVersion, HttpMethod method, String uri, boolean validateHeaders) {
super(httpVersion, validateHeaders, false);
- if (method == null) {
- throw new NullPointerException("method");
- }
- if (uri == null) {
- throw new NullPointerException("uri");
- }
- this.method = method;
- this.uri = uri;
+ this.method = checkNotNull(method, "method");
+ this.uri = checkNotNull(uri, "uri");
}
@Override
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
index d43a16fca0..99c1960f23 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpResponse.java
@@ -49,12 +49,15 @@ public class DefaultHttpResponse extends DefaultHttpMessage implements HttpRespo
* @param version the HTTP version of this response
* @param status the getStatus of this response
* @param validateHeaders validate the header names and values when adding them to the {@link HttpHeaders}
- * @param singleHeaderFields determines if HTTP headers with multiple values should be added as a single
- * field or as multiple header fields.
+ * @param singleFieldHeaders {@code true} to check and enforce that headers with the same name are appended
+ * to the same entry and comma separated.
+ * See RFC 7230, 3.2.2 .
+ * {@code false} to allow multiple header entries with the same name to
+ * coexist.
*/
public DefaultHttpResponse(HttpVersion version, HttpResponseStatus status, boolean validateHeaders,
- boolean singleHeaderFields) {
- super(version, validateHeaders, singleHeaderFields);
+ boolean singleFieldHeaders) {
+ super(version, validateHeaders, singleFieldHeaders);
if (status == null) {
throw new NullPointerException("status");
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultLastHttpContent.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultLastHttpContent.java
index 3836e0b059..0ff4b77dcd 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultLastHttpContent.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultLastHttpContent.java
@@ -15,18 +15,16 @@
*/
package io.netty.handler.codec.http;
+import java.util.Map;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-import io.netty.handler.codec.DefaultHeaders;
import io.netty.util.internal.StringUtil;
-import java.util.Map;
-
/**
* The default {@link LastHttpContent} implementation.
*/
public class DefaultLastHttpContent extends DefaultHttpContent implements LastHttpContent {
-
private final HttpHeaders trailingHeaders;
private final boolean validateHeaders;
@@ -108,24 +106,21 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
}
private static final class TrailingHttpHeaders extends DefaultHttpHeaders {
- private static final class TrailingHttpHeadersNameValidator implements
- DefaultHeaders.NameValidator {
-
- private static final TrailingHttpHeadersNameValidator INSTANCE = new TrailingHttpHeadersNameValidator();
-
+ private static final NameValidator TrailerNameValidator = new NameValidator() {
@Override
- public void validate(CharSequence name) {
- HeaderNameValidator.INSTANCE.validate(name);
- if (HttpHeaderNames.CONTENT_LENGTH.equalsIgnoreCase(name)
- || HttpHeaderNames.TRANSFER_ENCODING.equalsIgnoreCase(name)
- || HttpHeaderNames.TRAILER.equalsIgnoreCase(name)) {
+ public void validateName(CharSequence name) {
+ DefaultHttpHeaders.HttpNameValidator.validateName(name);
+ if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(name)
+ || HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(name)
+ || HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(name)) {
throw new IllegalArgumentException("prohibited trailing header: " + name);
}
}
- }
+ };
+ @SuppressWarnings({ "unchecked" })
TrailingHttpHeaders(boolean validate) {
- super(validate, validate ? TrailingHttpHeadersNameValidator.INSTANCE : NO_NAME_VALIDATOR, false);
+ super(validate, validate ? TrailerNameValidator : NameValidator.NOT_NULL);
}
}
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/EmptyHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/EmptyHttpHeaders.java
index 275807eb9c..e222c45417 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/EmptyHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/EmptyHttpHeaders.java
@@ -16,12 +16,35 @@
package io.netty.handler.codec.http;
-import io.netty.handler.codec.EmptyTextHeaders;
-import io.netty.handler.codec.TextHeaders;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Map.Entry;
-public class EmptyHttpHeaders extends EmptyTextHeaders implements HttpHeaders {
+import io.netty.handler.codec.EmptyHeaders;
+import io.netty.handler.codec.Headers;
+
+public class EmptyHttpHeaders extends EmptyHeaders implements HttpHeaders {
public static final EmptyHttpHeaders INSTANCE = new EmptyHttpHeaders();
+ private static final Iterator> EMPTY_STRING_ITERATOR =
+ new Iterator>() {
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public Entry next() {
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("remove");
+ }
+ };
protected EmptyHttpHeaders() {
}
@@ -117,7 +140,7 @@ public class EmptyHttpHeaders extends EmptyTextHeaders implements HttpHeaders {
}
@Override
- public HttpHeaders add(TextHeaders headers) {
+ public HttpHeaders add(Headers extends CharSequence> headers) {
super.add(headers);
return this;
}
@@ -213,13 +236,13 @@ public class EmptyHttpHeaders extends EmptyTextHeaders implements HttpHeaders {
}
@Override
- public HttpHeaders set(TextHeaders headers) {
+ public HttpHeaders set(Headers extends CharSequence> headers) {
super.set(headers);
return this;
}
@Override
- public HttpHeaders setAll(TextHeaders headers) {
+ public HttpHeaders setAll(Headers extends CharSequence> headers) {
super.setAll(headers);
return this;
}
@@ -229,4 +252,24 @@ public class EmptyHttpHeaders extends EmptyTextHeaders implements HttpHeaders {
super.clear();
return this;
}
+
+ @Override
+ public String getAsString(CharSequence name) {
+ return null;
+ }
+
+ @Override
+ public List getAllAsString(CharSequence name) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Iterator> iteratorAsString() {
+ return EMPTY_STRING_ITERATOR;
+ }
+
+ @Override
+ public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
+ return false;
+ }
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
index 6ba33719b7..4e29c5084e 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpClientUpgradeHandler.java
@@ -182,7 +182,7 @@ public class HttpClientUpgradeHandler extends HttpObjectAggregator {
throw new IllegalStateException(
"Switching Protocols response missing UPGRADE header");
}
- if (!AsciiString.equalsIgnoreCase(upgradeCodec.protocol(), upgradeHeader)) {
+ if (!AsciiString.contentEqualsIgnoreCase(upgradeCodec.protocol(), upgradeHeader)) {
throw new IllegalStateException(
"Switching Protocols response with unexpected UPGRADE protocol: "
+ upgradeHeader);
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java
index 0183da70f6..9e9c0ddf4c 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentCompressor.java
@@ -96,7 +96,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
protected Result beginEncode(HttpResponse headers, CharSequence acceptEncoding) throws Exception {
CharSequence contentEncoding = headers.headers().get(HttpHeaderNames.CONTENT_ENCODING);
if (contentEncoding != null &&
- !HttpHeaderValues.IDENTITY.equalsIgnoreCase(contentEncoding)) {
+ !HttpHeaderValues.IDENTITY.contentEqualsIgnoreCase(contentEncoding)) {
return null;
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java
index 2de627c68c..ce52f96ffc 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpContentDecoder.java
@@ -77,7 +77,7 @@ public abstract class HttpContentDecoder extends MessageToMessageDecoder values =
- new ArrayList(m.headers().getAll(HttpHeaderNames.TRANSFER_ENCODING));
+ List values = m.headers().getAll(HttpHeaderNames.TRANSFER_ENCODING);
if (values.isEmpty()) {
return;
}
Iterator valuesIt = values.iterator();
while (valuesIt.hasNext()) {
CharSequence value = valuesIt.next();
- if (HttpHeaderValues.CHUNKED.equalsIgnoreCase(value)) {
+ if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(value)) {
valuesIt.remove();
}
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
index 8be81f871a..df01db9690 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpHeaders.java
@@ -15,13 +15,17 @@
*/
package io.netty.handler.codec.http;
-import io.netty.handler.codec.TextHeaders;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
+import io.netty.handler.codec.Headers;
/**
* Provides the constants for the standard HTTP header names and values and
* commonly used utility methods that accesses an {@link HttpMessage}.
*/
-public interface HttpHeaders extends TextHeaders {
+public interface HttpHeaders extends Headers {
@Override
HttpHeaders add(CharSequence name, CharSequence value);
@@ -68,7 +72,7 @@ public interface HttpHeaders extends TextHeaders {
HttpHeaders addTimeMillis(CharSequence name, long value);
@Override
- HttpHeaders add(TextHeaders headers);
+ HttpHeaders add(Headers extends CharSequence> headers);
@Override
HttpHeaders set(CharSequence name, CharSequence value);
@@ -116,11 +120,41 @@ public interface HttpHeaders extends TextHeaders {
HttpHeaders setTimeMillis(CharSequence name, long value);
@Override
- HttpHeaders set(TextHeaders headers);
+ HttpHeaders set(Headers extends CharSequence> headers);
@Override
- HttpHeaders setAll(TextHeaders headers);
+ HttpHeaders setAll(Headers extends CharSequence> headers);
@Override
HttpHeaders clear();
+
+ /**
+ * {@link Headers#get(Object)} and convert the result to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return the first header value if the header is found. {@code null} if there's no such header.
+ */
+ String getAsString(CharSequence name);
+
+ /**
+ * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return a {@link List} of header values or an empty {@link List} if no values are found.
+ */
+ List getAllAsString(CharSequence name);
+
+ /**
+ * {@link Iterator} that converts each {@link Entry}'s key and value to a {@link String}.
+ */
+ Iterator> iteratorAsString();
+
+ /**
+ * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
+ *
+ * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
+ * @param name the name of the header to find
+ * @param value the value of the header to find
+ * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
+ * otherwise a case sensitive compare is run to compare values.
+ */
+ boolean contains(CharSequence name, CharSequence value, boolean ignoreCase);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpMethod.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpMethod.java
index f9c624e1e5..530d13fb6c 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpMethod.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpMethod.java
@@ -15,6 +15,7 @@
*/
package io.netty.handler.codec.http;
+import static io.netty.util.internal.ObjectUtil.checkNotNull;
import io.netty.util.AsciiString;
import java.util.HashMap;
@@ -85,8 +86,7 @@ public class HttpMethod implements Comparable {
*/
public static final HttpMethod CONNECT = new HttpMethod("CONNECT");
- private static final Map methodMap =
- new HashMap();
+ private static final Map methodMap = new HashMap();
static {
methodMap.put(OPTIONS.toString(), OPTIONS);
@@ -106,21 +106,8 @@ public class HttpMethod implements Comparable {
* will be returned. Otherwise, a new instance will be returned.
*/
public static HttpMethod valueOf(String name) {
- if (name == null) {
- throw new NullPointerException("name");
- }
-
- name = name.trim();
- if (name.isEmpty()) {
- throw new IllegalArgumentException("empty name");
- }
-
HttpMethod result = methodMap.get(name);
- if (result != null) {
- return result;
- } else {
- return new HttpMethod(name);
- }
+ return result != null ? result : new HttpMethod(name);
}
private final AsciiString name;
@@ -134,11 +121,7 @@ public class HttpMethod implements Comparable {
* ICAP
*/
public HttpMethod(String name) {
- if (name == null) {
- throw new NullPointerException("name");
- }
-
- name = name.trim();
+ name = checkNotNull(name, "name").trim();
if (name.isEmpty()) {
throw new IllegalArgumentException("empty name");
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
index f89a65a5ca..f8f9ca6a11 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
@@ -625,9 +625,9 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
} else {
splitHeader(line);
CharSequence headerName = name;
- if (!HttpHeaderNames.CONTENT_LENGTH.equalsIgnoreCase(headerName) &&
- !HttpHeaderNames.TRANSFER_ENCODING.equalsIgnoreCase(headerName) &&
- !HttpHeaderNames.TRAILER.equalsIgnoreCase(headerName)) {
+ if (!HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(headerName) &&
+ !HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(headerName) &&
+ !HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(headerName)) {
trailer.trailingHeaders().add(headerName, value);
}
lastHeader = name;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
index d65a399b1b..a06784687c 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
@@ -183,7 +183,7 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
this.factory = factory;
// Fill default values
- setMultipart(this.request.headers().getAndConvert(HttpHeaderNames.CONTENT_TYPE));
+ setMultipart(this.request.headers().getAsString(HttpHeaderNames.CONTENT_TYPE));
if (request instanceof HttpContent) {
// Offer automatically if the given request is als type of HttpContent
// See #1089
@@ -688,13 +688,13 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
return null;
}
String[] contents = splitMultipartHeader(newline);
- if (HttpHeaderNames.CONTENT_DISPOSITION.equalsIgnoreCase(contents[0])) {
+ if (HttpHeaderNames.CONTENT_DISPOSITION.contentEqualsIgnoreCase(contents[0])) {
boolean checkSecondArg;
if (currentStatus == MultiPartStatus.DISPOSITION) {
- checkSecondArg = HttpHeaderValues.FORM_DATA.equalsIgnoreCase(contents[1]);
+ checkSecondArg = HttpHeaderValues.FORM_DATA.contentEqualsIgnoreCase(contents[1]);
} else {
- checkSecondArg = HttpHeaderValues.ATTACHMENT.equalsIgnoreCase(contents[1])
- || HttpHeaderValues.FILE.equalsIgnoreCase(contents[1]);
+ checkSecondArg = HttpHeaderValues.ATTACHMENT.contentEqualsIgnoreCase(contents[1])
+ || HttpHeaderValues.FILE.contentEqualsIgnoreCase(contents[1]);
}
if (checkSecondArg) {
// read next values and store them in the map as Attribute
@@ -722,7 +722,7 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
currentFieldAttributes.put(attribute.getName(), attribute);
}
}
- } else if (HttpHeaderNames.CONTENT_TRANSFER_ENCODING.equalsIgnoreCase(contents[0])) {
+ } else if (HttpHeaderNames.CONTENT_TRANSFER_ENCODING.contentEqualsIgnoreCase(contents[0])) {
Attribute attribute;
try {
attribute = factory.createAttribute(request, HttpHeaderNames.CONTENT_TRANSFER_ENCODING.toString(),
@@ -733,7 +733,7 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(HttpHeaderNames.CONTENT_TRANSFER_ENCODING.toString(), attribute);
- } else if (HttpHeaderNames.CONTENT_LENGTH.equalsIgnoreCase(contents[0])) {
+ } else if (HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(contents[0])) {
Attribute attribute;
try {
attribute = factory.createAttribute(request, HttpHeaderNames.CONTENT_LENGTH.toString(),
@@ -744,9 +744,9 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest
throw new ErrorDataDecoderException(e);
}
currentFieldAttributes.put(HttpHeaderNames.CONTENT_LENGTH.toString(), attribute);
- } else if (HttpHeaderNames.CONTENT_TYPE.equalsIgnoreCase(contents[0])) {
+ } else if (HttpHeaderNames.CONTENT_TYPE.contentEqualsIgnoreCase(contents[0])) {
// Take care of possible "multipart/mixed"
- if (HttpHeaderValues.MULTIPART_MIXED.equalsIgnoreCase(contents[1])) {
+ if (HttpHeaderValues.MULTIPART_MIXED.contentEqualsIgnoreCase(contents[1])) {
if (currentStatus == MultiPartStatus.DISPOSITION) {
String values = StringUtil.substringAfter(contents[2], '=');
multipartMixedBoundary = "--" + values;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java
index 7fcfa4ab4b..2450bbd858 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java
@@ -141,7 +141,7 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder {
*/
public static boolean isMultipart(HttpRequest request) {
if (request.headers().contains(HttpHeaderNames.CONTENT_TYPE)) {
- return getMultipartDataBoundary(request.headers().getAndConvert(HttpHeaderNames.CONTENT_TYPE)) != null;
+ return getMultipartDataBoundary(request.headers().getAsString(HttpHeaderNames.CONTENT_TYPE)) != null;
} else {
return false;
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java
index 4ceaf24721..6433c0ef85 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java
@@ -717,7 +717,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
}
HttpHeaders headers = request.headers();
- List contentTypes = headers.getAllAndConvert(HttpHeaderNames.CONTENT_TYPE);
+ List contentTypes = headers.getAllAsString(HttpHeaderNames.CONTENT_TYPE);
List transferEncoding = headers.getAll(HttpHeaderNames.TRANSFER_ENCODING);
if (contentTypes != null) {
headers.remove(HttpHeaderNames.CONTENT_TYPE);
@@ -754,7 +754,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
if (transferEncoding != null) {
headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
for (CharSequence v : transferEncoding) {
- if (HttpHeaderValues.CHUNKED.equalsIgnoreCase(v)) {
+ if (HttpHeaderValues.CHUNKED.contentEqualsIgnoreCase(v)) {
// ignore
} else {
headers.add(HttpHeaderNames.TRANSFER_ENCODING, v);
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java
index 0997584b6e..c7ee50106f 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java
@@ -215,7 +215,7 @@ public abstract class WebSocketClientHandshaker {
// Verify the subprotocol that we received from the server.
// This must be one of our expected subprotocols - or null/empty if we didn't want to speak a subprotocol
- String receivedProtocol = response.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
+ String receivedProtocol = response.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
receivedProtocol = receivedProtocol != null ? receivedProtocol.trim() : null;
String expectedProtocol = expectedSubprotocol != null ? expectedSubprotocol : "";
boolean protocolValid = false;
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
index 51d69e02f4..3579bc07b0 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java
@@ -201,13 +201,13 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
HttpHeaders headers = response.headers();
CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE);
- if (!WEBSOCKET.equalsIgnoreCase(upgrade)) {
+ if (!WEBSOCKET.contentEqualsIgnoreCase(upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: "
+ upgrade);
}
CharSequence connection = headers.get(HttpHeaderNames.CONNECTION);
- if (!HttpHeaderValues.UPGRADE.equalsIgnoreCase(connection)) {
+ if (!HttpHeaderValues.UPGRADE.contentEqualsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ connection);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java
index 7d35aaecdd..820a080876 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker07.java
@@ -206,12 +206,12 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
}
CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE);
- if (!HttpHeaderValues.WEBSOCKET.equalsIgnoreCase(upgrade)) {
+ if (!HttpHeaderValues.WEBSOCKET.contentEqualsIgnoreCase(upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
CharSequence connection = headers.get(HttpHeaderNames.CONNECTION);
- if (!HttpHeaderValues.UPGRADE.equalsIgnoreCase(connection)) {
+ if (!HttpHeaderValues.UPGRADE.contentEqualsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java
index 666a36b27a..a8ff02ede0 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java
@@ -207,12 +207,12 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
}
CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE);
- if (!HttpHeaderValues.WEBSOCKET.equalsIgnoreCase(upgrade)) {
+ if (!HttpHeaderValues.WEBSOCKET.contentEqualsIgnoreCase(upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
CharSequence connection = headers.get(HttpHeaderNames.CONNECTION);
- if (!HttpHeaderValues.UPGRADE.equalsIgnoreCase(connection)) {
+ if (!HttpHeaderValues.UPGRADE.contentEqualsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java
index 0be0886401..52fa9a5df8 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java
@@ -217,12 +217,12 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
}
CharSequence upgrade = headers.get(HttpHeaderNames.UPGRADE);
- if (!HttpHeaderValues.WEBSOCKET.equalsIgnoreCase(upgrade)) {
+ if (!HttpHeaderValues.WEBSOCKET.contentEqualsIgnoreCase(upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
}
CharSequence connection = headers.get(HttpHeaderNames.CONNECTION);
- if (!HttpHeaderValues.UPGRADE.equalsIgnoreCase(connection)) {
+ if (!HttpHeaderValues.UPGRADE.contentEqualsIgnoreCase(connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java
index a3dc0671e4..705b7222da 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java
@@ -109,8 +109,8 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
// Serve the WebSocket handshake request.
- if (!HttpHeaderValues.UPGRADE.equalsIgnoreCase(req.headers().get(HttpHeaderNames.CONNECTION))
- || !WEBSOCKET.equalsIgnoreCase(req.headers().get(HttpHeaderNames.UPGRADE))) {
+ if (!HttpHeaderValues.UPGRADE.contentEqualsIgnoreCase(req.headers().get(HttpHeaderNames.CONNECTION))
+ || !WEBSOCKET.contentEqualsIgnoreCase(req.headers().get(HttpHeaderNames.UPGRADE))) {
throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
}
@@ -133,7 +133,7 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
// New handshake getMethod with a challenge:
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ORIGIN, req.headers().get(HttpHeaderNames.ORIGIN));
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_LOCATION, uri());
- String subprotocols = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
+ String subprotocols = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
@@ -146,8 +146,8 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
}
// Calculate the answer of the challenge.
- String key1 = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_KEY1);
- String key2 = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_KEY2);
+ String key1 = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_KEY1);
+ String key2 = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_KEY2);
int a = (int) (Long.parseLong(BEGINNING_DIGIT.matcher(key1).replaceAll("")) /
BEGINNING_SPACE.matcher(key1).replaceAll("").length());
int b = (int) (Long.parseLong(BEGINNING_DIGIT.matcher(key2).replaceAll("")) /
@@ -162,7 +162,7 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
// Old Hixie 75 handshake getMethod with no challenge:
res.headers().add(HttpHeaderNames.WEBSOCKET_ORIGIN, req.headers().get(HttpHeaderNames.ORIGIN));
res.headers().add(HttpHeaderNames.WEBSOCKET_LOCATION, uri());
- String protocol = req.headers().getAndConvert(HttpHeaderNames.WEBSOCKET_PROTOCOL);
+ String protocol = req.headers().getAsString(HttpHeaderNames.WEBSOCKET_PROTOCOL);
if (protocol != null) {
res.headers().add(HttpHeaderNames.WEBSOCKET_PROTOCOL, selectSubprotocol(protocol));
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java
index ebc94fa910..c467a476e6 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker07.java
@@ -142,7 +142,7 @@ public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker {
res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
- String subprotocols = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
+ String subprotocols = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java
index 8eb5193871..4697ab5fd2 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java
@@ -141,7 +141,7 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker {
res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
- String subprotocols = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
+ String subprotocols = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java
index cdca072246..8df20f3106 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java
@@ -139,7 +139,7 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
- String subprotocols = req.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
+ String subprotocols = req.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java
index 421a2beb7d..b0e41e8e41 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandler.java
@@ -63,7 +63,7 @@ public class WebSocketClientExtensionHandler extends ChannelHandlerAdapter {
public void write(final ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (msg instanceof HttpRequest && WebSocketExtensionUtil.isWebsocketUpgrade((HttpRequest) msg)) {
HttpRequest request = (HttpRequest) msg;
- String headerValue = request.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
+ String headerValue = request.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
for (WebSocketClientExtensionHandshaker extentionHandshaker : extensionHandshakers) {
WebSocketExtensionData extensionData = extentionHandshaker.newRequestData();
@@ -84,7 +84,7 @@ public class WebSocketClientExtensionHandler extends ChannelHandlerAdapter {
HttpResponse response = (HttpResponse) msg;
if (WebSocketExtensionUtil.isWebsocketUpgrade(response)) {
- String extensionsHeader = response.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
+ String extensionsHeader = response.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
if (extensionsHeader != null) {
List extensions =
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java
index bf685db38f..b9ec9803d1 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandler.java
@@ -69,7 +69,7 @@ public class WebSocketServerExtensionHandler extends ChannelHandlerAdapter {
HttpRequest request = (HttpRequest) msg;
if (WebSocketExtensionUtil.isWebsocketUpgrade(request)) {
- String extensionsHeader = request.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
+ String extensionsHeader = request.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
if (extensionsHeader != null) {
List extensions =
@@ -107,7 +107,7 @@ public class WebSocketServerExtensionHandler extends ChannelHandlerAdapter {
if (msg instanceof HttpResponse &&
WebSocketExtensionUtil.isWebsocketUpgrade((HttpResponse) msg) && validExtensions != null) {
HttpResponse response = (HttpResponse) msg;
- String headerValue = response.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
+ String headerValue = response.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS);
for (WebSocketServerExtension extension : validExtensions) {
WebSocketExtensionData extensionData = extension.newReponseData();
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
index 270812c713..4ebc75f975 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyHeaders.java
@@ -15,18 +15,28 @@
*/
package io.netty.handler.codec.spdy;
-import io.netty.handler.codec.DefaultTextHeaders;
-import io.netty.handler.codec.TextHeaders;
+import io.netty.handler.codec.CharSequenceValueConverter;
+import io.netty.handler.codec.DefaultHeaders;
+import io.netty.handler.codec.Headers;
+import io.netty.handler.codec.HeadersUtils;
-import java.util.LinkedHashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
-public class DefaultSpdyHeaders extends DefaultTextHeaders implements SpdyHeaders {
+import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
+import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
+
+public class DefaultSpdyHeaders extends DefaultHeaders implements SpdyHeaders {
+ private static final NameValidator SpydNameValidator = new NameValidator() {
+ @Override
+ public void validateName(CharSequence name) {
+ SpdyCodecUtil.validateHeaderName(name);
+ }
+ };
public DefaultSpdyHeaders() {
- super(new LinkedHashMap(),
- HeaderNameValidator.INSTANCE,
- HeaderValueConverterAndValidator.INSTANCE,
- false);
+ super(CASE_INSENSITIVE_HASHER, HeaderValueConverterAndValidator.INSTANCE, SpydNameValidator);
}
@Override
@@ -120,7 +130,7 @@ public class DefaultSpdyHeaders extends DefaultTextHeaders implements SpdyHeader
}
@Override
- public SpdyHeaders add(TextHeaders headers) {
+ public SpdyHeaders add(Headers extends CharSequence> headers) {
super.add(headers);
return this;
}
@@ -216,13 +226,13 @@ public class DefaultSpdyHeaders extends DefaultTextHeaders implements SpdyHeader
}
@Override
- public SpdyHeaders set(TextHeaders headers) {
+ public SpdyHeaders set(Headers extends CharSequence> headers) {
super.set(headers);
return this;
}
@Override
- public SpdyHeaders setAll(TextHeaders headers) {
+ public SpdyHeaders setAll(Headers extends CharSequence> headers) {
super.setAll(headers);
return this;
}
@@ -233,23 +243,38 @@ public class DefaultSpdyHeaders extends DefaultTextHeaders implements SpdyHeader
return this;
}
- private static class HeaderNameValidator implements NameValidator {
-
- public static final HeaderNameValidator INSTANCE = new HeaderNameValidator();
-
- @Override
- public void validate(CharSequence name) {
- SpdyCodecUtil.validateHeaderName(name);
- }
+ @Override
+ public String getAsString(CharSequence name) {
+ return HeadersUtils.getAsString(this, name);
}
- private static class HeaderValueConverterAndValidator extends CharSequenceConverter {
+ @Override
+ public List getAllAsString(CharSequence name) {
+ return HeadersUtils.getAllAsString(this, name);
+ }
+ @Override
+ public Iterator> iteratorAsString() {
+ return HeadersUtils.iteratorAsString(this);
+ }
+
+ @Override
+ public boolean contains(CharSequence name, CharSequence value) {
+ return contains(name, value, false);
+ }
+
+ @Override
+ public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
+ return contains(name, value,
+ ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
+ }
+
+ private static final class HeaderValueConverterAndValidator extends CharSequenceValueConverter {
public static final HeaderValueConverterAndValidator INSTANCE = new HeaderValueConverterAndValidator();
@Override
public CharSequence convertObject(Object value) {
- CharSequence seq;
+ final CharSequence seq;
if (value instanceof CharSequence) {
seq = (CharSequence) value;
} else {
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
index e82fccef2d..ebbcd52340 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHeaders.java
@@ -15,14 +15,18 @@
*/
package io.netty.handler.codec.spdy;
-import io.netty.handler.codec.TextHeaders;
+import io.netty.handler.codec.Headers;
import io.netty.util.AsciiString;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
/**
* Provides the constants for the standard SPDY HTTP header names and commonly
* used utility methods that access a {@link SpdyHeadersFrame}.
*/
-public interface SpdyHeaders extends TextHeaders {
+public interface SpdyHeaders extends Headers {
/**
* SPDY HTTP header names
@@ -102,7 +106,7 @@ public interface SpdyHeaders extends TextHeaders {
SpdyHeaders addTimeMillis(CharSequence name, long value);
@Override
- SpdyHeaders add(TextHeaders headers);
+ SpdyHeaders add(Headers extends CharSequence> headers);
@Override
SpdyHeaders set(CharSequence name, CharSequence value);
@@ -150,11 +154,41 @@ public interface SpdyHeaders extends TextHeaders {
SpdyHeaders setObject(CharSequence name, Object... values);
@Override
- SpdyHeaders set(TextHeaders headers);
+ SpdyHeaders set(Headers extends CharSequence> headers);
@Override
- SpdyHeaders setAll(TextHeaders headers);
+ SpdyHeaders setAll(Headers extends CharSequence> headers);
@Override
SpdyHeaders clear();
+
+ /**
+ * {@link Headers#get(Object)} and convert the result to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return the first header value if the header is found. {@code null} if there's no such header.
+ */
+ String getAsString(CharSequence name);
+
+ /**
+ * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return a {@link List} of header values or an empty {@link List} if no values are found.
+ */
+ List getAllAsString(CharSequence name);
+
+ /**
+ * {@link #iterator()} that converts each {@link Entry}'s key and value to a {@link String}.
+ */
+ Iterator> iteratorAsString();
+
+ /**
+ * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
+ *
+ * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
+ * @param name the name of the header to find
+ * @param value the value of the header to find
+ * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
+ * otherwise a case sensitive compare is run to compare values.
+ */
+ boolean contains(CharSequence name, CharSequence value, boolean ignoreCase);
}
diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java
index e91340a62f..0af0528681 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java
@@ -350,9 +350,9 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder {
throws Exception {
// Create the first line of the request from the name/value pairs
SpdyHeaders headers = requestFrame.headers();
- HttpMethod method = HttpMethod.valueOf(headers.getAndConvert(METHOD));
- String url = headers.getAndConvert(PATH);
- HttpVersion httpVersion = HttpVersion.valueOf(headers.getAndConvert(VERSION));
+ HttpMethod method = HttpMethod.valueOf(headers.getAsString(METHOD));
+ String url = headers.getAsString(PATH);
+ HttpVersion httpVersion = HttpVersion.valueOf(headers.getAsString(VERSION));
headers.remove(METHOD);
headers.remove(PATH);
headers.remove(VERSION);
@@ -386,7 +386,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder {
// Create the first line of the response from the name/value pairs
SpdyHeaders headers = responseFrame.headers();
HttpResponseStatus status = HttpResponseStatus.parseLine(headers.get(STATUS));
- HttpVersion version = HttpVersion.valueOf(headers.getAndConvert(VERSION));
+ HttpVersion version = HttpVersion.valueOf(headers.getAsString(VERSION));
headers.remove(STATUS);
headers.remove(VERSION);
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/CombinedHttpHeadersTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/CombinedHttpHeadersTest.java
new file mode 100644
index 0000000000..6b2327977a
--- /dev/null
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/CombinedHttpHeadersTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.codec.http;
+
+import io.netty.handler.codec.http.HttpHeadersTestUtils.HeaderValue;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static io.netty.util.AsciiString.contentEquals;
+import static org.junit.Assert.assertTrue;
+
+public class CombinedHttpHeadersTest {
+ private static final String HEADER_NAME = "testHeader";
+
+ @Test
+ public void addCharSequencesCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addCharSequencesCsvWithExistingHeader() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asArray());
+ headers.add(HEADER_NAME, HeaderValue.FIVE.subset(4));
+ assertCsvValues(headers, HeaderValue.FIVE);
+ }
+
+ @Test
+ public void addCharSequencesCsvWithValueContainingComma() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.SIX_QUOTED.subset(4));
+ assertTrue(contentEquals(HeaderValue.SIX_QUOTED.subsetAsCsvString(4), headers.get(HEADER_NAME)));
+ assertTrue(contentEquals(HeaderValue.SIX_QUOTED.subsetAsCsvString(4), headers.getAll(HEADER_NAME).get(0)));
+ }
+
+ @Test
+ public void addCharSequencesCsvWithValueContainingCommas() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.EIGHT.subset(6));
+ assertTrue(contentEquals(HeaderValue.EIGHT.subsetAsCsvString(6), headers.get(HEADER_NAME)));
+ assertTrue(contentEquals(HeaderValue.EIGHT.subsetAsCsvString(6), headers.getAll(HEADER_NAME).get(0)));
+ }
+
+ @Test (expected = NullPointerException.class)
+ public void addCharSequencesCsvNullValue() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ final String value = null;
+ headers.add(HEADER_NAME, value);
+ }
+
+ @Test
+ public void addCharSequencesCsvMultipleTimes() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ for (int i = 0; i < 5; ++i) {
+ headers.add(HEADER_NAME, "value");
+ }
+ assertTrue(contentEquals("value,value,value,value,value", headers.get(HEADER_NAME)));
+ }
+
+ @Test
+ public void addCharSequenceCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ addValues(headers, HeaderValue.ONE, HeaderValue.TWO, HeaderValue.THREE);
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addCharSequenceCsvSingleValue() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ addValues(headers, HeaderValue.ONE);
+ assertCsvValue(headers, HeaderValue.ONE);
+ }
+
+ @Test
+ public void addIterableCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asList());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addIterableCsvWithExistingHeader() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asArray());
+ headers.add(HEADER_NAME, HeaderValue.FIVE.subset(4));
+ assertCsvValues(headers, HeaderValue.FIVE);
+ }
+
+ @Test
+ public void addIterableCsvSingleValue() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.ONE.asList());
+ assertCsvValue(headers, HeaderValue.ONE);
+ }
+
+ @Test
+ public void addIterableCsvEmtpy() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.add(HEADER_NAME, Collections.emptyList());
+ assertTrue(contentEquals("", headers.getAll(HEADER_NAME).get(0)));
+ }
+
+ @Test
+ public void addObjectCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ addObjectValues(headers, HeaderValue.ONE, HeaderValue.TWO, HeaderValue.THREE);
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addObjectsCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.addObject(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addObjectsIterableCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.addObject(HEADER_NAME, HeaderValue.THREE.asList());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addObjectsCsvWithExistingHeader() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.addObject(HEADER_NAME, HeaderValue.THREE.asArray());
+ headers.addObject(HEADER_NAME, HeaderValue.FIVE.subset(4));
+ assertCsvValues(headers, HeaderValue.FIVE);
+ }
+
+ @Test
+ public void setCharSequenceCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.set(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setIterableCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.set(HEADER_NAME, HeaderValue.THREE.asList());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setObjectObjectsCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.setObject(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setObjectIterableCsv() {
+ final CombinedHttpHeaders headers = newCombinedHttpHeaders();
+ headers.setObject(HEADER_NAME, HeaderValue.THREE.asList());
+ assertCsvValues(headers, HeaderValue.THREE);
+ }
+
+ private static CombinedHttpHeaders newCombinedHttpHeaders() {
+ return new CombinedHttpHeaders(true);
+ }
+
+ private static void assertCsvValues(final CombinedHttpHeaders headers, final HeaderValue headerValue) {
+ assertTrue(contentEquals(headerValue.asCsv(), headers.get(HEADER_NAME)));
+ assertTrue(contentEquals(headerValue.asCsv(), headers.getAll(HEADER_NAME).get(0)));
+ }
+
+ private static void assertCsvValue(final CombinedHttpHeaders headers, final HeaderValue headerValue) {
+ assertTrue(contentEquals(headerValue.toString(), headers.get(HEADER_NAME)));
+ assertTrue(contentEquals(headerValue.toString(), headers.getAll(HEADER_NAME).get(0)));
+ }
+
+ private static void addValues(final CombinedHttpHeaders headers, HeaderValue... headerValues) {
+ for (HeaderValue v: headerValues) {
+ headers.add(HEADER_NAME, v.toString());
+ }
+ }
+
+ private static void addObjectValues(final CombinedHttpHeaders headers, HeaderValue... headerValues) {
+ for (HeaderValue v: headerValues) {
+ headers.addObject(HEADER_NAME, v.toString());
+ }
+ }
+}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/DefaultHttpHeadersTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/DefaultHttpHeadersTest.java
index e19a5b4d48..199cb82bdf 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/DefaultHttpHeadersTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/DefaultHttpHeadersTest.java
@@ -15,14 +15,23 @@
*/
package io.netty.handler.codec.http;
+import io.netty.handler.codec.http.HttpHeadersTestUtils.HeaderValue;
+import io.netty.util.AsciiString;
import org.junit.Test;
+import java.util.Iterator;
import java.util.List;
+import static io.netty.util.AsciiString.contentEquals;
import static java.util.Arrays.asList;
+import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
public class DefaultHttpHeadersTest {
+ private static final String HEADER_NAME = "testHeader";
@Test
public void keysShouldBeCaseInsensitive() {
@@ -56,4 +65,113 @@ public class DefaultHttpHeadersTest {
assertEquals(headers2, headers1);
assertEquals(headers1.hashCode(), headers2.hashCode());
}
+
+ @Test
+ public void testRemoveTransferEncodingIgnoreCase() {
+ HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
+ message.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "Chunked");
+ assertFalse(message.headers().isEmpty());
+ HttpHeaderUtil.setTransferEncodingChunked(message, false);
+ assertTrue(message.headers().isEmpty());
+ }
+
+ // Test for https://github.com/netty/netty/issues/1690
+ @Test
+ public void testGetOperations() {
+ HttpHeaders headers = new DefaultHttpHeaders();
+ headers.add("Foo", "1");
+ headers.add("Foo", "2");
+
+ assertEquals("1", headers.get("Foo"));
+
+ List values = headers.getAll("Foo");
+ assertEquals(2, values.size());
+ assertEquals("1", values.get(0));
+ assertEquals("2", values.get(1));
+ }
+
+ @Test
+ public void testEquansIgnoreCase() {
+ assertThat(AsciiString.contentEqualsIgnoreCase(null, null), is(true));
+ assertThat(AsciiString.contentEqualsIgnoreCase(null, "foo"), is(false));
+ assertThat(AsciiString.contentEqualsIgnoreCase("bar", null), is(false));
+ assertThat(AsciiString.contentEqualsIgnoreCase("FoO", "fOo"), is(true));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSetNullHeaderValueValidate() {
+ HttpHeaders headers = new DefaultHttpHeaders(true);
+ headers.set("test", (CharSequence) null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testSetNullHeaderValueNotValidate() {
+ HttpHeaders headers = new DefaultHttpHeaders(false);
+ headers.set("test", (CharSequence) null);
+ }
+
+ @Test
+ public void addCharSequences() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addIterable() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.add(HEADER_NAME, HeaderValue.THREE.asList());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void addObjects() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.addObject(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setCharSequences() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.set(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setIterable() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.set(HEADER_NAME, HeaderValue.THREE.asList());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setObjectObjects() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.setObject(HEADER_NAME, HeaderValue.THREE.asArray());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ @Test
+ public void setObjectIterable() {
+ final DefaultHttpHeaders headers = newDefaultDefaultHttpHeaders();
+ headers.setObject(HEADER_NAME, HeaderValue.THREE.asList());
+ assertDefaultValues(headers, HeaderValue.THREE);
+ }
+
+ private static void assertDefaultValues(final DefaultHttpHeaders headers, final HeaderValue headerValue) {
+ assertTrue(contentEquals(headerValue.asArray()[0], headers.get(HEADER_NAME)));
+ List expected = headerValue.asList();
+ List actual = headers.getAll(HEADER_NAME);
+ assertEquals(expected.size(), actual.size());
+ Iterator eItr = expected.iterator();
+ Iterator aItr = actual.iterator();
+ while (eItr.hasNext()) {
+ assertTrue(contentEquals(eItr.next(), aItr.next()));
+ }
+ }
+
+ private static DefaultHttpHeaders newDefaultDefaultHttpHeaders() {
+ return new DefaultHttpHeaders(true);
+ }
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java
index b81767709c..232307efd9 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentCompressorTest.java
@@ -303,8 +303,8 @@ public class HttpContentCompressorTest {
HttpResponse res = (HttpResponse) o;
assertThat(res, is(not(instanceOf(HttpContent.class))));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
assertThat(res.headers().get(HttpHeaderNames.CONTENT_LENGTH), is(nullValue()));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.CONTENT_ENCODING), is("gzip"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.CONTENT_ENCODING), is("gzip"));
}
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java
index c343b7443f..8d3c6f0ea6 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpContentEncoderTest.java
@@ -333,7 +333,7 @@ public class HttpContentEncoderTest {
HttpResponse res = (HttpResponse) o;
assertThat(res, is(not(instanceOf(HttpContent.class))));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
assertThat(res.headers().get(HttpHeaderNames.CONTENT_LENGTH), is(nullValue()));
HttpContent chunk = ch.readOutbound();
@@ -348,8 +348,8 @@ public class HttpContentEncoderTest {
HttpResponse res = (HttpResponse) o;
assertThat(res, is(not(instanceOf(HttpContent.class))));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
assertThat(res.headers().get(HttpHeaderNames.CONTENT_LENGTH), is(nullValue()));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.CONTENT_ENCODING), is("test"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.CONTENT_ENCODING), is("test"));
}
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderUtilTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderUtilTest.java
index 596cfb556d..ca393f2e8d 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderUtilTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeaderUtilTest.java
@@ -52,9 +52,9 @@ public class HttpHeaderUtilTest {
@Test
public void testEquansIgnoreCase() {
- assertThat(AsciiString.equalsIgnoreCase(null, null), is(true));
- assertThat(AsciiString.equalsIgnoreCase(null, "foo"), is(false));
- assertThat(AsciiString.equalsIgnoreCase("bar", null), is(false));
- assertThat(AsciiString.equalsIgnoreCase("FoO", "fOo"), is(true));
+ assertThat(AsciiString.contentEqualsIgnoreCase(null, null), is(true));
+ assertThat(AsciiString.contentEqualsIgnoreCase(null, "foo"), is(false));
+ assertThat(AsciiString.contentEqualsIgnoreCase("bar", null), is(false));
+ assertThat(AsciiString.contentEqualsIgnoreCase("FoO", "fOo"), is(true));
}
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java
deleted file mode 100644
index b98e3fd1f6..0000000000
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2013 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-package io.netty.handler.codec.http;
-
-import io.netty.util.AsciiString;
-
-import org.junit.Test;
-
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-public class HttpHeadersTest {
-
- @Test
- public void testRemoveTransferEncodingIgnoreCase() {
- HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
- message.headers().set(HttpHeaderNames.TRANSFER_ENCODING, "Chunked");
- assertFalse(message.headers().isEmpty());
- HttpHeaderUtil.setTransferEncodingChunked(message, false);
- assertTrue(message.headers().isEmpty());
- }
-
- // Test for https://github.com/netty/netty/issues/1690
- @Test
- public void testGetOperations() {
- HttpHeaders headers = new DefaultHttpHeaders();
- headers.add("Foo", "1");
- headers.add("Foo", "2");
-
- assertEquals("1", headers.get("Foo"));
-
- List values = headers.getAll("Foo");
- assertEquals(2, values.size());
- assertEquals("1", values.get(0));
- assertEquals("2", values.get(1));
- }
-
- @Test
- public void testEquansIgnoreCase() {
- assertThat(AsciiString.equalsIgnoreCase(null, null), is(true));
- assertThat(AsciiString.equalsIgnoreCase(null, "foo"), is(false));
- assertThat(AsciiString.equalsIgnoreCase("bar", null), is(false));
- assertThat(AsciiString.equalsIgnoreCase("FoO", "fOo"), is(true));
- }
-
- @Test(expected = NullPointerException.class)
- public void testSetNullHeaderValueValidate() {
- HttpHeaders headers = new DefaultHttpHeaders(true);
- headers.set("test", (CharSequence) null);
- }
-
- @Test(expected = NullPointerException.class)
- public void testSetNullHeaderValueNotValidate() {
- HttpHeaders headers = new DefaultHttpHeaders(false);
- headers.set("test", (CharSequence) null);
- }
-}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTestUtils.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTestUtils.java
new file mode 100644
index 0000000000..9b2e72030a
--- /dev/null
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpHeadersTestUtils.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.handler.codec.http;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static io.netty.util.internal.StringUtil.COMMA;
+import static io.netty.util.internal.StringUtil.DOUBLE_QUOTE;
+
+class HttpHeadersTestUtils {
+ public enum HeaderValue {
+ UNKNOWN("unknown", 0),
+ ONE("one", 1),
+ TWO("two", 2),
+ THREE("three", 3),
+ FOUR("four", 4),
+ FIVE("five", 5),
+ SIX_QUOTED("six,", 6),
+ SEVEN_QUOTED("seven; , GMT", 7),
+ EIGHT("eight", 8);
+
+ private final int nr;
+ private final String value;
+ private CharSequence[] array;
+
+ HeaderValue(final String value, final int nr) {
+ this.nr = nr;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+
+ public CharSequence[] asArray() {
+ if (array == null) {
+ final String[] arr = new String[nr];
+ for (int i = 1, y = 0; i <= nr; i++, y++) {
+ arr[y] = of(i).toString();
+ }
+ array = arr;
+ }
+ return array;
+ }
+
+ public String[] subset(final int from) {
+ final int size = from - 1;
+ final String[] arr = new String[nr - size];
+ System.arraycopy(asArray(), size, arr, 0, arr.length);
+ return arr;
+ }
+
+ public String subsetAsCsvString(final int from) {
+ final String[] subset = subset(from);
+ return asCsv(subset);
+ }
+
+ public List asList() {
+ return Arrays.asList(asArray());
+ }
+
+ public String asCsv(final CharSequence[] arr) {
+ final StringBuilder sb = new StringBuilder();
+ int end = arr.length - 1;
+ for (int i = 0; i < end; i++) {
+ final CharSequence value = arr[i];
+ quoted(sb, value).append(COMMA);
+ }
+ quoted(sb, arr[end]);
+ return sb.toString();
+ }
+
+ public CharSequence asCsv() {
+ return asCsv(asArray());
+ }
+
+ private static StringBuilder quoted(final StringBuilder sb, final CharSequence value) {
+ if (contains(value, COMMA) && !contains(value, DOUBLE_QUOTE)) {
+ return sb.append(DOUBLE_QUOTE).append(value).append(DOUBLE_QUOTE);
+ }
+ return sb.append(value);
+ }
+
+ private static boolean contains(CharSequence value, char c) {
+ for (int i = 0; i < value.length(); ++i) {
+ if (value.charAt(i) == c) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static final Map MAP;
+
+ static {
+ final Map map = new HashMap();
+ for (HeaderValue v : values()) {
+ final int nr = v.nr;
+ map.put(Integer.valueOf(nr), v);
+ }
+ MAP = map;
+ }
+
+ public static HeaderValue of(final int nr) {
+ final HeaderValue v = MAP.get(Integer.valueOf(nr));
+ return v == null ? UNKNOWN : v;
+ }
+ }
+}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
index 52b0df9d32..7407b43890 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
@@ -248,7 +248,7 @@ public class HttpResponseDecoderTest {
HttpResponse res = ch.readInbound();
assertThat(res.protocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
assertThat(res.status(), is(HttpResponseStatus.OK));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
assertThat(ch.readInbound(), is(nullValue()));
// Close the connection without sending anything.
@@ -269,7 +269,7 @@ public class HttpResponseDecoderTest {
HttpResponse res = ch.readInbound();
assertThat(res.protocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
assertThat(res.status(), is(HttpResponseStatus.OK));
- assertThat(res.headers().getAndConvert(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
+ assertThat(res.headers().getAsString(HttpHeaderNames.TRANSFER_ENCODING), is("chunked"));
// Read the partial content.
HttpContent content = ch.readInbound();
@@ -339,7 +339,7 @@ public class HttpResponseDecoderTest {
HttpResponse res = ch.readInbound();
assertThat(res.protocolVersion(), sameInstance(HttpVersion.HTTP_1_1));
assertThat(res.status(), is(HttpResponseStatus.OK));
- assertThat(res.headers().getAndConvert("X-Header"), is("h2=h2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
+ assertThat(res.headers().getAsString("X-Header"), is("h2=h2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT"));
assertThat(ch.readInbound(), is(nullValue()));
ch.writeInbound(Unpooled.wrappedBuffer(new byte[1024]));
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java
index 2ab2b54614..133fee9477 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpServerCodecTest.java
@@ -91,7 +91,7 @@ public class HttpServerCodecTest {
// Ensure the aggregator generates a full request.
FullHttpRequest req = ch.readInbound();
- assertThat(req.headers().getAndConvert(HttpHeaderNames.CONTENT_LENGTH), is("1"));
+ assertThat(req.headers().getAsString(HttpHeaderNames.CONTENT_LENGTH), is("1"));
assertThat(req.content().readableBytes(), is(1));
assertThat(req.content().readByte(), is((byte) 42));
req.release();
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsConfigTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsConfigTest.java
index a209d857e2..8c4faca2c8 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsConfigTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsConfigTest.java
@@ -95,20 +95,20 @@ public class CorsConfigTest {
@Test
public void preflightResponseHeadersSingleValue() {
final CorsConfig cors = withAnyOrigin().preflightResponseHeader("SingleValue", "value").build();
- assertThat(cors.preflightResponseHeaders().getAndConvert("SingleValue"), equalTo("value"));
+ assertThat(cors.preflightResponseHeaders().getAsString("SingleValue"), equalTo("value"));
}
@Test
public void preflightResponseHeadersMultipleValues() {
final CorsConfig cors = withAnyOrigin().preflightResponseHeader("MultipleValues", "value1", "value2").build();
- assertThat(cors.preflightResponseHeaders().getAllAndConvert("MultipleValues"), hasItems("value1", "value2"));
+ assertThat(cors.preflightResponseHeaders().getAllAsString("MultipleValues"), hasItems("value1", "value2"));
}
@Test
public void defaultPreflightResponseHeaders() {
final CorsConfig cors = withAnyOrigin().build();
assertThat(cors.preflightResponseHeaders().get(HttpHeaderNames.DATE), is(notNullValue()));
- assertThat(cors.preflightResponseHeaders().getAndConvert(HttpHeaderNames.CONTENT_LENGTH), is("0"));
+ assertThat(cors.preflightResponseHeaders().getAsString(HttpHeaderNames.CONTENT_LENGTH), is("0"));
}
@Test
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsHandlerTest.java
index d3a4270b29..4e35fea09f 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsHandlerTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/cors/CorsHandlerTest.java
@@ -47,14 +47,14 @@ public class CorsHandlerTest {
@Test
public void simpleRequestWithAnyOrigin() {
final HttpResponse response = simpleRequest(CorsConfig.withAnyOrigin().build(), "http://localhost:7777");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is("*"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is("*"));
}
@Test
public void simpleRequestWithOrigin() {
final String origin = "http://localhost:8888";
final HttpResponse response = simpleRequest(CorsConfig.withOrigin(origin).build(), origin);
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin));
}
@Test
@@ -63,9 +63,9 @@ public class CorsHandlerTest {
final String origin2 = "https://localhost:8888";
final String[] origins = {origin1, origin2};
final HttpResponse response1 = simpleRequest(CorsConfig.withOrigins(origins).build(), origin1);
- assertThat(response1.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin1));
+ assertThat(response1.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin1));
final HttpResponse response2 = simpleRequest(CorsConfig.withOrigins(origins).build(), origin2);
- assertThat(response2.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin2));
+ assertThat(response2.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is(origin2));
}
@Test
@@ -81,10 +81,10 @@ public class CorsHandlerTest {
.allowedRequestMethods(GET, DELETE)
.build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://localhost:8888"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_METHODS), containsString("GET"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_METHODS), containsString("DELETE"));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://localhost:8888"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_METHODS), containsString("GET"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_METHODS), containsString("DELETE"));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -94,21 +94,21 @@ public class CorsHandlerTest {
.allowedRequestHeaders("content-type", "xheader1")
.build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://localhost:8888"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_METHODS), containsString("OPTIONS"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_METHODS), containsString("GET"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_HEADERS), containsString("content-type"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_HEADERS), containsString("xheader1"));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is("http://localhost:8888"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_METHODS), containsString("OPTIONS"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_METHODS), containsString("GET"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_HEADERS), containsString("content-type"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_HEADERS), containsString("xheader1"));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
public void preflightRequestWithDefaultHeaders() {
final CorsConfig config = CorsConfig.withOrigin("http://localhost:8888").build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
- assertThat(response.headers().getAndConvert(CONTENT_LENGTH), is("0"));
+ assertThat(response.headers().getAsString(CONTENT_LENGTH), is("0"));
assertThat(response.headers().get(DATE), is(notNullValue()));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -117,8 +117,8 @@ public class CorsHandlerTest {
.preflightResponseHeader("CustomHeader", "somevalue")
.build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
- assertThat(response.headers().getAndConvert("CustomHeader"), equalTo("somevalue"));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString("CustomHeader"), equalTo("somevalue"));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -131,7 +131,7 @@ public class CorsHandlerTest {
.build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertValues(response, headerName, value1, value2);
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -144,7 +144,7 @@ public class CorsHandlerTest {
.build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
assertValues(response, headerName, value1, value2);
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -157,8 +157,8 @@ public class CorsHandlerTest {
}
}).build();
final HttpResponse response = preflightRequest(config, "http://localhost:8888", "content-type, xheader1");
- assertThat(response.headers().getAndConvert("GenHeader"), equalTo("generatedValue"));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString("GenHeader"), equalTo("generatedValue"));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
@@ -169,9 +169,9 @@ public class CorsHandlerTest {
.allowCredentials()
.build();
final HttpResponse response = preflightRequest(config, origin, "content-type, xheader1");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is(equalTo("*")));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), is(equalTo("*")));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(nullValue()));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is(equalTo("*")));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), is(equalTo("*")));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(nullValue()));
}
@Test
@@ -179,7 +179,7 @@ public class CorsHandlerTest {
final String origin = "null";
final CorsConfig config = CorsConfig.withOrigin(origin).allowCredentials().build();
final HttpResponse response = preflightRequest(config, origin, "content-type, xheader1");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(equalTo("true")));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_CREDENTIALS), is(equalTo("true")));
}
@Test
@@ -194,16 +194,16 @@ public class CorsHandlerTest {
public void simpleRequestCustomHeaders() {
final CorsConfig config = CorsConfig.withAnyOrigin().exposeHeaders("custom1", "custom2").build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("*"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom1"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom2"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("*"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom1"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("custom2"));
}
@Test
public void simpleRequestAllowCredentials() {
final CorsConfig config = CorsConfig.withAnyOrigin().allowCredentials().build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
}
@Test
@@ -217,17 +217,17 @@ public class CorsHandlerTest {
public void anyOriginAndAllowCredentialsShouldEchoRequestOrigin() {
final CorsConfig config = CorsConfig.withAnyOrigin().allowCredentials().build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("http://localhost:7777"));
- assertThat(response.headers().getAndConvert(VARY), equalTo(ORIGIN.toString()));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_CREDENTIALS), equalTo("true"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_ALLOW_ORIGIN), equalTo("http://localhost:7777"));
+ assertThat(response.headers().getAsString(VARY), equalTo(ORIGIN.toString()));
}
@Test
public void simpleRequestExposeHeaders() {
final CorsConfig config = CorsConfig.withAnyOrigin().exposeHeaders("one", "two").build();
final HttpResponse response = simpleRequest(config, "http://localhost:7777");
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("one"));
- assertThat(response.headers().getAndConvert(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("two"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("one"));
+ assertThat(response.headers().getAsString(ACCESS_CONTROL_EXPOSE_HEADERS), containsString("two"));
}
@Test
@@ -328,7 +328,7 @@ public class CorsHandlerTest {
}
private static void assertValues(final HttpResponse response, final String headerName, final String... values) {
- final String header = response.headers().getAndConvert(headerName);
+ final String header = response.headers().getAsString(headerName);
for (String value : values) {
assertThat(header, containsString(value));
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandlerTest.java
index e01ab6c626..c03aef60bd 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandlerTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketClientExtensionHandlerTest.java
@@ -67,14 +67,14 @@ public class WebSocketClientExtensionHandlerTest {
HttpRequest req2 = ch.readOutbound();
List reqExts = WebSocketExtensionUtil.extractExtensions(
- req2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ req2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
HttpResponse res = newUpgradeResponse("main");
ch.writeInbound(res);
HttpResponse res2 = ch.readInbound();
List resExts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
// test
assertEquals(2, reqExts.size());
@@ -117,14 +117,14 @@ public class WebSocketClientExtensionHandlerTest {
HttpRequest req2 = ch.readOutbound();
List reqExts = WebSocketExtensionUtil.extractExtensions(
- req2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ req2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
HttpResponse res = newUpgradeResponse("fallback");
ch.writeInbound(res);
HttpResponse res2 = ch.readInbound();
List resExts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
// test
assertEquals(2, reqExts.size());
@@ -180,14 +180,14 @@ public class WebSocketClientExtensionHandlerTest {
HttpRequest req2 = ch.readOutbound();
List reqExts = WebSocketExtensionUtil.extractExtensions(
- req2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ req2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
HttpResponse res = newUpgradeResponse("main, fallback");
ch.writeInbound(res);
HttpResponse res2 = ch.readInbound();
List resExts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
// test
assertEquals(2, reqExts.size());
@@ -237,7 +237,7 @@ public class WebSocketClientExtensionHandlerTest {
HttpRequest req2 = ch.readOutbound();
List reqExts = WebSocketExtensionUtil.extractExtensions(
- req2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ req2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
HttpResponse res = newUpgradeResponse("main, fallback");
ch.writeInbound(res);
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandlerTest.java
index 1282f5b7ef..d037e430a0 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandlerTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/WebSocketServerExtensionHandlerTest.java
@@ -76,7 +76,7 @@ public class WebSocketServerExtensionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List resExts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
// test
assertEquals(1, resExts.size());
@@ -127,7 +127,7 @@ public class WebSocketServerExtensionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List resExts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
// test
assertEquals(2, resExts.size());
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/compression/WebSocketServerCompressionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/compression/WebSocketServerCompressionHandlerTest.java
index f6a02a67ad..b2dc052314 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/compression/WebSocketServerCompressionHandlerTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/extensions/compression/WebSocketServerCompressionHandlerTest.java
@@ -45,7 +45,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertTrue(exts.get(0).parameters().isEmpty());
@@ -66,7 +66,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertEquals("10", exts.get(0).parameters().get(CLIENT_MAX_WINDOW));
@@ -87,7 +87,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertTrue(exts.get(0).parameters().isEmpty());
@@ -108,7 +108,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertEquals("10", exts.get(0).parameters().get(SERVER_MAX_WINDOW));
@@ -163,7 +163,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertTrue(exts.get(0).parameters().isEmpty());
@@ -185,7 +185,7 @@ public class WebSocketServerCompressionHandlerTest {
HttpResponse res2 = ch.readOutbound();
List exts = WebSocketExtensionUtil.extractExtensions(
- res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
+ res2.headers().getAsString(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS));
assertEquals(PERMESSAGE_DEFLATE_EXTENSION, exts.get(0).name());
assertTrue(exts.get(0).parameters().isEmpty());
diff --git a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java
index a249b9d80c..6c734be957 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/spdy/SpdySessionHandlerTest.java
@@ -84,7 +84,7 @@ public class SpdySessionHandlerTest {
assertEquals(last, spdyHeadersFrame.isLast());
for (CharSequence name: headers.names()) {
List expectedValues = headers.getAll(name);
- List receivedValues = new ArrayList(spdyHeadersFrame.headers().getAll(name));
+ List receivedValues = spdyHeadersFrame.headers().getAll(name);
assertTrue(receivedValues.containsAll(expectedValues));
receivedValues.removeAll(expectedValues);
assertTrue(receivedValues.isEmpty());
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
index a62d32ad2b..6aef682649 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2Headers.java
@@ -14,19 +14,16 @@
*/
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.BinaryHeaders;
-import io.netty.handler.codec.DefaultBinaryHeaders;
+import io.netty.handler.codec.ByteStringValueConverter;
import io.netty.handler.codec.DefaultHeaders;
+import io.netty.handler.codec.Headers;
import io.netty.util.ByteString;
-import java.io.Serializable;
-import java.util.Comparator;
-import java.util.List;
-import java.util.TreeMap;
-public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2Headers {
+public class DefaultHttp2Headers extends DefaultHeaders implements Http2Headers {
+ private HeaderEntry firstNonPseudo = head;
public DefaultHttp2Headers() {
- super(new TreeMap(Http2HeaderNameComparator.INSTANCE));
+ super(ByteStringValueConverter.INSTANCE);
}
@Override
@@ -120,7 +117,7 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
}
@Override
- public Http2Headers add(BinaryHeaders headers) {
+ public Http2Headers add(Headers extends ByteString> headers) {
super.add(headers);
return this;
}
@@ -216,13 +213,13 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
}
@Override
- public Http2Headers set(BinaryHeaders headers) {
+ public Http2Headers set(Headers extends ByteString> headers) {
super.set(headers);
return this;
}
@Override
- public Http2Headers setAll(BinaryHeaders headers) {
+ public Http2Headers setAll(Headers extends ByteString> headers) {
super.setAll(headers);
return this;
}
@@ -289,43 +286,37 @@ public class DefaultHttp2Headers extends DefaultBinaryHeaders implements Http2He
}
@Override
- public int hashCode() {
- return size();
+ protected final HeaderEntry newHeaderEntry(int h, ByteString name, ByteString value,
+ HeaderEntry next) {
+ return new Http2HeaderEntry(h, name, value, next);
}
- @Override
- public boolean equals(Object other) {
- if (!(other instanceof Http2Headers)) {
- return false;
- }
- Http2Headers headers = (Http2Headers) other;
- return DefaultHeaders.comparatorEquals(this, headers, ByteString.DEFAULT_COMPARATOR);
- }
+ private final class Http2HeaderEntry extends HeaderEntry {
+ protected Http2HeaderEntry(int hash, ByteString key, ByteString value, HeaderEntry next) {
+ super(hash, key);
+ this.value = value;
+ this.next = next;
- private static class Http2HeaderNameComparator implements Comparator, Serializable {
-
- public static final Http2HeaderNameComparator INSTANCE = new Http2HeaderNameComparator();
- private static final long serialVersionUID = 1109871697664666478L;
-
- @Override
- public int compare(ByteString one, ByteString two) {
- // Reserved header names come first.
- final boolean isPseudoHeader1 = !one.isEmpty() && one.byteAt(0) == ':';
- final boolean isPseudoHeader2 = !two.isEmpty() && two.byteAt(0) == ':';
- if (isPseudoHeader1 != isPseudoHeader2) {
- return isPseudoHeader1 ? -1 : 1;
- }
- final int delta = one.hashCode() - two.hashCode();
- if (delta == 0) {
- // If the hash code matches it's very likely for the two strings to be equal
- // and thus we optimistically compare them with the much faster equals method.
- if (one.equals(two)) {
- return 0;
- } else {
- return ByteString.DEFAULT_COMPARATOR.compare(one, two);
+ // Make sure the pseudo headers fields are first in iteration order
+ if (!key.isEmpty() && key.byteAt(0) == ':') {
+ after = firstNonPseudo;
+ before = firstNonPseudo.before();
+ } else {
+ after = head;
+ before = head.before();
+ if (firstNonPseudo == head) {
+ firstNonPseudo = this;
}
}
- return delta;
+ pointNeighborsToThis();
+ }
+
+ @Override
+ protected void remove() {
+ if (this == firstNonPseudo) {
+ firstNonPseudo = firstNonPseudo.after();
+ }
+ super.remove();
}
}
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
index e08941ba9f..e55f7554f7 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/EmptyHttp2Headers.java
@@ -15,11 +15,11 @@
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.BinaryHeaders;
-import io.netty.handler.codec.EmptyBinaryHeaders;
+import io.netty.handler.codec.EmptyHeaders;
+import io.netty.handler.codec.Headers;
import io.netty.util.ByteString;
-public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2Headers {
+public final class EmptyHttp2Headers extends EmptyHeaders implements Http2Headers {
public static final EmptyHttp2Headers INSTANCE = new EmptyHttp2Headers();
private EmptyHttp2Headers() {
@@ -116,7 +116,7 @@ public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2
}
@Override
- public Http2Headers add(BinaryHeaders headers) {
+ public Http2Headers add(Headers extends ByteString> headers) {
super.add(headers);
return this;
}
@@ -212,13 +212,13 @@ public final class EmptyHttp2Headers extends EmptyBinaryHeaders implements Http2
}
@Override
- public Http2Headers set(BinaryHeaders headers) {
+ public Http2Headers set(Headers extends ByteString> headers) {
super.set(headers);
return this;
}
@Override
- public Http2Headers setAll(BinaryHeaders headers) {
+ public Http2Headers setAll(Headers extends ByteString> headers) {
super.setAll(headers);
return this;
}
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
index 61a8bed800..92381a066b 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2Headers.java
@@ -15,19 +15,19 @@
package io.netty.handler.codec.http2;
-import io.netty.handler.codec.BinaryHeaders;
-import io.netty.util.ByteString;
-import io.netty.util.CharsetUtil;
-
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
+import io.netty.handler.codec.Headers;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
+
/**
* A collection of headers sent or received via HTTP/2.
*/
-public interface Http2Headers extends BinaryHeaders {
+public interface Http2Headers extends Headers {
/**
* HTTP/2 pseudo-headers names.
@@ -129,7 +129,7 @@ public interface Http2Headers extends BinaryHeaders {
Http2Headers addTimeMillis(ByteString name, long value);
@Override
- Http2Headers add(BinaryHeaders headers);
+ Http2Headers add(Headers extends ByteString> headers);
@Override
Http2Headers set(ByteString name, ByteString value);
@@ -177,10 +177,10 @@ public interface Http2Headers extends BinaryHeaders {
Http2Headers setTimeMillis(ByteString name, long value);
@Override
- Http2Headers set(BinaryHeaders headers);
+ Http2Headers set(Headers extends ByteString> headers);
@Override
- Http2Headers setAll(BinaryHeaders headers);
+ Http2Headers setAll(Headers extends ByteString> headers);
@Override
Http2Headers clear();
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
index 86fb67cece..f0ccfff3de 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/HttpUtil.java
@@ -274,7 +274,7 @@ public final class HttpUtil {
out.path(new AsciiString(request.uri()));
out.method(new AsciiString(request.method().toString()));
- String value = inHeaders.getAndConvert(HttpHeaderNames.HOST);
+ String value = inHeaders.getAsString(HttpHeaderNames.HOST);
if (value != null) {
URI hostUri = URI.create(value);
// The authority MUST NOT include the deprecated "userinfo" subcomponent
@@ -321,8 +321,8 @@ public final class HttpUtil {
AsciiString aValue = AsciiString.of(entry.getValue());
// https://tools.ietf.org/html/draft-ietf-httpbis-http2-16#section-8.1.2.2
// makes a special exception for TE
- if (!aName.equalsIgnoreCase(HttpHeaderNames.TE) ||
- aValue.equalsIgnoreCase(HttpHeaderValues.TRAILERS)) {
+ if (!aName.contentEqualsIgnoreCase(HttpHeaderNames.TE) ||
+ aValue.contentEqualsIgnoreCase(HttpHeaderValues.TRAILERS)) {
out.add(aName, aValue);
}
}
@@ -331,7 +331,7 @@ public final class HttpUtil {
}
/**
- * A visitor which translates HTTP/2 headers to HTTP/1 headers
+ * Utility which translates HTTP/2 headers to HTTP/1 headers.
*/
private static final class Http2ToHttpHeaderTranslator {
/**
diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
index 6d047b6af3..a3963d068d 100644
--- a/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
+++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/InboundHttp2ToHttpPriorityAdapter.java
@@ -14,11 +14,6 @@
*/
package io.netty.handler.codec.http2;
-import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
-import static io.netty.handler.codec.http2.Http2Exception.connectionError;
-
-import java.util.Map.Entry;
-
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.FullHttpMessage;
@@ -26,7 +21,11 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.util.AsciiString;
import io.netty.util.collection.IntObjectHashMap;
import io.netty.util.collection.IntObjectMap;
-import io.netty.util.internal.PlatformDependent;
+
+import java.util.Map.Entry;
+
+import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
+import static io.netty.handler.codec.http2.Http2Exception.connectionError;
/**
* Translate header/data/priority HTTP/2 frame events into HTTP events. Just as {@link InboundHttp2ToHttpAdapter}
@@ -135,12 +134,8 @@ public final class InboundHttp2ToHttpPriorityAdapter extends InboundHttp2ToHttpA
* @param http2Headers The target HTTP/2 headers
*/
private static void addHttpHeadersToHttp2Headers(HttpHeaders httpHeaders, final Http2Headers http2Headers) {
- try {
- for (Entry entry : httpHeaders) {
- http2Headers.add(AsciiString.of(entry.getKey()), AsciiString.of(entry.getValue()));
- }
- } catch (Exception ex) {
- PlatformDependent.throwException(ex);
+ for (Entry entry : httpHeaders) {
+ http2Headers.add(AsciiString.of(entry.getKey()), AsciiString.of(entry.getValue()));
}
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
index 38cdb71a07..fcf0ed1b13 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DataCompressionHttp2Test.java
@@ -49,7 +49,6 @@ import java.util.Random;
import java.util.concurrent.CountDownLatch;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -67,9 +66,9 @@ import static org.mockito.Mockito.verify;
* Test for data decompression in the HTTP/2 codec.
*/
public class DataCompressionHttp2Test {
- private static final AsciiString GET = as("GET");
- private static final AsciiString POST = as("POST");
- private static final AsciiString PATH = as("/some/path");
+ private static final AsciiString GET = new AsciiString("GET");
+ private static final AsciiString POST = new AsciiString("POST");
+ private static final AsciiString PATH = new AsciiString("/some/path");
@Mock
private Http2FrameListener serverListener;
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2FrameIOTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2FrameIOTest.java
index d0c464d3c5..b975281602 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2FrameIOTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2FrameIOTest.java
@@ -15,9 +15,29 @@
package io.netty.handler.codec.http2;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.buffer.UnpooledByteBufAllocator;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelPromise;
+import io.netty.util.AsciiString;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
+import io.netty.util.concurrent.EventExecutor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_HEADER_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_UNSIGNED_INT;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
@@ -29,26 +49,6 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.Unpooled;
-import io.netty.buffer.UnpooledByteBufAllocator;
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPromise;
-import io.netty.util.ByteString;
-import io.netty.util.CharsetUtil;
-import io.netty.util.concurrent.EventExecutor;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
/**
* Integration tests for {@link DefaultHttp2FrameReader} and {@link DefaultHttp2FrameWriter}.
@@ -365,8 +365,9 @@ public class DefaultHttp2FrameIOTest {
}
private static Http2Headers dummyHeaders() {
- return new DefaultHttp2Headers().method(as("GET")).scheme(as("https")).authority(as("example.org"))
- .path(as("/some/path")).add(as("accept"), as("*/*"));
+ return new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path"))
+ .add(new AsciiString("accept"), new AsciiString("*/*"));
}
private static Http2Headers largeHeaders() {
@@ -374,7 +375,7 @@ public class DefaultHttp2FrameIOTest {
for (int i = 0; i < 100; ++i) {
String key = "this-is-a-test-header-key-" + i;
String value = "this-is-a-test-header-value-" + i;
- headers.add(as(key), as(value));
+ headers.add(new AsciiString(key), new AsciiString(value));
}
return headers;
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeaderTableListSizeTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeaderTableListSizeTest.java
index 0a715ef7b3..c5cd5c4de5 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeaderTableListSizeTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeaderTableListSizeTest.java
@@ -15,12 +15,11 @@
package io.netty.handler.codec.http2;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
/**
* Tests for {@link DefaultHttp2HeaderTableListSize}.
*/
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
index 2067d9fd11..b825373fb2 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersDecoderTest.java
@@ -15,22 +15,21 @@
package io.netty.handler.codec.http2;
+import com.twitter.hpack.Encoder;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.util.AsciiString;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_HEADER_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_HEADER_TABLE_SIZE;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
import static io.netty.handler.codec.http2.Http2TestUtil.randomBytes;
import static io.netty.util.CharsetUtil.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-
-import java.io.ByteArrayOutputStream;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.twitter.hpack.Encoder;
/**
* Tests for {@link DefaultHttp2HeadersDecoder}.
@@ -51,7 +50,7 @@ public class DefaultHttp2HeadersDecoderTest {
Http2Headers headers = decoder.decodeHeaders(buf);
assertEquals(3, headers.size());
assertEquals("GET", headers.method().toString());
- assertEquals("avalue", headers.get(as("akey")).toString());
+ assertEquals("avalue", headers.get(new AsciiString("akey")).toString());
} finally {
buf.release();
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoderTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoderTest.java
index 3dc9c9d86a..b01010381b 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoderTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersEncoderTest.java
@@ -15,14 +15,14 @@
package io.netty.handler.codec.http2;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
-import static org.junit.Assert.assertTrue;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-
+import io.netty.util.AsciiString;
import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
/**
* Tests for {@link DefaultHttp2HeadersEncoder}.
*/
@@ -55,7 +55,7 @@ public class DefaultHttp2HeadersEncoderTest {
}
private static Http2Headers headers() {
- return new DefaultHttp2Headers().method(as("GET")).add(as("a"), as("1"))
- .add(as("a"), as("2"));
+ return new DefaultHttp2Headers().method(new AsciiString("GET")).add(new AsciiString("a"), new AsciiString("1"))
+ .add(new AsciiString("a"), new AsciiString("2"));
}
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
index 4c4abc0a5b..7839a8c0f9 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/DefaultHttp2HeadersTest.java
@@ -16,42 +16,83 @@
package io.netty.handler.codec.http2;
+import io.netty.handler.codec.http2.Http2Headers.PseudoHeaderName;
import io.netty.util.ByteString;
-import io.netty.util.CharsetUtil;
import org.junit.Test;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map.Entry;
+import java.util.Set;
-import static java.util.Arrays.asList;
+import static io.netty.util.ByteString.fromAscii;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
public class DefaultHttp2HeadersTest {
@Test
public void pseudoHeadersMustComeFirstWhenIterating() {
- DefaultHttp2Headers headers = new DefaultHttp2Headers();
- headers.add(bs("name1"), bs("value1"), bs("value2"));
- headers.method(bs("POST"));
- headers.add(bs("2name"), bs("value3"));
- headers.path(bs("/index.html"));
- headers.status(bs("200"));
- headers.authority(bs("netty.io"));
- headers.add(bs("name3"), bs("value4"));
- headers.scheme(bs("https"));
+ Http2Headers headers = newHeaders();
- Iterator> iter = headers.iterator();
- List names = new ArrayList();
- for (int i = 0; i < 5; i++) {
- names.add(iter.next().getKey());
- }
- assertTrue(names.containsAll(asList(bs(":method"), bs(":status"), bs(":path"), bs(":scheme"),
- bs(":authority"))));
+ verifyPseudoHeadersFirst(headers);
+ verifyAllPseudoHeadersPresent(headers);
}
- private static ByteString bs(String str) {
- return new ByteString(str, CharsetUtil.US_ASCII);
+ @Test
+ public void pseudoHeadersWithRemovePreservesPseudoIterationOrder() {
+ Http2Headers headers = newHeaders();
+
+ Set nonPseudoHeaders = new HashSet(headers.size());
+ for (Entry entry : headers) {
+ if (entry.getKey().isEmpty() || entry.getKey().byteAt(0) != ':') {
+ nonPseudoHeaders.add(entry.getKey());
+ }
+ }
+
+ // Remove all the non-pseudo headers and verify
+ for (ByteString nonPseudoHeader : nonPseudoHeaders) {
+ assertTrue(headers.remove(nonPseudoHeader));
+ verifyPseudoHeadersFirst(headers);
+ verifyAllPseudoHeadersPresent(headers);
+ }
+
+ // Add back all non-pseudo headers
+ for (ByteString nonPseudoHeader : nonPseudoHeaders) {
+ headers.add(nonPseudoHeader, fromAscii("goo"));
+ verifyPseudoHeadersFirst(headers);
+ verifyAllPseudoHeadersPresent(headers);
+ }
+ }
+
+ private static void verifyAllPseudoHeadersPresent(Http2Headers headers) {
+ for (PseudoHeaderName pseudoName : PseudoHeaderName.values()) {
+ assertNotNull(headers.get(pseudoName.value()));
+ }
+ }
+
+ private static void verifyPseudoHeadersFirst(Http2Headers headers) {
+ ByteString lastNonPseudoName = null;
+ for (Entry entry: headers) {
+ if (entry.getKey().isEmpty() || entry.getKey().byteAt(0) != ':') {
+ lastNonPseudoName = entry.getKey();
+ } else if (lastNonPseudoName != null) {
+ fail("All pseudo headers must be fist in iteration. Pseudo header " + entry.getKey() +
+ " is after a non pseudo header " + lastNonPseudoName);
+ }
+ }
+ }
+
+ private static Http2Headers newHeaders() {
+ Http2Headers headers = new DefaultHttp2Headers();
+ headers.add(fromAscii("name1"), fromAscii("value1"), fromAscii("value2"));
+ headers.method(fromAscii("POST"));
+ headers.add(fromAscii("2name"), fromAscii("value3"));
+ headers.path(fromAscii("/index.html"));
+ headers.status(fromAscii("200"));
+ headers.authority(fromAscii("netty.io"));
+ headers.add(fromAscii("name3"), fromAscii("value4"));
+ headers.scheme(fromAscii("https"));
+ return headers;
}
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java
index 583b1462ce..0b9f4b6a44 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2ConnectionRoundtripTest.java
@@ -15,28 +15,6 @@
package io.netty.handler.codec.http2;
-import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
-import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
-import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
-import static io.netty.handler.codec.http2.Http2TestUtil.FrameCountDown;
-import static io.netty.util.CharsetUtil.UTF_8;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
@@ -53,15 +31,11 @@ import io.netty.channel.ChannelPromise;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.http2.Http2TestUtil.FrameCountDown;
import io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable;
+import io.netty.util.AsciiString;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
-
-import java.io.ByteArrayOutputStream;
-import java.net.InetSocketAddress;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -70,6 +44,32 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.io.ByteArrayOutputStream;
+import java.net.InetSocketAddress;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+import static io.netty.handler.codec.http2.Http2Error.PROTOCOL_ERROR;
+import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
+import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
+import static io.netty.util.CharsetUtil.UTF_8;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
/**
* Tests the full HTTP/2 framing stack including the connection and preface handlers.
*/
@@ -495,8 +495,9 @@ public class Http2ConnectionRoundtripTest {
}
private static Http2Headers dummyHeaders() {
- return new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource2")).add(randomString(), randomString());
+ return new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2"))
+ .add(randomString(), randomString());
}
private void mockFlowControl(Http2FrameListener listener) throws Http2Exception {
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java
index 077d48ae4d..527f6819d7 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2FrameRoundtripTest.java
@@ -29,6 +29,7 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable;
+import io.netty.util.AsciiString;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
import org.junit.After;
@@ -46,7 +47,6 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
import static io.netty.util.CharsetUtil.UTF_8;
@@ -393,7 +393,8 @@ public class Http2FrameRoundtripTest {
}
private static Http2Headers headers() {
- return new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource2")).add(randomString(), randomString());
+ return new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2"))
+ .add(randomString(), randomString());
}
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2HeaderBlockIOTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2HeaderBlockIOTest.java
index 265d8c0ca5..951d96af17 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2HeaderBlockIOTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2HeaderBlockIOTest.java
@@ -15,16 +15,16 @@
package io.netty.handler.codec.http2;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
-import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
-import static org.junit.Assert.assertEquals;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
-
+import io.netty.util.AsciiString;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import static io.netty.handler.codec.http2.Http2TestUtil.randomString;
+import static org.junit.Assert.assertEquals;
+
/**
* Tests for encoding/decoding HTTP2 header blocks.
*/
@@ -55,23 +55,23 @@ public class Http2HeaderBlockIOTest {
@Test
public void successiveCallsShouldSucceed() throws Http2Exception {
Http2Headers in =
- new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path"))
- .add(as("accept"), as("*/*"));
+ new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path"))
+ .add(new AsciiString("accept"), new AsciiString("*/*"));
assertRoundtripSuccessful(in);
in =
- new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource1"))
- .add(as("accept"), as("image/jpeg"))
- .add(as("cache-control"), as("no-cache"));
+ new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource1"))
+ .add(new AsciiString("accept"), new AsciiString("image/jpeg"))
+ .add(new AsciiString("cache-control"), new AsciiString("no-cache"));
assertRoundtripSuccessful(in);
in =
- new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource2"))
- .add(as("accept"), as("image/png"))
- .add(as("cache-control"), as("no-cache"));
+ new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2"))
+ .add(new AsciiString("accept"), new AsciiString("image/png"))
+ .add(new AsciiString("cache-control"), new AsciiString("no-cache"));
assertRoundtripSuccessful(in);
}
@@ -91,11 +91,14 @@ public class Http2HeaderBlockIOTest {
}
private static Http2Headers headers() {
- return new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource2"))
- .add(as("accept"), as("image/png")).add(as("cache-control"), as("no-cache"))
- .add(as("custom"), as("value1")).add(as("custom"), as("value2"))
- .add(as("custom"), as("value3")).add(as("custom"), as("custom4"))
+ return new DefaultHttp2Headers().method(new AsciiString("GET")).scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org")).path(new AsciiString("/some/path/resource2"))
+ .add(new AsciiString("accept"), new AsciiString("image/png"))
+ .add(new AsciiString("cache-control"), new AsciiString("no-cache"))
+ .add(new AsciiString("custom"), new AsciiString("value1"))
+ .add(new AsciiString("custom"), new AsciiString("value2"))
+ .add(new AsciiString("custom"), new AsciiString("value3"))
+ .add(new AsciiString("custom"), new AsciiString("custom4"))
.add(randomString(), randomString());
}
}
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
index 3bfa13432e..68ed6a241a 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/Http2TestUtil.java
@@ -52,20 +52,6 @@ final class Http2TestUtil {
});
}
- /**
- * Converts a {@link String} into an {@link AsciiString}.
- */
- public static AsciiString as(String value) {
- return new AsciiString(value);
- }
-
- /**
- * Converts a byte array into a {@link ByteString}.
- */
- public static ByteString bs(byte[] value) {
- return new ByteString(value);
- }
-
/**
* Returns a byte array filled with random data.
*/
@@ -86,7 +72,7 @@ final class Http2TestUtil {
* Returns an {@link AsciiString} that wraps a randomly-filled byte array.
*/
public static ByteString randomString() {
- return bs(randomBytes());
+ return new ByteString(randomBytes());
}
private Http2TestUtil() {
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandlerTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandlerTest.java
index 9960de21e7..65e1c42907 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandlerTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/HttpToHttp2ConnectionHandlerTest.java
@@ -14,23 +14,6 @@
*/
package io.netty.handler.codec.http2;
-import static io.netty.handler.codec.http.HttpMethod.GET;
-import static io.netty.handler.codec.http.HttpMethod.POST;
-import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
-import static io.netty.util.CharsetUtil.UTF_8;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyShort;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
@@ -54,15 +37,9 @@ import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.codec.http2.Http2TestUtil.FrameCountDown;
+import io.netty.util.AsciiString;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
-
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -71,6 +48,29 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+import static io.netty.handler.codec.http.HttpMethod.GET;
+import static io.netty.handler.codec.http.HttpMethod.POST;
+import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+import static io.netty.util.CharsetUtil.UTF_8;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyShort;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
/**
* Testing the {@link HttpToHttp2ConnectionHandler} for {@link FullHttpRequest} objects into HTTP/2 frames
*/
@@ -122,10 +122,11 @@ public class HttpToHttp2ConnectionHandlerTest {
httpHeaders.add("foo", "goo2");
httpHeaders.add("foo2", "goo2");
final Http2Headers http2Headers =
- new DefaultHttp2Headers().method(as("GET")).path(as("/example"))
- .authority(as("www.example.org:5555")).scheme(as("http"))
- .add(as("foo"), as("goo")).add(as("foo"), as("goo2"))
- .add(as("foo2"), as("goo2"));
+ new DefaultHttp2Headers().method(new AsciiString("GET")).path(new AsciiString("/example"))
+ .authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http"))
+ .add(new AsciiString("foo"), new AsciiString("goo"))
+ .add(new AsciiString("foo"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo2"));
ChannelPromise writePromise = newPromise();
ChannelFuture writeFuture = clientChannel.writeAndFlush(request, writePromise);
@@ -161,10 +162,11 @@ public class HttpToHttp2ConnectionHandlerTest {
httpHeaders.add("foo", "goo2");
httpHeaders.add("foo2", "goo2");
final Http2Headers http2Headers =
- new DefaultHttp2Headers().method(as("POST")).path(as("/example"))
- .authority(as("www.example.org:5555")).scheme(as("http"))
- .add(as("foo"), as("goo")).add(as("foo"), as("goo2"))
- .add(as("foo2"), as("goo2"));
+ new DefaultHttp2Headers().method(new AsciiString("POST")).path(new AsciiString("/example"))
+ .authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http"))
+ .add(new AsciiString("foo"), new AsciiString("goo"))
+ .add(new AsciiString("foo"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo2"));
ChannelPromise writePromise = newPromise();
ChannelFuture writeFuture = clientChannel.writeAndFlush(request, writePromise);
@@ -202,14 +204,16 @@ public class HttpToHttp2ConnectionHandlerTest {
httpHeaders.add("foo", "goo2");
httpHeaders.add("foo2", "goo2");
final Http2Headers http2Headers =
- new DefaultHttp2Headers().method(as("POST")).path(as("/example"))
- .authority(as("www.example.org:5555")).scheme(as("http"))
- .add(as("foo"), as("goo")).add(as("foo"), as("goo2"))
- .add(as("foo2"), as("goo2"));
+ new DefaultHttp2Headers().method(new AsciiString("POST")).path(new AsciiString("/example"))
+ .authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http"))
+ .add(new AsciiString("foo"), new AsciiString("goo"))
+ .add(new AsciiString("foo"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo2"));
request.trailingHeaders().add("trailing", "bar");
- final Http2Headers http2TrailingHeaders = new DefaultHttp2Headers().add(as("trailing"), as("bar"));
+ final Http2Headers http2TrailingHeaders = new DefaultHttp2Headers()
+ .add(new AsciiString("trailing"), new AsciiString("bar"));
ChannelPromise writePromise = newPromise();
ChannelFuture writeFuture = clientChannel.writeAndFlush(request, writePromise);
@@ -251,17 +255,19 @@ public class HttpToHttp2ConnectionHandlerTest {
httpHeaders.add("foo", "goo2");
httpHeaders.add("foo2", "goo2");
final Http2Headers http2Headers =
- new DefaultHttp2Headers().method(as("POST")).path(as("/example"))
- .authority(as("www.example.org:5555")).scheme(as("http"))
- .add(as("foo"), as("goo")).add(as("foo"), as("goo2"))
- .add(as("foo2"), as("goo2"));
+ new DefaultHttp2Headers().method(new AsciiString("POST")).path(new AsciiString("/example"))
+ .authority(new AsciiString("www.example.org:5555")).scheme(new AsciiString("http"))
+ .add(new AsciiString("foo"), new AsciiString("goo"))
+ .add(new AsciiString("foo"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo2"));
final DefaultHttpContent httpContent = new DefaultHttpContent(Unpooled.copiedBuffer(text, UTF_8));
final LastHttpContent lastHttpContent = new DefaultLastHttpContent(Unpooled.copiedBuffer(text2, UTF_8));
lastHttpContent.trailingHeaders().add("trailing", "bar");
- final Http2Headers http2TrailingHeaders = new DefaultHttp2Headers().add(as("trailing"), as("bar"));
+ final Http2Headers http2TrailingHeaders = new DefaultHttp2Headers()
+ .add(new AsciiString("trailing"), new AsciiString("bar"));
ChannelPromise writePromise = newPromise();
ChannelFuture writeFuture = clientChannel.write(request, writePromise);
diff --git a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
index c898c829e5..fa444bc8ac 100644
--- a/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
+++ b/codec-http2/src/test/java/io/netty/handler/codec/http2/InboundHttp2ToHttpAdapterTest.java
@@ -59,7 +59,6 @@ import java.util.concurrent.CountDownLatch;
import static io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception;
import static io.netty.handler.codec.http2.Http2Exception.isStreamError;
-import static io.netty.handler.codec.http2.Http2TestUtil.as;
import static io.netty.handler.codec.http2.Http2TestUtil.runInChannel;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -210,8 +209,9 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.set(HttpUtil.ExtensionHeaderNames.AUTHORITY.text(), "example.org");
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).scheme(as("https"))
- .authority(as("example.org")).path(as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).
+ scheme(new AsciiString("https")).authority(new AsciiString("example.org"))
+ .path(new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -232,10 +232,10 @@ public class InboundHttp2ToHttpAdapterTest {
@Test
public void clientRequestSingleHeaderNonAsciiShouldThrow() throws Exception {
final Http2Headers http2Headers = new DefaultHttp2Headers()
- .method(as("GET"))
- .scheme(as("https"))
- .authority(as("example.org"))
- .path(as("/some/path/resource2"))
+ .method(new AsciiString("GET"))
+ .scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org"))
+ .path(new AsciiString("/some/path/resource2"))
.add(new AsciiString("çã".getBytes(CharsetUtil.UTF_8)),
new AsciiString("Ãã".getBytes(CharsetUtil.UTF_8)));
runInChannel(clientChannel, new Http2Runnable() {
@@ -259,8 +259,8 @@ public class InboundHttp2ToHttpAdapterTest {
HttpHeaders httpHeaders = request.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(
- as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
+ new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -289,8 +289,8 @@ public class InboundHttp2ToHttpAdapterTest {
HttpHeaders httpHeaders = request.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(
- as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
+ new AsciiString("/some/path/resource2"));
final int midPoint = text.length() / 2;
runInChannel(clientChannel, new Http2Runnable() {
@Override
@@ -323,8 +323,8 @@ public class InboundHttp2ToHttpAdapterTest {
HttpHeaders httpHeaders = request.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(
- as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
+ new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -361,10 +361,12 @@ public class InboundHttp2ToHttpAdapterTest {
trailingHeaders.set("FoO", "goo");
trailingHeaders.set("foO2", "goo2");
trailingHeaders.add("fOo2", "goo3");
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(
- as("/some/path/resource2"));
- final Http2Headers http2Headers2 = new DefaultHttp2Headers().set(as("foo"), as("goo"))
- .set(as("foo2"), as("goo2")).add(as("foo2"), as("goo3"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
+ new AsciiString("/some/path/resource2"));
+ final Http2Headers http2Headers2 = new DefaultHttp2Headers()
+ .set(new AsciiString("foo"), new AsciiString("goo"))
+ .set(new AsciiString("foo2"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo3"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -398,10 +400,12 @@ public class InboundHttp2ToHttpAdapterTest {
trailingHeaders.set("Foo", "goo");
trailingHeaders.set("fOo2", "goo2");
trailingHeaders.add("foO2", "goo3");
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("GET")).path(
- as("/some/path/resource2"));
- final Http2Headers http2Headers2 = new DefaultHttp2Headers().set(as("foo"), as("goo"))
- .set(as("foo2"), as("goo2")).add(as("foo2"), as("goo3"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("GET")).path(
+ new AsciiString("/some/path/resource2"));
+ final Http2Headers http2Headers2 = new DefaultHttp2Headers()
+ .set(new AsciiString("foo"), new AsciiString("goo"))
+ .set(new AsciiString("foo2"), new AsciiString("goo2"))
+ .add(new AsciiString("foo2"), new AsciiString("goo3"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -441,10 +445,10 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders2.setInt(HttpUtil.ExtensionHeaderNames.STREAM_DEPENDENCY_ID.text(), 3);
httpHeaders2.setInt(HttpUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), 123);
httpHeaders2.setInt(HttpHeaderNames.CONTENT_LENGTH, text2.length());
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("PUT")).path(
- as("/some/path/resource"));
- final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(as("PUT")).path(
- as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
+ new AsciiString("/some/path/resource"));
+ final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
+ new AsciiString("/some/path/resource2"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -488,10 +492,10 @@ public class InboundHttp2ToHttpAdapterTest {
HttpHeaders httpHeaders2 = request2.headers();
httpHeaders2.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 5);
httpHeaders2.setInt(HttpHeaderNames.CONTENT_LENGTH, text2.length());
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("PUT")).path(
- as("/some/path/resource"));
- final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(as("PUT")).path(
- as("/some/path/resource2"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
+ new AsciiString("/some/path/resource"));
+ final Http2Headers http2Headers2 = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(
+ new AsciiString("/some/path/resource2"));
HttpHeaders httpHeaders3 = request3.headers();
httpHeaders3.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 5);
httpHeaders3.setInt(HttpUtil.ExtensionHeaderNames.STREAM_DEPENDENCY_ID.text(), 3);
@@ -549,7 +553,8 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders = request.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
- final Http2Headers http2Headers3 = new DefaultHttp2Headers().method(as("GET")).path(as("/push/test"));
+ final Http2Headers http2Headers3 = new DefaultHttp2Headers().method(new AsciiString("GET"))
+ .path(new AsciiString("/push/test"));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() {
@@ -563,9 +568,10 @@ public class InboundHttp2ToHttpAdapterTest {
capturedRequests = requestCaptor.getAllValues();
assertEquals(request, capturedRequests.get(0));
- final Http2Headers http2Headers = new DefaultHttp2Headers().status(as("200"));
- final Http2Headers http2Headers2 = new DefaultHttp2Headers().status(as("201")).scheme(as("https"))
- .authority(as("example.org"));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().status(new AsciiString("200"));
+ final Http2Headers http2Headers2 = new DefaultHttp2Headers().status(new AsciiString("201"))
+ .scheme(new AsciiString("https"))
+ .authority(new AsciiString("example.org"));
runInChannel(serverConnectedChannel, new Http2Runnable() {
@Override
public void run() {
@@ -597,8 +603,10 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.set(HttpHeaderNames.EXPECT, HttpHeaderValues.CONTINUE);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
- final Http2Headers http2Headers = new DefaultHttp2Headers().method(as("PUT")).path(as("/info/test"))
- .set(as(HttpHeaderNames.EXPECT.toString()), as(HttpHeaderValues.CONTINUE.toString()));
+ final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("PUT"))
+ .path(new AsciiString("/info/test"))
+ .set(new AsciiString(HttpHeaderNames.EXPECT.toString()),
+ new AsciiString(HttpHeaderValues.CONTINUE.toString()));
final FullHttpMessage response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
final String text = "a big payload";
final ByteBuf payload = Unpooled.copiedBuffer(text.getBytes());
@@ -624,7 +632,7 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders = response.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
- final Http2Headers http2HeadersResponse = new DefaultHttp2Headers().status(as("100"));
+ final Http2Headers http2HeadersResponse = new DefaultHttp2Headers().status(new AsciiString("100"));
runInChannel(serverConnectedChannel, new Http2Runnable() {
@Override
public void run() {
@@ -661,7 +669,7 @@ public class InboundHttp2ToHttpAdapterTest {
httpHeaders = response2.headers();
httpHeaders.setInt(HttpUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
- final Http2Headers http2HeadersResponse2 = new DefaultHttp2Headers().status(as("200"));
+ final Http2Headers http2HeadersResponse2 = new DefaultHttp2Headers().status(new AsciiString("200"));
runInChannel(serverConnectedChannel, new Http2Runnable() {
@Override
public void run() {
diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/DefaultStompHeaders.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/DefaultStompHeaders.java
index a3bb2312ff..c940be648f 100644
--- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/DefaultStompHeaders.java
+++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/DefaultStompHeaders.java
@@ -16,15 +16,21 @@
package io.netty.handler.codec.stomp;
-import io.netty.handler.codec.DefaultTextHeaders;
-import io.netty.handler.codec.TextHeaders;
+import io.netty.handler.codec.CharSequenceValueConverter;
+import io.netty.handler.codec.DefaultHeaders;
+import io.netty.handler.codec.Headers;
+import io.netty.handler.codec.HeadersUtils;
-import java.util.TreeMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
-public class DefaultStompHeaders extends DefaultTextHeaders implements StompHeaders {
+import static io.netty.util.AsciiString.CASE_INSENSITIVE_HASHER;
+import static io.netty.util.AsciiString.CASE_SENSITIVE_HASHER;
+public class DefaultStompHeaders extends DefaultHeaders implements StompHeaders {
public DefaultStompHeaders() {
- super(new TreeMap(), NO_NAME_VALIDATOR, CharSequenceConverter.INSTANCE, false);
+ super(CharSequenceValueConverter.INSTANCE);
}
@Override
@@ -118,7 +124,7 @@ public class DefaultStompHeaders extends DefaultTextHeaders implements StompHead
}
@Override
- public StompHeaders add(TextHeaders headers) {
+ public StompHeaders add(Headers extends CharSequence> headers) {
super.add(headers);
return this;
}
@@ -214,13 +220,13 @@ public class DefaultStompHeaders extends DefaultTextHeaders implements StompHead
}
@Override
- public StompHeaders set(TextHeaders headers) {
+ public StompHeaders set(Headers extends CharSequence> headers) {
super.set(headers);
return this;
}
@Override
- public StompHeaders setAll(TextHeaders headers) {
+ public StompHeaders setAll(Headers extends CharSequence> headers) {
super.setAll(headers);
return this;
}
@@ -230,4 +236,30 @@ public class DefaultStompHeaders extends DefaultTextHeaders implements StompHead
super.clear();
return this;
}
+
+ @Override
+ public String getAsString(CharSequence name) {
+ return HeadersUtils.getAsString(this, name);
+ }
+
+ @Override
+ public List getAllAsString(CharSequence name) {
+ return HeadersUtils.getAllAsString(this, name);
+ }
+
+ @Override
+ public Iterator> iteratorAsString() {
+ return HeadersUtils.iteratorAsString(this);
+ }
+
+ @Override
+ public boolean contains(CharSequence name, CharSequence value) {
+ return contains(name, value, false);
+ }
+
+ @Override
+ public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
+ return contains(name, value,
+ ignoreCase ? CASE_INSENSITIVE_HASHER : CASE_SENSITIVE_HASHER);
+ }
}
diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
index 89c93db414..55cfa3d0ea 100644
--- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
+++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompHeaders.java
@@ -15,14 +15,18 @@
*/
package io.netty.handler.codec.stomp;
-import io.netty.handler.codec.TextHeaders;
+import io.netty.handler.codec.Headers;
import io.netty.util.AsciiString;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
/**
* The multimap data structure for the STOMP header names and values. It also provides the constants for the standard
* STOMP header names and values.
*/
-public interface StompHeaders extends TextHeaders {
+public interface StompHeaders extends Headers {
AsciiString ACCEPT_VERSION = new AsciiString("accept-version");
AsciiString HOST = new AsciiString("host");
@@ -90,7 +94,7 @@ public interface StompHeaders extends TextHeaders {
StompHeaders addTimeMillis(CharSequence name, long value);
@Override
- StompHeaders add(TextHeaders headers);
+ StompHeaders add(Headers extends CharSequence> headers);
@Override
StompHeaders set(CharSequence name, CharSequence value);
@@ -138,11 +142,41 @@ public interface StompHeaders extends TextHeaders {
StompHeaders setTimeMillis(CharSequence name, long value);
@Override
- StompHeaders set(TextHeaders headers);
+ StompHeaders set(Headers extends CharSequence> headers);
@Override
- StompHeaders setAll(TextHeaders headers);
+ StompHeaders setAll(Headers extends CharSequence> headers);
@Override
StompHeaders clear();
+
+ /**
+ * {@link Headers#get(Object)} and convert the result to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return the first header value if the header is found. {@code null} if there's no such header.
+ */
+ String getAsString(CharSequence name);
+
+ /**
+ * {@link Headers#getAll(Object)} and convert each element of {@link List} to a {@link String}.
+ * @param name the name of the header to retrieve
+ * @return a {@link List} of header values or an empty {@link List} if no values are found.
+ */
+ List getAllAsString(CharSequence name);
+
+ /**
+ * {@link #iterator()} that converts each {@link Entry}'s key and value to a {@link String}.
+ */
+ Iterator> iteratorAsString();
+
+ /**
+ * Returns {@code true} if a header with the {@code name} and {@code value} exists, {@code false} otherwise.
+ *
+ * If {@code ignoreCase} is {@code true} then a case insensitive compare is done on the value.
+ * @param name the name of the header to find
+ * @param value the value of the header to find
+ * @param ignoreCase {@code true} then a case insensitive compare is run to compare values.
+ * otherwise a case sensitive compare is run to compare values.
+ */
+ boolean contains(CharSequence name, CharSequence value, boolean ignoreCase);
}
diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeEncoder.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeEncoder.java
index e57aa5e607..dd32c7e90a 100644
--- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeEncoder.java
+++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeEncoder.java
@@ -15,6 +15,9 @@
*/
package io.netty.handler.codec.stomp;
+import java.util.List;
+import java.util.Map.Entry;
+
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.AsciiHeadersEncoder;
@@ -22,10 +25,6 @@ import io.netty.handler.codec.AsciiHeadersEncoder.NewlineType;
import io.netty.handler.codec.AsciiHeadersEncoder.SeparatorType;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.CharsetUtil;
-import io.netty.util.internal.PlatformDependent;
-
-import java.util.List;
-import java.util.Map.Entry;
/**
* Encodes a {@link StompFrame} or a {@link StompSubframe} into a {@link ByteBuf}.
diff --git a/codec-stomp/src/test/java/io/netty/handler/codec/stomp/StompTestConstants.java b/codec-stomp/src/test/java/io/netty/handler/codec/stomp/StompTestConstants.java
index e3e49a7daf..a427b944cc 100644
--- a/codec-stomp/src/test/java/io/netty/handler/codec/stomp/StompTestConstants.java
+++ b/codec-stomp/src/test/java/io/netty/handler/codec/stomp/StompTestConstants.java
@@ -18,8 +18,8 @@ package io.netty.handler.codec.stomp;
public final class StompTestConstants {
public static final String CONNECT_FRAME =
"CONNECT\n" +
- "accept-version:1.1,1.2\n" +
"host:stomp.github.org\n" +
+ "accept-version:1.1,1.2\n" +
'\n' +
'\0';
public static final String CONNECTED_FRAME =
diff --git a/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java b/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java
deleted file mode 100644
index f2a4000836..0000000000
--- a/codec/src/main/java/io/netty/handler/codec/BinaryHeaders.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License,
- * version 2.0 (the "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- */
-
-package io.netty.handler.codec;
-
-import io.netty.util.ByteString;
-
-/**
- * A typical {@code ByteString} multimap used by protocols that use binary headers (such as HTTP/2) for the
- * representation of arbitrary key-value data. {@link ByteString} is just a wrapper around a byte array but provides
- * some additional utility when handling text data.
- */
-public interface BinaryHeaders extends Headers {
-
- @Override
- BinaryHeaders add(ByteString name, ByteString value);
-
- @Override
- BinaryHeaders add(ByteString name, Iterable extends ByteString> values);
-
- @Override
- BinaryHeaders add(ByteString name, ByteString... values);
-
- @Override
- BinaryHeaders addObject(ByteString name, Object value);
-
- @Override
- BinaryHeaders addObject(ByteString name, Iterable> values);
-
- @Override
- BinaryHeaders addObject(ByteString name, Object... values);
-
- @Override
- BinaryHeaders addBoolean(ByteString name, boolean value);
-
- @Override
- BinaryHeaders addByte(ByteString name, byte value);
-
- @Override
- BinaryHeaders addChar(ByteString name, char value);
-
- @Override
- BinaryHeaders addShort(ByteString name, short value);
-
- @Override
- BinaryHeaders addInt(ByteString name, int value);
-
- @Override
- BinaryHeaders addLong(ByteString name, long value);
-
- @Override
- BinaryHeaders addFloat(ByteString name, float value);
-
- @Override
- BinaryHeaders addDouble(ByteString name, double value);
-
- @Override
- BinaryHeaders addTimeMillis(ByteString name, long value);
-
- /**
- * See {@link Headers#add(Headers)}
- */
- BinaryHeaders add(BinaryHeaders headers);
-
- @Override
- BinaryHeaders set(ByteString name, ByteString value);
-
- @Override
- BinaryHeaders set(ByteString name, Iterable extends ByteString> values);
-
- @Override
- BinaryHeaders set(ByteString name, ByteString... values);
-
- @Override
- BinaryHeaders setObject(ByteString name, Object value);
-
- @Override
- BinaryHeaders setObject(ByteString name, Iterable> values);
-
- @Override
- BinaryHeaders setObject(ByteString name, Object... values);
-
- @Override
- BinaryHeaders setBoolean(ByteString name, boolean value);
-
- @Override
- BinaryHeaders setByte(ByteString name, byte value);
-
- @Override
- BinaryHeaders setChar(ByteString name, char value);
-
- @Override
- BinaryHeaders setShort(ByteString name, short value);
-
- @Override
- BinaryHeaders setInt(ByteString name, int value);
-
- @Override
- BinaryHeaders setLong(ByteString name, long value);
-
- @Override
- BinaryHeaders setFloat(ByteString name, float value);
-
- @Override
- BinaryHeaders setDouble(ByteString name, double value);
-
- @Override
- BinaryHeaders setTimeMillis(ByteString name, long value);
-
- /**
- * See {@link Headers#set(Headers)}
- */
- BinaryHeaders set(BinaryHeaders headers);
-
- /**
- * See {@link Headers#setAll(Headers)}
- */
- BinaryHeaders setAll(BinaryHeaders headers);
-
- @Override
- BinaryHeaders clear();
-}
diff --git a/codec/src/main/java/io/netty/handler/codec/ByteStringValueConverter.java b/codec/src/main/java/io/netty/handler/codec/ByteStringValueConverter.java
new file mode 100644
index 0000000000..76df1a4e1a
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/ByteStringValueConverter.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.netty.handler.codec;
+
+import java.nio.charset.Charset;
+import java.text.ParseException;
+
+import io.netty.handler.codec.DefaultHeaders.HeaderDateFormat;
+import io.netty.util.ByteString;
+import io.netty.util.CharsetUtil;
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * Converts to/from native types, general {@link Object}, and {@link ByteString}s.
+ */
+public final class ByteStringValueConverter implements ValueConverter {
+ public static final ByteStringValueConverter INSTANCE = new ByteStringValueConverter();
+ private static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
+
+ private ByteStringValueConverter() {
+ }
+
+ @Override
+ public ByteString convertObject(Object value) {
+ if (value instanceof ByteString) {
+ return (ByteString) value;
+ }
+ if (value instanceof CharSequence) {
+ return new ByteString((CharSequence) value, DEFAULT_CHARSET);
+ }
+ return new ByteString(value.toString(), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertInt(int value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertLong(long value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertDouble(double value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertChar(char value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertBoolean(boolean value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public ByteString convertFloat(float value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public int convertToInt(ByteString value) {
+ return value.parseAsciiInt();
+ }
+
+ @Override
+ public long convertToLong(ByteString value) {
+ return value.parseAsciiLong();
+ }
+
+ @Override
+ public ByteString convertTimeMillis(long value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public long convertToTimeMillis(ByteString value) {
+ try {
+ return HeaderDateFormat.get().parse(value.toString());
+ } catch (ParseException e) {
+ PlatformDependent.throwException(e);
+ }
+ return 0;
+ }
+
+ @Override
+ public double convertToDouble(ByteString value) {
+ return value.parseAsciiDouble();
+ }
+
+ @Override
+ public char convertToChar(ByteString value) {
+ return value.parseChar();
+ }
+
+ @Override
+ public boolean convertToBoolean(ByteString value) {
+ return value.byteAt(0) != 0;
+ }
+
+ @Override
+ public float convertToFloat(ByteString value) {
+ return value.parseAsciiFloat();
+ }
+
+ @Override
+ public ByteString convertShort(short value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public short convertToShort(ByteString value) {
+ return value.parseAsciiShort();
+ }
+
+ @Override
+ public ByteString convertByte(byte value) {
+ return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
+ }
+
+ @Override
+ public byte convertToByte(ByteString value) {
+ return value.byteAt(0);
+ }
+}
diff --git a/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java b/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java
new file mode 100644
index 0000000000..c59450ee45
--- /dev/null
+++ b/codec/src/main/java/io/netty/handler/codec/CharSequenceValueConverter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2015 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package io.netty.handler.codec;
+
+import io.netty.handler.codec.DefaultHeaders.HeaderDateFormat;
+import io.netty.util.internal.PlatformDependent;
+
+import java.text.ParseException;
+
+/**
+ * Converts to/from native types, general {@link Object}, and {@link CharSequence}s.
+ */
+public class CharSequenceValueConverter implements ValueConverter {
+ public static final CharSequenceValueConverter INSTANCE = new CharSequenceValueConverter();
+
+ @Override
+ public CharSequence convertObject(Object value) {
+ if (value instanceof CharSequence) {
+ return (CharSequence) value;
+ }
+ return value.toString();
+ }
+
+ @Override
+ public CharSequence convertInt(int value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public CharSequence convertLong(long value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public CharSequence convertDouble(double value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public CharSequence convertChar(char value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public CharSequence convertBoolean(boolean value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public CharSequence convertFloat(float value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public boolean convertToBoolean(CharSequence value) {
+ return Boolean.parseBoolean(value.toString());
+ }
+
+ @Override
+ public CharSequence convertByte(byte value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public byte convertToByte(CharSequence value) {
+ return Byte.valueOf(value.toString());
+ }
+
+ @Override
+ public char convertToChar(CharSequence value) {
+ if (value.length() == 0) {
+ throw new IllegalArgumentException("'value' is empty.");
+ }
+ return value.charAt(0);
+ }
+
+ @Override
+ public CharSequence convertShort(short value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public short convertToShort(CharSequence value) {
+ return Short.valueOf(value.toString());
+ }
+
+ @Override
+ public int convertToInt(CharSequence value) {
+ return Integer.parseInt(value.toString());
+ }
+
+ @Override
+ public long convertToLong(CharSequence value) {
+ return Long.parseLong(value.toString());
+ }
+
+ @Override
+ public CharSequence convertTimeMillis(long value) {
+ return String.valueOf(value);
+ }
+
+ @Override
+ public long convertToTimeMillis(CharSequence value) {
+ try {
+ return HeaderDateFormat.get().parse(value.toString());
+ } catch (ParseException e) {
+ PlatformDependent.throwException(e);
+ }
+ return 0;
+ }
+
+ @Override
+ public float convertToFloat(CharSequence value) {
+ return Float.valueOf(value.toString());
+ }
+
+ @Override
+ public double convertToDouble(CharSequence value) {
+ return Double.valueOf(value.toString());
+ }
+}
diff --git a/codec/src/main/java/io/netty/handler/codec/ConvertibleHeaders.java b/codec/src/main/java/io/netty/handler/codec/ConvertibleHeaders.java
deleted file mode 100644
index ca3eae694a..0000000000
--- a/codec/src/main/java/io/netty/handler/codec/ConvertibleHeaders.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package io.netty.handler.codec;
-
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * Extension to the {@link Headers} interface to provide methods which convert the
- * native {@code UnconvertedType} to the not-native {@code ConvertedType}
- */
-public interface ConvertibleHeaders extends Headers {
-
- /**
- * Interface to do conversions to and from the two generic type parameters
- */
- interface TypeConverter {
- /**
- * Convert a native value
- * @param value The value to be converted
- * @return The conversion results
- */
- ConvertedType toConvertedType(UnconvertedType value);
-
- /**
- * Undo a conversion and restore the original native type
- * @param value The converted value
- * @return The original native type
- */
- UnconvertedType toUnconvertedType(ConvertedType value);
- }
-
- /**
- * Invokes {@link Headers#get(Object)} and does a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The value corresponding to {@code name} and then converted
- */
- ConvertedType getAndConvert(UnconvertedType name);
-
- /**
- * Invokes {@link Headers#get(Object, Object)} and does a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The value corresponding to {@code name} and then converted
- */
- ConvertedType getAndConvert(UnconvertedType name, ConvertedType defaultValue);
-
- /**
- * Invokes {@link Headers#getAndRemove(Object)} and does a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The value corresponding to {@code name} and then converted
- */
- ConvertedType getAndRemoveAndConvert(UnconvertedType name);
-
- /**
- * Invokes {@link Headers#getAndRemove(Object, Object)} and does
- * a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The value corresponding to {@code name} and then converted
- */
- ConvertedType getAndRemoveAndConvert(UnconvertedType name, ConvertedType defaultValue);
-
- /**
- * Invokes {@link Headers#getAll(Object)} and does a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The values corresponding to {@code name} and then converted
- */
- List getAllAndConvert(UnconvertedType name);
-
- /**
- * Invokes {@link Headers#getAllAndRemove(Object)} and does a conversion on the results if not {@code null}
- * @param name The name of entry to get
- * @return The values corresponding to {@code name} and then converted
- */
- List getAllAndRemoveAndConvert(UnconvertedType name);
-
- /**
- * Invokes {@link Headers#iterator()} and lazily does a conversion on the results as they are accessed
- *
- * @return Iterator which will provide converted values corresponding to {@code name}
- */
- Iterator> iteratorConverted();
-
- /**
- * Invokes {@link Headers#names()} and does a conversion on the results
- *
- * @return The values corresponding to {@code name} and then converted
- */
- Set namesAndConvert(Comparator comparator);
-}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java
deleted file mode 100644
index 2183e5d71d..0000000000
--- a/codec/src/main/java/io/netty/handler/codec/DefaultBinaryHeaders.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package io.netty.handler.codec;
-
-import io.netty.util.ByteString;
-import io.netty.util.CharsetUtil;
-import io.netty.util.internal.PlatformDependent;
-
-import java.nio.charset.Charset;
-import java.text.ParseException;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class DefaultBinaryHeaders extends DefaultHeaders implements BinaryHeaders {
-
- private static final NameValidator NO_NAME_VALIDATOR = DefaultHeaders.NoNameValidator.instance();
-
- public DefaultBinaryHeaders() {
- this(new TreeMap(ByteString.DEFAULT_COMPARATOR));
- }
-
- public DefaultBinaryHeaders(Map map) {
- this(map, NO_NAME_VALIDATOR);
- }
-
- public DefaultBinaryHeaders(Map map, NameValidator nameValidator) {
- super(map, nameValidator, ByteStringConverter.INSTANCE);
- }
-
- @Override
- public BinaryHeaders add(ByteString name, ByteString value) {
- super.add(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders add(ByteString name, Iterable extends ByteString> values) {
- super.add(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders add(ByteString name, ByteString... values) {
- super.add(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders addObject(ByteString name, Object value) {
- super.addObject(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addObject(ByteString name, Iterable> values) {
- super.addObject(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders addObject(ByteString name, Object... values) {
- super.addObject(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders addBoolean(ByteString name, boolean value) {
- super.addBoolean(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addChar(ByteString name, char value) {
- super.addChar(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addByte(ByteString name, byte value) {
- super.addByte(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addShort(ByteString name, short value) {
- super.addShort(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addInt(ByteString name, int value) {
- super.addInt(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addLong(ByteString name, long value) {
- super.addLong(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addFloat(ByteString name, float value) {
- super.addFloat(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addDouble(ByteString name, double value) {
- super.addDouble(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders addTimeMillis(ByteString name, long value) {
- super.addTimeMillis(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders add(BinaryHeaders headers) {
- super.add(headers);
- return this;
- }
-
- @Override
- public BinaryHeaders set(ByteString name, ByteString value) {
- super.set(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders set(ByteString name, Iterable extends ByteString> values) {
- super.set(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders set(ByteString name, ByteString... values) {
- super.set(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders setObject(ByteString name, Object value) {
- super.setObject(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setObject(ByteString name, Iterable> values) {
- super.setObject(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders setObject(ByteString name, Object... values) {
- super.setObject(name, values);
- return this;
- }
-
- @Override
- public BinaryHeaders setBoolean(ByteString name, boolean value) {
- super.setBoolean(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setChar(ByteString name, char value) {
- super.setChar(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setByte(ByteString name, byte value) {
- super.setByte(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setShort(ByteString name, short value) {
- super.setShort(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setInt(ByteString name, int value) {
- super.setInt(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setLong(ByteString name, long value) {
- super.setLong(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setFloat(ByteString name, float value) {
- super.setFloat(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setDouble(ByteString name, double value) {
- super.setDouble(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders setTimeMillis(ByteString name, long value) {
- super.setTimeMillis(name, value);
- return this;
- }
-
- @Override
- public BinaryHeaders set(BinaryHeaders headers) {
- super.set(headers);
- return this;
- }
-
- @Override
- public BinaryHeaders setAll(BinaryHeaders headers) {
- super.setAll(headers);
- return this;
- }
-
- @Override
- public BinaryHeaders clear() {
- super.clear();
- return this;
- }
-
- public static final class ByteStringConverter implements ValueConverter {
-
- public static final ByteStringConverter INSTANCE = new ByteStringConverter();
- private static final Charset DEFAULT_CHARSET = CharsetUtil.UTF_8;
-
- private ByteStringConverter() {
- }
-
- @Override
- public ByteString convertObject(Object value) {
- if (value instanceof ByteString) {
- return (ByteString) value;
- }
- if (value instanceof CharSequence) {
- return new ByteString((CharSequence) value, DEFAULT_CHARSET);
- }
- return new ByteString(value.toString(), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertInt(int value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertLong(long value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertDouble(double value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertChar(char value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertBoolean(boolean value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public ByteString convertFloat(float value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public int convertToInt(ByteString value) {
- return value.parseAsciiInt();
- }
-
- @Override
- public long convertToLong(ByteString value) {
- return value.parseAsciiLong();
- }
-
- @Override
- public ByteString convertTimeMillis(long value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public long convertToTimeMillis(ByteString value) {
- try {
- return HeaderDateFormat.get().parse(value.toString());
- } catch (ParseException e) {
- PlatformDependent.throwException(e);
- }
- return 0;
- }
-
- @Override
- public double convertToDouble(ByteString value) {
- return value.parseAsciiDouble();
- }
-
- @Override
- public char convertToChar(ByteString value) {
- return value.parseChar();
- }
-
- @Override
- public boolean convertToBoolean(ByteString value) {
- return value.byteAt(0) != 0;
- }
-
- @Override
- public float convertToFloat(ByteString value) {
- return value.parseAsciiFloat();
- }
-
- @Override
- public ByteString convertShort(short value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public short convertToShort(ByteString value) {
- return value.parseAsciiShort();
- }
-
- @Override
- public ByteString convertByte(byte value) {
- return new ByteString(String.valueOf(value), DEFAULT_CHARSET);
- }
-
- @Override
- public byte convertToByte(ByteString value) {
- return value.byteAt(0);
- }
- }
-}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultConvertibleHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultConvertibleHeaders.java
deleted file mode 100644
index 3c7863799d..0000000000
--- a/codec/src/main/java/io/netty/handler/codec/DefaultConvertibleHeaders.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2014 The Netty Project
- *
- * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
- * "License"); you may not use this file except in compliance with the License. You may obtain a
- * copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- */
-package io.netty.handler.codec;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class DefaultConvertibleHeaders extends DefaultHeaders
- implements ConvertibleHeaders {
-
- private final TypeConverter typeConverter;
-
- public DefaultConvertibleHeaders(Map map,
- NameValidator nameValidator,
- ValueConverter valueConverter,
- TypeConverter typeConverter) {
- super(map, nameValidator, valueConverter);
- this.typeConverter = typeConverter;
- }
-
- @Override
- public ConvertedType getAndConvert(UnconvertedType name) {
- return getAndConvert(name, null);
- }
-
- @Override
- public ConvertedType getAndConvert(UnconvertedType name, ConvertedType defaultValue) {
- UnconvertedType v = get(name);
- if (v == null) {
- return defaultValue;
- }
- return typeConverter.toConvertedType(v);
- }
-
- @Override
- public ConvertedType getAndRemoveAndConvert(UnconvertedType name) {
- return getAndRemoveAndConvert(name, null);
- }
-
- @Override
- public ConvertedType getAndRemoveAndConvert(UnconvertedType name, ConvertedType defaultValue) {
- UnconvertedType v = getAndRemove(name);
- if (v == null) {
- return defaultValue;
- }
- return typeConverter.toConvertedType(v);
- }
-
- @Override
- public List getAllAndConvert(UnconvertedType name) {
- List all = getAll(name);
- List allConverted = new ArrayList(all.size());
- for (int i = 0; i < all.size(); ++i) {
- allConverted.add(typeConverter.toConvertedType(all.get(i)));
- }
- return allConverted;
- }
-
- @Override
- public List getAllAndRemoveAndConvert(UnconvertedType name) {
- List all = getAllAndRemove(name);
- List allConverted = new ArrayList(all.size());
- for (int i = 0; i < all.size(); ++i) {
- allConverted.add(typeConverter.toConvertedType(all.get(i)));
- }
- return allConverted;
- }
-
- @Override
- public Iterator> iteratorConverted() {
- return new ConvertedIterator();
- }
-
- @Override
- public Set namesAndConvert(Comparator comparator) {
- Set names = names();
- Set namesConverted = new TreeSet(comparator);
- for (UnconvertedType unconverted : names) {
- namesConverted.add(typeConverter.toConvertedType(unconverted));
- }
- return namesConverted;
- }
-
- private final class ConvertedIterator implements Iterator> {
- private final Iterator> iter = iterator();
-
- @Override
- public boolean hasNext() {
- return iter.hasNext();
- }
-
- @Override
- public Entry next() {
- Entry next = iter.next();
-
- return new ConvertedEntry(next);
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- private final class ConvertedEntry implements Entry {
- private final Entry entry;
- private ConvertedType name;
- private ConvertedType value;
-
- ConvertedEntry(Entry entry) {
- this.entry = entry;
- }
-
- @Override
- public ConvertedType getKey() {
- if (name == null) {
- name = typeConverter.toConvertedType(entry.getKey());
- }
- return name;
- }
-
- @Override
- public ConvertedType getValue() {
- if (value == null) {
- value = typeConverter.toConvertedType(entry.getValue());
- }
- return value;
- }
-
- @Override
- public ConvertedType setValue(ConvertedType value) {
- ConvertedType old = getValue();
- entry.setValue(typeConverter.toUnconvertedType(value));
- return old;
- }
-
- @Override
- public String toString() {
- return entry.toString();
- }
- }
-}
diff --git a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
index 6e08fcac90..09781e2530 100644
--- a/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
+++ b/codec/src/main/java/io/netty/handler/codec/DefaultHeaders.java
@@ -14,30 +14,27 @@
*/
package io.netty.handler.codec;
+import io.netty.util.HashingStrategy;
import io.netty.util.concurrent.FastThreadLocal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.Comparator;
+import java.util.Arrays;
+import java.util.Date;
import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TimeZone;
-import java.util.Date;
-import java.util.TreeMap;
+import static io.netty.util.HashingStrategy.JAVA_HASHER;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Collections.unmodifiableList;
-import static java.util.Collections.unmodifiableSet;
-
/**
* Default implementation of {@link Headers};
@@ -45,28 +42,71 @@ import static java.util.Collections.unmodifiableSet;
* @param the type of the header name and value.
*/
public class DefaultHeaders implements Headers {
+ /**
+ * How big the underlying array is for the hash data structure.
+ *
+ * This should be a power of 2 so the {@link #index(int)} method can full address the memory.
+ */
+ private static final int ARRAY_SIZE = 1 << 4;
+ private static final int HASH_MASK = ARRAY_SIZE - 1;
+
+ private static int index(int hash) {
+ // Fold the upper 16 bits onto the 16 lower bits so more of the hash code is represented
+ // when translating to an index.
+ return ((hash >>> 16) ^ hash) & HASH_MASK;
+ }
+
+ @SuppressWarnings("unchecked")
+ private final HeaderEntry[] entries = new DefaultHeaders.HeaderEntry[ARRAY_SIZE];
+ protected final HeaderEntry head = new HeaderEntry();
- private final Map map;
- private final NameValidator nameValidator;
private final ValueConverter valueConverter;
+ private final NameValidator nameValidator;
+ private final HashingStrategy hashingStrategy;
int size;
- boolean hasMultipleValues;
+ public interface NameValidator {
+ void validateName(T name);
- public DefaultHeaders(Map map, NameValidator nameValidator, ValueConverter valueConverter) {
- this.map = checkNotNull(map, "map");
- this.nameValidator = checkNotNull(nameValidator, "nameValidator");
+ @SuppressWarnings("rawtypes")
+ NameValidator NOT_NULL = new NameValidator() {
+ @Override
+ public void validateName(Object name) {
+ checkNotNull(name, "name");
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ public DefaultHeaders(ValueConverter valueConverter) {
+ this(JAVA_HASHER, valueConverter, NameValidator.NOT_NULL);
+ }
+
+ public DefaultHeaders(HashingStrategy nameHashingStrategy,
+ ValueConverter valueConverter, NameValidator nameValidator) {
this.valueConverter = checkNotNull(valueConverter, "valueConverter");
+ this.nameValidator = checkNotNull(nameValidator, "nameValidator");
+ this.hashingStrategy = checkNotNull(nameHashingStrategy, "nameHashingStrategy");
+ head.before = head.after = head;
}
@Override
- @SuppressWarnings("unchecked")
public T get(T name) {
- Object value = map.get(name);
- if (isList(value)) {
- return ((List) value).get(0);
+ checkNotNull(name, "name");
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ HeaderEntry e = entries[i];
+ T value = null;
+ // loop until the first header was found
+ while (e != null) {
+ if (e.hash == h && hashingStrategy.equals(name, e.key)) {
+ value = e.value;
+ }
+
+ e = e.next;
}
- return (T) value;
+ return value;
}
@Override
@@ -79,19 +119,9 @@ public class DefaultHeaders implements Headers {
}
@Override
- @SuppressWarnings("unchecked")
public T getAndRemove(T name) {
- Object value = map.remove(name);
- if (value == null) {
- return null;
- }
- if (isList(value)) {
- List value0 = (List) value;
- size -= value0.size();
- return value0.get(0);
- }
- size--;
- return (T) value;
+ int h = hashingStrategy.hashCode(name);
+ return remove0(h, index(h), checkNotNull(name, "name"));
}
@Override
@@ -104,16 +134,21 @@ public class DefaultHeaders implements Headers {
}
@Override
- @SuppressWarnings("unchecked")
public List getAll(T name) {
- Object value = map.get(name);
- if (isList(value)) {
- return unmodifiableList((List) value);
+ checkNotNull(name, "name");
+
+ LinkedList values = new LinkedList();
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ HeaderEntry e = entries[i];
+ while (e != null) {
+ if (e.hash == h && hashingStrategy.equals(name, e.key)) {
+ values.addFirst(e.getValue());
+ }
+ e = e.next;
}
- if (value == null) {
- return emptyList();
- }
- return singletonList((T) value);
+ return values;
}
@Override
@@ -128,16 +163,6 @@ public class DefaultHeaders implements Headers {
return get(name) != null;
}
- @Override
- @SuppressWarnings("unchecked")
- public boolean contains(T name, T value) {
- Object values = map.get(name);
- if (isList(values)) {
- return ((List) values).contains(value);
- }
- return values != null && values.equals(value);
- }
-
@Override
public boolean containsObject(T name, Object value) {
return contains(name, valueConverter.convertObject(checkNotNull(value, "value")));
@@ -145,63 +170,68 @@ public class DefaultHeaders implements Headers {
@Override
public boolean containsBoolean(T name, boolean value) {
- return contains(name, valueConverter.convertBoolean(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertBoolean(value));
}
@Override
public boolean containsByte(T name, byte value) {
- return contains(name, valueConverter.convertByte(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertByte(value));
}
@Override
public boolean containsChar(T name, char value) {
- return contains(name, valueConverter.convertChar(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertChar(value));
}
@Override
public boolean containsShort(T name, short value) {
- return contains(name, valueConverter.convertShort(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertShort(value));
}
@Override
public boolean containsInt(T name, int value) {
- return contains(name, valueConverter.convertInt(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertInt(value));
}
@Override
public boolean containsLong(T name, long value) {
- return contains(name, valueConverter.convertLong(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertLong(value));
}
@Override
public boolean containsFloat(T name, float value) {
- return contains(name, valueConverter.convertFloat(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertFloat(value));
}
@Override
public boolean containsDouble(T name, double value) {
- return contains(name, valueConverter.convertDouble(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertDouble(value));
}
@Override
public boolean containsTimeMillis(T name, long value) {
- return contains(name, valueConverter.convertTimeMillis(checkNotNull(value, "value")));
+ return contains(name, valueConverter.convertTimeMillis(value));
}
- @Override
@SuppressWarnings("unchecked")
- public boolean contains(T name, T value, Comparator super T> valueComparator) {
- Object values = map.get(name);
- if (isList(values)) {
- List values0 = (List) values;
- for (int i = 0; i < values0.size(); i++) {
- if (valueComparator.compare(value, values0.get(i)) == 0) {
- return true;
- }
+ @Override
+ public boolean contains(T name, T value) {
+ return contains(name, value, JAVA_HASHER);
+ }
+
+ protected final boolean contains(T name, T value, HashingStrategy super T> valueHashingStrategy) {
+ checkNotNull(name, "name");
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ HeaderEntry e = entries[i];
+ while (e != null) {
+ if (e.hash == h && hashingStrategy.equals(name, e.key) && valueHashingStrategy.equals(value, e.value)) {
+ return true;
}
- return false;
+ e = e.next;
}
- return values != null && valueComparator.compare((T) values, value) == 0;
+ return false;
}
@Override
@@ -211,54 +241,48 @@ public class DefaultHeaders implements Headers {
@Override
public boolean isEmpty() {
- return map.isEmpty();
+ return head == head.after;
}
@Override
public Set names() {
- return unmodifiableSet(map.keySet());
+ Set names = new LinkedHashSet(size());
+ HeaderEntry e = head.after;
+ while (e != head) {
+ names.add(e.getKey());
+ e = e.after;
+ }
+ return names;
}
@Override
public Headers add(T name, T value) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(value, "value");
- Object prevValue = map.put(name, value);
- size++;
- if (prevValue != null) {
- appendValue(name, value, prevValue);
- }
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ add0(h, i, name, value);
return this;
}
- @SuppressWarnings("unchecked")
- private void appendValue(T name, T value, Object prevValue) {
- hasMultipleValues = true;
- if (isList(prevValue)) {
- ((List) prevValue).add(value);
- map.put(name, prevValue);
- } else {
- List values = newList();
- values.add((T) prevValue);
- values.add(value);
- map.put(name, values);
- }
- }
-
@Override
public Headers add(T name, Iterable extends T> values) {
- checkNotNull(values, "values");
- for (T value : values) {
- add(name, value);
+ nameValidator.validateName(name);
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ for (T v: values) {
+ add0(h, i, name, v);
}
return this;
}
@Override
public Headers add(T name, T... values) {
- checkNotNull(values, "values");
- for (int i = 0; i < values.length; i++) {
- add(name, values[i]);
+ nameValidator.validateName(name);
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ for (T v: values) {
+ add0(h, i, name, v);
}
return this;
}
@@ -337,46 +361,69 @@ public class DefaultHeaders implements Headers {
if (headers == this) {
throw new IllegalArgumentException("can't add to itself.");
}
- for (Entry extends T, ? extends T> header : headers) {
- add(header.getKey(), header.getValue());
+ if (headers instanceof DefaultHeaders) {
+ @SuppressWarnings("unchecked")
+ DefaultHeaders defaultHeaders = (DefaultHeaders) headers;
+ HeaderEntry e = defaultHeaders.head.after;
+ while (e != defaultHeaders.head) {
+ add(e.key, e.value);
+ e = e.after;
+ }
+ return this;
+ } else {
+ for (Entry extends T, ? extends T> header : headers) {
+ add(header.getKey(), header.getValue());
+ }
}
return this;
}
@Override
public Headers set(T name, T value) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(value, "value");
- Object oldValue = map.put(name, value);
- updateSizeAfterSet(oldValue, 1);
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+ remove0(h, i, name);
+ add0(h, i, name, value);
return this;
}
@Override
public Headers set(T name, Iterable extends T> values) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(values, "values");
- List list = newList();
- for (T value : values) {
- list.add(checkNotNull(value, "value"));
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+
+ remove0(h, i, name);
+ for (T v: values) {
+ if (v == null) {
+ break;
+ }
+ add0(h, i, name, v);
}
- Object oldValue = map.put(name, list);
- updateSizeAfterSet(oldValue, list.size());
- hasMultipleValues = true;
+
return this;
}
@Override
public Headers set(T name, T... values) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(values, "values");
- List list = newList(values.length);
- for (int i = 0; i < values.length; i++) {
- list.add(checkNotNull(values[i], "value"));
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+
+ remove0(h, i, name);
+ for (T v: values) {
+ if (v == null) {
+ break;
+ }
+ add0(h, i, name, v);
}
- Object oldValue = map.put(name, list);
- updateSizeAfterSet(oldValue, values.length);
- hasMultipleValues = true;
+
return this;
}
@@ -389,33 +436,39 @@ public class DefaultHeaders implements Headers {
@Override
public Headers setObject(T name, Iterable> values) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(values, "values");
- List list = newList();
- for (Object value : values) {
- value = checkNotNull(value, "value");
- T convertedValue = checkNotNull(valueConverter.convertObject(value), "convertedValue");
- list.add(convertedValue);
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+
+ remove0(h, i, name);
+ for (Object v: values) {
+ if (v == null) {
+ break;
+ }
+ add0(h, i, name, valueConverter.convertObject(v));
}
- Object oldValue = map.put(name, list);
- updateSizeAfterSet(oldValue, list.size());
- hasMultipleValues = true;
+
return this;
}
@Override
public Headers setObject(T name, Object... values) {
- validateName(name);
+ nameValidator.validateName(name);
checkNotNull(values, "values");
- List list = newList(values.length);
- for (int i = 0; i < values.length; i++) {
- Object value = checkNotNull(values[i], "value");
- T convertedValue = checkNotNull(valueConverter.convertObject(value), "convertedValue");
- list.add(convertedValue);
+
+ int h = hashingStrategy.hashCode(name);
+ int i = index(h);
+
+ remove0(h, i, name);
+ for (Object v: values) {
+ if (v == null) {
+ break;
+ }
+ add0(h, i, name, valueConverter.convertObject(v));
}
- Object oldValue = map.put(name, list);
- updateSizeAfterSet(oldValue, list.size());
- hasMultipleValues = true;
+
return this;
}
@@ -471,7 +524,17 @@ public class DefaultHeaders implements Headers {
return this;
}
clear();
- add(headers);
+ if (headers instanceof DefaultHeaders) {
+ @SuppressWarnings("unchecked")
+ DefaultHeaders defaultHeaders = (DefaultHeaders) headers;
+ HeaderEntry e = defaultHeaders.head.after;
+ while (e != defaultHeaders.head) {
+ add(e.key, e.value);
+ e = e.after;
+ }
+ } else {
+ add(headers);
+ }
return this;
}
@@ -497,227 +560,147 @@ public class DefaultHeaders implements Headers {
@Override
public Headers clear() {
- map.clear();
- hasMultipleValues = false;
+ Arrays.fill(entries, null);
+ head.before = head.after = head;
size = 0;
return this;
}
@Override
- @SuppressWarnings("unchecked")
public Iterator> iterator() {
- Object iter = map.entrySet().iterator();
- return !hasMultipleValues ? (Iterator>) iter
- : new NameValueIterator((Iterator>) iter);
+ return new HeaderIterator();
}
@Override
public Boolean getBoolean(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToBoolean(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToBoolean(v) : null;
}
@Override
public boolean getBoolean(T name, boolean defaultValue) {
Boolean v = getBoolean(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Byte getByte(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToByte(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToByte(v) : null;
}
@Override
public byte getByte(T name, byte defaultValue) {
Byte v = getByte(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Character getChar(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToChar(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToChar(v) : null;
}
@Override
public char getChar(T name, char defaultValue) {
Character v = getChar(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Short getShort(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToShort(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToShort(v) : null;
}
@Override
public short getShort(T name, short defaultValue) {
Short v = getShort(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Integer getInt(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToInt(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToInt(v) : null;
}
@Override
public int getInt(T name, int defaultValue) {
Integer v = getInt(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Long getLong(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToLong(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToLong(v) : null;
}
@Override
public long getLong(T name, long defaultValue) {
Long v = getLong(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Float getFloat(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToFloat(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToFloat(v) : null;
}
@Override
public float getFloat(T name, float defaultValue) {
Float v = getFloat(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Double getDouble(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToDouble(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToDouble(v) : null;
}
@Override
public double getDouble(T name, double defaultValue) {
Double v = getDouble(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Long getTimeMillis(T name) {
T v = get(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToTimeMillis(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToTimeMillis(v) : null;
}
@Override
public long getTimeMillis(T name, long defaultValue) {
Long v = getTimeMillis(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Boolean getBooleanAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToBoolean(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToBoolean(v) : null;
}
@Override
public boolean getBooleanAndRemove(T name, boolean defaultValue) {
Boolean v = getBooleanAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Byte getByteAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToByte(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToByte(v) : null;
}
@Override
public byte getByteAndRemove(T name, byte defaultValue) {
Byte v = getByteAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
@@ -736,148 +719,142 @@ public class DefaultHeaders implements Headers {
@Override
public char getCharAndRemove(T name, char defaultValue) {
Character v = getCharAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Short getShortAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToShort(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToShort(v) : null;
}
@Override
public short getShortAndRemove(T name, short defaultValue) {
Short v = getShortAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Integer getIntAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToInt(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToInt(v) : null;
}
@Override
public int getIntAndRemove(T name, int defaultValue) {
Integer v = getIntAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Long getLongAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToLong(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToLong(v) : null;
}
@Override
public long getLongAndRemove(T name, long defaultValue) {
Long v = getLongAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Float getFloatAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToFloat(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToFloat(v) : null;
}
@Override
public float getFloatAndRemove(T name, float defaultValue) {
Float v = getFloatAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Double getDoubleAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToDouble(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToDouble(v) : null;
}
@Override
public double getDoubleAndRemove(T name, double defaultValue) {
Double v = getDoubleAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
@Override
public Long getTimeMillisAndRemove(T name) {
T v = getAndRemove(name);
- if (v == null) {
- return null;
- }
- try {
- return valueConverter.convertToTimeMillis(v);
- } catch (Throwable ignored) {
- return null;
- }
+ return v != null ? valueConverter.convertToTimeMillis(v) : null;
}
@Override
public long getTimeMillisAndRemove(T name, long defaultValue) {
Long v = getTimeMillisAndRemove(name);
- return v == null ? defaultValue : v;
+ return v != null ? v : defaultValue;
}
- @Override
@SuppressWarnings("unchecked")
+ @Override
public boolean equals(Object o) {
- if (!(o instanceof DefaultHeaders)) {
+ if (!(o instanceof Headers)) {
return false;
}
- DefaultHeaders