Skip to content

Commit a4720e3

Browse files
authored
Merge pull request #1548 from baranowb/UNDERTOW-2340
[UNDERTOW-2340] Remove Content-Length header when request is deflated.
2 parents 29fc22c + 3eabc54 commit a4720e3

File tree

8 files changed

+540
-22
lines changed

8 files changed

+540
-22
lines changed

core/src/main/java/io/undertow/io/AsyncReceiverImpl.java

+34-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.undertow.server.Connectors;
2525
import io.undertow.server.HttpHandler;
2626
import io.undertow.server.HttpServerExchange;
27+
import io.undertow.util.HeaderMap;
2728
import io.undertow.util.Headers;
2829
import io.undertow.util.StatusCodes;
2930
import org.xnio.ChannelListener;
@@ -108,6 +109,9 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
108109
return;
109110
}
110111
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
112+
if(contentLengthString == null) {
113+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
114+
}
111115
long contentLength;
112116
final ByteArrayOutputStream sb;
113117
if (contentLengthString != null) {
@@ -137,7 +141,12 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
137141
res = channel.read(buffer);
138142
if (res == -1) {
139143
done = true;
140-
callback.handle(exchange, sb.toString(charset.name()));
144+
final String message = sb.toString(charset.name());
145+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
146+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
147+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
148+
}
149+
callback.handle(exchange, message);
141150
return;
142151
} else if (res == 0) {
143152
channel.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
@@ -159,7 +168,12 @@ public void handleEvent(StreamSourceChannel channel) {
159168
Connectors.executeRootHandler(new HttpHandler() {
160169
@Override
161170
public void handleRequest(HttpServerExchange exchange) throws Exception {
162-
callback.handle(exchange, sb.toString(charset.name()));
171+
final String message = sb.toString(charset.name());
172+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
173+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
174+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
175+
}
176+
callback.handle(exchange, message);
163177
}
164178
}, exchange);
165179
return;
@@ -238,6 +252,9 @@ public void receivePartialString(final PartialStringCallback callback, final Err
238252
return;
239253
}
240254
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
255+
if(contentLengthString == null) {
256+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
257+
}
241258
long contentLength;
242259
if (contentLengthString != null) {
243260
contentLength = Long.parseLong(contentLengthString);
@@ -396,7 +413,12 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
396413
res = channel.read(buffer);
397414
if (res == -1) {
398415
done = true;
399-
callback.handle(exchange, sb.toByteArray());
416+
final byte[] message = sb.toByteArray();
417+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
418+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
419+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
420+
}
421+
callback.handle(exchange, message);
400422
return;
401423
} else if (res == 0) {
402424
channel.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
@@ -418,7 +440,12 @@ public void handleEvent(StreamSourceChannel channel) {
418440
Connectors.executeRootHandler(new HttpHandler() {
419441
@Override
420442
public void handleRequest(HttpServerExchange exchange) throws Exception {
421-
callback.handle(exchange, sb.toByteArray());
443+
final byte[] message = sb.toByteArray();
444+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
445+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
446+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
447+
}
448+
callback.handle(exchange, message);
422449
}
423450
}, exchange);
424451
return;
@@ -495,6 +522,9 @@ public void receivePartialBytes(final PartialBytesCallback callback, final Error
495522
return;
496523
}
497524
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
525+
if(contentLengthString == null) {
526+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
527+
}
498528
long contentLength;
499529
if (contentLengthString != null) {
500530
contentLength = Long.parseLong(contentLengthString);

core/src/main/java/io/undertow/io/BlockingReceiverImpl.java

+25-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.undertow.UndertowMessages;
3131
import io.undertow.connector.PooledByteBuffer;
3232
import io.undertow.server.HttpServerExchange;
33+
import io.undertow.util.HeaderMap;
3334
import io.undertow.util.Headers;
3435
import io.undertow.util.StatusCodes;
3536

@@ -100,6 +101,9 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
100101
return;
101102
}
102103
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
104+
if(contentLengthString == null) {
105+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
106+
}
103107
long contentLength;
104108
final ByteArrayOutputStream sb;
105109
if (contentLengthString != null) {
@@ -125,7 +129,12 @@ public void receiveFullString(final FullStringCallback callback, final ErrorCall
125129
while ((s = inputStream.read(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), pooled.getBuffer().remaining())) > 0) {
126130
sb.write(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), s);
127131
}
128-
callback.handle(exchange, sb.toString(charset.name()));
132+
final String message = sb.toString(charset.name());
133+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
134+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
135+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length());
136+
}
137+
callback.handle(exchange, message);
129138
} else {
130139
throw UndertowMessages.MESSAGES.failedToAllocateResource();
131140
}
@@ -154,6 +163,9 @@ public void receivePartialString(final PartialStringCallback callback, final Err
154163
return;
155164
}
156165
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
166+
if(contentLengthString == null) {
167+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
168+
}
157169
long contentLength;
158170
if (contentLengthString != null) {
159171
contentLength = Long.parseLong(contentLengthString);
@@ -209,6 +221,9 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
209221
return;
210222
}
211223
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
224+
if(contentLengthString == null) {
225+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
226+
}
212227
long contentLength;
213228
final ByteArrayOutputStream sb;
214229
if (contentLengthString != null) {
@@ -234,7 +249,12 @@ public void receiveFullBytes(final FullBytesCallback callback, final ErrorCallba
234249
while ((s = inputStream.read(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), pooled.getBuffer().remaining())) > 0) {
235250
sb.write(pooled.getBuffer().array(), pooled.getBuffer().arrayOffset(), s);
236251
}
237-
callback.handle(exchange, sb.toByteArray());
252+
final byte[] message = sb.toByteArray();
253+
final HeaderMap requestHeaders = exchange.getRequestHeaders();
254+
if(requestHeaders.contains(Headers.X_CONTENT_LENGTH) && !requestHeaders.contains(Headers.CONTENT_LENGTH)) {
255+
requestHeaders.put(Headers.CONTENT_LENGTH, message.length);
256+
}
257+
callback.handle(exchange, message);
238258
} else {
239259
throw UndertowMessages.MESSAGES.failedToAllocateResource();
240260
}
@@ -263,6 +283,9 @@ public void receivePartialBytes(final PartialBytesCallback callback, final Error
263283
return;
264284
}
265285
String contentLengthString = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
286+
if(contentLengthString == null) {
287+
contentLengthString = exchange.getRequestHeaders().getFirst(Headers.X_CONTENT_LENGTH);
288+
}
266289
long contentLength;
267290
if (contentLengthString != null) {
268291
contentLength = Long.parseLong(contentLengthString);

core/src/main/java/io/undertow/server/handlers/encoding/RequestEncodingHandler.java

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
6161
// Nested handlers or even servlet filters may implement logic to decode encoded request data.
6262
// Since the data is no longer encoded, we remove the encoding header.
6363
exchange.getRequestHeaders().remove(Headers.CONTENT_ENCODING);
64+
final String encodedContentLength = exchange.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
65+
if(encodedContentLength != null) {
66+
exchange.getRequestHeaders().remove(Headers.CONTENT_LENGTH);
67+
exchange.getRequestHeaders().put(Headers.X_CONTENT_LENGTH, encodedContentLength);
68+
}
6469
}
6570
next.handleRequest(exchange);
6671
}

