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 6873dd9045..d9a7d1316b 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 @@ -474,6 +474,7 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD } firstpos = currentpos; currentStatus = MultiPartStatus.EPILOGUE; + undecodedChunk.readerIndex(firstpos); return; } if (contRead && currentAttribute != null) { @@ -485,7 +486,8 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD } undecodedChunk.readerIndex(firstpos); } else { - // end of line so keep index + // end of line or end of block so keep index to last valid position + undecodedChunk.readerIndex(firstpos); } } catch (ErrorDataDecoderException e) { // error while decoding @@ -604,6 +606,7 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD } firstpos = currentpos; currentStatus = MultiPartStatus.EPILOGUE; + undecodedChunk.readerIndex(firstpos); return; } if (contRead && currentAttribute != null) { @@ -615,7 +618,8 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD } undecodedChunk.readerIndex(firstpos); } else { - // end of line so keep index + // end of line or end of block so keep index to last valid position + undecodedChunk.readerIndex(firstpos); } } catch (ErrorDataDecoderException e) { // error while decoding 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 d1fbd0fd79..ea9dad54ec 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 @@ -23,6 +23,7 @@ import io.netty.handler.codec.DecoderResult; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultHttpContent; import io.netty.handler.codec.http.DefaultHttpRequest; +import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; @@ -186,4 +187,58 @@ public class HttpPostRequestDecoderTest { aDecodedData.release(); aDecoder.destroy(); } + + // See https://github.com/netty/netty/issues/2305 + @Test + public void testChunkCorrect() throws Exception { + String payload = "town=794649819&town=784444184&town=794649672&town=794657800&town=" + + "794655734&town=794649377&town=794652136&town=789936338&town=789948986&town=" + + "789949643&town=786358677&town=794655880&town=786398977&town=789901165&town=" + + "789913325&town=789903418&town=789903579&town=794645251&town=794694126&town=" + + "794694831&town=794655274&town=789913656&town=794653956&town=794665634&town=" + + "789936598&town=789904658&town=789899210&town=799696252&town=794657521&town=" + + "789904837&town=789961286&town=789958704&town=789948839&town=789933899&town=" + + "793060398&town=794659180&town=794659365&town=799724096&town=794696332&town=" + + "789953438&town=786398499&town=794693372&town=789935439&town=794658041&town=" + + "789917595&town=794655427&town=791930372&town=794652891&town=794656365&town=" + + "789960339&town=794645586&town=794657688&town=794697211&town=789937427&town=" + + "789902813&town=789941130&town=794696907&town=789904328&town=789955151&town=" + + "789911570&town=794655074&town=789939531&town=789935242&town=789903835&town=" + + "789953800&town=794649962&town=789939841&town=789934819&town=789959672&town=" + + "794659043&town=794657035&town=794658938&town=794651746&town=794653732&town=" + + "794653881&town=786397909&town=794695736&town=799724044&town=794695926&town=" + + "789912270&town=794649030&town=794657946&town=794655370&town=794659660&town=" + + "794694617&town=799149862&town=789953234&town=789900476&town=794654995&town=" + + "794671126&town=789908868&town=794652942&town=789955605&town=789901934&town=" + + "789950015&town=789937922&town=789962576&town=786360170&town=789954264&town=" + + "789911738&town=789955416&town=799724187&town=789911879&town=794657462&town=" + + "789912561&town=789913167&town=794655195&town=789938266&town=789952099&town=" + + "794657160&town=789949414&town=794691293&town=794698153&town=789935636&town=" + + "789956374&town=789934635&town=789935475&town=789935085&town=794651425&town=" + + "794654936&town=794655680&town=789908669&town=794652031&town=789951298&town=" + + "789938382&town=794651503&town=794653330&town=817675037&town=789951623&town=" + + "789958999&town=789961555&town=794694050&town=794650241&town=794656286&town=" + + "794692081&town=794660090&town=794665227&town=794665136&town=794669931"; + DefaultHttpRequest defaultHttpRequest = + new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); + + HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(defaultHttpRequest); + + int firstChunk = 10; + int middleChunk = 1024; + + HttpContent part1 = new DefaultHttpContent(Unpooled.wrappedBuffer( + payload.substring(0, firstChunk).getBytes())); + HttpContent part2 = new DefaultHttpContent(Unpooled.wrappedBuffer( + payload.substring(firstChunk, firstChunk + middleChunk).getBytes())); + HttpContent part3 = new DefaultHttpContent(Unpooled.wrappedBuffer( + payload.substring(firstChunk + middleChunk, firstChunk + middleChunk * 2).getBytes())); + HttpContent part4 = new DefaultHttpContent(Unpooled.wrappedBuffer( + payload.substring(firstChunk + middleChunk * 2).getBytes())); + + decoder.offer(part1); + decoder.offer(part2); + decoder.offer(part3); + decoder.offer(part4); + } }