[#2650] Allow to disable http header validation in SpdyHttpDecoder and SpdyHttpCodec
Motivation: HTTP header validation can be expensive so we should allow to disable it like we do in HttpObjectDecoder. Modification: Add constructor argument to disable validation. Result: Performance improvement
This commit is contained in:
parent
dfa5a88978
commit
edc7abb461
@ -27,4 +27,11 @@ public final class SpdyHttpCodec extends ChannelHandlerAppender {
|
|||||||
public SpdyHttpCodec(SpdyVersion version, int maxContentLength) {
|
public SpdyHttpCodec(SpdyVersion version, int maxContentLength) {
|
||||||
super(new SpdyHttpDecoder(version, maxContentLength), new SpdyHttpEncoder(version));
|
super(new SpdyHttpDecoder(version, maxContentLength), new SpdyHttpEncoder(version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance with the specified decoder options.
|
||||||
|
*/
|
||||||
|
public SpdyHttpCodec(SpdyVersion version, int maxContentLength, boolean validateHttpHeaders) {
|
||||||
|
super(new SpdyHttpDecoder(version, maxContentLength, validateHttpHeaders), new SpdyHttpEncoder(version));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ import static io.netty.handler.codec.spdy.SpdyHeaders.HttpNames.*;
|
|||||||
*/
|
*/
|
||||||
public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
||||||
|
|
||||||
|
private final boolean validateHeaders;
|
||||||
private final int spdyVersion;
|
private final int spdyVersion;
|
||||||
private final int maxContentLength;
|
private final int maxContentLength;
|
||||||
private final Map<Integer, FullHttpMessage> messageMap;
|
private final Map<Integer, FullHttpMessage> messageMap;
|
||||||
@ -56,7 +57,20 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
* a {@link TooLongFrameException} will be raised.
|
* a {@link TooLongFrameException} will be raised.
|
||||||
*/
|
*/
|
||||||
public SpdyHttpDecoder(SpdyVersion version, int maxContentLength) {
|
public SpdyHttpDecoder(SpdyVersion version, int maxContentLength) {
|
||||||
this(version, maxContentLength, new HashMap<Integer, FullHttpMessage>());
|
this(version, maxContentLength, new HashMap<Integer, FullHttpMessage>(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
*
|
||||||
|
* @param version the protocol version
|
||||||
|
* @param maxContentLength the maximum length of the message content.
|
||||||
|
* If the length of the message content exceeds this value,
|
||||||
|
* a {@link TooLongFrameException} will be raised.
|
||||||
|
* @param validateHeaders {@code true} if http headers should be validated
|
||||||
|
*/
|
||||||
|
public SpdyHttpDecoder(SpdyVersion version, int maxContentLength, boolean validateHeaders) {
|
||||||
|
this(version, maxContentLength, new HashMap<Integer, FullHttpMessage>(), validateHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,6 +83,21 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
* @param messageMap the {@link Map} used to hold partially received messages.
|
* @param messageMap the {@link Map} used to hold partially received messages.
|
||||||
*/
|
*/
|
||||||
protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map<Integer, FullHttpMessage> messageMap) {
|
protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map<Integer, FullHttpMessage> messageMap) {
|
||||||
|
this(version, maxContentLength, messageMap, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance with the specified parameters.
|
||||||
|
*
|
||||||
|
* @param version the protocol version
|
||||||
|
* @param maxContentLength the maximum length of the message content.
|
||||||
|
* If the length of the message content exceeds this value,
|
||||||
|
* a {@link TooLongFrameException} will be raised.
|
||||||
|
* @param messageMap the {@link Map} used to hold partially received messages.
|
||||||
|
* @param validateHeaders {@code true} if http headers should be validated
|
||||||
|
*/
|
||||||
|
protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map<Integer,
|
||||||
|
FullHttpMessage> messageMap, boolean validateHeaders) {
|
||||||
if (version == null) {
|
if (version == null) {
|
||||||
throw new NullPointerException("version");
|
throw new NullPointerException("version");
|
||||||
}
|
}
|
||||||
@ -79,6 +108,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
spdyVersion = version.getVersion();
|
spdyVersion = version.getVersion();
|
||||||
this.maxContentLength = maxContentLength;
|
this.maxContentLength = maxContentLength;
|
||||||
this.messageMap = messageMap;
|
this.messageMap = messageMap;
|
||||||
|
this.validateHeaders = validateHeaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FullHttpMessage putMessage(int streamId, FullHttpMessage message) {
|
protected FullHttpMessage putMessage(int streamId, FullHttpMessage message) {
|
||||||
@ -137,7 +167,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
FullHttpResponse httpResponseWithEntity =
|
FullHttpResponse httpResponseWithEntity =
|
||||||
createHttpResponse(spdyVersion, spdySynStreamFrame);
|
createHttpResponse(ctx, spdySynStreamFrame, validateHeaders);
|
||||||
|
|
||||||
// Set the Stream-ID, Associated-To-Stream-ID, Priority, and URL as headers
|
// Set the Stream-ID, Associated-To-Stream-ID, Priority, and URL as headers
|
||||||
httpResponseWithEntity.headers().set(Names.STREAM_ID, streamId);
|
httpResponseWithEntity.headers().set(Names.STREAM_ID, streamId);
|
||||||
@ -212,7 +242,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FullHttpResponse httpResponseWithEntity = createHttpResponse(spdyVersion, spdySynReplyFrame);
|
FullHttpResponse httpResponseWithEntity = createHttpResponse(ctx, spdySynReplyFrame, validateHeaders);
|
||||||
|
|
||||||
// Set the Stream-ID as a header
|
// Set the Stream-ID as a header
|
||||||
httpResponseWithEntity.headers().set(Names.STREAM_ID, streamId);
|
httpResponseWithEntity.headers().set(Names.STREAM_ID, streamId);
|
||||||
@ -328,8 +358,8 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static FullHttpResponse createHttpResponse(
|
private static FullHttpResponse createHttpResponse(ChannelHandlerContext ctx, SpdyHeadersFrame responseFrame,
|
||||||
int spdyVersion, SpdyHeadersFrame responseFrame) throws Exception {
|
boolean validateHeaders) throws Exception {
|
||||||
|
|
||||||
// Create the first line of the response from the name/value pairs
|
// Create the first line of the response from the name/value pairs
|
||||||
SpdyHeaders headers = responseFrame.headers();
|
SpdyHeaders headers = responseFrame.headers();
|
||||||
@ -338,7 +368,7 @@ public class SpdyHttpDecoder extends MessageToMessageDecoder<SpdyFrame> {
|
|||||||
headers.remove(STATUS);
|
headers.remove(STATUS);
|
||||||
headers.remove(VERSION);
|
headers.remove(VERSION);
|
||||||
|
|
||||||
FullHttpResponse res = new DefaultFullHttpResponse(version, status);
|
FullHttpResponse res = new DefaultFullHttpResponse(version, status, ctx.alloc().buffer(), validateHeaders);
|
||||||
for (Map.Entry<String, String> e: responseFrame.headers()) {
|
for (Map.Entry<String, String> e: responseFrame.headers()) {
|
||||||
res.headers().add(e.getKey(), e.getValue());
|
res.headers().add(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user