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) {