Fix regression in HttpPostStandardRequestDecoder to always decode + to whitespace (#10285)

Motivations
-----------
HttpPostStandardRequestDecoder was changed in 4.1.50 to provide its own
ByteBuf UrlDecoder. Prior to this change, it was using the decodeComponent
method from QueryStringDecoder which decoded + characters to
whitespaces. This behavior needs to be preserved to maintain backward
compatibility.

Modifications
-------------
Changed HttpPostStandardRequestDecoder to detect + bytes and decode them
toe whitespaces. Added a test.

Results
-------
Addresses issues#10284
This commit is contained in:
Fabien Renaud 2020-05-14 00:28:40 -07:00 committed by GitHub
parent caf51b7284
commit d5087deec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 3 deletions

View File

@ -656,7 +656,7 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
}
private static ByteBuf decodeAttribute(ByteBuf b, Charset charset) {
int firstEscaped = b.forEachByte(new ByteProcessor.IndexOfProcessor((byte) '%'));
int firstEscaped = b.forEachByte(new UrlEncodedDetector());
if (firstEscaped == -1) {
return null; // nothing to decode
}
@ -714,6 +714,13 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
factory.removeHttpDataFromClean(request, data);
}
private static final class UrlEncodedDetector implements ByteProcessor {
@Override
public boolean process(byte value) throws Exception {
return value != '%' && value != '+';
}
}
private static final class UrlDecoder implements ByteProcessor {
private final ByteBuf output;
@ -742,6 +749,8 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD
}
} else if (value == '%') {
nextEscapedIdx = 1;
} else if (value == '+') {
output.writeByte(' ');
} else {
output.writeByte(value);
}

View File

@ -829,7 +829,7 @@ public class HttpPostRequestDecoderTest {
@Test
public void testDecodeFullHttpRequestWithUrlEncodedBody() throws Exception {
byte[] bodyBytes = "foo=bar&a=b&empty=&city=%3c%22new%22%20york%20city%3e".getBytes();
byte[] bodyBytes = "foo=bar&a=b&empty=&city=%3c%22new%22%20york%20city%3e&other_city=los+angeles".getBytes();
ByteBuf content = Unpooled.directBuffer(bodyBytes.length);
content.writeBytes(bodyBytes);
@ -838,7 +838,7 @@ public class HttpPostRequestDecoderTest {
assertFalse(decoder.getBodyHttpDatas().isEmpty());
assertFalse(decoder.getBodyHttpDatas().isEmpty());
assertEquals(4, decoder.getBodyHttpDatas().size());
assertEquals(5, decoder.getBodyHttpDatas().size());
Attribute attr = (Attribute) decoder.getBodyHttpData("foo");
assertTrue(attr.getByteBuf().isDirect());
@ -856,6 +856,10 @@ public class HttpPostRequestDecoderTest {
assertTrue(attr.getByteBuf().isDirect());
assertEquals("<\"new\" york city>", attr.getValue());
attr = (Attribute) decoder.getBodyHttpData("other_city");
assertTrue(attr.getByteBuf().isDirect());
assertEquals("los angeles", attr.getValue());
decoder.destroy();
req.release();
}