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;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -34,35 +31,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
private static final int BUCKET_SIZE = 17;
|
||||
|
||||
private static final Set<String> KNOWN_NAMES = createSet(Names.class);
|
||||
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) {
|
||||
private static int hash(String name) {
|
||||
int h = 0;
|
||||
for (int i = name.length() - 1; i >= 0; i --) {
|
||||
char c = name.charAt(i);
|
||||
if (validate) {
|
||||
valideHeaderNameChar(c);
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c += 32;
|
||||
}
|
||||
c = toLowerCase(c);
|
||||
h = 31 * h + c;
|
||||
}
|
||||
|
||||
@ -76,10 +51,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
}
|
||||
|
||||
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();
|
||||
if (nameLen != name2.length()) {
|
||||
return false;
|
||||
@ -89,7 +60,13 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
char c1 = name1.charAt(i);
|
||||
char c2 = name2.charAt(i);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -97,13 +74,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static char toLowerCase(char c) {
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
c += 32;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private static int index(int hash) {
|
||||
return hash % BUCKET_SIZE;
|
||||
}
|
||||
@ -117,27 +87,25 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
}
|
||||
|
||||
public DefaultHttpHeaders(boolean validate) {
|
||||
head.before = head.after = head;
|
||||
this.validate = validate;
|
||||
head.before = head.after = head;
|
||||
}
|
||||
|
||||
void validateHeaderValue0(String headerValue) {
|
||||
if (KNOWN_VALUES.contains(headerValue)) {
|
||||
return;
|
||||
}
|
||||
validateHeaderValue(headerValue);
|
||||
void validateHeaderName0(String headerName) {
|
||||
validateHeaderName(headerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders add(final String name, final Object value) {
|
||||
String strVal = toString(value);
|
||||
boolean validateName = false;
|
||||
String strVal;
|
||||
if (validate) {
|
||||
validateHeaderValue0(strVal);
|
||||
validateName = !KNOWN_NAMES.contains(name);
|
||||
validateHeaderName0(name);
|
||||
strVal = toString(value);
|
||||
validateHeaderValue(strVal);
|
||||
} else {
|
||||
strVal = toString(value);
|
||||
}
|
||||
|
||||
int h = hash(name, validateName);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
add0(h, i, name, strVal);
|
||||
return this;
|
||||
@ -145,17 +113,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
@Override
|
||||
public HttpHeaders add(String name, Iterable<?> values) {
|
||||
boolean validateName = false;
|
||||
if (validate) {
|
||||
validateName = !KNOWN_NAMES.contains(name);
|
||||
validateHeaderName0(name);
|
||||
}
|
||||
|
||||
int h = hash(name, validateName);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
for (Object v: values) {
|
||||
String vstr = toString(v);
|
||||
if (validate) {
|
||||
validateHeaderValue0(vstr);
|
||||
validateHeaderValue(vstr);
|
||||
}
|
||||
add0(h, i, name, vstr);
|
||||
}
|
||||
@ -178,7 +144,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
int h = hash(name, false);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
remove0(h, i, name);
|
||||
return this;
|
||||
@ -222,14 +188,15 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
@Override
|
||||
public HttpHeaders set(final String name, final Object value) {
|
||||
String strVal = toString(value);
|
||||
boolean validateName = false;
|
||||
String strVal;
|
||||
if (validate) {
|
||||
validateHeaderValue0(strVal);
|
||||
validateName = !KNOWN_NAMES.contains(name);
|
||||
validateHeaderName0(name);
|
||||
strVal = toString(value);
|
||||
validateHeaderValue(strVal);
|
||||
} else {
|
||||
strVal = toString(value);
|
||||
}
|
||||
|
||||
int h = hash(name, validateName);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
remove0(h, i, name);
|
||||
add0(h, i, name, strVal);
|
||||
@ -241,13 +208,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
if (values == null) {
|
||||
throw new NullPointerException("values");
|
||||
}
|
||||
|
||||
boolean validateName = false;
|
||||
if (validate) {
|
||||
validateName = !KNOWN_NAMES.contains(name);
|
||||
validateHeaderName0(name);
|
||||
}
|
||||
|
||||
int h = hash(name, validateName);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
|
||||
remove0(h, i, name);
|
||||
@ -257,7 +222,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
}
|
||||
String strVal = toString(v);
|
||||
if (validate) {
|
||||
validateHeaderValue0(strVal);
|
||||
validateHeaderValue(strVal);
|
||||
}
|
||||
add0(h, i, name, strVal);
|
||||
}
|
||||
@ -274,15 +239,11 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
@Override
|
||||
public String get(final String name) {
|
||||
return get(name, false);
|
||||
}
|
||||
|
||||
private String get(final String name, boolean last) {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
|
||||
int h = hash(name, false);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
HeaderEntry e = entries[i];
|
||||
String value = null;
|
||||
@ -290,9 +251,6 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
while (e != null) {
|
||||
if (e.hash == h && eq(name, e.key)) {
|
||||
value = e.value;
|
||||
if (last) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
e = e.next;
|
||||
@ -308,7 +266,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
LinkedList<String> values = new LinkedList<String>();
|
||||
|
||||
int h = hash(name, false);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
HeaderEntry e = entries[i];
|
||||
while (e != null) {
|
||||
@ -340,7 +298,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
|
||||
@Override
|
||||
public boolean contains(String name) {
|
||||
return get(name, true) != null;
|
||||
return get(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -354,7 +312,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
|
||||
int h = hash(name, false);
|
||||
int h = hash(name);
|
||||
int i = index(h);
|
||||
HeaderEntry e = entries[i];
|
||||
while (e != null) {
|
||||
@ -472,9 +430,7 @@ public class DefaultHttpHeaders extends HttpHeaders {
|
||||
if (value == null) {
|
||||
throw new NullPointerException("value");
|
||||
}
|
||||
if (validate) {
|
||||
validateHeaderValue0(value);
|
||||
}
|
||||
validateHeaderValue(value);
|
||||
String oldValue = this.value;
|
||||
this.value = value;
|
||||
return oldValue;
|
||||
|
@ -93,44 +93,13 @@ public class DefaultLastHttpContent extends DefaultHttpContent implements LastHt
|
||||
}
|
||||
|
||||
private static final class TrailingHeaders extends DefaultHttpHeaders {
|
||||
|
||||
TrailingHeaders(boolean validateHeaders) {
|
||||
super(validateHeaders);
|
||||
TrailingHeaders(boolean validate) {
|
||||
super(validate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders add(String name, Object value) {
|
||||
if (validate) {
|
||||
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) {
|
||||
void validateHeaderName0(String name) {
|
||||
super.validateHeaderName0(name);
|
||||
if (name.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH) ||
|
||||
name.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING) ||
|
||||
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) {
|
||||
String connection = message.headers().get(Names.CONNECTION);
|
||||
|
||||
boolean close = Values.CLOSE.equalsIgnoreCase(connection);
|
||||
if (close) {
|
||||
if (Values.CLOSE.equalsIgnoreCase(connection)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.getProtocolVersion().isKeepAliveDefault()) {
|
||||
return !close;
|
||||
return !Values.CLOSE.equalsIgnoreCase(connection);
|
||||
} else {
|
||||
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 ++) {
|
||||
//Actually get the character
|
||||
char character = headerName.charAt(index);
|
||||
valideHeaderNameChar(character);
|
||||
}
|
||||
}
|
||||
|
||||
static void valideHeaderNameChar(char c) {
|
||||
//Check to see if the character is not an ASCII character
|
||||
if (c > 127) {
|
||||
throw new IllegalArgumentException(
|
||||
"Header name cannot contain non-ASCII characters: " + c);
|
||||
}
|
||||
|
||||
//Check for prohibited characters.
|
||||
switch (c) {
|
||||
case '\t': case '\n': case 0x0b: case '\f': case '\r':
|
||||
case ' ': case ',': case ':': case ';': case '=':
|
||||
//Check to see if the character is not an ASCII character
|
||||
if (character > 127) {
|
||||
throw new IllegalArgumentException(
|
||||
"Header name cannot contain the following prohibited characters: " +
|
||||
"=,;: \\t\\r\\n\\v\\f ");
|
||||
"Header name cannot contain non-ASCII characters: " + headerName);
|
||||
}
|
||||
|
||||
//Check for prohibited characters.
|
||||
switch (character) {
|
||||
case '\t': case '\n': case 0x0b: case '\f': case '\r':
|
||||
case ' ': case ',': case ':': case ';': case '=':
|
||||
throw new IllegalArgumentException(
|
||||
"Header name cannot contain the following prohibited characters: " +
|
||||
"=,;: \\t\\r\\n\\v\\f: " + headerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user