This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 29936562310 CAMEL-19899: Process attachments before reading the 
request body for HttpServletRequest
29936562310 is described below

commit 29936562310ba9a431a050059fc501d92064374c
Author: James Netherton <[email protected]>
AuthorDate: Fri Sep 22 11:07:41 2023 +0100

    CAMEL-19899: Process attachments before reading the request body for 
HttpServletRequest
---
 .../camel/http/common/DefaultHttpBinding.java      |  5 +-
 .../component/servlet/MultipartUploadTest.java     | 78 ++++++++++++++++++++++
 .../servlet/ServletCamelRouterTestSupport.java     | 16 +++++
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
index b7cb755c818..73a4549b05b 100644
--- 
a/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
+++ 
b/components/camel-http-common/src/main/java/org/apache/camel/http/common/DefaultHttpBinding.java
@@ -199,6 +199,9 @@ public class DefaultHttpBinding implements HttpBinding {
     protected void readBody(HttpServletRequest request, Message message) {
         LOG.trace("readBody {}", request);
 
+        // Process attachments first as some servlet containers expect the 
body to not have been read at this point
+        populateAttachments(request, message);
+
         // lets parse the body
         Object body = message.getBody();
         // reset the stream cache if the body is the instance of StreamCache
@@ -226,8 +229,6 @@ public class DefaultHttpBinding implements HttpBinding {
                 message.setBody(null);
             }
         }
-
-        populateAttachments(request, message);
     }
 
     protected void populateRequestParameters(HttpServletRequest request, 
Message message) {
diff --git 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/MultipartUploadTest.java
 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/MultipartUploadTest.java
new file mode 100644
index 00000000000..fcc9f05ecd0
--- /dev/null
+++ 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/MultipartUploadTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import jakarta.activation.DataHandler;
+import jakarta.servlet.MultipartConfigElement;
+
+import io.undertow.servlet.api.DeploymentInfo;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.attachment.AttachmentMessage;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MultipartUploadTest extends ServletCamelRouterTestSupport {
+
+    @Override
+    protected DeploymentInfo getDeploymentInfo() {
+        DeploymentInfo deploymentInfo = super.getDeploymentInfo();
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        MultipartConfigElement defaultMultipartConfig = new 
MultipartConfigElement(tmpDir);
+        deploymentInfo.setDefaultMultipartConfig(defaultMultipartConfig);
+        return deploymentInfo;
+    }
+
+    @Test
+    void testMultipartUpload() throws IOException {
+        String content = "Hello World";
+        InputStream inputStream = 
context.getTypeConverter().convertTo(InputStream.class, content);
+        PostMethodWebRequest request
+                = new PostMethodWebRequest(
+                        contextUrl + "/services/multipartUpload", inputStream, 
"multipart/form-data; boundary=----Boundary");
+        WebResponse response = query(request);
+        assertEquals(content, response.getText());
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("servlet:multipartUpload?attachmentMultipartBinding=true")
+                        .process(new Processor() {
+                            @Override
+                            public void process(Exchange exchange) throws 
Exception {
+                                AttachmentMessage message = 
exchange.getMessage(AttachmentMessage.class);
+                                DataHandler file = 
message.getAttachment("file");
+                                if (file != null) {
+                                    
exchange.getMessage().setBody(file.getContent());
+                                } else {
+                                    exchange.getMessage().setBody(null);
+                                }
+                            }
+                        });
+            }
+        };
+    }
+}
diff --git 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/ServletCamelRouterTestSupport.java
 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/ServletCamelRouterTestSupport.java
index d1da5d6a98c..c9f1debc04c 100644
--- 
a/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/ServletCamelRouterTestSupport.java
+++ 
b/components/camel-servlet/src/test/java/org/apache/camel/component/servlet/ServletCamelRouterTestSupport.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Field;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -36,6 +37,7 @@ import io.undertow.servlet.api.DeploymentManager;
 import org.apache.camel.test.AvailablePortFinder;
 import org.apache.camel.test.junit5.CamelTestSupport;
 import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 
@@ -101,10 +103,24 @@ public class ServletCamelRouterTestSupport extends 
CamelTestSupport {
         con.setRequestMethod(req.getMethod());
         if (req instanceof PostMethodWebRequest) {
             con.setDoOutput(true);
+            String contentType = con.getRequestProperty("Content-Type");
+            boolean isMultipart = ObjectHelper.isNotEmpty(contentType) && 
contentType.startsWith("multipart/form-data");
+            if (isMultipart) {
+                StringBuilder builder = new StringBuilder();
+                builder.append("------Boundary\r\n");
+                builder.append("Content-Disposition: form-data; name=\"file\"; 
filename=\"test.txt\"\r\n");
+                builder.append("Content-Type: 
application/octet-stream\r\n\r\n");
+                
con.getOutputStream().write(builder.toString().getBytes(StandardCharsets.UTF_8));
+            }
+
             InputStream is = ((PostMethodWebRequest) req).content;
             if (is != null) {
                 IOHelper.copy(is, con.getOutputStream());
             }
+
+            if (isMultipart) {
+                
con.getOutputStream().write("\r\n------Boundary--\r\n".getBytes(StandardCharsets.UTF_8));
+            }
         }
         int code = con.getResponseCode();
         if (exceptionsThrownOnErrorStatus && code >= 
HttpURLConnection.HTTP_BAD_REQUEST) {

Reply via email to