You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ff...@apache.org on 2019/10/23 15:37:04 UTC

[camel] branch camel-2.x updated: [CAMEL-14105]avoid using deprecated org.eclipse.jetty.util.MultiPartInputStreamParser

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

ffang pushed a commit to branch camel-2.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-2.x by this push:
     new b71cf87  [CAMEL-14105]avoid using deprecated org.eclipse.jetty.util.MultiPartInputStreamParser
b71cf87 is described below

commit b71cf87b0d29db8d3ba265f443555e410456d27a
Author: Freeman Fang <fr...@gmail.com>
AuthorDate: Wed Oct 23 11:36:40 2019 -0400

    [CAMEL-14105]avoid using deprecated org.eclipse.jetty.util.MultiPartInputStreamParser
---
 .../camel/component/jetty/JettyHttpComponent.java  | 14 ++++-
 .../camel/component/jetty/JettyHttpEndpoint.java   |  4 +-
 .../camel/component/jetty/MultiPartFilter.java     | 66 ++++++++++++++++++++++
 .../src/main/docs/jetty-component.adoc             |  2 +-
 .../component/jetty9/AttachmentHttpBinding.java    | 18 ++++--
 .../jetty/MultiPartFormWithCustomFilterTest.java   |  2 +-
 6 files changed, 96 insertions(+), 10 deletions(-)

diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
index b07e74c..bad5862 100644
--- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java
@@ -32,6 +32,7 @@ import java.util.Locale;
 import java.util.Map;
 import javax.management.MBeanServer;
 import javax.servlet.Filter;
+import javax.servlet.MultipartConfigElement;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -78,6 +79,8 @@ import org.eclipse.jetty.jmx.MBeanContainer;
 import org.eclipse.jetty.server.AbstractConnector;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.MultiPartFormDataCompliance;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Response;
 import org.eclipse.jetty.server.Server;
@@ -90,7 +93,6 @@ import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.servlets.CrossOriginFilter;
-import org.eclipse.jetty.servlets.MultiPartFilter;
 import org.eclipse.jetty.util.component.Container;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -1344,9 +1346,19 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements
         holder.setAsyncSupported(true);
         holder.setInitParameter(CamelServlet.ASYNC_PARAM, Boolean.toString(endpoint.isAsync()));
         context.addServlet(holder, "/*");
+        
+        File file = File.createTempFile("camel", "");
+        file.delete();
+        
+        //must register the MultipartConfig to make jetty server multipart aware
+        holder.getRegistration().setMultipartConfig(new MultipartConfigElement(file.getParentFile().getAbsolutePath(), -1, -1, 0));
 
         // use rest enabled resolver in case we use rest
         camelServlet.setServletResolveConsumerStrategy(new HttpRestServletResolveConsumerStrategy());
+        
+        //must make RFC7578 as default to avoid using the deprecated MultiPartInputStreamParser
+        connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration()
+             .setMultiPartFormDataCompliance(MultiPartFormDataCompliance.RFC7578);
 
         return camelServlet;
     }
diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
index ac2a460..68344bb 100644
--- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpEndpoint.java
@@ -64,7 +64,7 @@ public abstract class JettyHttpEndpoint extends HttpCommonEndpoint {
     @UriParam(label = "consumer",
             description = "If this option is true, Jetty JMX support will be enabled for this endpoint. See Jetty JMX support for more details.")
     private boolean enableJmx;
-    @UriParam(description = "Whether Jetty org.eclipse.jetty.servlets.MultiPartFilter is enabled or not."
+    @UriParam(description = "Whether org.apache.camel.component.jetty.MultiPartFilter is enabled or not."
             + " You should set this value to false when bridging endpoints, to ensure multipart requests is proxied/bridged as well.")
     private boolean enableMultipartFilter;
     @UriParam(label = "consumer", defaultValue = "true",
@@ -297,7 +297,7 @@ public abstract class JettyHttpEndpoint extends HttpCommonEndpoint {
     }
 
     /**
-     * Whether Jetty org.eclipse.jetty.servlets.MultiPartFilter is enabled or not.
+     * Whether org.apache.camel.component.jetty.MultiPartFilter is enabled or not.
      * You should set this value to false when bridging endpoints, to ensure multipart requests is proxied/bridged as well.
      */
     public void setEnableMultipartFilter(boolean enableMultipartFilter) {
diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/MultiPartFilter.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/MultiPartFilter.java
new file mode 100644
index 0000000..87f141d
--- /dev/null
+++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/MultiPartFilter.java
@@ -0,0 +1,66 @@
+/**
+ * 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.jetty;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+
+/**
+ * To enable handle attachments with Jetty 9 when this filter is set.
+ * <p/>
+ * To replace the deprecated org.eclipse.jetty.servlets.MultiPartFilter
+ * Tell AttachmentHttpBinding to use Servlet 3 HttpServletRequest.getParts API 
+ */
+public class MultiPartFilter implements Filter {
+    
+    public static final String MULTIPART = "populate.multipart";
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws IOException, ServletException {
+        HttpServletRequest srequest = (HttpServletRequest)request;
+        if (srequest.getContentType() == null || !srequest.getContentType().startsWith("multipart/form-data")) {
+            chain.doFilter(request, response);
+        } else {
+            srequest.getParts(); //load and init attachments
+            request.setAttribute(MULTIPART, Boolean.TRUE);
+            chain.doFilter(request, response);
+        }
+    }
+
+    @Override
+    public void destroy() {
+        
+    }
+    
+   
+
+}
diff --git a/components/camel-jetty9/src/main/docs/jetty-component.adoc b/components/camel-jetty9/src/main/docs/jetty-component.adoc
index bb3c4f4..99e76ad 100644
--- a/components/camel-jetty9/src/main/docs/jetty-component.adoc
+++ b/components/camel-jetty9/src/main/docs/jetty-component.adoc
@@ -134,7 +134,7 @@ with the following path and query parameters:
 | Name | Description | Default | Type
 | *chunked* (common) | If this option is false the Servlet will disable the HTTP streaming and set the content-length header on the response | true | boolean
 | *disableStreamCache* (common) | Determines whether or not the raw input stream from Servlet is cached or not (Camel will read the stream into a in memory/overflow to file, Stream caching) cache. By default Camel will cache the Servlet input stream to support reading it multiple times to ensure it Camel can retrieve all data from the stream. However you can set this option to true when you for example need to access the raw stream, such as streaming it directly to a file or other persis [...]
-| *enableMultipartFilter* (common) | Whether Jetty org.eclipse.jetty.servlets.MultiPartFilter is enabled or not. You should set this value to false when bridging endpoints, to ensure multipart requests is proxied/bridged as well. | false | boolean
+| *enableMultipartFilter* (common) | Whether org.apache.camel.component.jetty.MultiPartFilter is enabled or not. You should set this value to false when bridging endpoints, to ensure multipart requests is proxied/bridged as well. | false | boolean
 | *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to filter header to and from Camel message. |  | HeaderFilterStrategy
 | *transferException* (common) | If enabled and an Exchange failed processing on the consumer side, and if the caused Exception was send back serialized in the response as a application/x-java-serialized-object content type. On the producer side the exception will be deserialized and thrown as is, instead of the HttpOperationFailedException. The caused exception is required to be serialized. This is by default turned off. If you enable this then be aware that Java will deserialize the in [...]
 | *httpBinding* (common) | To use a custom HttpBinding to control the mapping between Camel message and HttpClient. |  | HttpBinding
diff --git a/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java b/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
index b72f0c6..10a654b 100644
--- a/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
+++ b/components/camel-jetty9/src/main/java/org/apache/camel/component/jetty9/AttachmentHttpBinding.java
@@ -31,11 +31,11 @@ import javax.servlet.http.Part;
 import org.apache.camel.Attachment;
 import org.apache.camel.Exchange;
 import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.jetty.MultiPartFilter;
 import org.apache.camel.http.common.DefaultHttpBinding;
 import org.apache.camel.http.common.HttpHelper;
 import org.apache.camel.http.common.HttpMessage;
 import org.apache.camel.impl.DefaultAttachment;
-import org.eclipse.jetty.util.MultiPartInputStreamParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,12 +52,11 @@ final class AttachmentHttpBinding extends DefaultHttpBinding {
 
     @Override
     protected void populateAttachments(HttpServletRequest request, HttpMessage message) {
-        Object object = request.getAttribute("org.eclipse.jetty.servlet.MultiPartFile.multiPartInputStream");
-        if (object instanceof MultiPartInputStreamParser) {
-            MultiPartInputStreamParser parser = (MultiPartInputStreamParser)object;
+        Boolean object = (Boolean)request.getAttribute(MultiPartFilter.MULTIPART);
+        if (object != null && object) {
             Collection<Part> parts;
             try {
-                parts = parser.getParts();
+                parts = request.getParts();
                 for (Part part : parts) {
                     DataSource ds = new PartDataSource(part);
                     Attachment attachment = new DefaultAttachment(ds);
@@ -67,6 +66,15 @@ final class AttachmentHttpBinding extends DefaultHttpBinding {
                         }
                     }
                     message.addAttachmentObject(part.getName(), attachment);
+                    String name = part.getSubmittedFileName();
+                    Object value = message.getAttachment(name);
+                    Map<String, Object> headers = message.getHeaders();
+                    if (getHeaderFilterStrategy() != null
+                        && !getHeaderFilterStrategy().applyFilterToExternalHeaders(name, value, message.getExchange())
+                        && name != null) {
+                        HttpHelper.appendHeader(headers, name, value);
+                    }
+                    
                 }
             } catch (Exception e) {
                 throw new RuntimeCamelException("Cannot populate attachments", e);
diff --git a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormWithCustomFilterTest.java b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormWithCustomFilterTest.java
index aeae20a..bb11f4b 100644
--- a/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormWithCustomFilterTest.java
+++ b/components/camel-jetty9/src/test/java/org/apache/camel/component/jetty/MultiPartFormWithCustomFilterTest.java
@@ -37,7 +37,7 @@ import org.apache.commons.httpclient.methods.multipart.FilePart;
 import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.StringPart;
-import org.eclipse.jetty.servlets.MultiPartFilter;
+
 import org.junit.Test;
 
 public class MultiPartFormWithCustomFilterTest extends BaseJettyTest {