diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java index 4cb82e678d..a71e2a14a2 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java @@ -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); } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java index 7efdc55849..02958d46aa 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java @@ -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(); }