Limit the access of the HttpHeaders for performance reasons

This commit is contained in:
Norman Maurer 2013-12-18 13:55:15 +01:00
parent e9f09ea9f5
commit 0052d83db1

View File

@ -110,6 +110,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
private HttpMessage message; private HttpMessage message;
private long chunkSize; private long chunkSize;
private int headerSize; private int headerSize;
private long contentLength = Long.MIN_VALUE;
private final AppendableCharSequence sb = new AppendableCharSequence(128); private final AppendableCharSequence sb = new AppendableCharSequence(128);
/** /**
@ -222,7 +223,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
reset(); reset();
return; return;
} }
long contentLength = HttpHeaders.getContentLength(message, -1); long contentLength = contentLength();
if (contentLength == 0 || contentLength == -1 && isDecodingRequest()) { if (contentLength == 0 || contentLength == -1 && isDecodingRequest()) {
out.add(message); out.add(message);
out.add(LastHttpContent.EMPTY_LAST_CONTENT); out.add(LastHttpContent.EMPTY_LAST_CONTENT);
@ -236,7 +237,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
if (nextState == State.READ_FIXED_LENGTH_CONTENT) { if (nextState == State.READ_FIXED_LENGTH_CONTENT) {
// chunkSize will be decreased as the READ_FIXED_LENGTH_CONTENT state reads data chunk by chunk. // chunkSize will be decreased as the READ_FIXED_LENGTH_CONTENT state reads data chunk by chunk.
chunkSize = HttpHeaders.getContentLength(message, -1); chunkSize = contentLength;
} }
// We return here, this forces decode to be called again where we will decode the content // We return here, this forces decode to be called again where we will decode the content
@ -371,8 +372,6 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
// Handle the last unfinished message. // Handle the last unfinished message.
if (message != null) { if (message != null) {
HttpMessage message = this.message;
this.message = null;
// Check if the closure of the connection signifies the end of the content. // Check if the closure of the connection signifies the end of the content.
boolean prematureClosure; boolean prematureClosure;
@ -383,9 +382,9 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
// Compare the length of the received content and the 'Content-Length' header. // Compare the length of the received content and the 'Content-Length' header.
// If the 'Content-Length' header is absent, the length of the content is determined by the end of the // If the 'Content-Length' header is absent, the length of the content is determined by the end of the
// connection, so it is perfectly fine. // connection, so it is perfectly fine.
long expectedContentLength = HttpHeaders.getContentLength(message, -1); prematureClosure = contentLength() > 0;
prematureClosure = expectedContentLength > 0;
} }
reset();
if (!prematureClosure) { if (!prematureClosure) {
out.add(LastHttpContent.EMPTY_LAST_CONTENT); out.add(LastHttpContent.EMPTY_LAST_CONTENT);
@ -419,7 +418,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
private void reset() { private void reset() {
HttpMessage message = this.message; HttpMessage message = this.message;
this.message = null; this.message = null;
contentLength = Long.MIN_VALUE;
if (!isDecodingRequest()) { if (!isDecodingRequest()) {
HttpResponse res = (HttpResponse) message; HttpResponse res = (HttpResponse) message;
if (res != null && res.getStatus().code() == 101) { if (res != null && res.getStatus().code() == 101) {
@ -499,7 +498,7 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
nextState = State.SKIP_CONTROL_CHARS; nextState = State.SKIP_CONTROL_CHARS;
} else if (HttpHeaders.isTransferEncodingChunked(message)) { } else if (HttpHeaders.isTransferEncodingChunked(message)) {
nextState = State.READ_CHUNK_SIZE; nextState = State.READ_CHUNK_SIZE;
} else if (HttpHeaders.getContentLength(message, -1) >= 0) { } else if (contentLength() >= 0) {
nextState = State.READ_FIXED_LENGTH_CONTENT; nextState = State.READ_FIXED_LENGTH_CONTENT;
} else { } else {
nextState = State.READ_VARIABLE_LENGTH_CONTENT; nextState = State.READ_VARIABLE_LENGTH_CONTENT;
@ -507,6 +506,13 @@ public abstract class HttpObjectDecoder extends ReplayingDecoder<HttpObjectDecod
return nextState; return nextState;
} }
private long contentLength() {
if (contentLength == Long.MIN_VALUE) {
contentLength = HttpHeaders.getContentLength(message, -1);
}
return contentLength;
}
private LastHttpContent readTrailingHeaders(ByteBuf buffer) { private LastHttpContent readTrailingHeaders(ByteBuf buffer) {
headerSize = 0; headerSize = 0;
AppendableCharSequence line = readHeader(buffer); AppendableCharSequence line = readHeader(buffer);