Issue #4115 - Drop HTTP/2 pseudo headers.

Updates after review.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Simone Bordet 2019-10-09 21:01:30 +02:00
parent 609c144ae0
commit 6acc9f7be5
4 changed files with 36 additions and 17 deletions

View File

@ -69,6 +69,11 @@ public class HttpField
return _name;
}
public String getLowCaseName()
{
return _header != null ? _header.lowCaseName() : StringUtil.asciiToLowerCase(_name);
}
public String getValue()
{
return _value;

View File

@ -149,6 +149,7 @@ public enum HttpHeader
}
private final String _string;
private final String _lowCase;
private final byte[] _bytes;
private final byte[] _bytesColonSpace;
private final ByteBuffer _buffer;
@ -156,11 +157,17 @@ public enum HttpHeader
HttpHeader(String s)
{
_string = s;
_lowCase = StringUtil.asciiToLowerCase(s);
_bytes = StringUtil.getBytes(s);
_bytesColonSpace = StringUtil.getBytes(s + ": ");
_buffer = ByteBuffer.wrap(_bytes);
}
public String lowCaseName()
{
return _lowCase;
}
public ByteBuffer toBuffer()
{
return _buffer.asReadOnlyBuffer();

View File

@ -261,7 +261,7 @@ public class HpackContext
_dynamicTableSizeInBytes += size;
_dynamicTable.add(entry);
_fieldMap.put(field, entry);
_nameMap.put(StringUtil.asciiToLowerCase(field.getName()), entry);
_nameMap.put(field.getLowCaseName(), entry);
if (LOG.isDebugEnabled())
LOG.debug(String.format("HdrTbl[%x] added %s", hashCode(), entry));
@ -383,7 +383,7 @@ public class HpackContext
_dynamicTableSizeInBytes -= entry.getSize();
entry._slot = -1;
_fieldMap.remove(entry.getHttpField());
String lc = StringUtil.asciiToLowerCase(entry.getHttpField().getName());
String lc = entry.getHttpField().getLowCaseName();
if (entry == _nameMap.get(lc))
_nameMap.remove(lc);
}

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.hpack;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
@ -27,6 +28,7 @@ import java.util.Set;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
@ -77,6 +79,9 @@ public class HpackEncoder
private static final EnumSet<HttpHeader> IGNORED_HEADERS = EnumSet.of(HttpHeader.CONNECTION, HttpHeader.KEEP_ALIVE,
HttpHeader.PROXY_CONNECTION, HttpHeader.TRANSFER_ENCODING, HttpHeader.UPGRADE);
private static final PreEncodedHttpField TE_TRAILERS = new PreEncodedHttpField(HttpHeader.TE, "trailers");
private static final PreEncodedHttpField C_SCHEME_HTTP = new PreEncodedHttpField(HttpHeader.C_SCHEME, "http");
private static final PreEncodedHttpField C_SCHEME_HTTPS = new PreEncodedHttpField(HttpHeader.C_SCHEME, "https");
private static final EnumMap<HttpMethod, PreEncodedHttpField> C_METHODS = new EnumMap<>(HttpMethod.class);
static
{
@ -84,6 +89,10 @@ public class HpackEncoder
{
STATUSES[code.getCode()] = new PreEncodedHttpField(HttpHeader.C_STATUS, Integer.toString(code.getCode()));
}
for (HttpMethod method : HttpMethod.values())
{
C_METHODS.put(method, new PreEncodedHttpField(HttpHeader.C_METHOD, method.asString()));
}
}
private final HpackContext _context;
@ -161,19 +170,15 @@ public class HpackEncoder
LOG.debug(String.format("CtxTbl[%x] encoding", _context.hashCode()));
HttpFields fields = metadata.getFields();
if (isValidateEncoding())
// Verify that we can encode without errors.
if (isValidateEncoding() && fields != null)
{
// Verify that we can encode without errors.
if (fields != null)
for (HttpField field : fields)
{
for (HttpField field : fields)
{
String name = field.getName();
String lowName = StringUtil.asciiToLowerCase(name);
char firstChar = lowName.charAt(0);
if (firstChar <= ' ' || firstChar == ':')
throw new HpackException.StreamException("Invalid header name: '%s'", name);
}
String name = field.getName();
char firstChar = name.charAt(0);
if (firstChar <= ' ' || firstChar == ':')
throw new HpackException.StreamException("Invalid header name: '%s'", name);
}
}
@ -190,10 +195,12 @@ public class HpackEncoder
{
MetaData.Request request = (MetaData.Request)metadata;
// TODO optimise these to avoid HttpField creation
String scheme = request.getURI().getScheme();
encode(buffer, new HttpField(HttpHeader.C_SCHEME, scheme == null ? HttpScheme.HTTP.asString() : scheme));
encode(buffer, new HttpField(HttpHeader.C_METHOD, request.getMethod()));
encode(buffer, HttpScheme.HTTPS.is(scheme) ? C_SCHEME_HTTPS : C_SCHEME_HTTP);
String method = request.getMethod();
HttpMethod httpMethod = HttpMethod.fromString(method);
HttpField methodField = C_METHODS.get(httpMethod);
encode(buffer, methodField == null ? new HttpField(HttpHeader.C_METHOD, method) : methodField);
encode(buffer, new HttpField(HttpHeader.C_AUTHORITY, request.getURI().getAuthority()));
encode(buffer, new HttpField(HttpHeader.C_PATH, request.getURI().getPathQuery()));
}
@ -229,7 +236,7 @@ public class HpackEncoder
encode(buffer, TE_TRAILERS);
continue;
}
String name = StringUtil.asciiToLowerCase(field.getName());
String name = field.getLowCaseName();
if (hopHeaders != null && hopHeaders.contains(name))
continue;
encode(buffer, field);