Use the same HttpHeaders optimisations in master as in 4.0
This commit is contained in:
parent
0fa6dcefc5
commit
f84a50d3cb
@ -15,12 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec.http;
|
package io.netty.handler.codec.http;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -34,35 +31,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
private static final int BUCKET_SIZE = 17;
|
private static final int BUCKET_SIZE = 17;
|
||||||
|
|
||||||
private static final Set<String> KNOWN_NAMES = createSet(Names.class);
|
private static int hash(String name) {
|
||||||
private static final Set<String> KNOWN_VALUES = createSet(Values.class);
|
|
||||||
|
|
||||||
private static Set<String> createSet(Class<?> clazz) {
|
|
||||||
Set<String> set = new HashSet<String>();
|
|
||||||
Field[] fields = clazz.getDeclaredFields();
|
|
||||||
|
|
||||||
for (Field f: fields) {
|
|
||||||
int m = f.getModifiers();
|
|
||||||
if (Modifier.isPublic(m) && Modifier.isStatic(m) && Modifier.isFinal(m)
|
|
||||||
&& f.getType().isAssignableFrom(String.class)) {
|
|
||||||
try {
|
|
||||||
set.add((String) f.get(null));
|
|
||||||
} catch (Throwable cause) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return set;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int hash(String name, boolean validate) {
|
|
||||||
int h = 0;
|
int h = 0;
|
||||||
for (int i = name.length() - 1; i >= 0; i --) {
|
for (int i = name.length() - 1; i >= 0; i --) {
|
||||||
char c = name.charAt(i);
|
char c = name.charAt(i);
|
||||||
if (validate) {
|
if (c >= 'A' && c <= 'Z') {
|
||||||
valideHeaderNameChar(c);
|
c += 32;
|
||||||
}
|
}
|
||||||
c = toLowerCase(c);
|
|
||||||
h = 31 * h + c;
|
h = 31 * h + c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,10 +51,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean eq(String name1, String name2) {
|
private static boolean eq(String name1, String name2) {
|
||||||
if (name1 == name2) {
|
|
||||||
// check for object equality as the user may reuse our static fields in HttpHeaders.Names
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int nameLen = name1.length();
|
int nameLen = name1.length();
|
||||||
if (nameLen != name2.length()) {
|
if (nameLen != name2.length()) {
|
||||||
return false;
|
return false;
|
||||||
@ -89,7 +60,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
char c1 = name1.charAt(i);
|
char c1 = name1.charAt(i);
|
||||||
char c2 = name2.charAt(i);
|
char c2 = name2.charAt(i);
|
||||||
if (c1 != c2) {
|
if (c1 != c2) {
|
||||||
if (toLowerCase(c1) != toLowerCase(c2)) {
|
if (c1 >= 'A' && c1 <= 'Z') {
|
||||||
|
c1 += 32;
|
||||||
|
}
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z') {
|
||||||
|
c2 += 32;
|
||||||
|
}
|
||||||
|
if (c1 != c2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,13 +74,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static char toLowerCase(char c) {
|
|
||||||
if (c >= 'A' && c <= 'Z') {
|
|
||||||
c += 32;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int index(int hash) {
|
private static int index(int hash) {
|
||||||
return hash % BUCKET_SIZE;
|
return hash % BUCKET_SIZE;
|
||||||
}
|
}
|
||||||
@ -117,27 +87,25 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DefaultHttpHeaders(boolean validate) {
|
public DefaultHttpHeaders(boolean validate) {
|
||||||
head.before = head.after = head;
|
|
||||||
this.validate = validate;
|
this.validate = validate;
|
||||||
|
head.before = head.after = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
void validateHeaderValue0(String headerValue) {
|
void validateHeaderName0(String headerName) {
|
||||||
if (KNOWN_VALUES.contains(headerValue)) {
|
validateHeaderName(headerName);
|
||||||
return;
|
|
||||||
}
|
|
||||||
validateHeaderValue(headerValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders add(final String name, final Object value) {
|
public HttpHeaders add(final String name, final Object value) {
|
||||||
String strVal = toString(value);
|
String strVal;
|
||||||
boolean validateName = false;
|
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateHeaderValue0(strVal);
|
validateHeaderName0(name);
|
||||||
validateName = !KNOWN_NAMES.contains(name);
|
strVal = toString(value);
|
||||||
|
validateHeaderValue(strVal);
|
||||||
|
} else {
|
||||||
|
strVal = toString(value);
|
||||||
}
|
}
|
||||||
|
int h = hash(name);
|
||||||
int h = hash(name, validateName);
|
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
add0(h, i, name, strVal);
|
add0(h, i, name, strVal);
|
||||||
return this;
|
return this;
|
||||||
@ -145,17 +113,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders add(String name, Iterable<?> values) {
|
public HttpHeaders add(String name, Iterable<?> values) {
|
||||||
boolean validateName = false;
|
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateName = !KNOWN_NAMES.contains(name);
|
validateHeaderName0(name);
|
||||||
}
|
}
|
||||||
|
int h = hash(name);
|
||||||
int h = hash(name, validateName);
|
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
for (Object v: values) {
|
for (Object v: values) {
|
||||||
String vstr = toString(v);
|
String vstr = toString(v);
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateHeaderValue0(vstr);
|
validateHeaderValue(vstr);
|
||||||
}
|
}
|
||||||
add0(h, i, name, vstr);
|
add0(h, i, name, vstr);
|
||||||
}
|
}
|
||||||
@ -178,7 +144,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new NullPointerException("name");
|
throw new NullPointerException("name");
|
||||||
}
|
}
|
||||||
int h = hash(name, false);
|
int h = hash(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
remove0(h, i, name);
|
remove0(h, i, name);
|
||||||
return this;
|
return this;
|
||||||
@ -222,14 +188,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders set(final String name, final Object value) {
|
public HttpHeaders set(final String name, final Object value) {
|
||||||
String strVal = toString(value);
|
String strVal;
|
||||||
boolean validateName = false;
|
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateHeaderValue0(strVal);
|
validateHeaderName0(name);
|
||||||
validateName = !KNOWN_NAMES.contains(name);
|
strVal = toString(value);
|
||||||
|
validateHeaderValue(strVal);
|
||||||
|
} else {
|
||||||
|
strVal = toString(value);
|
||||||
}
|
}
|
||||||
|
int h = hash(name);
|
||||||
int h = hash(name, validateName);
|
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
remove0(h, i, name);
|
remove0(h, i, name);
|
||||||
add0(h, i, name, strVal);
|
add0(h, i, name, strVal);
|
||||||
@ -241,13 +208,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
if (values == null) {
|
if (values == null) {
|
||||||
throw new NullPointerException("values");
|
throw new NullPointerException("values");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean validateName = false;
|
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateName = !KNOWN_NAMES.contains(name);
|
validateHeaderName0(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int h = hash(name, validateName);
|
int h = hash(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
|
|
||||||
remove0(h, i, name);
|
remove0(h, i, name);
|
||||||
@ -257,7 +222,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
}
|
}
|
||||||
String strVal = toString(v);
|
String strVal = toString(v);
|
||||||
if (validate) {
|
if (validate) {
|
||||||
validateHeaderValue0(strVal);
|
validateHeaderValue(strVal);
|
||||||
}
|
}
|
||||||
add0(h, i, name, strVal);
|
add0(h, i, name, strVal);
|
||||||
}
|
}
|
||||||
@ -274,15 +239,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String get(final String name) {
|
public String get(final String name) {
|
||||||
return get(name, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String get(final String name, boolean last) {
|
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
throw new NullPointerException("name");
|
throw new NullPointerException("name");
|
||||||
}
|
}
|
||||||
|
|
||||||
int h = hash(name, false);
|
int h = hash(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
HeaderEntry e = entries[i];
|
HeaderEntry e = entries[i];
|
||||||
String value = null;
|
String value = null;
|
||||||
@ -290,9 +251,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
while (e != null) {
|
while (e != null) {
|
||||||
if (e.hash == h && eq(name, e.key)) {
|
if (e.hash == h && eq(name, e.key)) {
|
||||||
value = e.value;
|
value = e.value;
|
||||||
if (last) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e = e.next;
|
e = e.next;
|
||||||
@ -308,7 +266,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
LinkedList<String> values = new LinkedList<String>();
|
LinkedList<String> values = new LinkedList<String>();
|
||||||
|
|
||||||
int h = hash(name, false);
|
int h = hash(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
HeaderEntry e = entries[i];
|
HeaderEntry e = entries[i];
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
@ -340,7 +298,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contains(String name) {
|
public boolean contains(String name) {
|
||||||
return get(name, true) != null;
|
return get(name) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -354,7 +312,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
throw new NullPointerException("name");
|
throw new NullPointerException("name");
|
||||||
}
|
}
|
||||||
|
|
||||||
int h = hash(name, false);
|
int h = hash(name);
|
||||||
int i = index(h);
|
int i = index(h);
|
||||||
HeaderEntry e = entries[i];
|
HeaderEntry e = entries[i];
|
||||||
while (e != null) {
|
while (e != null) {
|
||||||
@ -472,9 +430,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new NullPointerException("value");
|
throw new NullPointerException("value");
|
||||||
}
|
}
|
||||||
if (validate) {
|
validateHeaderValue(value);
|
||||||
validateHeaderValue0(value);
|
|
||||||
}
|
|
||||||
String oldValue = this.value;
|
String oldValue = this.value;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
return oldValue;
|
return oldValue;
|
||||||
|
@ -93,44 +93,13 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class TrailingHeaders extends DefaultHttpHeaders {
|
private static final class TrailingHeaders extends DefaultHttpHeaders {
|
||||||
|
TrailingHeaders(boolean validate) {
|
||||||
TrailingHeaders(boolean validateHeaders) {
|
super(validate);
|
||||||
super(validateHeaders);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders add(String name, Object value) {
|
void validateHeaderName0(String name) {
|
||||||
if (validate) {
|
super.validateHeaderName0(name);
|
||||||
validateName(name);
|
|
||||||
}
|
|
||||||
return super.add(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpHeaders add(String name, Iterable<?> values) {
|
|
||||||
if (validate) {
|
|
||||||
validateName(name);
|
|
||||||
}
|
|
||||||
return super.add(name, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpHeaders set(String name, Iterable<?> values) {
|
|
||||||
if (validate) {
|
|
||||||
validateName(name);
|
|
||||||
}
|
|
||||||
return super.set(name, values);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpHeaders set(String name, Object value) {
|
|
||||||
if (validate) {
|
|
||||||
validateName(name);
|
|
||||||
}
|
|
||||||
return super.set(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void validateName(String name) {
|
|
||||||
if (name.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH) ||
|
if (name.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH) ||
|
||||||
name.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING) ||
|
name.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING) ||
|
||||||
name.equalsIgnoreCase(HttpHeaders.Names.TRAILER)) {
|
name.equalsIgnoreCase(HttpHeaders.Names.TRAILER)) {
|
||||||
|
@ -546,14 +546,12 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
*/
|
*/
|
||||||
public static boolean isKeepAlive(HttpMessage message) {
|
public static boolean isKeepAlive(HttpMessage message) {
|
||||||
String connection = message.headers().get(Names.CONNECTION);
|
String connection = message.headers().get(Names.CONNECTION);
|
||||||
|
if (Values.CLOSE.equalsIgnoreCase(connection)) {
|
||||||
boolean close = Values.CLOSE.equalsIgnoreCase(connection);
|
|
||||||
if (close) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
||||||
return !close;
|
return !Values.CLOSE.equalsIgnoreCase(connection);
|
||||||
} else {
|
} else {
|
||||||
return Values.KEEP_ALIVE.equalsIgnoreCase(connection);
|
return Values.KEEP_ALIVE.equalsIgnoreCase(connection);
|
||||||
}
|
}
|
||||||
@ -1021,24 +1019,21 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
|
|||||||
for (int index = 0; index < headerName.length(); index ++) {
|
for (int index = 0; index < headerName.length(); index ++) {
|
||||||
//Actually get the character
|
//Actually get the character
|
||||||
char character = headerName.charAt(index);
|
char character = headerName.charAt(index);
|
||||||
valideHeaderNameChar(character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void valideHeaderNameChar(char c) {
|
|
||||||
//Check to see if the character is not an ASCII character
|
//Check to see if the character is not an ASCII character
|
||||||
if (c > 127) {
|
if (character > 127) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Header name cannot contain non-ASCII characters: " + c);
|
"Header name cannot contain non-ASCII characters: " + headerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for prohibited characters.
|
//Check for prohibited characters.
|
||||||
switch (c) {
|
switch (character) {
|
||||||
case '\t': case '\n': case 0x0b: case '\f': case '\r':
|
case '\t': case '\n': case 0x0b: case '\f': case '\r':
|
||||||
case ' ': case ',': case ':': case ';': case '=':
|
case ' ': case ',': case ':': case ';': case '=':
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Header name cannot contain the following prohibited characters: " +
|
"Header name cannot contain the following prohibited characters: " +
|
||||||
"=,;: \\t\\r\\n\\v\\f ");
|
"=,;: \\t\\r\\n\\v\\f: " + headerName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user