core/src/main/java/io/undertow/util/Headers.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private Headers() {
114114
public static final String VIA_STRING = "Via";
115115
public static final String WARNING_STRING = "Warning";
116116
public static final String WWW_AUTHENTICATE_STRING = "WWW-Authenticate";
117+
public static final String X_CONTENT_LENGTH_STRING = "X-Content-Length";
117118
public static final String X_CONTENT_TYPE_OPTIONS_STRING = "X-Content-Type-Options";
118119
public static final String X_DISABLE_PUSH_STRING = "X-Disable-Push";
119120
public static final String X_FORWARDED_FOR_STRING = "X-Forwarded-For";
@@ -123,7 +124,6 @@ private Headers() {
123124
public static final String X_FORWARDED_SERVER_STRING = "X-Forwarded-Server";
124125
public static final String X_FRAME_OPTIONS_STRING = "X-Frame-Options";
125126
public static final String X_XSS_PROTECTION_STRING = "X-Xss-Protection";
126-
127127
// Header names
128128

129129
public static final HttpString ACCEPT = new HttpString(ACCEPT_STRING, 1);
@@ -200,15 +200,16 @@ private Headers() {
200200
public static final HttpString VIA = new HttpString(VIA_STRING, 72);
201201
public static final HttpString WARNING = new HttpString(WARNING_STRING, 73);
202202
public static final HttpString WWW_AUTHENTICATE = new HttpString(WWW_AUTHENTICATE_STRING, 74);
203-
public static final HttpString X_CONTENT_TYPE_OPTIONS = new HttpString(X_CONTENT_TYPE_OPTIONS_STRING, 75);
204-
public static final HttpString X_DISABLE_PUSH = new HttpString(X_DISABLE_PUSH_STRING, 76);
205-
public static final HttpString X_FORWARDED_FOR = new HttpString(X_FORWARDED_FOR_STRING, 77);
206-
public static final HttpString X_FORWARDED_HOST = new HttpString(X_FORWARDED_HOST_STRING, 78);
207-
public static final HttpString X_FORWARDED_PORT = new HttpString(X_FORWARDED_PORT_STRING, 79);
208-
public static final HttpString X_FORWARDED_PROTO = new HttpString(X_FORWARDED_PROTO_STRING, 80);
209-
public static final HttpString X_FORWARDED_SERVER = new HttpString(X_FORWARDED_SERVER_STRING, 81);
210-
public static final HttpString X_FRAME_OPTIONS = new HttpString(X_FRAME_OPTIONS_STRING, 82);
211-
public static final HttpString X_XSS_PROTECTION = new HttpString(X_XSS_PROTECTION_STRING, 83);
203+
public static final HttpString X_CONTENT_LENGTH = new HttpString(X_CONTENT_LENGTH_STRING, 75);
204+
public static final HttpString X_CONTENT_TYPE_OPTIONS = new HttpString(X_CONTENT_TYPE_OPTIONS_STRING, 76);
205+
public static final HttpString X_DISABLE_PUSH = new HttpString(X_DISABLE_PUSH_STRING, 77);
206+
public static final HttpString X_FORWARDED_FOR = new HttpString(X_FORWARDED_FOR_STRING, 78);
207+
public static final HttpString X_FORWARDED_HOST = new HttpString(X_FORWARDED_HOST_STRING, 79);
208+
public static final HttpString X_FORWARDED_PORT = new HttpString(X_FORWARDED_PORT_STRING, 80);
209+
public static final HttpString X_FORWARDED_PROTO = new HttpString(X_FORWARDED_PROTO_STRING, 81);
210+
public static final HttpString X_FORWARDED_SERVER = new HttpString(X_FORWARDED_SERVER_STRING, 82);
211+
public static final HttpString X_FRAME_OPTIONS = new HttpString(X_FRAME_OPTIONS_STRING, 83);
212+
public static final HttpString X_XSS_PROTECTION = new HttpString(X_XSS_PROTECTION_STRING, 84);
212213
// Content codings
213214

214215
public static final HttpString COMPRESS = new HttpString("compress");

core/src/test/java/io/undertow/server/handlers/encoding/RequestContentEncodingTestCase.java

+4-6
Original file line numberDiff line numberDiff line change
@@ -67,26 +67,24 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception {
6767
exchange.getResponseSender().send(message, IoCallback.END_EXCHANGE);
6868
}
6969
});
70-
final EncodingHandler wrappedEncode = new EncodingHandler(contentEncodingRepository).setNext(encode);
7170

7271
final HttpHandler decode = new RequestEncodingHandler(new HttpHandler() {
7372
@Override
7473
public void handleRequest(HttpServerExchange exchange) throws Exception {
7574
exchange.getRequestReceiver().receiveFullBytes(new Receiver.FullBytesCallback() {
7675
@Override
7776
public void handle(HttpServerExchange exchange, byte[] message) {
77+
Assert.assertTrue(exchange.getRequestContentLength()>0);
7878
exchange.getResponseSender().send(ByteBuffer.wrap(message));
7979
}
8080
});
8181
}
8282
}).addEncoding("deflate", InflatingStreamSourceConduit.WRAPPER)
8383
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER);
84-
final HttpHandler wrappedDecode = new RequestEncodingHandler(decode)
85-
.addEncoding("deflate", InflatingStreamSourceConduit.WRAPPER)
86-
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER);
84+
8785
PathHandler pathHandler = new PathHandler();
88-
pathHandler.addPrefixPath("/encode", wrappedEncode);
89-
pathHandler.addPrefixPath("/decode", wrappedDecode);
86+
pathHandler.addPrefixPath("/encode", encode);
87+
pathHandler.addPrefixPath("/decode", decode);
9088

9189
DefaultServer.setRootHandler(pathHandler);
9290
}

0 commit comments

Comments
 (0)