diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java index 45dd7d8339..0b757991d1 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoder.java @@ -15,7 +15,6 @@ */ package io.netty.handler.codec.http.multipart; -import static io.netty.buffer.Unpooled.wrappedBuffer; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.DecoderResult; @@ -44,6 +43,8 @@ import java.util.ListIterator; import java.util.Map; import java.util.regex.Pattern; +import static io.netty.buffer.Unpooled.*; + /** * This encoder will help to encode Request for a FORM as POST. */ @@ -111,7 +112,7 @@ public class HttpPostRequestEncoder implements ChunkedInput { /** * The final Multipart List of InterfaceHttpData including encoding */ - private final List multipartHttpDatas; + final List multipartHttpDatas; /** * Does this request is a Multipart request @@ -121,12 +122,12 @@ public class HttpPostRequestEncoder implements ChunkedInput { /** * If multipart, this is the boundary for the flobal multipart */ - private String multipartDataBoundary; + String multipartDataBoundary; /** * If multipart, there could be internal multiparts (mixed) to the global multipart. Only one level is allowed. */ - private String multipartMixedBoundary; + String multipartMixedBoundary; /** * To check if the header has been finalized */ @@ -571,16 +572,48 @@ public class HttpPostRequestEncoder implements ChunkedInput { .size() - 2); // remove past size globalBodySize -= pastAttribute.size(); - String replacement = "--" + multipartDataBoundary + "\r\n"; - replacement += HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + HttpPostBodyUtil.FORM_DATA - + "; " + HttpPostBodyUtil.NAME + "=\"" + fileUpload.getName() + "\"\r\n"; - replacement += HttpHeaders.Names.CONTENT_TYPE + ": " + HttpPostBodyUtil.MULTIPART_MIXED + "; " - + HttpHeaders.Values.BOUNDARY + '=' + multipartMixedBoundary + "\r\n\r\n"; - replacement += "--" + multipartMixedBoundary + "\r\n"; - replacement += HttpPostBodyUtil.CONTENT_DISPOSITION + ": " + HttpPostBodyUtil.ATTACHMENT + "; " - + HttpPostBodyUtil.FILENAME + "=\"" + fileUpload.getFilename() + "\"\r\n"; - pastAttribute.setValue(replacement, 1); + StringBuilder replacement = new StringBuilder( + 139 + multipartDataBoundary.length() + multipartMixedBoundary.length() * 2 + + fileUpload.getFilename().length() + fileUpload.getName().length()); + + replacement.append("--"); + replacement.append(multipartDataBoundary); + replacement.append("\r\n"); + + replacement.append(HttpPostBodyUtil.CONTENT_DISPOSITION); + replacement.append(": "); + replacement.append(HttpPostBodyUtil.FORM_DATA); + replacement.append("; "); + replacement.append(HttpPostBodyUtil.NAME); + replacement.append("=\""); + replacement.append(fileUpload.getName()); + replacement.append("\"\r\n"); + + replacement.append(HttpHeaders.Names.CONTENT_TYPE); + replacement.append(": "); + replacement.append(HttpPostBodyUtil.MULTIPART_MIXED); + replacement.append("; "); + replacement.append(HttpHeaders.Values.BOUNDARY); + replacement.append('='); + replacement.append(multipartMixedBoundary); + replacement.append("\r\n\r\n"); + + replacement.append("--"); + replacement.append(multipartMixedBoundary); + replacement.append("\r\n"); + + replacement.append(HttpPostBodyUtil.CONTENT_DISPOSITION); + replacement.append(": "); + replacement.append(HttpPostBodyUtil.ATTACHMENT); + replacement.append("; "); + replacement.append(HttpPostBodyUtil.FILENAME); + replacement.append("=\""); + replacement.append(fileUpload.getFilename()); + replacement.append("\"\r\n"); + + pastAttribute.setValue(replacement.toString(), 1); pastAttribute.setValue("", 2); + // update past size globalBodySize += pastAttribute.size(); @@ -677,10 +710,9 @@ public class HttpPostRequestEncoder implements ChunkedInput { headers.remove(HttpHeaders.Names.CONTENT_TYPE); for (String contentType : contentTypes) { // "multipart/form-data; boundary=--89421926422648" - if (contentType.toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA.toString())) { - // ignore - } else if (contentType.toLowerCase().startsWith( - HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.toString())) { + String lowercased = contentType.toLowerCase(); + if (lowercased.startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA.toString()) || + lowercased.startsWith(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED.toString())) { // ignore } else { headers.add(HttpHeaders.Names.CONTENT_TYPE, contentType); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoderTest.java index 3e478c2b94..7826f8b83f 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestEncoderTest.java @@ -15,22 +15,19 @@ */ package io.netty.handler.codec.http.multipart; -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import java.io.File; -import java.lang.reflect.Field; -import java.util.List; - -import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder.EncoderMode; - import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder.EncoderMode; import io.netty.util.CharsetUtil; +import org.junit.Test; + +import java.io.File; +import java.util.List; + +import static org.junit.Assert.*; /** {@link HttpPostRequestEncoder} test case. */ public class HttpPostRequestEncoderTest { @@ -45,7 +42,7 @@ public class HttpPostRequestEncoderTest { encoder.addBodyAttribute("foo", "bar"); encoder.addBodyFileUpload("quux", file1, "text/plain", false); - String multipartDataBoundary = getEncoderField(encoder, "multipartDataBoundary"); + String multipartDataBoundary = encoder.multipartDataBoundary; String content = getRequestBody(encoder); String expected = "--" + multipartDataBoundary + "\r\n" + @@ -80,8 +77,8 @@ public class HttpPostRequestEncoderTest { // We have to query the value of these two fields before finalizing // the request, which unsets one of them. - String multipartDataBoundary = getEncoderField(encoder, "multipartDataBoundary"); - String multipartMixedBoundary = getEncoderField(encoder, "multipartMixedBoundary"); + String multipartDataBoundary = encoder.multipartDataBoundary; + String multipartMixedBoundary = encoder.multipartMixedBoundary; String content = getRequestBody(encoder); String expected = "--" + multipartDataBoundary + "\r\n" + @@ -128,7 +125,7 @@ public class HttpPostRequestEncoderTest { encoder.addBodyFileUpload("quux", file1, "text/plain", false); encoder.addBodyFileUpload("quux", file2, "text/plain", false); - String multipartDataBoundary = getEncoderField(encoder, "multipartDataBoundary"); + String multipartDataBoundary = encoder.multipartDataBoundary; String content = getRequestBody(encoder); String expected = "--" + multipartDataBoundary + "\r\n" + @@ -167,7 +164,7 @@ public class HttpPostRequestEncoderTest { encoder.addBodyAttribute("foo", "bar"); encoder.addBodyFileUpload("quux", file1, "text/plain", false); - String multipartDataBoundary = getEncoderField(encoder, "multipartDataBoundary"); + String multipartDataBoundary = encoder.multipartDataBoundary; String content = getRequestBody(encoder); String expected = "--" + multipartDataBoundary + "\r\n" + @@ -188,10 +185,10 @@ public class HttpPostRequestEncoderTest { assertEquals(expected, content); } - private String getRequestBody(HttpPostRequestEncoder encoder) throws Exception { + private static String getRequestBody(HttpPostRequestEncoder encoder) throws Exception { encoder.finalizeRequest(); - List chunks = getEncoderField(encoder, "multipartHttpDatas"); + List chunks = encoder.multipartHttpDatas; ByteBuf[] buffers = new ByteBuf[chunks.size()]; for (int i = 0; i < buffers.length; i++) { @@ -205,15 +202,4 @@ public class HttpPostRequestEncoderTest { return Unpooled.wrappedBuffer(buffers).toString(CharsetUtil.UTF_8); } - - private A getEncoderField(HttpPostRequestEncoder encoder, String fieldName) throws Exception { - return this.getField(encoder, HttpPostRequestEncoder.class, fieldName); - } - - @SuppressWarnings("unchecked") - private A getField(T instance, Class klass, String fieldName) throws Exception { - Field requestField = klass.getDeclaredField(fieldName); - requestField.setAccessible(true); - return (A) requestField.get(instance); - } }