Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UNDERTOW-2340] Remove Content-Length header when request is deflated. #1548

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 34 additions & 4 deletions core/src/main/java/io/undertow/io/AsyncReceiverImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.undertow.server.Connectors;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.StatusCodes;
import org.xnio.ChannelListener;
Expand Down Expand Up @@ -108,6 +109,9 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
final ByteArrayOutputStream sb;
if (contentLengthString != null) {
Expand Down Expand Up @@ -137,7 +141,12 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
res = channel.read(buffer);
if (res == -1) {
done = true;
callback.handle(exchange, sb.toString(charset.name()));
final String message = sb.toString(charset.name());
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
}
callback.handle(exchange, message);
return;
} else if (res == 0) {
channel.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
Expand All @@ -159,7 +168,12 @@ public void handleEvent(StreamSourceChannel channel) {
Connectors.executeRootHandler(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
callback.handle(exchange, sb.toString(charset.name()));
final String message = sb.toString(charset.name());
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
}
callback.handle(exchange, message);
}
}, exchange);
return;
Expand Down Expand Up @@ -238,6 +252,9 @@ public void receivePartialString(final PartialStringCallback callback, final Err
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
if (contentLengthString != null) {
contentLength = Long.parseLong(contentLengthString);
Expand Down Expand Up @@ -396,7 +413,12 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
res = channel.read(buffer);
if (res == -1) {
done = true;
callback.handle(exchange, sb.toByteArray());
final byte[] message = sb.toByteArray();
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
}
callback.handle(exchange, message);
return;
} else if (res == 0) {
channel.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
Expand All @@ -418,7 +440,12 @@ public void handleEvent(StreamSourceChannel channel) {
Connectors.executeRootHandler(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
callback.handle(exchange, sb.toByteArray());
final byte[] message = sb.toByteArray();
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
}
callback.handle(exchange, message);
}
}, exchange);
return;
Expand Down Expand Up @@ -495,6 +522,9 @@ public void receivePartialBytes(final PartialBytesCallback callback, final Error
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
if (contentLengthString != null) {
contentLength = Long.parseLong(contentLengthString);
Expand Down
27 changes: 25 additions & 2 deletions core/src/main/java/io/undertow/io/BlockingReceiverImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import io.undertow.UndertowMessages;
import io.undertow.connector.PooledByteBuffer;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderMap;
import io.undertow.util.Headers;
import io.undertow.util.StatusCodes;

Expand Down Expand Up @@ -100,6 +101,9 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
final ByteArrayOutputStream sb;
if (contentLengthString != null) {
Expand All @@ -125,7 +129,12 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
while ((s = inputStream.read(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), pooled.getBuffer().remaining())) > 0) {
sb.write(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), s);
}
callback.handle(exchange, sb.toString(charset.name()));
final String message = sb.toString(charset.name());
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
}
callback.handle(exchange, message);
} else {
throw UndertowMessages.MESSAGES.failedToAllocateResource();
}
Expand Down Expand Up @@ -154,6 +163,9 @@ public void receivePartialString(final PartialStringCallback callback, final Err
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
if (contentLengthString != null) {
contentLength = Long.parseLong(contentLengthString);
Expand Down Expand Up @@ -209,6 +221,9 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
final ByteArrayOutputStream sb;
if (contentLengthString != null) {
Expand All @@ -234,7 +249,12 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
while ((s = inputStream.read(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), pooled.getBuffer().remaining())) > 0) {
sb.write(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), s);
}
callback.handle(exchange, sb.toByteArray());
final byte[] message = sb.toByteArray();
final HeaderMap requestHeaders = exchange.getRequestHeaders();
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
}
callback.handle(exchange, message);
} else {
throw UndertowMessages.MESSAGES.failedToAllocateResource();
}
Expand Down Expand Up @@ -263,6 +283,9 @@ public void receivePartialBytes(final PartialBytesCallback callback, final Error
return;
}
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(contentLengthString == null) {
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
}
long contentLength;
if (contentLengthString != null) {
contentLength = Long.parseLong(contentLengthString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
// Nested handlers or even servlet filters may implement logic to decode encoded request data.
// Since the data is no longer encoded, we remove the encoding header.
exchange.getRequestHeaders().remove(Headers.CONTENT_ENCODING);
final String encodedContentLength = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
if(encodedContentLength != null) {
exchange.getRequestHeaders().remove(Headers.CONTENT_LENGTH);
exchange.getRequestHeaders().put(Headers.X_CONTENT_LENGTH, encodedContentLength);
}
}
next.handleRequest(exchange);
}
Expand Down
21 changes: 11 additions & 10 deletions core/src/main/java/io/undertow/util/Headers.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ private Headers() {
public static final String VIA_STRING = "Via";
public static final String WARNING_STRING = "Warning";
public static final String WWW_AUTHENTICATE_STRING = "WWW-Authenticate";
public static final String X_CONTENT_LENGTH_STRING = "X-Content-Length";
public static final String X_CONTENT_TYPE_OPTIONS_STRING = "X-Content-Type-Options";
public static final String X_DISABLE_PUSH_STRING = "X-Disable-Push";
public static final String X_FORWARDED_FOR_STRING = "X-Forwarded-For";
Expand All @@ -123,7 +124,6 @@ private Headers() {
public static final String X_FORWARDED_SERVER_STRING = "X-Forwarded-Server";
public static final String X_FRAME_OPTIONS_STRING = "X-Frame-Options";
public static final String X_XSS_PROTECTION_STRING = "X-Xss-Protection";

// Header names

public static final HttpString ACCEPT = new HttpString(ACCEPT_STRING, 1);
Expand Down Expand Up @@ -200,15 +200,16 @@ private Headers() {
public static final HttpString VIA = new HttpString(VIA_STRING, 72);
public static final HttpString WARNING = new HttpString(WARNING_STRING, 73);
public static final HttpString WWW_AUTHENTICATE = new HttpString(WWW_AUTHENTICATE_STRING, 74);
public static final HttpString X_CONTENT_TYPE_OPTIONS = new HttpString(X_CONTENT_TYPE_OPTIONS_STRING, 75);
public static final HttpString X_DISABLE_PUSH = new HttpString(X_DISABLE_PUSH_STRING, 76);
public static final HttpString X_FORWARDED_FOR = new HttpString(X_FORWARDED_FOR_STRING, 77);
public static final HttpString X_FORWARDED_HOST = new HttpString(X_FORWARDED_HOST_STRING, 78);
public static final HttpString X_FORWARDED_PORT = new HttpString(X_FORWARDED_PORT_STRING, 79);
public static final HttpString X_FORWARDED_PROTO = new HttpString(X_FORWARDED_PROTO_STRING, 80);
public static final HttpString X_FORWARDED_SERVER = new HttpString(X_FORWARDED_SERVER_STRING, 81);
public static final HttpString X_FRAME_OPTIONS = new HttpString(X_FRAME_OPTIONS_STRING, 82);
public static final HttpString X_XSS_PROTECTION = new HttpString(X_XSS_PROTECTION_STRING, 83);
public static final HttpString X_CONTENT_LENGTH = new HttpString(X_CONTENT_LENGTH_STRING, 75);
public static final HttpString X_CONTENT_TYPE_OPTIONS = new HttpString(X_CONTENT_TYPE_OPTIONS_STRING, 76);
public static final HttpString X_DISABLE_PUSH = new HttpString(X_DISABLE_PUSH_STRING, 77);
public static final HttpString X_FORWARDED_FOR = new HttpString(X_FORWARDED_FOR_STRING, 78);
public static final HttpString X_FORWARDED_HOST = new HttpString(X_FORWARDED_HOST_STRING, 79);
public static final HttpString X_FORWARDED_PORT = new HttpString(X_FORWARDED_PORT_STRING, 80);
public static final HttpString X_FORWARDED_PROTO = new HttpString(X_FORWARDED_PROTO_STRING, 81);
public static final HttpString X_FORWARDED_SERVER = new HttpString(X_FORWARDED_SERVER_STRING, 82);
public static final HttpString X_FRAME_OPTIONS = new HttpString(X_FRAME_OPTIONS_STRING, 83);
public static final HttpString X_XSS_PROTECTION = new HttpString(X_XSS_PROTECTION_STRING, 84);
// Content codings

public static final HttpString COMPRESS = new HttpString("compress");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,24 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
exchange.getResponseSender().send(message, IoCallback.END_EXCHANGE);
}
});
final EncodingHandler wrappedEncode = new EncodingHandler(contentEncodingRepository).setNext(encode);

final HttpHandler decode = new RequestEncodingHandler(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
exchange.getRequestReceiver().receiveFullBytes(new Receiver.FullBytesCallback() {
@Override
public void handle(HttpServerExchange exchange, byte[] message) {
Assert.assertTrue(exchange.getRequestContentLength()>0);
exchange.getResponseSender().send(ByteBuffer.wrap(message));
}
});
}
}).addEncoding("deflate", InflatingStreamSourceConduit.WRAPPER)
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER);
final HttpHandler wrappedDecode = new RequestEncodingHandler(decode)
.addEncoding("deflate", InflatingStreamSourceConduit.WRAPPER)
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER);

PathHandler pathHandler = new PathHandler();
pathHandler.addPrefixPath("/encode", wrappedEncode);
pathHandler.addPrefixPath("/decode", wrappedDecode);
pathHandler.addPrefixPath("/encode", encode);
pathHandler.addPrefixPath("/decode", decode);

DefaultServer.setRootHandler(pathHandler);
}
Expand Down