Optimize the decoding and encoding of HTTP for better performance

* No need to calculate the hash of known header names multiple times
* Optimize header encoding
* Also optimize the encoding of known header values
* Optimize encoding of HTTP method, version and status
This commit is contained in:
Norman Maurer 2013-11-24 19:48:02 +01:00
parent 8be11dd79a
commit b067566a7c
35 changed files with 703 additions and 443 deletions

View File

@ -15,6 +15,8 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
@ -31,31 +33,12 @@ public class DefaultHttpHeaders extends HttpHeaders {
private static final int BUCKET_SIZE = 17; private static final int BUCKET_SIZE = 17;
private static int hash(String name) {
int h = 0;
for (int i = name.length() - 1; i >= 0; i --) {
char c = name.charAt(i);
if (c >= 'A' && c <= 'Z') {
c += 32;
}
h = 31 * h + c;
}
if (h > 0) {
return h;
} else if (h == Integer.MIN_VALUE) {
return Integer.MAX_VALUE;
} else {
return -h;
}
}
private static int index(int hash) { private static int index(int hash) {
return hash % BUCKET_SIZE; return hash % BUCKET_SIZE;
} }
private final HeaderEntry[] entries = new HeaderEntry[BUCKET_SIZE]; private final HeaderEntry[] entries = new HeaderEntry[BUCKET_SIZE];
private final HeaderEntry head = new HeaderEntry(-1, null, null); private final HeaderEntry head = new HeaderEntry();
protected final boolean validate; protected final boolean validate;
public DefaultHttpHeaders() { public DefaultHttpHeaders() {
@ -67,19 +50,50 @@ public class DefaultHttpHeaders extends HttpHeaders {
head.before = head.after = head; head.before = head.after = head;
} }
void validateHeaderName0(String headerName) { void validateHeaderName0(CharSequence headerName) {
validateHeaderName(headerName); validateHeaderName(headerName);
} }
@Override @Override
public HttpHeaders add(final String name, final Object value) { public HttpHeaders add(HttpHeaders headers) {
String strVal; if (headers instanceof DefaultHttpHeaders) {
DefaultHttpHeaders defaultHttpHeaders = (DefaultHttpHeaders) headers;
HeaderEntry e = defaultHttpHeaders.head.after;
while (e != defaultHttpHeaders.head) {
add(e.key, e.value);
e = e.after;
}
return this;
} else {
return super.add(headers);
}
}
@Override
public HttpHeaders set(HttpHeaders headers) {
if (headers instanceof DefaultHttpHeaders) {
clear();
DefaultHttpHeaders defaultHttpHeaders = (DefaultHttpHeaders) headers;
HeaderEntry e = defaultHttpHeaders.head.after;
while (e != defaultHttpHeaders.head) {
add(e.key, e.value);
e = e.after;
}
return this;
} else {
return super.set(headers);
}
}
@Override
public HttpHeaders add(final CharSequence name, final Object value) {
CharSequence strVal;
if (validate) { if (validate) {
validateHeaderName0(name); validateHeaderName0(name);
strVal = toString(value); strVal = toCharsequence(value);
validateHeaderValue(strVal); validateHeaderValue(strVal);
} else { } else {
strVal = toString(value); strVal = toCharsequence(value);
} }
int h = hash(name); int h = hash(name);
int i = index(h); int i = index(h);
@ -88,14 +102,14 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public HttpHeaders add(String name, Iterable<?> values) { public HttpHeaders add(CharSequence name, Iterable<?> values) {
if (validate) { if (validate) {
validateHeaderName0(name); validateHeaderName0(name);
} }
int h = hash(name); int h = hash(name);
int i = index(h); int i = index(h);
for (Object v: values) { for (Object v: values) {
String vstr = toString(v); CharSequence vstr = toCharsequence(v);
if (validate) { if (validate) {
validateHeaderValue(vstr); validateHeaderValue(vstr);
} }
@ -104,7 +118,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
return this; return this;
} }
private void add0(int h, int i, final String name, final String value) { private void add0(int h, int i, final CharSequence name, final CharSequence value) {
// Update the hash table. // Update the hash table.
HeaderEntry e = entries[i]; HeaderEntry e = entries[i];
HeaderEntry newEntry; HeaderEntry newEntry;
@ -116,7 +130,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public HttpHeaders remove(final String name) { public HttpHeaders remove(final CharSequence name) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
@ -126,7 +140,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
return this; return this;
} }
private void remove0(int h, int i, String name) { private void remove0(int h, int i, CharSequence name) {
HeaderEntry e = entries[i]; HeaderEntry e = entries[i];
if (e == null) { if (e == null) {
return; return;
@ -163,14 +177,14 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public HttpHeaders set(final String name, final Object value) { public HttpHeaders set(final CharSequence name, final Object value) {
String strVal; CharSequence strVal;
if (validate) { if (validate) {
validateHeaderName0(name); validateHeaderName0(name);
strVal = toString(value); strVal = toCharsequence(value);
validateHeaderValue(strVal); validateHeaderValue(strVal);
} else { } else {
strVal = toString(value); strVal = toCharsequence(value);
} }
int h = hash(name); int h = hash(name);
int i = index(h); int i = index(h);
@ -180,7 +194,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public HttpHeaders set(final String name, final Iterable<?> values) { public HttpHeaders set(final CharSequence name, final Iterable<?> values) {
if (values == null) { if (values == null) {
throw new NullPointerException("values"); throw new NullPointerException("values");
} }
@ -196,7 +210,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
if (v == null) { if (v == null) {
break; break;
} }
String strVal = toString(v); CharSequence strVal = toCharsequence(v);
if (validate) { if (validate) {
validateHeaderValue(strVal); validateHeaderValue(strVal);
} }
@ -214,7 +228,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public String get(final String name) { public String get(final CharSequence name) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
@ -222,7 +236,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
int h = hash(name); int h = hash(name);
int i = index(h); int i = index(h);
HeaderEntry e = entries[i]; HeaderEntry e = entries[i];
String value = null; CharSequence value = null;
// loop until the first header was found // loop until the first header was found
while (e != null) { while (e != null) {
if (e.hash == h && equalsIgnoreCase(name, e.key)) { if (e.hash == h && equalsIgnoreCase(name, e.key)) {
@ -231,11 +245,14 @@ public class DefaultHttpHeaders extends HttpHeaders {
e = e.next; e = e.next;
} }
return value; if (value != null) {
return value.toString();
}
return null;
} }
@Override @Override
public List<String> getAll(final String name) { public List<String> getAll(final CharSequence name) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
@ -247,7 +264,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
HeaderEntry e = entries[i]; HeaderEntry e = entries[i];
while (e != null) { while (e != null) {
if (e.hash == h && equalsIgnoreCase(name, e.key)) { if (e.hash == h && equalsIgnoreCase(name, e.key)) {
values.addFirst(e.value); values.addFirst(e.getValue());
} }
e = e.next; e = e.next;
} }
@ -273,7 +290,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public boolean contains(String name) { public boolean contains(CharSequence name) {
return get(name) != null; return get(name) != null;
} }
@ -283,7 +300,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
} }
@Override @Override
public boolean contains(String name, String value, boolean ignoreCaseValue) { public boolean contains(CharSequence name, CharSequence value, boolean ignoreCaseValue) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
@ -315,18 +332,26 @@ public class DefaultHttpHeaders extends HttpHeaders {
HeaderEntry e = head.after; HeaderEntry e = head.after;
while (e != head) { while (e != head) {
names.add(e.key); names.add(e.getKey());
e = e.after; e = e.after;
} }
return names; return names;
} }
private static String toString(Object value) { void encode(ByteBuf buf) {
HeaderEntry e = head.after;
while (e != head) {
e.encode(buf);
e = e.after;
}
}
private static CharSequence toCharsequence(Object value) {
if (value == null) { if (value == null) {
return null; return null;
} }
if (value instanceof String) { if (value instanceof CharSequence) {
return (String) value; return (CharSequence) value;
} }
if (value instanceof Number) { if (value instanceof Number) {
return value.toString(); return value.toString();
@ -368,17 +393,23 @@ public class DefaultHttpHeaders extends HttpHeaders {
private final class HeaderEntry implements Map.Entry<String, String> { private final class HeaderEntry implements Map.Entry<String, String> {
final int hash; final int hash;
final String key; final CharSequence key;
String value; CharSequence value;
HeaderEntry next; HeaderEntry next;
HeaderEntry before, after; HeaderEntry before, after;
HeaderEntry(int hash, String key, String value) { HeaderEntry(int hash, CharSequence key, CharSequence value) {
this.hash = hash; this.hash = hash;
this.key = key; this.key = key;
this.value = value; this.value = value;
} }
HeaderEntry() {
hash = -1;
key = null;
value = null;
}
void remove() { void remove() {
before.after = after; before.after = after;
after.before = before; after.before = before;
@ -393,12 +424,12 @@ public class DefaultHttpHeaders extends HttpHeaders {
@Override @Override
public String getKey() { public String getKey() {
return key; return key.toString();
} }
@Override @Override
public String getValue() { public String getValue() {
return value; return value.toString();
} }
@Override @Override
@ -407,14 +438,18 @@ public class DefaultHttpHeaders extends HttpHeaders {
throw new NullPointerException("value"); throw new NullPointerException("value");
} }
validateHeaderValue(value); validateHeaderValue(value);
String oldValue = this.value; CharSequence oldValue = this.value;
this.value = value; this.value = value;
return oldValue; return oldValue.toString();
} }
@Override @Override
public String toString() { public String toString() {
return key + '=' + value; return key.toString() + '=' + value.toString();
}
void encode(ByteBuf buf) {
HttpHeaders.encode(key, value, buf);
} }
} }
} }

View File

@ -100,11 +100,11 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
} }
@Override @Override
void validateHeaderName0(String name) { void validateHeaderName0(CharSequence name) {
super.validateHeaderName0(name); super.validateHeaderName0(name);
if (name.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH) || if (equalsIgnoreCase(name, HttpHeaders.Names.CONTENT_LENGTH) ||
name.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING) || equalsIgnoreCase(name, HttpHeaders.Names.TRANSFER_ENCODING) ||
name.equalsIgnoreCase(HttpHeaders.Names.TRAILER)) { equalsIgnoreCase(name, HttpHeaders.Names.TRAILER)) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"prohibited trailing header: " + name); "prohibited trailing header: " + name);
} }

View File

@ -93,10 +93,10 @@ public class HttpContentCompressor extends HttpContentEncoder {
} }
@Override @Override
protected Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception { protected Result beginEncode(HttpResponse headers, CharSequence acceptEncoding) throws Exception {
String contentEncoding = headers.headers().get(HttpHeaders.Names.CONTENT_ENCODING); String contentEncoding = headers.headers().get(HttpHeaders.Names.CONTENT_ENCODING);
if (contentEncoding != null && if (contentEncoding != null &&
!HttpHeaders.Values.IDENTITY.equalsIgnoreCase(contentEncoding)) { !HttpHeaders.equalsIgnoreCase(HttpHeaders.Values.IDENTITY, contentEncoding)) {
return null; return null;
} }
@ -123,11 +123,11 @@ public class HttpContentCompressor extends HttpContentEncoder {
wrapper, compressionLevel, windowBits, memLevel))); wrapper, compressionLevel, windowBits, memLevel)));
} }
protected ZlibWrapper determineWrapper(String acceptEncoding) { protected ZlibWrapper determineWrapper(CharSequence acceptEncoding) {
float starQ = -1.0f; float starQ = -1.0f;
float gzipQ = -1.0f; float gzipQ = -1.0f;
float deflateQ = -1.0f; float deflateQ = -1.0f;
for (String encoding: StringUtil.split(acceptEncoding, ',')) { for (String encoding: StringUtil.split(acceptEncoding.toString(), ',')) {
float q = 1.0f; float q = 1.0f;
int equalsPos = encoding.indexOf('='); int equalsPos = encoding.indexOf('=');
if (equalsPos != -1) { if (equalsPos != -1) {

View File

@ -91,13 +91,13 @@ public abstract class HttpContentDecoder extends MessageToMessageDecoder<HttpObj
if (contentEncoding != null) { if (contentEncoding != null) {
contentEncoding = contentEncoding.trim(); contentEncoding = contentEncoding.trim();
} else { } else {
contentEncoding = HttpHeaders.Values.IDENTITY; contentEncoding = HttpHeaders.Values.IDENTITY.toString();
} }
if ((decoder = newContentDecoder(contentEncoding)) != null) { if ((decoder = newContentDecoder(contentEncoding)) != null) {
// Decode the content and remove or replace the existing headers // Decode the content and remove or replace the existing headers
// so that the message looks like a decoded message. // so that the message looks like a decoded message.
String targetContentEncoding = getTargetContentEncoding(contentEncoding); CharSequence targetContentEncoding = getTargetContentEncoding(contentEncoding);
if (HttpHeaders.Values.IDENTITY.equals(targetContentEncoding)) { if (HttpHeaders.Values.IDENTITY.equals(targetContentEncoding)) {
// Do NOT set the 'Content-Encoding' header if the target encoding is 'identity' // Do NOT set the 'Content-Encoding' header if the target encoding is 'identity'
// as per: http://tools.ietf.org/html/rfc2616#section-14.11 // as per: http://tools.ietf.org/html/rfc2616#section-14.11
@ -185,7 +185,7 @@ public abstract class HttpContentDecoder extends MessageToMessageDecoder<HttpObj
* @return the expected content encoding of the new content * @return the expected content encoding of the new content
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
protected String getTargetContentEncoding(String contentEncoding) throws Exception { protected CharSequence getTargetContentEncoding(String contentEncoding) throws Exception {
return HttpHeaders.Values.IDENTITY; return HttpHeaders.Values.IDENTITY;
} }

View File

@ -31,18 +31,18 @@ import java.util.Queue;
/** /**
* Encodes the content of the outbound {@link HttpResponse} and {@link HttpContent}. * Encodes the content of the outbound {@link HttpResponse} and {@link HttpContent}.
* The original content is replaced with the new content encoded by the * The original content is replaced with the new content encoded by the
* {@link EmbeddedChannel}, which is created by {@link #beginEncode(HttpResponse, String)}. * {@link EmbeddedChannel}, which is created by {@link #beginEncode(HttpResponse, CharSequence)}.
* Once encoding is finished, the value of the <tt>'Content-Encoding'</tt> header * Once encoding is finished, the value of the <tt>'Content-Encoding'</tt> header
* is set to the target content encoding, as returned by * is set to the target content encoding, as returned by
* {@link #beginEncode(HttpResponse, String)}. * {@link #beginEncode(HttpResponse, CharSequence)}.
* Also, the <tt>'Content-Length'</tt> header is updated to the length of the * Also, the <tt>'Content-Length'</tt> header is updated to the length of the
* encoded content. If there is no supported or allowed encoding in the * encoded content. If there is no supported or allowed encoding in the
* corresponding {@link HttpRequest}'s {@code "Accept-Encoding"} header, * corresponding {@link HttpRequest}'s {@code "Accept-Encoding"} header,
* {@link #beginEncode(HttpResponse, String)} should return {@code null} so that * {@link #beginEncode(HttpResponse, CharSequence)} should return {@code null} so that
* no encoding occurs (i.e. pass-through). * no encoding occurs (i.e. pass-through).
* <p> * <p>
* Please note that this is an abstract class. You have to extend this class * Please note that this is an abstract class. You have to extend this class
* and implement {@link #beginEncode(HttpResponse, String)} properly to make * and implement {@link #beginEncode(HttpResponse, CharSequence)} properly to make
* this class functional. For example, refer to the source code of * this class functional. For example, refer to the source code of
* {@link HttpContentCompressor}. * {@link HttpContentCompressor}.
* <p> * <p>
@ -58,8 +58,8 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec<HttpReque
AWAIT_CONTENT AWAIT_CONTENT
} }
private final Queue<String> acceptEncodingQueue = new ArrayDeque<String>(); private final Queue<CharSequence> acceptEncodingQueue = new ArrayDeque<CharSequence>();
private String acceptEncoding; private CharSequence acceptEncoding;
private EmbeddedChannel encoder; private EmbeddedChannel encoder;
private State state = State.AWAIT_HEADERS; private State state = State.AWAIT_HEADERS;
@ -71,7 +71,7 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec<HttpReque
@Override @Override
protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out)
throws Exception { throws Exception {
String acceptedEncoding = msg.headers().get(HttpHeaders.Names.ACCEPT_ENCODING); CharSequence acceptedEncoding = msg.headers().get(HttpHeaders.Names.ACCEPT_ENCODING);
if (acceptedEncoding == null) { if (acceptedEncoding == null) {
acceptedEncoding = HttpHeaders.Values.IDENTITY; acceptedEncoding = HttpHeaders.Values.IDENTITY;
} }
@ -228,7 +228,7 @@ public abstract class HttpContentEncoder extends MessageToMessageCodec<HttpReque
* {@code null} if {@code acceptEncoding} is unsupported or rejected * {@code null} if {@code acceptEncoding} is unsupported or rejected
* and thus the content should be handled as-is (i.e. no encoding). * and thus the content should be handled as-is (i.e. no encoding).
*/ */
protected abstract Result beginEncode(HttpResponse headers, String acceptEncoding) throws Exception; protected abstract Result beginEncode(HttpResponse headers, CharSequence acceptEncoding) throws Exception;
@Override @Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {

View File

@ -0,0 +1,60 @@
/*
* 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.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
final class HttpHeaderEntity implements CharSequence {
private final String name;
private final int hash;
private final byte[] bytes;
public HttpHeaderEntity(String name) {
this.name = name;
hash = HttpHeaders.hash(name);
bytes = name.getBytes(CharsetUtil.US_ASCII);
}
int hash() {
return hash;
}
@Override
public int length() {
return bytes.length;
}
@Override
public char charAt(int index) {
return (char) bytes[index];
}
@Override
public CharSequence subSequence(int start, int end) {
return new HttpHeaderEntity(name.substring(start, end));
}
@Override
public String toString() {
return name;
}
void encode(ByteBuf buf) {
buf.writeBytes(bytes);
}
}

View File

@ -15,6 +15,8 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import java.text.ParseException; import java.text.ParseException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
@ -25,6 +27,9 @@ import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import static io.netty.handler.codec.http.HttpConstants.CR;
import static io.netty.handler.codec.http.HttpConstants.LF;
/** /**
* Provides the constants for the standard HTTP header names and values and * Provides the constants for the standard HTTP header names and values and
@ -32,14 +37,17 @@ import java.util.Set;
*/ */
public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>> { public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>> {
private static final byte[] HEADER_SEPERATOR = { HttpConstants.COLON, HttpConstants.SP };
private static final byte[] CRLF = { CR, LF };
public static final HttpHeaders EMPTY_HEADERS = new HttpHeaders() { public static final HttpHeaders EMPTY_HEADERS = new HttpHeaders() {
@Override @Override
public String get(String name) { public String get(CharSequence name) {
return null; return null;
} }
@Override @Override
public List<String> getAll(String name) { public List<String> getAll(CharSequence name) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -49,7 +57,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
} }
@Override @Override
public boolean contains(String name) { public boolean contains(CharSequence name) {
return false; return false;
} }
@ -64,27 +72,27 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
} }
@Override @Override
public HttpHeaders add(String name, Object value) { public HttpHeaders add(CharSequence name, Object value) {
throw new UnsupportedOperationException("read only"); throw new UnsupportedOperationException("read only");
} }
@Override @Override
public HttpHeaders add(String name, Iterable<?> values) { public HttpHeaders add(CharSequence name, Iterable<?> values) {
throw new UnsupportedOperationException("read only"); throw new UnsupportedOperationException("read only");
} }
@Override @Override
public HttpHeaders set(String name, Object value) { public HttpHeaders set(CharSequence name, Object value) {
throw new UnsupportedOperationException("read only"); throw new UnsupportedOperationException("read only");
} }
@Override @Override
public HttpHeaders set(String name, Iterable<?> values) { public HttpHeaders set(CharSequence name, Iterable<?> values) {
throw new UnsupportedOperationException("read only"); throw new UnsupportedOperationException("read only");
} }
@Override @Override
public HttpHeaders remove(String name) { public HttpHeaders remove(CharSequence name) {
throw new UnsupportedOperationException("read only"); throw new UnsupportedOperationException("read only");
} }
@ -106,295 +114,302 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
/** /**
* {@code "Accept"} * {@code "Accept"}
*/ */
public static final String ACCEPT = "Accept"; public static final CharSequence ACCEPT = newEntity("Accept");
/** /**
* {@code "Accept-Charset"} * {@code "Accept-Charset"}
*/ */
public static final String ACCEPT_CHARSET = "Accept-Charset"; public static final CharSequence ACCEPT_CHARSET = newEntity("Accept-Charset");
/** /**
* {@code "Accept-Encoding"} * {@code "Accept-Encoding"}
*/ */
public static final String ACCEPT_ENCODING = "Accept-Encoding"; public static final CharSequence ACCEPT_ENCODING = newEntity("Accept-Encoding");
/** /**
* {@code "Accept-Language"} * {@code "Accept-Language"}
*/ */
public static final String ACCEPT_LANGUAGE = "Accept-Language"; public static final CharSequence ACCEPT_LANGUAGE = newEntity("Accept-Language");
/** /**
* {@code "Accept-Ranges"} * {@code "Accept-Ranges"}
*/ */
public static final String ACCEPT_RANGES = "Accept-Ranges"; public static final CharSequence ACCEPT_RANGES = newEntity("Accept-Ranges");
/** /**
* {@code "Accept-Patch"} * {@code "Accept-Patch"}
*/ */
public static final String ACCEPT_PATCH = "Accept-Patch"; public static final CharSequence ACCEPT_PATCH = newEntity("Accept-Patch");
/** /**
* {@code "Access-Control-Allow-Credentials"} * {@code "Access-Control-Allow-Credentials"}
*/ */
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS = "Access-Control-Allow-Credentials"; public static final CharSequence ACCESS_CONTROL_ALLOW_CREDENTIALS =
newEntity("Access-Control-Allow-Credentials");
/** /**
* {@code "Access-Control-Allow-Headers"} * {@code "Access-Control-Allow-Headers"}
*/ */
public static final String ACCESS_CONTROL_ALLOW_HEADERS = "Access-Control-Allow-Headers"; public static final CharSequence ACCESS_CONTROL_ALLOW_HEADERS =
newEntity("Access-Control-Allow-Headers");
/** /**
* {@code "Access-Control-Allow-Methods"} * {@code "Access-Control-Allow-Methods"}
*/ */
public static final String ACCESS_CONTROL_ALLOW_METHODS = "Access-Control-Allow-Methods"; public static final CharSequence ACCESS_CONTROL_ALLOW_METHODS =
newEntity("Access-Control-Allow-Methods");
/** /**
* {@code "Access-Control-Allow-Origin"} * {@code "Access-Control-Allow-Origin"}
*/ */
public static final String ACCESS_CONTROL_ALLOW_ORIGIN = "Access-Control-Allow-Origin"; public static final CharSequence ACCESS_CONTROL_ALLOW_ORIGIN =
newEntity("Access-Control-Allow-Origin");
/** /**
* {@code "Access-Control-Expose-Headers"} * {@code "Access-Control-Expose-Headers"}
*/ */
public static final String ACCESS_CONTROL_EXPOSE_HEADERS = "Access-Control-Expose-Headers"; public static final CharSequence ACCESS_CONTROL_EXPOSE_HEADERS =
newEntity("Access-Control-Expose-Headers");
/** /**
* {@code "Access-Control-Max-Age"} * {@code "Access-Control-Max-Age"}
*/ */
public static final String ACCESS_CONTROL_MAX_AGE = "Access-Control-Max-Age"; public static final CharSequence ACCESS_CONTROL_MAX_AGE = newEntity("Access-Control-Max-Age");
/** /**
* {@code "Access-Control-Request-Headers"} * {@code "Access-Control-Request-Headers"}
*/ */
public static final String ACCESS_CONTROL_REQUEST_HEADERS = "Access-Control-Request-Headers"; public static final CharSequence ACCESS_CONTROL_REQUEST_HEADERS =
newEntity("Access-Control-Request-Headers");
/** /**
* {@code "Access-Control-Request-Method"} * {@code "Access-Control-Request-Method"}
*/ */
public static final String ACCESS_CONTROL_REQUEST_METHOD = "Access-Control-Request-Method"; public static final CharSequence ACCESS_CONTROL_REQUEST_METHOD =
newEntity("Access-Control-Request-Method");
/** /**
* {@code "Age"} * {@code "Age"}
*/ */
public static final String AGE = "Age"; public static final CharSequence AGE = newEntity("Age");
/** /**
* {@code "Allow"} * {@code "Allow"}
*/ */
public static final String ALLOW = "Allow"; public static final CharSequence ALLOW = newEntity("Allow");
/** /**
* {@code "Authorization"} * {@code "Authorization"}
*/ */
public static final String AUTHORIZATION = "Authorization"; public static final CharSequence AUTHORIZATION = newEntity("Authorization");
/** /**
* {@code "Cache-Control"} * {@code "Cache-Control"}
*/ */
public static final String CACHE_CONTROL = "Cache-Control"; public static final CharSequence CACHE_CONTROL = newEntity("Cache-Control");
/** /**
* {@code "Connection"} * {@code "Connection"}
*/ */
public static final String CONNECTION = "Connection"; public static final CharSequence CONNECTION = newEntity("Connection");
/** /**
* {@code "Content-Base"} * {@code "Content-Base"}
*/ */
public static final String CONTENT_BASE = "Content-Base"; public static final CharSequence CONTENT_BASE = newEntity("Content-Base");
/** /**
* {@code "Content-Encoding"} * {@code "Content-Encoding"}
*/ */
public static final String CONTENT_ENCODING = "Content-Encoding"; public static final CharSequence CONTENT_ENCODING = newEntity("Content-Encoding");
/** /**
* {@code "Content-Language"} * {@code "Content-Language"}
*/ */
public static final String CONTENT_LANGUAGE = "Content-Language"; public static final CharSequence CONTENT_LANGUAGE = newEntity("Content-Language");
/** /**
* {@code "Content-Length"} * {@code "Content-Length"}
*/ */
public static final String CONTENT_LENGTH = "Content-Length"; public static final CharSequence CONTENT_LENGTH = newEntity("Content-Length");
/** /**
* {@code "Content-Location"} * {@code "Content-Location"}
*/ */
public static final String CONTENT_LOCATION = "Content-Location"; public static final CharSequence CONTENT_LOCATION = newEntity("Content-Location");
/** /**
* {@code "Content-Transfer-Encoding"} * {@code "Content-Transfer-Encoding"}
*/ */
public static final String CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding"; public static final CharSequence CONTENT_TRANSFER_ENCODING = newEntity("Content-Transfer-Encoding");
/** /**
* {@code "Content-MD5"} * {@code "Content-MD5"}
*/ */
public static final String CONTENT_MD5 = "Content-MD5"; public static final CharSequence CONTENT_MD5 = newEntity("Content-MD5");
/** /**
* {@code "Content-Range"} * {@code "Content-Range"}
*/ */
public static final String CONTENT_RANGE = "Content-Range"; public static final CharSequence CONTENT_RANGE = newEntity("Content-Range");
/** /**
* {@code "Content-Type"} * {@code "Content-Type"}
*/ */
public static final String CONTENT_TYPE = "Content-Type"; public static final CharSequence CONTENT_TYPE = newEntity("Content-Type");
/** /**
* {@code "Cookie"} * {@code "Cookie"}
*/ */
public static final String COOKIE = "Cookie"; public static final CharSequence COOKIE = newEntity("Cookie");
/** /**
* {@code "Date"} * {@code "Date"}
*/ */
public static final String DATE = "Date"; public static final CharSequence DATE = newEntity("Date");
/** /**
* {@code "ETag"} * {@code "ETag"}
*/ */
public static final String ETAG = "ETag"; public static final CharSequence ETAG = newEntity("ETag");
/** /**
* {@code "Expect"} * {@code "Expect"}
*/ */
public static final String EXPECT = "Expect"; public static final CharSequence EXPECT = newEntity("Expect");
/** /**
* {@code "Expires"} * {@code "Expires"}
*/ */
public static final String EXPIRES = "Expires"; public static final CharSequence EXPIRES = newEntity("Expires");
/** /**
* {@code "From"} * {@code "From"}
*/ */
public static final String FROM = "From"; public static final CharSequence FROM = newEntity("From");
/** /**
* {@code "Host"} * {@code "Host"}
*/ */
public static final String HOST = "Host"; public static final CharSequence HOST = newEntity("Host");
/** /**
* {@code "If-Match"} * {@code "If-Match"}
*/ */
public static final String IF_MATCH = "If-Match"; public static final CharSequence IF_MATCH = newEntity("If-Match");
/** /**
* {@code "If-Modified-Since"} * {@code "If-Modified-Since"}
*/ */
public static final String IF_MODIFIED_SINCE = "If-Modified-Since"; public static final CharSequence IF_MODIFIED_SINCE = newEntity("If-Modified-Since");
/** /**
* {@code "If-None-Match"} * {@code "If-None-Match"}
*/ */
public static final String IF_NONE_MATCH = "If-None-Match"; public static final CharSequence IF_NONE_MATCH = newEntity("If-None-Match");
/** /**
* {@code "If-Range"} * {@code "If-Range"}
*/ */
public static final String IF_RANGE = "If-Range"; public static final CharSequence IF_RANGE = newEntity("If-Range");
/** /**
* {@code "If-Unmodified-Since"} * {@code "If-Unmodified-Since"}
*/ */
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since"; public static final CharSequence IF_UNMODIFIED_SINCE = newEntity("If-Unmodified-Since");
/** /**
* {@code "Last-Modified"} * {@code "Last-Modified"}
*/ */
public static final String LAST_MODIFIED = "Last-Modified"; public static final CharSequence LAST_MODIFIED = newEntity("Last-Modified");
/** /**
* {@code "Location"} * {@code "Location"}
*/ */
public static final String LOCATION = "Location"; public static final CharSequence LOCATION = newEntity("Location");
/** /**
* {@code "Max-Forwards"} * {@code "Max-Forwards"}
*/ */
public static final String MAX_FORWARDS = "Max-Forwards"; public static final CharSequence MAX_FORWARDS = newEntity("Max-Forwards");
/** /**
* {@code "Origin"} * {@code "Origin"}
*/ */
public static final String ORIGIN = "Origin"; public static final CharSequence ORIGIN = newEntity("Origin");
/** /**
* {@code "Pragma"} * {@code "Pragma"}
*/ */
public static final String PRAGMA = "Pragma"; public static final CharSequence PRAGMA = newEntity("Pragma");
/** /**
* {@code "Proxy-Authenticate"} * {@code "Proxy-Authenticate"}
*/ */
public static final String PROXY_AUTHENTICATE = "Proxy-Authenticate"; public static final CharSequence PROXY_AUTHENTICATE = newEntity("Proxy-Authenticate");
/** /**
* {@code "Proxy-Authorization"} * {@code "Proxy-Authorization"}
*/ */
public static final String PROXY_AUTHORIZATION = "Proxy-Authorization"; public static final CharSequence PROXY_AUTHORIZATION = newEntity("Proxy-Authorization");
/** /**
* {@code "Range"} * {@code "Range"}
*/ */
public static final String RANGE = "Range"; public static final CharSequence RANGE = newEntity("Range");
/** /**
* {@code "Referer"} * {@code "Referer"}
*/ */
public static final String REFERER = "Referer"; public static final CharSequence REFERER = newEntity("Referer");
/** /**
* {@code "Retry-After"} * {@code "Retry-After"}
*/ */
public static final String RETRY_AFTER = "Retry-After"; public static final CharSequence RETRY_AFTER = newEntity("Retry-After");
/** /**
* {@code "Sec-WebSocket-Key1"} * {@code "Sec-WebSocket-Key1"}
*/ */
public static final String SEC_WEBSOCKET_KEY1 = "Sec-WebSocket-Key1"; public static final CharSequence SEC_WEBSOCKET_KEY1 = newEntity("Sec-WebSocket-Key1");
/** /**
* {@code "Sec-WebSocket-Key2"} * {@code "Sec-WebSocket-Key2"}
*/ */
public static final String SEC_WEBSOCKET_KEY2 = "Sec-WebSocket-Key2"; public static final CharSequence SEC_WEBSOCKET_KEY2 = newEntity("Sec-WebSocket-Key2");
/** /**
* {@code "Sec-WebSocket-Location"} * {@code "Sec-WebSocket-Location"}
*/ */
public static final String SEC_WEBSOCKET_LOCATION = "Sec-WebSocket-Location"; public static final CharSequence SEC_WEBSOCKET_LOCATION = newEntity("Sec-WebSocket-Location");
/** /**
* {@code "Sec-WebSocket-Origin"} * {@code "Sec-WebSocket-Origin"}
*/ */
public static final String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin"; public static final CharSequence SEC_WEBSOCKET_ORIGIN = newEntity("Sec-WebSocket-Origin");
/** /**
* {@code "Sec-WebSocket-Protocol"} * {@code "Sec-WebSocket-Protocol"}
*/ */
public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol"; public static final CharSequence SEC_WEBSOCKET_PROTOCOL = newEntity("Sec-WebSocket-Protocol");
/** /**
* {@code "Sec-WebSocket-Version"} * {@code "Sec-WebSocket-Version"}
*/ */
public static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version"; public static final CharSequence SEC_WEBSOCKET_VERSION = newEntity("Sec-WebSocket-Version");
/** /**
* {@code "Sec-WebSocket-Key"} * {@code "Sec-WebSocket-Key"}
*/ */
public static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key"; public static final CharSequence SEC_WEBSOCKET_KEY = newEntity("Sec-WebSocket-Key");
/** /**
* {@code "Sec-WebSocket-Accept"} * {@code "Sec-WebSocket-Accept"}
*/ */
public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept"; public static final CharSequence SEC_WEBSOCKET_ACCEPT = newEntity("Sec-WebSocket-Accept");
/** /**
* {@code "Server"} * {@code "Server"}
*/ */
public static final String SERVER = "Server"; public static final CharSequence SERVER = newEntity("Server");
/** /**
* {@code "Set-Cookie"} * {@code "Set-Cookie"}
*/ */
public static final String SET_COOKIE = "Set-Cookie"; public static final CharSequence SET_COOKIE = newEntity("Set-Cookie");
/** /**
* {@code "Set-Cookie2"} * {@code "Set-Cookie2"}
*/ */
public static final String SET_COOKIE2 = "Set-Cookie2"; public static final CharSequence SET_COOKIE2 = newEntity("Set-Cookie2");
/** /**
* {@code "TE"} * {@code "TE"}
*/ */
public static final String TE = "TE"; public static final CharSequence TE = newEntity("TE");
/** /**
* {@code "Trailer"} * {@code "Trailer"}
*/ */
public static final String TRAILER = "Trailer"; public static final CharSequence TRAILER = newEntity("Trailer");
/** /**
* {@code "Transfer-Encoding"} * {@code "Transfer-Encoding"}
*/ */
public static final String TRANSFER_ENCODING = "Transfer-Encoding"; public static final CharSequence TRANSFER_ENCODING = newEntity("Transfer-Encoding");
/** /**
* {@code "Upgrade"} * {@code "Upgrade"}
*/ */
public static final String UPGRADE = "Upgrade"; public static final CharSequence UPGRADE = newEntity("Upgrade");
/** /**
* {@code "User-Agent"} * {@code "User-Agent"}
*/ */
public static final String USER_AGENT = "User-Agent"; public static final CharSequence USER_AGENT = newEntity("User-Agent");
/** /**
* {@code "Vary"} * {@code "Vary"}
*/ */
public static final String VARY = "Vary"; public static final CharSequence VARY = newEntity("Vary");
/** /**
* {@code "Via"} * {@code "Via"}
*/ */
public static final String VIA = "Via"; public static final CharSequence VIA = newEntity("Via");
/** /**
* {@code "Warning"} * {@code "Warning"}
*/ */
public static final String WARNING = "Warning"; public static final CharSequence WARNING = newEntity("Warning");
/** /**
* {@code "WebSocket-Location"} * {@code "WebSocket-Location"}
*/ */
public static final String WEBSOCKET_LOCATION = "WebSocket-Location"; public static final CharSequence WEBSOCKET_LOCATION = newEntity("WebSocket-Location");
/** /**
* {@code "WebSocket-Origin"} * {@code "WebSocket-Origin"}
*/ */
public static final String WEBSOCKET_ORIGIN = "WebSocket-Origin"; public static final CharSequence WEBSOCKET_ORIGIN = newEntity("WebSocket-Origin");
/** /**
* {@code "WebSocket-Protocol"} * {@code "WebSocket-Protocol"}
*/ */
public static final String WEBSOCKET_PROTOCOL = "WebSocket-Protocol"; public static final CharSequence WEBSOCKET_PROTOCOL = newEntity("WebSocket-Protocol");
/** /**
* {@code "WWW-Authenticate"} * {@code "WWW-Authenticate"}
*/ */
public static final String WWW_AUTHENTICATE = "WWW-Authenticate"; public static final CharSequence WWW_AUTHENTICATE = newEntity("WWW-Authenticate");
private Names() { private Names() {
} }
@ -407,132 +422,132 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
/** /**
* {@code "application/x-www-form-urlencoded"} * {@code "application/x-www-form-urlencoded"}
*/ */
public static final String APPLICATION_X_WWW_FORM_URLENCODED = public static final CharSequence APPLICATION_X_WWW_FORM_URLENCODED =
"application/x-www-form-urlencoded"; newEntity("application/x-www-form-urlencoded");
/** /**
* {@code "base64"} * {@code "base64"}
*/ */
public static final String BASE64 = "base64"; public static final CharSequence BASE64 = newEntity("base64");
/** /**
* {@code "binary"} * {@code "binary"}
*/ */
public static final String BINARY = "binary"; public static final CharSequence BINARY = newEntity("binary");
/** /**
* {@code "boundary"} * {@code "boundary"}
*/ */
public static final String BOUNDARY = "boundary"; public static final CharSequence BOUNDARY = newEntity("boundary");
/** /**
* {@code "bytes"} * {@code "bytes"}
*/ */
public static final String BYTES = "bytes"; public static final CharSequence BYTES = newEntity("bytes");
/** /**
* {@code "charset"} * {@code "charset"}
*/ */
public static final String CHARSET = "charset"; public static final CharSequence CHARSET = newEntity("charset");
/** /**
* {@code "chunked"} * {@code "chunked"}
*/ */
public static final String CHUNKED = "chunked"; public static final CharSequence CHUNKED = newEntity("chunked");
/** /**
* {@code "close"} * {@code "close"}
*/ */
public static final String CLOSE = "close"; public static final CharSequence CLOSE = newEntity("close");
/** /**
* {@code "compress"} * {@code "compress"}
*/ */
public static final String COMPRESS = "compress"; public static final CharSequence COMPRESS = newEntity("compress");
/** /**
* {@code "100-continue"} * {@code "100-continue"}
*/ */
public static final String CONTINUE = "100-continue"; public static final CharSequence CONTINUE = newEntity("100-continue");
/** /**
* {@code "deflate"} * {@code "deflate"}
*/ */
public static final String DEFLATE = "deflate"; public static final CharSequence DEFLATE = newEntity("deflate");
/** /**
* {@code "gzip"} * {@code "gzip"}
*/ */
public static final String GZIP = "gzip"; public static final CharSequence GZIP = newEntity("gzip");
/** /**
* {@code "identity"} * {@code "identity"}
*/ */
public static final String IDENTITY = "identity"; public static final CharSequence IDENTITY = newEntity("identity");
/** /**
* {@code "keep-alive"} * {@code "keep-alive"}
*/ */
public static final String KEEP_ALIVE = "keep-alive"; public static final CharSequence KEEP_ALIVE = newEntity("keep-alive");
/** /**
* {@code "max-age"} * {@code "max-age"}
*/ */
public static final String MAX_AGE = "max-age"; public static final CharSequence MAX_AGE = newEntity("max-age");
/** /**
* {@code "max-stale"} * {@code "max-stale"}
*/ */
public static final String MAX_STALE = "max-stale"; public static final CharSequence MAX_STALE = newEntity("max-stale");
/** /**
* {@code "min-fresh"} * {@code "min-fresh"}
*/ */
public static final String MIN_FRESH = "min-fresh"; public static final CharSequence MIN_FRESH = newEntity("min-fresh");
/** /**
* {@code "multipart/form-data"} * {@code "multipart/form-data"}
*/ */
public static final String MULTIPART_FORM_DATA = "multipart/form-data"; public static final CharSequence MULTIPART_FORM_DATA = newEntity("multipart/form-data");
/** /**
* {@code "must-revalidate"} * {@code "must-revalidate"}
*/ */
public static final String MUST_REVALIDATE = "must-revalidate"; public static final CharSequence MUST_REVALIDATE = newEntity("must-revalidate");
/** /**
* {@code "no-cache"} * {@code "no-cache"}
*/ */
public static final String NO_CACHE = "no-cache"; public static final CharSequence NO_CACHE = newEntity("no-cache");
/** /**
* {@code "no-store"} * {@code "no-store"}
*/ */
public static final String NO_STORE = "no-store"; public static final CharSequence NO_STORE = newEntity("no-store");
/** /**
* {@code "no-transform"} * {@code "no-transform"}
*/ */
public static final String NO_TRANSFORM = "no-transform"; public static final CharSequence NO_TRANSFORM = newEntity("no-transform");
/** /**
* {@code "none"} * {@code "none"}
*/ */
public static final String NONE = "none"; public static final CharSequence NONE = newEntity("none");
/** /**
* {@code "only-if-cached"} * {@code "only-if-cached"}
*/ */
public static final String ONLY_IF_CACHED = "only-if-cached"; public static final CharSequence ONLY_IF_CACHED = newEntity("only-if-cached");
/** /**
* {@code "private"} * {@code "private"}
*/ */
public static final String PRIVATE = "private"; public static final CharSequence PRIVATE = newEntity("private");
/** /**
* {@code "proxy-revalidate"} * {@code "proxy-revalidate"}
*/ */
public static final String PROXY_REVALIDATE = "proxy-revalidate"; public static final CharSequence PROXY_REVALIDATE = newEntity("proxy-revalidate");
/** /**
* {@code "public"} * {@code "public"}
*/ */
public static final String PUBLIC = "public"; public static final CharSequence PUBLIC = newEntity("public");
/** /**
* {@code "quoted-printable"} * {@code "quoted-printable"}
*/ */
public static final String QUOTED_PRINTABLE = "quoted-printable"; public static final CharSequence QUOTED_PRINTABLE = newEntity("quoted-printable");
/** /**
* {@code "s-maxage"} * {@code "s-maxage"}
*/ */
public static final String S_MAXAGE = "s-maxage"; public static final CharSequence S_MAXAGE = newEntity("s-maxage");
/** /**
* {@code "trailers"} * {@code "trailers"}
*/ */
public static final String TRAILERS = "trailers"; public static final CharSequence TRAILERS = newEntity("trailers");
/** /**
* {@code "Upgrade"} * {@code "Upgrade"}
*/ */
public static final String UPGRADE = "Upgrade"; public static final CharSequence UPGRADE = newEntity("Upgrade");
/** /**
* {@code "WebSocket"} * {@code "WebSocket"}
*/ */
public static final String WEBSOCKET = "WebSocket"; public static final CharSequence WEBSOCKET = newEntity("WebSocket");
private Values() { private Values() {
} }
@ -600,7 +615,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* *
* @return the header value or {@code null} if there is no such header * @return the header value or {@code null} if there is no such header
*/ */
public static String getHeader(HttpMessage message, String name) { public static String getHeader(HttpMessage message, CharSequence name) {
return message.headers().get(name); return message.headers().get(name);
} }
@ -612,7 +627,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @return the header value or the {@code defaultValue} if there is no such * @return the header value or the {@code defaultValue} if there is no such
* header * header
*/ */
public static String getHeader(HttpMessage message, String name, String defaultValue) { public static String getHeader(HttpMessage message, CharSequence name, String defaultValue) {
String value = message.headers().get(name); String value = message.headers().get(name);
if (value == null) { if (value == null) {
return defaultValue; return defaultValue;
@ -628,7 +643,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* and {@link Calendar} which are formatted to the date format defined in * and {@link Calendar} which are formatted to the date format defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
*/ */
public static void setHeader(HttpMessage message, String name, Object value) { public static void setHeader(HttpMessage message, CharSequence name, Object value) {
message.headers().set(name, value); message.headers().set(name, value);
} }
@ -646,7 +661,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* } * }
* </pre> * </pre>
*/ */
public static void setHeader(HttpMessage message, String name, Iterable<?> values) { public static void setHeader(HttpMessage message, CharSequence name, Iterable<?> values) {
message.headers().set(name, values); message.headers().set(name, values);
} }
@ -657,14 +672,14 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* and {@link Calendar} which are formatted to the date format defined in * and {@link Calendar} which are formatted to the date format defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>. * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>.
*/ */
public static void addHeader(HttpMessage message, String name, Object value) { public static void addHeader(HttpMessage message, CharSequence name, Object value) {
message.headers().add(name, value); message.headers().add(name, value);
} }
/** /**
* Removes the header with the specified name. * Removes the header with the specified name.
*/ */
public static void removeHeader(HttpMessage message, String name) { public static void removeHeader(HttpMessage message, CharSequence name) {
message.headers().remove(name); message.headers().remove(name);
} }
@ -684,7 +699,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @throws NumberFormatException * @throws NumberFormatException
* if there is no such header or the header value is not a number * if there is no such header or the header value is not a number
*/ */
public static int getIntHeader(HttpMessage message, String name) { public static int getIntHeader(HttpMessage message, CharSequence name) {
String value = getHeader(message, name); String value = getHeader(message, name);
if (value == null) { if (value == null) {
throw new NumberFormatException("header not found: " + name); throw new NumberFormatException("header not found: " + name);
@ -700,7 +715,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @return the header value or the {@code defaultValue} if there is no such * @return the header value or the {@code defaultValue} if there is no such
* header or the header value is not a number * header or the header value is not a number
*/ */
public static int getIntHeader(HttpMessage message, String name, int defaultValue) { public static int getIntHeader(HttpMessage message, CharSequence name, int defaultValue) {
String value = getHeader(message, name); String value = getHeader(message, name);
if (value == null) { if (value == null) {
return defaultValue; return defaultValue;
@ -717,7 +732,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* Sets a new integer header with the specified name and value. If there * Sets a new integer header with the specified name and value. If there
* is an existing header with the same name, the existing header is removed. * is an existing header with the same name, the existing header is removed.
*/ */
public static void setIntHeader(HttpMessage message, String name, int value) { public static void setIntHeader(HttpMessage message, CharSequence name, int value) {
message.headers().set(name, value); message.headers().set(name, value);
} }
@ -725,14 +740,14 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* Sets a new integer header with the specified name and values. If there * Sets a new integer header with the specified name and values. If there
* is an existing header with the same name, the existing header is removed. * is an existing header with the same name, the existing header is removed.
*/ */
public static void setIntHeader(HttpMessage message, String name, Iterable<Integer> values) { public static void setIntHeader(HttpMessage message, CharSequence name, Iterable<Integer> values) {
message.headers().set(name, values); message.headers().set(name, values);
} }
/** /**
* Adds a new integer header with the specified name and value. * Adds a new integer header with the specified name and value.
*/ */
public static void addIntHeader(HttpMessage message, String name, int value) { public static void addIntHeader(HttpMessage message, CharSequence name, int value) {
message.headers().add(name, value); message.headers().add(name, value);
} }
@ -745,7 +760,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @throws ParseException * @throws ParseException
* if there is no such header or the header value is not a formatted date * if there is no such header or the header value is not a formatted date
*/ */
public static Date getDateHeader(HttpMessage message, String name) throws ParseException { public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException {
String value = getHeader(message, name); String value = getHeader(message, name);
if (value == null) { if (value == null) {
throw new ParseException("header not found: " + name, 0); throw new ParseException("header not found: " + name, 0);
@ -761,7 +776,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @return the header value or the {@code defaultValue} if there is no such * @return the header value or the {@code defaultValue} if there is no such
* header or the header value is not a formatted date * header or the header value is not a formatted date
*/ */
public static Date getDateHeader(HttpMessage message, String name, Date defaultValue) { public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
final String value = getHeader(message, name); final String value = getHeader(message, name);
if (value == null) { if (value == null) {
return defaultValue; return defaultValue;
@ -780,7 +795,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* The specified value is formatted as defined in * The specified value is formatted as defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
*/ */
public static void setDateHeader(HttpMessage message, String name, Date value) { public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
if (value != null) { if (value != null) {
message.headers().set(name, HttpHeaderDateFormat.get().format(value)); message.headers().set(name, HttpHeaderDateFormat.get().format(value));
} else { } else {
@ -794,7 +809,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* The specified values are formatted as defined in * The specified values are formatted as defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
*/ */
public static void setDateHeader(HttpMessage message, String name, Iterable<Date> values) { public static void setDateHeader(HttpMessage message, CharSequence name, Iterable<Date> values) {
message.headers().set(name, values); message.headers().set(name, values);
} }
@ -803,7 +818,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* value is formatted as defined in * value is formatted as defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a> * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
*/ */
public static void addDateHeader(HttpMessage message, String name, Date value) { public static void addDateHeader(HttpMessage message, CharSequence name, Date value) {
message.headers().add(name, value); message.headers().add(name, value);
} }
@ -1010,7 +1025,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* *
* @param headerName The header name being validated * @param headerName The header name being validated
*/ */
static void validateHeaderName(String headerName) { static void validateHeaderName(CharSequence headerName) {
//Check to see if the name is null //Check to see if the name is null
if (headerName == null) { if (headerName == null) {
throw new NullPointerException("Header names cannot be null"); throw new NullPointerException("Header names cannot be null");
@ -1042,7 +1057,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* *
* @param headerValue The value being validated * @param headerValue The value being validated
*/ */
static void validateHeaderValue(String headerValue) { static void validateHeaderValue(CharSequence headerValue) {
//Check to see if the value is null //Check to see if the value is null
if (headerValue == null) { if (headerValue == null) {
throw new NullPointerException("Header values cannot be null"); throw new NullPointerException("Header values cannot be null");
@ -1183,6 +1198,72 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
} }
return true; return true;
} }
static int hash(CharSequence name) {
if (name instanceof HttpHeaderEntity) {
return ((HttpHeaderEntity) name).hash();
}
int h = 0;
for (int i = name.length() - 1; i >= 0; i --) {
char c = name.charAt(i);
if (c >= 'A' && c <= 'Z') {
c += 32;
}
h = 31 * h + c;
}
if (h > 0) {
return h;
} else if (h == Integer.MIN_VALUE) {
return Integer.MAX_VALUE;
} else {
return -h;
}
}
static void encode(HttpHeaders headers, ByteBuf buf) {
if (headers instanceof DefaultHttpHeaders) {
((DefaultHttpHeaders) headers).encode(buf);
} else {
for (Entry<String, String> header: headers) {
encode(header.getKey(), header.getValue(), buf);
}
}
}
static void encode(CharSequence key, CharSequence value, ByteBuf buf) {
encodeAscii(key, buf);
buf.writeBytes(HEADER_SEPERATOR);
encodeAscii(value, buf);
buf.writeBytes(CRLF);
}
public static void encodeAscii(CharSequence seq, ByteBuf buf) {
if (seq instanceof HttpHeaderEntity) {
((HttpHeaderEntity) seq).encode(buf);
} else {
encodeAscii0(seq, buf);
}
}
static void encodeAscii0(CharSequence seq, ByteBuf buf) {
int length = seq.length();
for (int i = 0 ; i < length; i++) {
buf.writeByte((byte) seq.charAt(i));
}
}
/**
* Create a new {@link CharSequence} which is optimized for reuse as {@link HttpHeaders} name or value.
* So if you have a Header name or value that you want to reuse you should make use of this.
*/
public static CharSequence newEntity(String name) {
if (name == null) {
throw new NullPointerException("name");
}
return new HttpHeaderEntity(name);
}
protected HttpHeaders() { } protected HttpHeaders() { }
/** /**
@ -1192,7 +1273,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param name The name of the header to search * @param name The name of the header to search
* @return The first header value or {@code null} if there is no such header * @return The first header value or {@code null} if there is no such header
*/ */
public abstract String get(String name); public abstract String get(CharSequence name);
/** /**
* Returns the values of headers with the specified name * Returns the values of headers with the specified name
@ -1201,7 +1282,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @return A {@link List} of header values which will be empty if no values * @return A {@link List} of header values which will be empty if no values
* are found * are found
*/ */
public abstract List<String> getAll(String name); public abstract List<String> getAll(CharSequence name);
/** /**
* Returns the all headers that this message contains. * Returns the all headers that this message contains.
@ -1217,7 +1298,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param name The name of the header to search for * @param name The name of the header to search for
* @return True if at least one header is found * @return True if at least one header is found
*/ */
public abstract boolean contains(String name); public abstract boolean contains(CharSequence name);
/** /**
* Checks if no header exists. * Checks if no header exists.
@ -1244,7 +1325,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* *
* @return {@code this} * @return {@code this}
*/ */
public abstract HttpHeaders add(String name, Object value); public abstract HttpHeaders add(CharSequence name, Object value);
/** /**
* Adds a new header with the specified name and values. * Adds a new header with the specified name and values.
@ -1263,7 +1344,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param values The values of the headers being set * @param values The values of the headers being set
* @return {@code this} * @return {@code this}
*/ */
public abstract HttpHeaders add(String name, Iterable<?> values); public abstract HttpHeaders add(CharSequence name, Iterable<?> values);
/** /**
* Adds all header entries of the specified {@code headers}. * Adds all header entries of the specified {@code headers}.
@ -1293,7 +1374,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param value The value of the header being set * @param value The value of the header being set
* @return {@code this} * @return {@code this}
*/ */
public abstract HttpHeaders set(String name, Object value); public abstract HttpHeaders set(CharSequence name, Object value);
/** /**
* Sets a header with the specified name and values. * Sets a header with the specified name and values.
@ -1314,7 +1395,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param values The values of the headers being set * @param values The values of the headers being set
* @return {@code this} * @return {@code this}
*/ */
public abstract HttpHeaders set(String name, Iterable<?> values); public abstract HttpHeaders set(CharSequence name, Iterable<?> values);
/** /**
* Cleans the current header entries and copies all header entries of the specified {@code headers}. * Cleans the current header entries and copies all header entries of the specified {@code headers}.
@ -1338,7 +1419,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param name The name of the header to remove * @param name The name of the header to remove
* @return {@code this} * @return {@code this}
*/ */
public abstract HttpHeaders remove(String name); public abstract HttpHeaders remove(CharSequence name);
/** /**
* Removes all headers from this {@link HttpMessage}. * Removes all headers from this {@link HttpMessage}.
@ -1355,7 +1436,7 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
* @param ignoreCaseValue {@code true} if case should be ignored * @param ignoreCaseValue {@code true} if case should be ignored
* @return contains {@code true} if it contains it {@code false} otherwise * @return contains {@code true} if it contains it {@code false} otherwise
*/ */
public boolean contains(String name, String value, boolean ignoreCaseValue) { public boolean contains(CharSequence name, CharSequence value, boolean ignoreCaseValue) {
List<String> values = getAll(name); List<String> values = getAll(name);
if (values.isEmpty()) { if (values.isEmpty()) {
return false; return false;

View File

@ -15,6 +15,9 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -31,7 +34,7 @@ public class HttpMethod implements Comparable<HttpMethod> {
* capabilities of a server, without implying a resource action or initiating a resource * capabilities of a server, without implying a resource action or initiating a resource
* retrieval. * retrieval.
*/ */
public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS"); public static final HttpMethod OPTIONS = new HttpMethod("OPTIONS", true);
/** /**
* The GET getMethod means retrieve whatever information (in the form of an entity) is identified * The GET getMethod means retrieve whatever information (in the form of an entity) is identified
@ -39,49 +42,49 @@ public class HttpMethod implements Comparable<HttpMethod> {
* produced data which shall be returned as the entity in the response and not the source text * produced data which shall be returned as the entity in the response and not the source text
* of the process, unless that text happens to be the output of the process. * of the process, unless that text happens to be the output of the process.
*/ */
public static final HttpMethod GET = new HttpMethod("GET"); public static final HttpMethod GET = new HttpMethod("GET", true);
/** /**
* The HEAD getMethod is identical to GET except that the server MUST NOT return a message-body * The HEAD getMethod is identical to GET except that the server MUST NOT return a message-body
* in the response. * in the response.
*/ */
public static final HttpMethod HEAD = new HttpMethod("HEAD"); public static final HttpMethod HEAD = new HttpMethod("HEAD", true);
/** /**
* The POST getMethod is used to request that the origin server accept the entity enclosed in the * The POST getMethod is used to request that the origin server accept the entity enclosed in the
* request as a new subordinate of the resource identified by the Request-URI in the * request as a new subordinate of the resource identified by the Request-URI in the
* Request-Line. * Request-Line.
*/ */
public static final HttpMethod POST = new HttpMethod("POST"); public static final HttpMethod POST = new HttpMethod("POST", true);
/** /**
* The PUT getMethod requests that the enclosed entity be stored under the supplied Request-URI. * The PUT getMethod requests that the enclosed entity be stored under the supplied Request-URI.
*/ */
public static final HttpMethod PUT = new HttpMethod("PUT"); public static final HttpMethod PUT = new HttpMethod("PUT", true);
/** /**
* The PATCH getMethod requests that a set of changes described in the * The PATCH getMethod requests that a set of changes described in the
* request entity be applied to the resource identified by the Request-URI. * request entity be applied to the resource identified by the Request-URI.
*/ */
public static final HttpMethod PATCH = new HttpMethod("PATCH"); public static final HttpMethod PATCH = new HttpMethod("PATCH", true);
/** /**
* The DELETE getMethod requests that the origin server delete the resource identified by the * The DELETE getMethod requests that the origin server delete the resource identified by the
* Request-URI. * Request-URI.
*/ */
public static final HttpMethod DELETE = new HttpMethod("DELETE"); public static final HttpMethod DELETE = new HttpMethod("DELETE", true);
/** /**
* The TRACE getMethod is used to invoke a remote, application-layer loop- back of the request * The TRACE getMethod is used to invoke a remote, application-layer loop- back of the request
* message. * message.
*/ */
public static final HttpMethod TRACE = new HttpMethod("TRACE"); public static final HttpMethod TRACE = new HttpMethod("TRACE", true);
/** /**
* This specification reserves the getMethod name CONNECT for use with a proxy that can dynamically * This specification reserves the getMethod name CONNECT for use with a proxy that can dynamically
* switch to being a tunnel * switch to being a tunnel
*/ */
public static final HttpMethod CONNECT = new HttpMethod("CONNECT"); public static final HttpMethod CONNECT = new HttpMethod("CONNECT", true);
private static final Map<String, HttpMethod> methodMap = private static final Map<String, HttpMethod> methodMap =
new HashMap<String, HttpMethod>(); new HashMap<String, HttpMethod>();
@ -122,6 +125,7 @@ public class HttpMethod implements Comparable<HttpMethod> {
} }
private final String name; private final String name;
private final byte[] bytes;
/** /**
* Creates a new HTTP getMethod with the specified name. You will not need to * Creates a new HTTP getMethod with the specified name. You will not need to
@ -131,6 +135,10 @@ public class HttpMethod implements Comparable<HttpMethod> {
* <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a> * <a href="http://en.wikipedia.org/wiki/Internet_Content_Adaptation_Protocol">ICAP</a>
*/ */
public HttpMethod(String name) { public HttpMethod(String name) {
this(name, false);
}
private HttpMethod(String name, boolean bytes) {
if (name == null) { if (name == null) {
throw new NullPointerException("name"); throw new NullPointerException("name");
} }
@ -142,12 +150,17 @@ public class HttpMethod implements Comparable<HttpMethod> {
for (int i = 0; i < name.length(); i ++) { for (int i = 0; i < name.length(); i ++) {
if (Character.isISOControl(name.charAt(i)) || if (Character.isISOControl(name.charAt(i)) ||
Character.isWhitespace(name.charAt(i))) { Character.isWhitespace(name.charAt(i))) {
throw new IllegalArgumentException("invalid character in name"); throw new IllegalArgumentException("invalid character in name");
} }
} }
this.name = name; this.name = name;
if (bytes) {
this.bytes = name.getBytes(CharsetUtil.US_ASCII);
} else {
this.bytes = null;
}
} }
/** /**
@ -181,4 +194,12 @@ public class HttpMethod implements Comparable<HttpMethod> {
public int compareTo(HttpMethod o) { public int compareTo(HttpMethod o) {
return name().compareTo(o.name()); return name().compareTo(o.name());
} }
void encode(ByteBuf buf) {
if (bytes == null) {
HttpHeaders.encodeAscii0(name, buf);
} else {
buf.writeBytes(bytes);
}
}
} }

View File

@ -23,7 +23,6 @@ import io.netty.util.CharsetUtil;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
import java.util.List; import java.util.List;
import java.util.Map;
import static io.netty.buffer.Unpooled.*; import static io.netty.buffer.Unpooled.*;
import static io.netty.handler.codec.http.HttpConstants.*; import static io.netty.handler.codec.http.HttpConstants.*;
@ -45,7 +44,6 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
private static final byte[] CRLF = { CR, LF }; private static final byte[] CRLF = { CR, LF };
private static final byte[] ZERO_CRLF = { '0', CR, LF }; private static final byte[] ZERO_CRLF = { '0', CR, LF };
private static final byte[] ZERO_CRLF_CRLF = { '0', CR, LF, CR, LF }; private static final byte[] ZERO_CRLF_CRLF = { '0', CR, LF, CR, LF };
private static final byte[] HEADER_SEPARATOR = { COLON, SP };
private static final ByteBuf CRLF_BUF = unreleasableBuffer(directBuffer(CRLF.length).writeBytes(CRLF)); private static final ByteBuf CRLF_BUF = unreleasableBuffer(directBuffer(CRLF.length).writeBytes(CRLF));
private static final ByteBuf ZERO_CRLF_CRLF_BUF = unreleasableBuffer(directBuffer(ZERO_CRLF_CRLF.length) private static final ByteBuf ZERO_CRLF_CRLF_BUF = unreleasableBuffer(directBuffer(ZERO_CRLF_CRLF.length)
.writeBytes(ZERO_CRLF_CRLF)); .writeBytes(ZERO_CRLF_CRLF));
@ -70,7 +68,7 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
ByteBuf buf = ctx.alloc().buffer(); ByteBuf buf = ctx.alloc().buffer();
// Encode the message. // Encode the message.
encodeInitialLine(buf, m); encodeInitialLine(buf, m);
encodeHeaders(buf, m.headers()); HttpHeaders.encode(m.headers(), buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
out.add(buf); out.add(buf);
state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK; state = HttpHeaders.isTransferEncodingChunked(m) ? ST_CONTENT_CHUNK : ST_CONTENT_NON_CHUNK;
@ -119,7 +117,7 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
} else { } else {
ByteBuf buf = ctx.alloc().buffer(); ByteBuf buf = ctx.alloc().buffer();
buf.writeBytes(ZERO_CRLF); buf.writeBytes(ZERO_CRLF);
encodeHeaders(buf, headers); HttpHeaders.encode(headers, buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
out.add(buf); out.add(buf);
} }
@ -165,24 +163,5 @@ public abstract class HttpObjectEncoder<H extends HttpMessage> extends MessageTo
throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg)); throw new IllegalStateException("unexpected message type: " + StringUtil.simpleClassName(msg));
} }
private static void encodeHeaders(ByteBuf buf, HttpHeaders headers) {
for (Map.Entry<String, String> h: headers) {
encodeHeader(buf, h.getKey(), h.getValue());
}
}
private static void encodeHeader(ByteBuf buf, String header, String value) {
encodeAscii(header, buf);
buf.writeBytes(HEADER_SEPARATOR);
encodeAscii(value, buf);
buf.writeBytes(CRLF);
}
protected static void encodeAscii(String s, ByteBuf buf) {
for (int i = 0; i < s.length(); i++) {
buf.writeByte(s.charAt(i));
}
}
protected abstract void encodeInitialLine(ByteBuf buf, H message) throws Exception; protected abstract void encodeInitialLine(ByteBuf buf, H message) throws Exception;
} }

View File

@ -35,7 +35,7 @@ public class HttpRequestEncoder extends HttpObjectEncoder<HttpRequest> {
@Override @Override
protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception { protected void encodeInitialLine(ByteBuf buf, HttpRequest request) throws Exception {
encodeAscii(request.getMethod().toString(), buf); request.getMethod().encode(buf);
buf.writeByte(SP); buf.writeByte(SP);
// Add / as absolute path if no is present. // Add / as absolute path if no is present.
@ -57,7 +57,7 @@ public class HttpRequestEncoder extends HttpObjectEncoder<HttpRequest> {
buf.writeBytes(uri.getBytes(CharsetUtil.UTF_8)); buf.writeBytes(uri.getBytes(CharsetUtil.UTF_8));
buf.writeByte(SP); buf.writeByte(SP);
encodeAscii(request.getProtocolVersion().toString(), buf); request.getProtocolVersion().encode(buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
} }
} }

View File

@ -33,11 +33,9 @@ public class HttpResponseEncoder extends HttpObjectEncoder<HttpResponse> {
@Override @Override
protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception { protected void encodeInitialLine(ByteBuf buf, HttpResponse response) throws Exception {
encodeAscii(response.getProtocolVersion().toString(), buf); response.getProtocolVersion().encode(buf);
buf.writeByte(SP); buf.writeByte(SP);
encodeAscii(String.valueOf(response.getStatus().code()), buf); response.getStatus().encode(buf);
buf.writeByte(SP);
encodeAscii(String.valueOf(response.getStatus().reasonPhrase()), buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
} }
} }

View File

@ -15,6 +15,11 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpConstants.SP;
/** /**
* The response code and its description of HTTP or its derived protocols, such as * The response code and its description of HTTP or its derived protocols, such as
* <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and * <a href="http://en.wikipedia.org/wiki/Real_Time_Streaming_Protocol">RTSP</a> and
@ -25,282 +30,290 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
/** /**
* 100 Continue * 100 Continue
*/ */
public static final HttpResponseStatus CONTINUE = new HttpResponseStatus(100, "Continue"); public static final HttpResponseStatus CONTINUE = new HttpResponseStatus(100, "Continue", true);
/** /**
* 101 Switching Protocols * 101 Switching Protocols
*/ */
public static final HttpResponseStatus SWITCHING_PROTOCOLS = new HttpResponseStatus(101, "Switching Protocols"); public static final HttpResponseStatus SWITCHING_PROTOCOLS =
new HttpResponseStatus(101, "Switching Protocols", true);
/** /**
* 102 Processing (WebDAV, RFC2518) * 102 Processing (WebDAV, RFC2518)
*/ */
public static final HttpResponseStatus PROCESSING = new HttpResponseStatus(102, "Processing"); public static final HttpResponseStatus PROCESSING = new HttpResponseStatus(102, "Processing", true);
/** /**
* 200 OK * 200 OK
*/ */
public static final HttpResponseStatus OK = new HttpResponseStatus(200, "OK"); public static final HttpResponseStatus OK = new HttpResponseStatus(200, "OK", true);
/** /**
* 201 Created * 201 Created
*/ */
public static final HttpResponseStatus CREATED = new HttpResponseStatus(201, "Created"); public static final HttpResponseStatus CREATED = new HttpResponseStatus(201, "Created", true);
/** /**
* 202 Accepted * 202 Accepted
*/ */
public static final HttpResponseStatus ACCEPTED = new HttpResponseStatus(202, "Accepted"); public static final HttpResponseStatus ACCEPTED = new HttpResponseStatus(202, "Accepted", true);
/** /**
* 203 Non-Authoritative Information (since HTTP/1.1) * 203 Non-Authoritative Information (since HTTP/1.1)
*/ */
public static final HttpResponseStatus NON_AUTHORITATIVE_INFORMATION = public static final HttpResponseStatus NON_AUTHORITATIVE_INFORMATION =
new HttpResponseStatus(203, "Non-Authoritative Information"); new HttpResponseStatus(203, "Non-Authoritative Information", true);
/** /**
* 204 No Content * 204 No Content
*/ */
public static final HttpResponseStatus NO_CONTENT = new HttpResponseStatus(204, "No Content"); public static final HttpResponseStatus NO_CONTENT = new HttpResponseStatus(204, "No Content", true);
/** /**
* 205 Reset Content * 205 Reset Content
*/ */
public static final HttpResponseStatus RESET_CONTENT = new HttpResponseStatus(205, "Reset Content"); public static final HttpResponseStatus RESET_CONTENT = new HttpResponseStatus(205, "Reset Content", true);
/** /**
* 206 Partial Content * 206 Partial Content
*/ */
public static final HttpResponseStatus PARTIAL_CONTENT = new HttpResponseStatus(206, "Partial Content"); public static final HttpResponseStatus PARTIAL_CONTENT = new HttpResponseStatus(206, "Partial Content", true);
/** /**
* 207 Multi-Status (WebDAV, RFC2518) * 207 Multi-Status (WebDAV, RFC2518)
*/ */
public static final HttpResponseStatus MULTI_STATUS = new HttpResponseStatus(207, "Multi-Status"); public static final HttpResponseStatus MULTI_STATUS = new HttpResponseStatus(207, "Multi-Status", true);
/** /**
* 300 Multiple Choices * 300 Multiple Choices
*/ */
public static final HttpResponseStatus MULTIPLE_CHOICES = new HttpResponseStatus(300, "Multiple Choices"); public static final HttpResponseStatus MULTIPLE_CHOICES = new HttpResponseStatus(300, "Multiple Choices", true);
/** /**
* 301 Moved Permanently * 301 Moved Permanently
*/ */
public static final HttpResponseStatus MOVED_PERMANENTLY = new HttpResponseStatus(301, "Moved Permanently"); public static final HttpResponseStatus MOVED_PERMANENTLY = new HttpResponseStatus(301, "Moved Permanently", true);
/** /**
* 302 Found * 302 Found
*/ */
public static final HttpResponseStatus FOUND = new HttpResponseStatus(302, "Found"); public static final HttpResponseStatus FOUND = new HttpResponseStatus(302, "Found", true);
/** /**
* 303 See Other (since HTTP/1.1) * 303 See Other (since HTTP/1.1)
*/ */
public static final HttpResponseStatus SEE_OTHER = new HttpResponseStatus(303, "See Other"); public static final HttpResponseStatus SEE_OTHER = new HttpResponseStatus(303, "See Other", true);
/** /**
* 304 Not Modified * 304 Not Modified
*/ */
public static final HttpResponseStatus NOT_MODIFIED = new HttpResponseStatus(304, "Not Modified"); public static final HttpResponseStatus NOT_MODIFIED = new HttpResponseStatus(304, "Not Modified", true);
/** /**
* 305 Use Proxy (since HTTP/1.1) * 305 Use Proxy (since HTTP/1.1)
*/ */
public static final HttpResponseStatus USE_PROXY = new HttpResponseStatus(305, "Use Proxy"); public static final HttpResponseStatus USE_PROXY = new HttpResponseStatus(305, "Use Proxy", true);
/** /**
* 307 Temporary Redirect (since HTTP/1.1) * 307 Temporary Redirect (since HTTP/1.1)
*/ */
public static final HttpResponseStatus TEMPORARY_REDIRECT = new HttpResponseStatus(307, "Temporary Redirect"); public static final HttpResponseStatus TEMPORARY_REDIRECT = new HttpResponseStatus(307, "Temporary Redirect", true);
/** /**
* 400 Bad Request * 400 Bad Request
*/ */
public static final HttpResponseStatus BAD_REQUEST = new HttpResponseStatus(400, "Bad Request"); public static final HttpResponseStatus BAD_REQUEST = new HttpResponseStatus(400, "Bad Request", true);
/** /**
* 401 Unauthorized * 401 Unauthorized
*/ */
public static final HttpResponseStatus UNAUTHORIZED = new HttpResponseStatus(401, "Unauthorized"); public static final HttpResponseStatus UNAUTHORIZED = new HttpResponseStatus(401, "Unauthorized", true);
/** /**
* 402 Payment Required * 402 Payment Required
*/ */
public static final HttpResponseStatus PAYMENT_REQUIRED = new HttpResponseStatus(402, "Payment Required"); public static final HttpResponseStatus PAYMENT_REQUIRED = new HttpResponseStatus(402, "Payment Required", true);
/** /**
* 403 Forbidden * 403 Forbidden
*/ */
public static final HttpResponseStatus FORBIDDEN = new HttpResponseStatus(403, "Forbidden"); public static final HttpResponseStatus FORBIDDEN = new HttpResponseStatus(403, "Forbidden", true);
/** /**
* 404 Not Found * 404 Not Found
*/ */
public static final HttpResponseStatus NOT_FOUND = new HttpResponseStatus(404, "Not Found"); public static final HttpResponseStatus NOT_FOUND = new HttpResponseStatus(404, "Not Found", true);
/** /**
* 405 Method Not Allowed * 405 Method Not Allowed
*/ */
public static final HttpResponseStatus METHOD_NOT_ALLOWED = new HttpResponseStatus(405, "Method Not Allowed"); public static final HttpResponseStatus METHOD_NOT_ALLOWED = new HttpResponseStatus(405, "Method Not Allowed", true);
/** /**
* 406 Not Acceptable * 406 Not Acceptable
*/ */
public static final HttpResponseStatus NOT_ACCEPTABLE = new HttpResponseStatus(406, "Not Acceptable"); public static final HttpResponseStatus NOT_ACCEPTABLE = new HttpResponseStatus(406, "Not Acceptable", true);
/** /**
* 407 Proxy Authentication Required * 407 Proxy Authentication Required
*/ */
public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED = public static final HttpResponseStatus PROXY_AUTHENTICATION_REQUIRED =
new HttpResponseStatus(407, "Proxy Authentication Required"); new HttpResponseStatus(407, "Proxy Authentication Required", true);
/** /**
* 408 Request Timeout * 408 Request Timeout
*/ */
public static final HttpResponseStatus REQUEST_TIMEOUT = new HttpResponseStatus(408, "Request Timeout"); public static final HttpResponseStatus REQUEST_TIMEOUT = new HttpResponseStatus(408, "Request Timeout", true);
/** /**
* 409 Conflict * 409 Conflict
*/ */
public static final HttpResponseStatus CONFLICT = new HttpResponseStatus(409, "Conflict"); public static final HttpResponseStatus CONFLICT = new HttpResponseStatus(409, "Conflict", true);
/** /**
* 410 Gone * 410 Gone
*/ */
public static final HttpResponseStatus GONE = new HttpResponseStatus(410, "Gone"); public static final HttpResponseStatus GONE = new HttpResponseStatus(410, "Gone", true);
/** /**
* 411 Length Required * 411 Length Required
*/ */
public static final HttpResponseStatus LENGTH_REQUIRED = new HttpResponseStatus(411, "Length Required"); public static final HttpResponseStatus LENGTH_REQUIRED = new HttpResponseStatus(411, "Length Required", true);
/** /**
* 412 Precondition Failed * 412 Precondition Failed
*/ */
public static final HttpResponseStatus PRECONDITION_FAILED = new HttpResponseStatus(412, "Precondition Failed"); public static final HttpResponseStatus PRECONDITION_FAILED =
new HttpResponseStatus(412, "Precondition Failed", true);
/** /**
* 413 Request Entity Too Large * 413 Request Entity Too Large
*/ */
public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE = public static final HttpResponseStatus REQUEST_ENTITY_TOO_LARGE =
new HttpResponseStatus(413, "Request Entity Too Large"); new HttpResponseStatus(413, "Request Entity Too Large", true);
/** /**
* 414 Request-URI Too Long * 414 Request-URI Too Long
*/ */
public static final HttpResponseStatus REQUEST_URI_TOO_LONG = new HttpResponseStatus(414, "Request-URI Too Long"); public static final HttpResponseStatus REQUEST_URI_TOO_LONG =
new HttpResponseStatus(414, "Request-URI Too Long", true);
/** /**
* 415 Unsupported Media Type * 415 Unsupported Media Type
*/ */
public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE = public static final HttpResponseStatus UNSUPPORTED_MEDIA_TYPE =
new HttpResponseStatus(415, "Unsupported Media Type"); new HttpResponseStatus(415, "Unsupported Media Type", true);
/** /**
* 416 Requested Range Not Satisfiable * 416 Requested Range Not Satisfiable
*/ */
public static final HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE = public static final HttpResponseStatus REQUESTED_RANGE_NOT_SATISFIABLE =
new HttpResponseStatus(416, "Requested Range Not Satisfiable"); new HttpResponseStatus(416, "Requested Range Not Satisfiable", true);
/** /**
* 417 Expectation Failed * 417 Expectation Failed
*/ */
public static final HttpResponseStatus EXPECTATION_FAILED = new HttpResponseStatus(417, "Expectation Failed"); public static final HttpResponseStatus EXPECTATION_FAILED = new HttpResponseStatus(417, "Expectation Failed", true);
/** /**
* 422 Unprocessable Entity (WebDAV, RFC4918) * 422 Unprocessable Entity (WebDAV, RFC4918)
*/ */
public static final HttpResponseStatus UNPROCESSABLE_ENTITY = new HttpResponseStatus(422, "Unprocessable Entity"); public static final HttpResponseStatus UNPROCESSABLE_ENTITY =
new HttpResponseStatus(422, "Unprocessable Entity", true);
/** /**
* 423 Locked (WebDAV, RFC4918) * 423 Locked (WebDAV, RFC4918)
*/ */
public static final HttpResponseStatus LOCKED = new HttpResponseStatus(423, "Locked"); public static final HttpResponseStatus LOCKED = new HttpResponseStatus(423, "Locked", true);
/** /**
* 424 Failed Dependency (WebDAV, RFC4918) * 424 Failed Dependency (WebDAV, RFC4918)
*/ */
public static final HttpResponseStatus FAILED_DEPENDENCY = new HttpResponseStatus(424, "Failed Dependency"); public static final HttpResponseStatus FAILED_DEPENDENCY = new HttpResponseStatus(424, "Failed Dependency", true);
/** /**
* 425 Unordered Collection (WebDAV, RFC3648) * 425 Unordered Collection (WebDAV, RFC3648)
*/ */
public static final HttpResponseStatus UNORDERED_COLLECTION = new HttpResponseStatus(425, "Unordered Collection"); public static final HttpResponseStatus UNORDERED_COLLECTION =
new HttpResponseStatus(425, "Unordered Collection", true);
/** /**
* 426 Upgrade Required (RFC2817) * 426 Upgrade Required (RFC2817)
*/ */
public static final HttpResponseStatus UPGRADE_REQUIRED = new HttpResponseStatus(426, "Upgrade Required"); public static final HttpResponseStatus UPGRADE_REQUIRED = new HttpResponseStatus(426, "Upgrade Required", true);
/** /**
* 428 Precondition Required (RFC6585) * 428 Precondition Required (RFC6585)
*/ */
public static final HttpResponseStatus PRECONDITION_REQUIRED = new HttpResponseStatus(428, "Precondition Required"); public static final HttpResponseStatus PRECONDITION_REQUIRED =
new HttpResponseStatus(428, "Precondition Required", true);
/** /**
* 429 Too Many Requests (RFC6585) * 429 Too Many Requests (RFC6585)
*/ */
public static final HttpResponseStatus TOO_MANY_REQUESTS = new HttpResponseStatus(429, "Too Many Requests"); public static final HttpResponseStatus TOO_MANY_REQUESTS = new HttpResponseStatus(429, "Too Many Requests", true);
/** /**
* 431 Request Header Fields Too Large (RFC6585) * 431 Request Header Fields Too Large (RFC6585)
*/ */
public static final HttpResponseStatus REQUEST_HEADER_FIELDS_TOO_LARGE = public static final HttpResponseStatus REQUEST_HEADER_FIELDS_TOO_LARGE =
new HttpResponseStatus(431, "Request Header Fields Too Large"); new HttpResponseStatus(431, "Request Header Fields Too Large", true);
/** /**
* 500 Internal Server Error * 500 Internal Server Error
*/ */
public static final HttpResponseStatus INTERNAL_SERVER_ERROR = public static final HttpResponseStatus INTERNAL_SERVER_ERROR =
new HttpResponseStatus(500, "Internal Server Error"); new HttpResponseStatus(500, "Internal Server Error", true);
/** /**
* 501 Not Implemented * 501 Not Implemented
*/ */
public static final HttpResponseStatus NOT_IMPLEMENTED = new HttpResponseStatus(501, "Not Implemented"); public static final HttpResponseStatus NOT_IMPLEMENTED = new HttpResponseStatus(501, "Not Implemented", true);
/** /**
* 502 Bad Gateway * 502 Bad Gateway
*/ */
public static final HttpResponseStatus BAD_GATEWAY = new HttpResponseStatus(502, "Bad Gateway"); public static final HttpResponseStatus BAD_GATEWAY = new HttpResponseStatus(502, "Bad Gateway", true);
/** /**
* 503 Service Unavailable * 503 Service Unavailable
*/ */
public static final HttpResponseStatus SERVICE_UNAVAILABLE = new HttpResponseStatus(503, "Service Unavailable"); public static final HttpResponseStatus SERVICE_UNAVAILABLE =
new HttpResponseStatus(503, "Service Unavailable", true);
/** /**
* 504 Gateway Timeout * 504 Gateway Timeout
*/ */
public static final HttpResponseStatus GATEWAY_TIMEOUT = new HttpResponseStatus(504, "Gateway Timeout"); public static final HttpResponseStatus GATEWAY_TIMEOUT = new HttpResponseStatus(504, "Gateway Timeout", true);
/** /**
* 505 HTTP Version Not Supported * 505 HTTP Version Not Supported
*/ */
public static final HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED = public static final HttpResponseStatus HTTP_VERSION_NOT_SUPPORTED =
new HttpResponseStatus(505, "HTTP Version Not Supported"); new HttpResponseStatus(505, "HTTP Version Not Supported", true);
/** /**
* 506 Variant Also Negotiates (RFC2295) * 506 Variant Also Negotiates (RFC2295)
*/ */
public static final HttpResponseStatus VARIANT_ALSO_NEGOTIATES = public static final HttpResponseStatus VARIANT_ALSO_NEGOTIATES =
new HttpResponseStatus(506, "Variant Also Negotiates"); new HttpResponseStatus(506, "Variant Also Negotiates", true);
/** /**
* 507 Insufficient Storage (WebDAV, RFC4918) * 507 Insufficient Storage (WebDAV, RFC4918)
*/ */
public static final HttpResponseStatus INSUFFICIENT_STORAGE = new HttpResponseStatus(507, "Insufficient Storage"); public static final HttpResponseStatus INSUFFICIENT_STORAGE =
new HttpResponseStatus(507, "Insufficient Storage", true);
/** /**
* 510 Not Extended (RFC2774) * 510 Not Extended (RFC2774)
*/ */
public static final HttpResponseStatus NOT_EXTENDED = new HttpResponseStatus(510, "Not Extended"); public static final HttpResponseStatus NOT_EXTENDED = new HttpResponseStatus(510, "Not Extended", true);
/** /**
* 511 Network Authentication Required (RFC6585) * 511 Network Authentication Required (RFC6585)
*/ */
public static final HttpResponseStatus NETWORK_AUTHENTICATION_REQUIRED = public static final HttpResponseStatus NETWORK_AUTHENTICATION_REQUIRED =
new HttpResponseStatus(511, "Network Authentication Required"); new HttpResponseStatus(511, "Network Authentication Required", true);
/** /**
* Returns the {@link HttpResponseStatus} represented by the specified code. * Returns the {@link HttpResponseStatus} represented by the specified code.
@ -443,12 +456,17 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
private final int code; private final int code;
private final String reasonPhrase; private final String reasonPhrase;
private final byte[] bytes;
/** /**
* Creates a new instance with the specified {@code code} and its * Creates a new instance with the specified {@code code} and its
* {@code reasonPhrase}. * {@code reasonPhrase}.
*/ */
public HttpResponseStatus(int code, String reasonPhrase) { public HttpResponseStatus(int code, String reasonPhrase) {
this(code, reasonPhrase, false);
}
private HttpResponseStatus(int code, String reasonPhrase, boolean bytes) {
if (code < 0) { if (code < 0) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"code: " + code + " (expected: 0+)"); "code: " + code + " (expected: 0+)");
@ -462,15 +480,20 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
char c = reasonPhrase.charAt(i); char c = reasonPhrase.charAt(i);
// Check prohibited characters. // Check prohibited characters.
switch (c) { switch (c) {
case '\n': case '\r': case '\n': case '\r':
throw new IllegalArgumentException( throw new IllegalArgumentException(
"reasonPhrase contains one of the following prohibited characters: " + "reasonPhrase contains one of the following prohibited characters: " +
"\\r\\n: " + reasonPhrase); "\\r\\n: " + reasonPhrase);
} }
} }
this.code = code; this.code = code;
this.reasonPhrase = reasonPhrase; this.reasonPhrase = reasonPhrase;
if (bytes) {
this.bytes = (code + " " + reasonPhrase).getBytes(CharsetUtil.US_ASCII);
} else {
this.bytes = null;
}
} }
/** /**
@ -514,4 +537,14 @@ public class HttpResponseStatus implements Comparable<HttpResponseStatus> {
buf.append(reasonPhrase); buf.append(reasonPhrase);
return buf.toString(); return buf.toString();
} }
void encode(ByteBuf buf) {
if (bytes == null) {
HttpHeaders.encodeAscii0(String.valueOf(code()), buf);
buf.writeByte(SP);
HttpHeaders.encodeAscii0(String.valueOf(reasonPhrase()), buf);
} else {
buf.writeBytes(bytes);
}
}
} }

View File

@ -15,6 +15,9 @@
*/ */
package io.netty.handler.codec.http; package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.util.CharsetUtil;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -34,12 +37,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
/** /**
* HTTP/1.0 * HTTP/1.0
*/ */
public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false); public static final HttpVersion HTTP_1_0 = new HttpVersion("HTTP", 1, 0, false, true);
/** /**
* HTTP/1.1 * HTTP/1.1
*/ */
public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true); public static final HttpVersion HTTP_1_1 = new HttpVersion("HTTP", 1, 1, true, true);
/** /**
* Returns an existing or new {@link HttpVersion} instance which matches to * Returns an existing or new {@link HttpVersion} instance which matches to
@ -90,6 +93,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
private final int minorVersion; private final int minorVersion;
private final String text; private final String text;
private final boolean keepAliveDefault; private final boolean keepAliveDefault;
private final byte[] bytes;
/** /**
* Creates a new HTTP version with the specified version string. You will * Creates a new HTTP version with the specified version string. You will
@ -122,6 +126,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
minorVersion = Integer.parseInt(m.group(3)); minorVersion = Integer.parseInt(m.group(3));
this.text = protocolName + '/' + majorVersion + '.' + minorVersion; this.text = protocolName + '/' + majorVersion + '.' + minorVersion;
this.keepAliveDefault = keepAliveDefault; this.keepAliveDefault = keepAliveDefault;
bytes = null;
} }
/** /**
@ -138,6 +143,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
public HttpVersion( public HttpVersion(
String protocolName, int majorVersion, int minorVersion, String protocolName, int majorVersion, int minorVersion,
boolean keepAliveDefault) { boolean keepAliveDefault) {
this(protocolName, majorVersion, minorVersion, keepAliveDefault, false);
}
private HttpVersion(
String protocolName, int majorVersion, int minorVersion,
boolean keepAliveDefault, boolean bytes) {
if (protocolName == null) { if (protocolName == null) {
throw new NullPointerException("protocolName"); throw new NullPointerException("protocolName");
} }
@ -149,7 +160,7 @@ public class HttpVersion implements Comparable<HttpVersion> {
for (int i = 0; i < protocolName.length(); i ++) { for (int i = 0; i < protocolName.length(); i ++) {
if (Character.isISOControl(protocolName.charAt(i)) || if (Character.isISOControl(protocolName.charAt(i)) ||
Character.isWhitespace(protocolName.charAt(i))) { Character.isWhitespace(protocolName.charAt(i))) {
throw new IllegalArgumentException("invalid character in protocolName"); throw new IllegalArgumentException("invalid character in protocolName");
} }
} }
@ -166,6 +177,11 @@ public class HttpVersion implements Comparable<HttpVersion> {
this.minorVersion = minorVersion; this.minorVersion = minorVersion;
text = protocolName + '/' + majorVersion + '.' + minorVersion; text = protocolName + '/' + majorVersion + '.' + minorVersion;
this.keepAliveDefault = keepAliveDefault; this.keepAliveDefault = keepAliveDefault;
if (bytes) {
this.bytes = text.getBytes(CharsetUtil.US_ASCII);
} else {
this.bytes = null;
}
} }
/** /**
@ -244,4 +260,12 @@ public class HttpVersion implements Comparable<HttpVersion> {
return minorVersion() - o.minorVersion(); return minorVersion() - o.minorVersion();
} }
void encode(ByteBuf buf) {
if (bytes == null) {
HttpHeaders.encodeAscii0(text, buf);
} else {
buf.writeBytes(bytes);
}
}
} }

View File

@ -18,7 +18,7 @@ package io.netty.handler.codec.http.multipart;
import java.io.Serializable; import java.io.Serializable;
import java.util.Comparator; import java.util.Comparator;
final class CaseIgnoringComparator implements Comparator<String>, Serializable { final class CaseIgnoringComparator implements Comparator<CharSequence>, Serializable {
private static final long serialVersionUID = 4582133183775373862L; private static final long serialVersionUID = 4582133183775373862L;
@ -28,8 +28,26 @@ final class CaseIgnoringComparator implements Comparator<String>, Serializable {
} }
@Override @Override
public int compare(String o1, String o2) { public int compare(CharSequence o1, CharSequence o2) {
return o1.compareToIgnoreCase(o2); int o1Length = o1.length();
int o2Length = o2.length();
int min = Math.min(o1Length, o2Length);
for (int i = 0; i < min; i++) {
char c1 = o1.charAt(i);
char c2 = o2.charAt(i);
if (c1 != c2) {
c1 = Character.toUpperCase(c1);
c2 = Character.toUpperCase(c2);
if (c1 != c2) {
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2);
if (c1 != c2) {
return c1 - c2;
}
}
}
}
return o1Length - o2Length;
} }
@SuppressWarnings("MethodMayBeStatic") @SuppressWarnings("MethodMayBeStatic")

View File

@ -152,9 +152,9 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder {
// Check if Post using "multipart/form-data; boundary=--89421926422648" // Check if Post using "multipart/form-data; boundary=--89421926422648"
String[] headerContentType = splitHeaderContentType(contentType); String[] headerContentType = splitHeaderContentType(contentType);
if (headerContentType[0].toLowerCase().startsWith( if (headerContentType[0].toLowerCase().startsWith(
HttpHeaders.Values.MULTIPART_FORM_DATA) && HttpHeaders.Values.MULTIPART_FORM_DATA.toString()) &&
headerContentType[1].toLowerCase().startsWith( headerContentType[1].toLowerCase().startsWith(
HttpHeaders.Values.BOUNDARY)) { HttpHeaders.Values.BOUNDARY.toString())) {
String[] boundary = StringUtil.split(headerContentType[1], '='); String[] boundary = StringUtil.split(headerContentType[1], '=');
if (boundary.length != 2) { if (boundary.length != 2) {
throw new ErrorDataDecoderException("Needs a boundary value"); throw new ErrorDataDecoderException("Needs a boundary value");

View File

@ -663,9 +663,10 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
headers.remove(HttpHeaders.Names.CONTENT_TYPE); headers.remove(HttpHeaders.Names.CONTENT_TYPE);
for (String contentType : contentTypes) { for (String contentType : contentTypes) {
// "multipart/form-data; boundary=--89421926422648" // "multipart/form-data; boundary=--89421926422648"
if (contentType.toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA)) { if (contentType.toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA.toString())) {
// ignore // ignore
} else if (contentType.toLowerCase().startsWith(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) { } else if (contentType.toLowerCase().startsWith(
HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.toString())) {
// ignore // ignore
} else { } else {
headers.add(HttpHeaders.Names.CONTENT_TYPE, contentType); headers.add(HttpHeaders.Names.CONTENT_TYPE, contentType);
@ -694,7 +695,7 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
if (transferEncoding != null) { if (transferEncoding != null) {
headers.remove(HttpHeaders.Names.TRANSFER_ENCODING); headers.remove(HttpHeaders.Names.TRANSFER_ENCODING);
for (String v : transferEncoding) { for (String v : transferEncoding) {
if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) { if (HttpHeaders.equalsIgnoreCase(v, HttpHeaders.Values.CHUNKED)) {
// ignore // ignore
} else { } else {
headers.add(HttpHeaders.Names.TRANSFER_ENCODING, v); headers.add(HttpHeaders.Names.TRANSFER_ENCODING, v);

View File

@ -198,13 +198,13 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker {
HttpHeaders headers = response.headers(); HttpHeaders headers = response.headers();
String upgrade = headers.get(Names.UPGRADE); String upgrade = headers.get(Names.UPGRADE);
if (!Values.WEBSOCKET.equalsIgnoreCase(upgrade)) { if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " throw new WebSocketHandshakeException("Invalid handshake response upgrade: "
+ upgrade); + upgrade);
} }
String connection = headers.get(Names.CONNECTION); String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) { if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ connection); + connection);
} }

View File

@ -40,7 +40,7 @@ import java.net.URI;
public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker { public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker07.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker07.class);
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(Values.WEBSOCKET.toString().toLowerCase());
public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private String expectedChallengeResponseString; private String expectedChallengeResponseString;
@ -118,7 +118,7 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
HttpHeaders headers = request.headers(); HttpHeaders headers = request.headers();
headers.add(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()) headers.add(Names.UPGRADE, WEBSOCKET)
.add(Names.CONNECTION, Values.UPGRADE) .add(Names.CONNECTION, Values.UPGRADE)
.add(Names.SEC_WEBSOCKET_KEY, key) .add(Names.SEC_WEBSOCKET_KEY, key)
.add(Names.HOST, wsURL.getHost()); .add(Names.HOST, wsURL.getHost());
@ -172,12 +172,12 @@ public class WebSocketClientHandshaker07 extends WebSocketClientHandshaker {
} }
String upgrade = headers.get(Names.UPGRADE); String upgrade = headers.get(Names.UPGRADE);
if (!Values.WEBSOCKET.equalsIgnoreCase(upgrade)) { if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade); throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
} }
String connection = headers.get(Names.CONNECTION); String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) { if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection); throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
} }

View File

@ -40,6 +40,8 @@ import java.net.URI;
public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker08.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker08.class);
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(
HttpHeaders.Values.WEBSOCKET.toString().toLowerCase());
public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@ -118,7 +120,7 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
HttpHeaders headers = request.headers(); HttpHeaders headers = request.headers();
headers.add(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()) headers.add(Names.UPGRADE, WEBSOCKET)
.add(Names.CONNECTION, Values.UPGRADE) .add(Names.CONNECTION, Values.UPGRADE)
.add(Names.SEC_WEBSOCKET_KEY, key) .add(Names.SEC_WEBSOCKET_KEY, key)
.add(Names.HOST, wsURL.getHost()); .add(Names.HOST, wsURL.getHost());
@ -172,12 +174,12 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker {
} }
String upgrade = headers.get(Names.UPGRADE); String upgrade = headers.get(Names.UPGRADE);
if (!Values.WEBSOCKET.equalsIgnoreCase(upgrade)) { if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade); throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
} }
String connection = headers.get(Names.CONNECTION); String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) { if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection); throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
} }

View File

@ -40,6 +40,7 @@ import java.net.URI;
public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker13.class); private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker13.class);
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(Values.WEBSOCKET.toString().toLowerCase());
public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@ -129,7 +130,7 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
HttpHeaders headers = request.headers(); HttpHeaders headers = request.headers();
headers.add(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()) headers.add(Names.UPGRADE, WEBSOCKET)
.add(Names.CONNECTION, Values.UPGRADE) .add(Names.CONNECTION, Values.UPGRADE)
.add(Names.SEC_WEBSOCKET_KEY, key) .add(Names.SEC_WEBSOCKET_KEY, key)
.add(Names.HOST, wsURL.getHost() + ':' + wsPort); .add(Names.HOST, wsURL.getHost() + ':' + wsPort);
@ -182,12 +183,12 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker {
} }
String upgrade = headers.get(Names.UPGRADE); String upgrade = headers.get(Names.UPGRADE);
if (!Values.WEBSOCKET.equalsIgnoreCase(upgrade)) { if (!HttpHeaders.equalsIgnoreCase(Values.WEBSOCKET, upgrade)) {
throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade); throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + upgrade);
} }
String connection = headers.get(Names.CONNECTION); String connection = headers.get(Names.CONNECTION);
if (!Values.UPGRADE.equalsIgnoreCase(connection)) { if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, connection)) {
throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection); throw new WebSocketHandshakeException("Invalid handshake response connection: " + connection);
} }

View File

@ -109,8 +109,8 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker {
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) { protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
// Serve the WebSocket handshake request. // Serve the WebSocket handshake request.
if (!Values.UPGRADE.equalsIgnoreCase(req.headers().get(CONNECTION)) if (!HttpHeaders.equalsIgnoreCase(Values.UPGRADE, req.headers().get(CONNECTION))
|| !WEBSOCKET.equalsIgnoreCase(req.headers().get(Names.UPGRADE))) { || !HttpHeaders.equalsIgnoreCase(WEBSOCKET, req.headers().get(Names.UPGRADE))) {
throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade"); throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade");
} }

View File

@ -23,7 +23,6 @@ import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpHeaders.Values.*;
import static io.netty.handler.codec.http.HttpVersion.*; import static io.netty.handler.codec.http.HttpVersion.*;
/** /**
@ -35,6 +34,9 @@ import static io.netty.handler.codec.http.HttpVersion.*;
*/ */
public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker { public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker {
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(
HttpHeaders.Values.WEBSOCKET.toString().toLowerCase());
public static final String WEBSOCKET_07_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String WEBSOCKET_07_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private final boolean allowExtensions; private final boolean allowExtensions;
@ -114,7 +116,7 @@ public class WebSocketServerHandshaker07 extends WebSocketServerHandshaker {
logger.debug(String.format("WS Version 7 Server Handshake key: %s. Response: %s.", key, accept)); logger.debug(String.format("WS Version 7 Server Handshake key: %s. Response: %s.", key, accept));
} }
res.headers().add(Names.UPGRADE, WEBSOCKET.toLowerCase()); res.headers().add(Names.UPGRADE, WEBSOCKET);
res.headers().add(Names.CONNECTION, Names.UPGRADE); res.headers().add(Names.CONNECTION, Names.UPGRADE);
res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept); res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept);
String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL); String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL);

View File

@ -23,7 +23,6 @@ import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpHeaders.Values.*;
import static io.netty.handler.codec.http.HttpVersion.*; import static io.netty.handler.codec.http.HttpVersion.*;
/** /**
@ -35,6 +34,9 @@ import static io.netty.handler.codec.http.HttpVersion.*;
*/ */
public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker {
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(
HttpHeaders.Values.WEBSOCKET.toString().toLowerCase());
public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private final boolean allowExtensions; private final boolean allowExtensions;
@ -113,7 +115,7 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker {
logger.debug(String.format("WS Version 8 Server Handshake key: %s. Response: %s.", key, accept)); logger.debug(String.format("WS Version 8 Server Handshake key: %s. Response: %s.", key, accept));
} }
res.headers().add(Names.UPGRADE, WEBSOCKET.toLowerCase()); res.headers().add(Names.UPGRADE, WEBSOCKET);
res.headers().add(Names.CONNECTION, Names.UPGRADE); res.headers().add(Names.CONNECTION, Names.UPGRADE);
res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept); res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept);
String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL); String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL);

View File

@ -23,7 +23,6 @@ import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
import static io.netty.handler.codec.http.HttpHeaders.Values.*;
import static io.netty.handler.codec.http.HttpVersion.*; import static io.netty.handler.codec.http.HttpVersion.*;
/** /**
@ -33,6 +32,8 @@ import static io.netty.handler.codec.http.HttpVersion.*;
* </p> * </p>
*/ */
public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
private static final CharSequence WEBSOCKET = HttpHeaders.newEntity(
HttpHeaders.Values.WEBSOCKET.toString().toLowerCase());
public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@ -111,7 +112,7 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker {
logger.debug(String.format("WS Version 13 Server Handshake key: %s. Response: %s.", key, accept)); logger.debug(String.format("WS Version 13 Server Handshake key: %s. Response: %s.", key, accept));
} }
res.headers().add(Names.UPGRADE, WEBSOCKET.toLowerCase()); res.headers().add(Names.UPGRADE, WEBSOCKET);
res.headers().add(Names.CONNECTION, Names.UPGRADE); res.headers().add(Names.CONNECTION, Names.UPGRADE);
res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept); res.headers().add(Names.SEC_WEBSOCKET_ACCEPT, accept);
String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL); String subprotocols = req.headers().get(Names.SEC_WEBSOCKET_PROTOCOL);

View File

@ -30,179 +30,179 @@ public final class RtspHeaders {
/** /**
* {@code "Accept"} * {@code "Accept"}
*/ */
public static final String ACCEPT = HttpHeaders.Names.ACCEPT; public static final CharSequence ACCEPT = HttpHeaders.Names.ACCEPT;
/** /**
* {@code "Accept-Encoding"} * {@code "Accept-Encoding"}
*/ */
public static final String ACCEPT_ENCODING = HttpHeaders.Names.ACCEPT_ENCODING; public static final CharSequence ACCEPT_ENCODING = HttpHeaders.Names.ACCEPT_ENCODING;
/** /**
* {@code "Accept-Lanugage"} * {@code "Accept-Lanugage"}
*/ */
public static final String ACCEPT_LANGUAGE = HttpHeaders.Names.ACCEPT_LANGUAGE; public static final CharSequence ACCEPT_LANGUAGE = HttpHeaders.Names.ACCEPT_LANGUAGE;
/** /**
* {@code "Allow"} * {@code "Allow"}
*/ */
public static final String ALLOW = "Allow"; public static final CharSequence ALLOW = HttpHeaders.newEntity("Allow");
/** /**
* {@code "Authorization"} * {@code "Authorization"}
*/ */
public static final String AUTHORIZATION = HttpHeaders.Names.AUTHORIZATION; public static final CharSequence AUTHORIZATION = HttpHeaders.Names.AUTHORIZATION;
/** /**
* {@code "Bandwidth"} * {@code "Bandwidth"}
*/ */
public static final String BANDWIDTH = "Bandwidth"; public static final CharSequence BANDWIDTH = HttpHeaders.newEntity("Bandwidth");
/** /**
* {@code "Blocksize"} * {@code "Blocksize"}
*/ */
public static final String BLOCKSIZE = "Blocksize"; public static final CharSequence BLOCKSIZE = HttpHeaders.newEntity("Blocksize");
/** /**
* {@code "Cache-Control"} * {@code "Cache-Control"}
*/ */
public static final String CACHE_CONTROL = HttpHeaders.Names.CACHE_CONTROL; public static final CharSequence CACHE_CONTROL = HttpHeaders.Names.CACHE_CONTROL;
/** /**
* {@code "Conference"} * {@code "Conference"}
*/ */
public static final String CONFERENCE = "Conference"; public static final CharSequence CONFERENCE = HttpHeaders.newEntity("Conference");
/** /**
* {@code "Connection"} * {@code "Connection"}
*/ */
public static final String CONNECTION = HttpHeaders.Names.CONNECTION; public static final CharSequence CONNECTION = HttpHeaders.Names.CONNECTION;
/** /**
* {@code "Content-Base"} * {@code "Content-Base"}
*/ */
public static final String CONTENT_BASE = HttpHeaders.Names.CONTENT_BASE; public static final CharSequence CONTENT_BASE = HttpHeaders.Names.CONTENT_BASE;
/** /**
* {@code "Content-Encoding"} * {@code "Content-Encoding"}
*/ */
public static final String CONTENT_ENCODING = HttpHeaders.Names.CONTENT_ENCODING; public static final CharSequence CONTENT_ENCODING = HttpHeaders.Names.CONTENT_ENCODING;
/** /**
* {@code "Content-Language"} * {@code "Content-Language"}
*/ */
public static final String CONTENT_LANGUAGE = HttpHeaders.Names.CONTENT_LANGUAGE; public static final CharSequence CONTENT_LANGUAGE = HttpHeaders.Names.CONTENT_LANGUAGE;
/** /**
* {@code "Content-Length"} * {@code "Content-Length"}
*/ */
public static final String CONTENT_LENGTH = HttpHeaders.Names.CONTENT_LENGTH; public static final CharSequence CONTENT_LENGTH = HttpHeaders.Names.CONTENT_LENGTH;
/** /**
* {@code "Content-Location"} * {@code "Content-Location"}
*/ */
public static final String CONTENT_LOCATION = HttpHeaders.Names.CONTENT_LOCATION; public static final CharSequence CONTENT_LOCATION = HttpHeaders.Names.CONTENT_LOCATION;
/** /**
* {@code "Content-Type"} * {@code "Content-Type"}
*/ */
public static final String CONTENT_TYPE = HttpHeaders.Names.CONTENT_TYPE; public static final CharSequence CONTENT_TYPE = HttpHeaders.Names.CONTENT_TYPE;
/** /**
* {@code "CSeq"} * {@code "CSeq"}
*/ */
public static final String CSEQ = "CSeq"; public static final CharSequence CSEQ = HttpHeaders.newEntity("CSeq");
/** /**
* {@code "Date"} * {@code "Date"}
*/ */
public static final String DATE = HttpHeaders.Names.DATE; public static final CharSequence DATE = HttpHeaders.Names.DATE;
/** /**
* {@code "Expires"} * {@code "Expires"}
*/ */
public static final String EXPIRES = HttpHeaders.Names.EXPIRES; public static final CharSequence EXPIRES = HttpHeaders.Names.EXPIRES;
/** /**
* {@code "From"} * {@code "From"}
*/ */
public static final String FROM = HttpHeaders.Names.FROM; public static final CharSequence FROM = HttpHeaders.Names.FROM;
/** /**
* {@code "Host"} * {@code "Host"}
*/ */
public static final String HOST = HttpHeaders.Names.HOST; public static final CharSequence HOST = HttpHeaders.Names.HOST;
/** /**
* {@code "If-Match"} * {@code "If-Match"}
*/ */
public static final String IF_MATCH = HttpHeaders.Names.IF_MATCH; public static final CharSequence IF_MATCH = HttpHeaders.Names.IF_MATCH;
/** /**
* {@code "If-Modified-Since"} * {@code "If-Modified-Since"}
*/ */
public static final String IF_MODIFIED_SINCE = HttpHeaders.Names.IF_MODIFIED_SINCE; public static final CharSequence IF_MODIFIED_SINCE = HttpHeaders.Names.IF_MODIFIED_SINCE;
/** /**
* {@code "KeyMgmt"} * {@code "KeyMgmt"}
*/ */
public static final String KEYMGMT = "KeyMgmt"; public static final CharSequence KEYMGMT = HttpHeaders.newEntity("KeyMgmt");
/** /**
* {@code "Last-Modified"} * {@code "Last-Modified"}
*/ */
public static final String LAST_MODIFIED = HttpHeaders.Names.LAST_MODIFIED; public static final CharSequence LAST_MODIFIED = HttpHeaders.Names.LAST_MODIFIED;
/** /**
* {@code "Proxy-Authenticate"} * {@code "Proxy-Authenticate"}
*/ */
public static final String PROXY_AUTHENTICATE = HttpHeaders.Names.PROXY_AUTHENTICATE; public static final CharSequence PROXY_AUTHENTICATE = HttpHeaders.Names.PROXY_AUTHENTICATE;
/** /**
* {@code "Proxy-Require"} * {@code "Proxy-Require"}
*/ */
public static final String PROXY_REQUIRE = "Proxy-Require"; public static final CharSequence PROXY_REQUIRE = HttpHeaders.newEntity("Proxy-Require");
/** /**
* {@code "Public"} * {@code "Public"}
*/ */
public static final String PUBLIC = "Public"; public static final CharSequence PUBLIC = HttpHeaders.newEntity("Public");
/** /**
* {@code "Range"} * {@code "Range"}
*/ */
public static final String RANGE = HttpHeaders.Names.RANGE; public static final CharSequence RANGE = HttpHeaders.Names.RANGE;
/** /**
* {@code "Referer"} * {@code "Referer"}
*/ */
public static final String REFERER = HttpHeaders.Names.REFERER; public static final CharSequence REFERER = HttpHeaders.Names.REFERER;
/** /**
* {@code "Require"} * {@code "Require"}
*/ */
public static final String REQUIRE = "Require"; public static final CharSequence REQUIRE = HttpHeaders.newEntity("Require");
/** /**
* {@code "Retry-After"} * {@code "Retry-After"}
*/ */
public static final String RETRT_AFTER = HttpHeaders.Names.RETRY_AFTER; public static final CharSequence RETRT_AFTER = HttpHeaders.Names.RETRY_AFTER;
/** /**
* {@code "RTP-Info"} * {@code "RTP-Info"}
*/ */
public static final String RTP_INFO = "RTP-Info"; public static final CharSequence RTP_INFO = HttpHeaders.newEntity("RTP-Info");
/** /**
* {@code "Scale"} * {@code "Scale"}
*/ */
public static final String SCALE = "Scale"; public static final CharSequence SCALE = HttpHeaders.newEntity("Scale");
/** /**
* {@code "Session"} * {@code "Session"}
*/ */
public static final String SESSION = "Session"; public static final CharSequence SESSION = HttpHeaders.newEntity("Session");
/** /**
* {@code "Server"} * {@code "Server"}
*/ */
public static final String SERVER = HttpHeaders.Names.SERVER; public static final CharSequence SERVER = HttpHeaders.Names.SERVER;
/** /**
* {@code "Speed"} * {@code "Speed"}
*/ */
public static final String SPEED = "Speed"; public static final CharSequence SPEED = HttpHeaders.newEntity("Speed");
/** /**
* {@code "Timestamp"} * {@code "Timestamp"}
*/ */
public static final String TIMESTAMP = "Timestamp"; public static final CharSequence TIMESTAMP = HttpHeaders.newEntity("Timestamp");
/** /**
* {@code "Transport"} * {@code "Transport"}
*/ */
public static final String TRANSPORT = "Transport"; public static final CharSequence TRANSPORT = HttpHeaders.newEntity("Transport");
/** /**
* {@code "Unsupported"} * {@code "Unsupported"}
*/ */
public static final String UNSUPPORTED = "Unsupported"; public static final CharSequence UNSUPPORTED = HttpHeaders.newEntity("Unsupported");
/** /**
* {@code "User-Agent"} * {@code "User-Agent"}
*/ */
public static final String USER_AGENT = HttpHeaders.Names.USER_AGENT; public static final CharSequence USER_AGENT = HttpHeaders.Names.USER_AGENT;
/** /**
* {@code "Vary"} * {@code "Vary"}
*/ */
public static final String VARY = HttpHeaders.Names.VARY; public static final CharSequence VARY = HttpHeaders.Names.VARY;
/** /**
* {@code "Via"} * {@code "Via"}
*/ */
public static final String VIA = HttpHeaders.Names.VIA; public static final CharSequence VIA = HttpHeaders.Names.VIA;
/** /**
* {@code "WWW-Authenticate"} * {@code "WWW-Authenticate"}
*/ */
public static final String WWW_AUTHENTICATE = HttpHeaders.Names.WWW_AUTHENTICATE; public static final CharSequence WWW_AUTHENTICATE = HttpHeaders.Names.WWW_AUTHENTICATE;
private Names() { private Names() {
} }
@ -215,171 +215,171 @@ public final class RtspHeaders {
/** /**
* {@code "append"} * {@code "append"}
*/ */
public static final String APPEND = "append"; public static final CharSequence APPEND = HttpHeaders.newEntity("append");
/** /**
* {@code "AVP"} * {@code "AVP"}
*/ */
public static final String AVP = "AVP"; public static final CharSequence AVP = HttpHeaders.newEntity("AVP");
/** /**
* {@code "bytes"} * {@code "bytes"}
*/ */
public static final String BYTES = HttpHeaders.Values.BYTES; public static final CharSequence BYTES = HttpHeaders.Values.BYTES;
/** /**
* {@code "charset"} * {@code "charset"}
*/ */
public static final String CHARSET = HttpHeaders.Values.CHARSET; public static final CharSequence CHARSET = HttpHeaders.Values.CHARSET;
/** /**
* {@code "client_port"} * {@code "client_port"}
*/ */
public static final String CLIENT_PORT = "client_port"; public static final CharSequence CLIENT_PORT = HttpHeaders.newEntity("client_port");
/** /**
* {@code "clock"} * {@code "clock"}
*/ */
public static final String CLOCK = "clock"; public static final CharSequence CLOCK = HttpHeaders.newEntity("clock");
/** /**
* {@code "close"} * {@code "close"}
*/ */
public static final String CLOSE = HttpHeaders.Values.CLOSE; public static final CharSequence CLOSE = HttpHeaders.Values.CLOSE;
/** /**
* {@code "compress"} * {@code "compress"}
*/ */
public static final String COMPRESS = HttpHeaders.Values.COMPRESS; public static final CharSequence COMPRESS = HttpHeaders.Values.COMPRESS;
/** /**
* {@code "100-continue"} * {@code "100-continue"}
*/ */
public static final String CONTINUE = HttpHeaders.Values.CONTINUE; public static final CharSequence CONTINUE = HttpHeaders.Values.CONTINUE;
/** /**
* {@code "deflate"} * {@code "deflate"}
*/ */
public static final String DEFLATE = HttpHeaders.Values.DEFLATE; public static final CharSequence DEFLATE = HttpHeaders.Values.DEFLATE;
/** /**
* {@code "destination"} * {@code "destination"}
*/ */
public static final String DESTINATION = "destination"; public static final CharSequence DESTINATION = HttpHeaders.newEntity("destination");
/** /**
* {@code "gzip"} * {@code "gzip"}
*/ */
public static final String GZIP = HttpHeaders.Values.GZIP; public static final CharSequence GZIP = HttpHeaders.Values.GZIP;
/** /**
* {@code "identity"} * {@code "identity"}
*/ */
public static final String IDENTITY = HttpHeaders.Values.IDENTITY; public static final CharSequence IDENTITY = HttpHeaders.Values.IDENTITY;
/** /**
* {@code "interleaved"} * {@code "interleaved"}
*/ */
public static final String INTERLEAVED = "interleaved"; public static final CharSequence INTERLEAVED = HttpHeaders.newEntity("interleaved");
/** /**
* {@code "keep-alive"} * {@code "keep-alive"}
*/ */
public static final String KEEP_ALIVE = HttpHeaders.Values.KEEP_ALIVE; public static final CharSequence KEEP_ALIVE = HttpHeaders.Values.KEEP_ALIVE;
/** /**
* {@code "layers"} * {@code "layers"}
*/ */
public static final String LAYERS = "layers"; public static final CharSequence LAYERS = HttpHeaders.newEntity("layers");
/** /**
* {@code "max-age"} * {@code "max-age"}
*/ */
public static final String MAX_AGE = HttpHeaders.Values.MAX_AGE; public static final CharSequence MAX_AGE = HttpHeaders.Values.MAX_AGE;
/** /**
* {@code "max-stale"} * {@code "max-stale"}
*/ */
public static final String MAX_STALE = HttpHeaders.Values.MAX_STALE; public static final CharSequence MAX_STALE = HttpHeaders.Values.MAX_STALE;
/** /**
* {@code "min-fresh"} * {@code "min-fresh"}
*/ */
public static final String MIN_FRESH = HttpHeaders.Values.MIN_FRESH; public static final CharSequence MIN_FRESH = HttpHeaders.Values.MIN_FRESH;
/** /**
* {@code "mode"} * {@code "mode"}
*/ */
public static final String MODE = "mode"; public static final CharSequence MODE = HttpHeaders.newEntity("mode");
/** /**
* {@code "multicast"} * {@code "multicast"}
*/ */
public static final String MULTICAST = "multicast"; public static final CharSequence MULTICAST = HttpHeaders.newEntity("multicast");
/** /**
* {@code "must-revalidate"} * {@code "must-revalidate"}
*/ */
public static final String MUST_REVALIDATE = HttpHeaders.Values.MUST_REVALIDATE; public static final CharSequence MUST_REVALIDATE = HttpHeaders.Values.MUST_REVALIDATE;
/** /**
* {@code "none"} * {@code "none"}
*/ */
public static final String NONE = HttpHeaders.Values.NONE; public static final CharSequence NONE = HttpHeaders.Values.NONE;
/** /**
* {@code "no-cache"} * {@code "no-cache"}
*/ */
public static final String NO_CACHE = HttpHeaders.Values.NO_CACHE; public static final CharSequence NO_CACHE = HttpHeaders.Values.NO_CACHE;
/** /**
* {@code "no-transform"} * {@code "no-transform"}
*/ */
public static final String NO_TRANSFORM = HttpHeaders.Values.NO_TRANSFORM; public static final CharSequence NO_TRANSFORM = HttpHeaders.Values.NO_TRANSFORM;
/** /**
* {@code "only-if-cached"} * {@code "only-if-cached"}
*/ */
public static final String ONLY_IF_CACHED = HttpHeaders.Values.ONLY_IF_CACHED; public static final CharSequence ONLY_IF_CACHED = HttpHeaders.Values.ONLY_IF_CACHED;
/** /**
* {@code "port"} * {@code "port"}
*/ */
public static final String PORT = "port"; public static final CharSequence PORT = HttpHeaders.newEntity("port");
/** /**
* {@code "private"} * {@code "private"}
*/ */
public static final String PRIVATE = HttpHeaders.Values.PRIVATE; public static final CharSequence PRIVATE = HttpHeaders.Values.PRIVATE;
/** /**
* {@code "proxy-revalidate"} * {@code "proxy-revalidate"}
*/ */
public static final String PROXY_REVALIDATE = HttpHeaders.Values.PROXY_REVALIDATE; public static final CharSequence PROXY_REVALIDATE = HttpHeaders.Values.PROXY_REVALIDATE;
/** /**
* {@code "public"} * {@code "public"}
*/ */
public static final String PUBLIC = HttpHeaders.Values.PUBLIC; public static final CharSequence PUBLIC = HttpHeaders.Values.PUBLIC;
/** /**
* {@code "RTP"} * {@code "RTP"}
*/ */
public static final String RTP = "RTP"; public static final CharSequence RTP = HttpHeaders.newEntity("RTP");
/** /**
* {@code "rtptime"} * {@code "rtptime"}
*/ */
public static final String RTPTIME = "rtptime"; public static final CharSequence RTPTIME = HttpHeaders.newEntity("rtptime");
/** /**
* {@code "seq"} * {@code "seq"}
*/ */
public static final String SEQ = "seq"; public static final CharSequence SEQ = HttpHeaders.newEntity("seq");
/** /**
* {@code "server_port"} * {@code "server_port"}
*/ */
public static final String SERVER_PORT = "server_port"; public static final CharSequence SERVER_PORT = HttpHeaders.newEntity("server_port");
/** /**
* {@code "ssrc"} * {@code "ssrc"}
*/ */
public static final String SSRC = "ssrc"; public static final CharSequence SSRC = HttpHeaders.newEntity("ssrc");
/** /**
* {@code "TCP"} * {@code "TCP"}
*/ */
public static final String TCP = "TCP"; public static final CharSequence TCP = HttpHeaders.newEntity("TCP");
/** /**
* {@code "time"} * {@code "time"}
*/ */
public static final String TIME = "time"; public static final CharSequence TIME = HttpHeaders.newEntity("time");
/** /**
* {@code "timeout"} * {@code "timeout"}
*/ */
public static final String TIMEOUT = "timeout"; public static final CharSequence TIMEOUT = HttpHeaders.newEntity("timeout");
/** /**
* {@code "ttl"} * {@code "ttl"}
*/ */
public static final String TTL = "ttl"; public static final CharSequence TTL = HttpHeaders.newEntity("ttl");
/** /**
* {@code "UDP"} * {@code "UDP"}
*/ */
public static final String UDP = "UDP"; public static final CharSequence UDP = HttpHeaders.newEntity("UDP");
/** /**
* {@code "unicast"} * {@code "unicast"}
*/ */
public static final String UNICAST = "unicast"; public static final CharSequence UNICAST = HttpHeaders.newEntity("unicast");
/** /**
* {@code "url"} * {@code "url"}
*/ */
public static final String URL = "url"; public static final CharSequence URL = HttpHeaders.newEntity("url");
private Values() { } private Values() { }
} }

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.rtsp;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequest;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
@ -38,11 +39,11 @@ public class RtspRequestEncoder extends RtspObjectEncoder<HttpRequest> {
@Override @Override
protected void encodeInitialLine(ByteBuf buf, HttpRequest request) protected void encodeInitialLine(ByteBuf buf, HttpRequest request)
throws Exception { throws Exception {
encodeAscii(request.getMethod().toString(), buf); HttpHeaders.encodeAscii(request.getMethod().toString(), buf);
buf.writeByte(SP); buf.writeByte(SP);
buf.writeBytes(request.getUri().getBytes(CharsetUtil.UTF_8)); buf.writeBytes(request.getUri().getBytes(CharsetUtil.UTF_8));
buf.writeByte(SP); buf.writeByte(SP);
encodeAscii(request.getProtocolVersion().toString(), buf); HttpHeaders.encodeAscii(request.getProtocolVersion().toString(), buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
} }
} }

View File

@ -17,6 +17,7 @@ package io.netty.handler.codec.rtsp;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponse;
import io.netty.util.CharsetUtil; import io.netty.util.CharsetUtil;
@ -38,11 +39,11 @@ public class RtspResponseEncoder extends RtspObjectEncoder<HttpResponse> {
@Override @Override
protected void encodeInitialLine(ByteBuf buf, HttpResponse response) protected void encodeInitialLine(ByteBuf buf, HttpResponse response)
throws Exception { throws Exception {
encodeAscii(response.getProtocolVersion().toString(), buf); HttpHeaders.encodeAscii(response.getProtocolVersion().toString(), buf);
buf.writeByte(SP); buf.writeByte(SP);
buf.writeBytes(String.valueOf(response.getStatus().code()).getBytes(CharsetUtil.US_ASCII)); buf.writeBytes(String.valueOf(response.getStatus().code()).getBytes(CharsetUtil.US_ASCII));
buf.writeByte(SP); buf.writeByte(SP);
encodeAscii(String.valueOf(response.getStatus().reasonPhrase()), buf); HttpHeaders.encodeAscii(String.valueOf(response.getStatus().reasonPhrase()), buf);
buf.writeBytes(CRLF); buf.writeBytes(CRLF);
} }
} }

View File

@ -33,7 +33,7 @@ public class HttpContentEncoderTest {
private static final class TestEncoder extends HttpContentEncoder { private static final class TestEncoder extends HttpContentEncoder {
@Override @Override
protected Result beginEncode(HttpResponse headers, String acceptEncoding) { protected Result beginEncode(HttpResponse headers, CharSequence acceptEncoding) {
return new Result("test", new EmbeddedChannel(new MessageToByteEncoder<ByteBuf>() { return new Result("test", new EmbeddedChannel(new MessageToByteEncoder<ByteBuf>() {
@Override @Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception { protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) throws Exception {

View File

@ -127,7 +127,7 @@ public class WebSocketRequestBuilder {
.method(HttpMethod.GET) .method(HttpMethod.GET)
.uri("/test") .uri("/test")
.host("server.example.com") .host("server.example.com")
.upgrade(WEBSOCKET.toLowerCase()) .upgrade(WEBSOCKET.toString().toLowerCase())
.key("dGhlIHNhbXBsZSBub25jZQ==") .key("dGhlIHNhbXBsZSBub25jZQ==")
.origin("http://example.com") .origin("http://example.com")
.version13() .version13()

View File

@ -45,7 +45,7 @@ public class WebSocketServerHandshaker00Test {
HTTP_1_1, HttpMethod.GET, "/chat", Unpooled.copiedBuffer("^n:ds[4U", CharsetUtil.US_ASCII)); HTTP_1_1, HttpMethod.GET, "/chat", Unpooled.copiedBuffer("^n:ds[4U", CharsetUtil.US_ASCII));
req.headers().set(Names.HOST, "server.example.com"); req.headers().set(Names.HOST, "server.example.com");
req.headers().set(Names.UPGRADE, WEBSOCKET.toLowerCase()); req.headers().set(Names.UPGRADE, WEBSOCKET.toString().toLowerCase());
req.headers().set(Names.CONNECTION, "Upgrade"); req.headers().set(Names.CONNECTION, "Upgrade");
req.headers().set(Names.ORIGIN, "http://example.com"); req.headers().set(Names.ORIGIN, "http://example.com");
req.headers().set(Names.SEC_WEBSOCKET_KEY1, "4 @1 46546xW%0l 1 5"); req.headers().set(Names.SEC_WEBSOCKET_KEY1, "4 @1 46546xW%0l 1 5");

View File

@ -41,7 +41,7 @@ public class WebSocketServerHandshaker08Test {
FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat"); FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat");
req.headers().set(Names.HOST, "server.example.com"); req.headers().set(Names.HOST, "server.example.com");
req.headers().set(Names.UPGRADE, WEBSOCKET.toLowerCase()); req.headers().set(Names.UPGRADE, WEBSOCKET.toString().toLowerCase());
req.headers().set(Names.CONNECTION, "Upgrade"); req.headers().set(Names.CONNECTION, "Upgrade");
req.headers().set(Names.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ=="); req.headers().set(Names.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
req.headers().set(Names.SEC_WEBSOCKET_ORIGIN, "http://example.com"); req.headers().set(Names.SEC_WEBSOCKET_ORIGIN, "http://example.com");

View File

@ -41,7 +41,7 @@ public class WebSocketServerHandshaker13Test {
FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat"); FullHttpRequest req = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat");
req.headers().set(Names.HOST, "server.example.com"); req.headers().set(Names.HOST, "server.example.com");
req.headers().set(Names.UPGRADE, WEBSOCKET.toLowerCase()); req.headers().set(Names.UPGRADE, WEBSOCKET.toString().toLowerCase());
req.headers().set(Names.CONNECTION, "Upgrade"); req.headers().set(Names.CONNECTION, "Upgrade");
req.headers().set(Names.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ=="); req.headers().set(Names.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
req.headers().set(Names.SEC_WEBSOCKET_ORIGIN, "http://example.com"); req.headers().set(Names.SEC_WEBSOCKET_ORIGIN, "http://example.com");

View File

@ -93,7 +93,7 @@ public class WebSocketServerProtocolHandlerTest {
.uri("/test") .uri("/test")
.key(null) .key(null)
.connection("Upgrade") .connection("Upgrade")
.upgrade(WEBSOCKET.toLowerCase()) .upgrade(WEBSOCKET.toString().toLowerCase())
.version13() .version13()
.build(); .build();

View File

@ -188,8 +188,8 @@ public class HttpUploadClient {
HttpHeaders headers = request.headers(); HttpHeaders headers = request.headers();
headers.set(HttpHeaders.Names.HOST, host); headers.set(HttpHeaders.Names.HOST, host);
headers.set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); headers.set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
headers.set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP + ',' headers.set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP.toString() + ','
+ HttpHeaders.Values.DEFLATE); + HttpHeaders.Values.DEFLATE.toString());
headers.set(HttpHeaders.Names.ACCEPT_CHARSET, "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); headers.set(HttpHeaders.Names.ACCEPT_CHARSET, "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
headers.set(HttpHeaders.Names.ACCEPT_LANGUAGE, "fr"); headers.set(HttpHeaders.Names.ACCEPT_LANGUAGE, "fr");

View File

@ -286,9 +286,9 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
responseContent.setLength(0); responseContent.setLength(0);
// Decide whether to close the connection or not. // Decide whether to close the connection or not.
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.headers().get(CONNECTION)) boolean close = request.headers().contains(CONNECTION, HttpHeaders.Values.CLOSE, true)
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) || request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(CONNECTION)); && !request.headers().contains(CONNECTION, HttpHeaders.Values.KEEP_ALIVE, true);
// Build the response object. // Build the response object.
FullHttpResponse response = new DefaultFullHttpResponse( FullHttpResponse response = new DefaultFullHttpResponse(