You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2018/06/11 08:29:01 UTC

[GitHub] liubao68 closed pull request #758: [SCB-203] Servlet rest support upload

liubao68 closed pull request #758: [SCB-203] Servlet rest support upload
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/758
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/common/common-rest/pom.xml b/common/common-rest/pom.xml
index d94f44795..c3a80de61 100644
--- a/common/common-rest/pom.xml
+++ b/common/common-rest/pom.xml
@@ -51,7 +51,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.servicecomb</groupId>
-      <artifactId>foundation-metrics</artifactId>
+      <artifactId>foundation-test-scaffolding</artifactId>
     </dependency>
   </dependencies>
 </project>
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
index 4937213a6..c3b72abba 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
@@ -58,4 +58,16 @@ private RestConst() {
   public static final String CONSUMER_HEADER = "servicecomb-rest-consumer-header";
 
   public static final String READ_STREAM_PART = "servicecomb-readStreamPart";
+
+  public static final String UPLOAD_DIR = "cse.uploads.directory";
+
+  // limit of one upload file, only available for servlet rest transport
+  public static final String UPLOAD_MAX_FILE_SIZE = "cse.uploads.maxFileSize";
+
+  // limit of upload request body
+  public static final String UPLOAD_MAX_SIZE = "cse.uploads.maxSize";
+
+  // the size threshold after which files will be written to disk
+  // only available for servlet rest transport
+  public static final String UPLOAD_FILE_SIZE_THRESHOLD = "cse.uploads.fileSizeThreshold";
 }
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java
new file mode 100644
index 000000000..b487a966f
--- /dev/null
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java
@@ -0,0 +1,102 @@
+/*
+ * 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.servicecomb.common.rest;
+
+import javax.servlet.MultipartConfigElement;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.DynamicPropertyFactory;
+
+public class UploadConfig {
+  private static final Logger LOGGER = LoggerFactory.getLogger(UploadConfig.class);
+
+  /**
+   * null means not support upload
+   */
+  private String location;
+
+  /**
+   * limit of one upload file, only available for servlet rest transport
+   */
+  private long maxFileSize;
+
+  /**
+   * limit of upload request body
+   */
+  private long maxSize;
+
+  /**
+   * the size threshold after which files will be written to disk, only available for servlet rest transport
+   */
+  private int fileSizeThreshold;
+
+  public UploadConfig() {
+    location = DynamicPropertyFactory.getInstance().getStringProperty(RestConst.UPLOAD_DIR, null).get();
+    maxFileSize = DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_FILE_SIZE, -1L).get();
+    maxSize = DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_SIZE, -1L).get();
+    fileSizeThreshold = DynamicPropertyFactory.getInstance().getIntProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 0)
+        .get();
+  }
+
+  public String getLocation() {
+    return location;
+  }
+
+  public void setLocation(String location) {
+    this.location = location;
+  }
+
+  public long getMaxFileSize() {
+    return maxFileSize;
+  }
+
+  public void setMaxFileSize(long maxFileSize) {
+    this.maxFileSize = maxFileSize;
+  }
+
+  public long getMaxSize() {
+    return maxSize;
+  }
+
+  public void setMaxSize(long maxSize) {
+    this.maxSize = maxSize;
+  }
+
+  public int getFileSizeThreshold() {
+    return fileSizeThreshold;
+  }
+
+  public void setFileSizeThreshold(int fileSizeThreshold) {
+    this.fileSizeThreshold = fileSizeThreshold;
+  }
+
+  public MultipartConfigElement toMultipartConfigElement() {
+    String location = DynamicPropertyFactory.getInstance().getStringProperty(RestConst.UPLOAD_DIR, null).get();
+    if (location == null) {
+      LOGGER.info("{} is null, not support upload.", RestConst.UPLOAD_DIR);
+      return null;
+    }
+
+    return new MultipartConfigElement(
+        location,
+        DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_FILE_SIZE, -1L).get(),
+        DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_SIZE, -1L).get(),
+        DynamicPropertyFactory.getInstance().getIntProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 0).get());
+  }
+}
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
index c6bb7e94f..0ab6ff4b1 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java
@@ -106,7 +106,7 @@ protected void doEndWithUpload() {
     request.setChunked(true);
 
     String boundary = "boundary" + UUID.randomUUID().toString();
-    putHeader(CONTENT_TYPE, MULTIPART_FORM_DATA + "; boundary=" + boundary);
+    putHeader(CONTENT_TYPE, MULTIPART_FORM_DATA + "; charset=UTF-8; boundary=" + boundary);
 
     genBodyForm(boundary);
 
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java
new file mode 100644
index 000000000..00d6f7461
--- /dev/null
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java
@@ -0,0 +1,86 @@
+/*
+ * 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.servicecomb.common.rest;
+
+import javax.servlet.MultipartConfigElement;
+
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestUploadConfig {
+  @Before
+  public void setUp() {
+    ArchaiusUtils.resetConfig();
+  }
+
+  @After
+  public void tearDown() {
+    ArchaiusUtils.resetConfig();
+  }
+
+  @Test
+  public void getMultipartConfig_notSupport() {
+    UploadConfig uploadConfig = new UploadConfig();
+
+    Assert.assertNull(uploadConfig.toMultipartConfigElement());
+    Assert.assertEquals(-1L, uploadConfig.getMaxFileSize());
+    Assert.assertEquals(-1L, uploadConfig.getMaxSize());
+    Assert.assertEquals(0, uploadConfig.getFileSizeThreshold());
+  }
+
+  @Test
+  public void getMultipartConfig_default() {
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_DIR, "upload");
+
+    UploadConfig uploadConfig = new UploadConfig();
+    MultipartConfigElement multipartConfigElement = uploadConfig.toMultipartConfigElement();
+
+    Assert.assertEquals("upload", uploadConfig.getLocation());
+    Assert.assertEquals(-1L, uploadConfig.getMaxFileSize());
+    Assert.assertEquals(-1L, uploadConfig.getMaxSize());
+    Assert.assertEquals(0, uploadConfig.getFileSizeThreshold());
+
+    Assert.assertEquals("upload", multipartConfigElement.getLocation());
+    Assert.assertEquals(-1L, multipartConfigElement.getMaxFileSize());
+    Assert.assertEquals(-1L, multipartConfigElement.getMaxRequestSize());
+    Assert.assertEquals(0, multipartConfigElement.getFileSizeThreshold());
+  }
+
+  @Test
+  public void getMultipartConfig_config() {
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_DIR, "upload");
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_MAX_FILE_SIZE, 1);
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_MAX_SIZE, 2);
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 3);
+
+    UploadConfig uploadConfig = new UploadConfig();
+    MultipartConfigElement multipartConfigElement = uploadConfig.toMultipartConfigElement();
+
+    Assert.assertEquals("upload", uploadConfig.getLocation());
+    Assert.assertEquals(1, uploadConfig.getMaxFileSize());
+    Assert.assertEquals(2, uploadConfig.getMaxSize());
+    Assert.assertEquals(3, uploadConfig.getFileSizeThreshold());
+
+    Assert.assertEquals("upload", multipartConfigElement.getLocation());
+    Assert.assertEquals(1, multipartConfigElement.getMaxFileSize());
+    Assert.assertEquals(2, multipartConfigElement.getMaxRequestSize());
+    Assert.assertEquals(3, multipartConfigElement.getFileSizeThreshold());
+  }
+}
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
index d14c10e36..137063fd4 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java
@@ -16,7 +16,9 @@
  */
 package org.apache.servicecomb.common.rest.codec.param;
 
+import java.util.HashMap;
 import java.util.Map;
+import java.util.UUID;
 
 import javax.servlet.http.Part;
 import javax.ws.rs.core.MediaType;
@@ -141,4 +143,29 @@ public void testAttachOnPartIsNull() {
     Map<String, Part> uploads = Deencapsulation.getField(restClientRequest, "uploads");
     Assert.assertTrue(uploads.isEmpty());
   }
+
+  @Test
+  public void doEndWithUpload() {
+    Map<String, String> headers = new HashMap<>();
+    new MockUp<HttpClientRequest>(request) {
+      @Mock
+      HttpClientRequest putHeader(String name, String value) {
+        headers.put(name, value);
+        return request;
+      }
+    };
+
+    UUID uuid = new UUID(0, 0);
+    new Expectations(UUID.class) {
+      {
+        UUID.randomUUID();
+        result = uuid;
+      }
+    };
+    RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null);
+    restClientRequest.doEndWithUpload();
+
+    Assert.assertEquals("multipart/form-data; charset=UTF-8; boundary=boundary00000000-0000-0000-0000-000000000000",
+        headers.get(HttpHeaders.CONTENT_TYPE.toString()));
+  }
 }
diff --git a/demo/demo-server-servlet/pom.xml b/demo/demo-server-servlet/pom.xml
index 4c5292ba1..7ee9e8e3e 100644
--- a/demo/demo-server-servlet/pom.xml
+++ b/demo/demo-server-servlet/pom.xml
@@ -33,7 +33,7 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.servicecomb.demo</groupId>
-      <artifactId>pojo-server</artifactId>
+      <artifactId>springmvc-server</artifactId>
     </dependency>
   </dependencies>
 
diff --git a/demo/demo-server-servlet/src/main/resources/microservice.yaml b/demo/demo-server-servlet/src/main/resources/microservice.yaml
index cbcc3220e..469a68eed 100644
--- a/demo/demo-server-servlet/src/main/resources/microservice.yaml
+++ b/demo/demo-server-servlet/src/main/resources/microservice.yaml
@@ -15,7 +15,12 @@
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
 
+cse-config-order: 100
+
 servicecomb:
   rest:
     servlet:
       urlPattern: /rest/*
+    address: 0.0.0.0:8080?sslEnabled=false
+  highway:
+    address: 0.0.0.0:7070?sslEnabled=false
diff --git a/demo/demo-server-servlet/src/main/webapp/WEB-INF/web.xml b/demo/demo-server-servlet/src/main/webapp/WEB-INF/web.xml
index 0cddbc2de..cb2b22e58 100644
--- a/demo/demo-server-servlet/src/main/webapp/WEB-INF/web.xml
+++ b/demo/demo-server-servlet/src/main/webapp/WEB-INF/web.xml
@@ -24,7 +24,6 @@
     <param-name>contextConfigLocation</param-name>
     <param-value>
       classpath*:META-INF/spring/*.bean.xml
-      classpath*:app-config.xml
     </param-value>
   </context-param>
 
diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
index 8ee4ab4a3..35540611a 100644
--- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
+++ b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java
@@ -50,8 +50,9 @@ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx
     String clientSignature = requestEx.getHeader("signature");
     LOGGER.info("check request signature, client: {}, server: {}.", clientSignature, signature);
     if (!signature.equals(clientSignature)) {
-      LOGGER.error("check request signature failed");
-      return Response.create(Status.UNAUTHORIZED, "check request signature failed");
+      LOGGER.error("check request signature failed: {}", invocation.getInvocationQualifiedName());
+      return Response
+          .create(Status.UNAUTHORIZED, "check request signature failed: " + invocation.getInvocationQualifiedName());
     }
 
     return null;
diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java
index 1435d20d5..33e485b1f 100644
--- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java
+++ b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java
@@ -22,6 +22,9 @@
 import java.util.Comparator;
 import java.util.List;
 
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.lang.StringUtils;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
 
@@ -55,9 +58,11 @@ public static String genSignature(HttpServletRequestEx requestEx) {
       }
     }
 
-    byte[] bytes = requestEx.getBodyBytes();
-    if (bytes != null) {
-      hasher.putBytes(bytes, 0, requestEx.getBodyBytesLength());
+    if (!StringUtils.startsWithIgnoreCase(requestEx.getContentType(), MediaType.APPLICATION_FORM_URLENCODED)) {
+      byte[] bytes = requestEx.getBodyBytes();
+      if (bytes != null) {
+        hasher.putBytes(bytes, 0, requestEx.getBodyBytesLength());
+      }
     }
 
     return hasher.hash().toString();
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
index 8cae971f5..8d96d9ccf 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java
@@ -115,10 +115,10 @@ public String fileUpload(@RequestPart(name = "file1") MultipartFile file1,
   @RequestMapping(path = "/responseEntity", method = RequestMethod.POST)
   public ResponseEntity<Date> responseEntity(InvocationContext c1, @RequestAttribute("date") Date date) {
     HttpHeaders headers = new HttpHeaders();
-    headers.add("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE).toString());
+    headers.add("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE));
 
     InvocationContext c2 = ContextUtils.getInvocationContext();
-    headers.add("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE).toString());
+    headers.add("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE));
 
     return new ResponseEntity<>(date, headers, HttpStatus.ACCEPTED);
   }
@@ -127,13 +127,7 @@ public String fileUpload(@RequestPart(name = "file1") MultipartFile file1,
       @ResponseHeader(name = "h2", response = String.class)})
   @RequestMapping(path = "/responseEntity", method = RequestMethod.PATCH)
   public ResponseEntity<Date> responseEntityPATCH(InvocationContext c1, @RequestAttribute("date") Date date) {
-    HttpHeaders headers = new HttpHeaders();
-    headers.add("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE).toString());
-
-    InvocationContext c2 = ContextUtils.getInvocationContext();
-    headers.add("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE).toString());
-
-    return new ResponseEntity<>(date, headers, HttpStatus.ACCEPTED);
+    return responseEntity(c1, date);
   }
 
   @ApiResponse(code = 200, response = User.class, message = "")
diff --git a/demo/perf/src/main/resources/microservice.yaml b/demo/perf/src/main/resources/microservice.yaml
index 254a85be9..ffa9c2327 100644
--- a/demo/perf/src/main/resources/microservice.yaml
+++ b/demo/perf/src/main/resources/microservice.yaml
@@ -41,7 +41,7 @@ servicecomb:
     transport: rest
   metrics:
     window_time: 1000
-servicecomb.metrics.publisher.defaultLog.enabled: true
+    publisher.defaultLog.enabled: true
 
 sync-count: 10
 async-count: 20
diff --git a/spring-boot-starter/spring-boot-starter-transport/src/main/java/org/apache/servicecomb/springboot/starter/transport/RestServletInitializer.java b/spring-boot-starter/spring-boot-starter-transport/src/main/java/org/apache/servicecomb/springboot/starter/transport/RestServletInitializer.java
index 0055c5b0b..175f567e4 100644
--- a/spring-boot-starter/spring-boot-starter-transport/src/main/java/org/apache/servicecomb/springboot/starter/transport/RestServletInitializer.java
+++ b/spring-boot-starter/spring-boot-starter-transport/src/main/java/org/apache/servicecomb/springboot/starter/transport/RestServletInitializer.java
@@ -24,7 +24,6 @@
 import javax.servlet.ServletException;
 
 import org.apache.commons.configuration.Configuration;
-import org.apache.servicecomb.transport.rest.servlet.RestServletInjector;
 import org.apache.servicecomb.transport.rest.servlet.ServletConfig;
 import org.apache.servicecomb.transport.rest.servlet.ServletUtils;
 import org.slf4j.Logger;
@@ -60,8 +59,8 @@ public void onStartup(ServletContext servletContext) throws ServletException {
         Configuration configuration = (Configuration) DynamicPropertyFactory.getBackingConfigurationSource();
         configuration.setProperty(ServletConfig.KEY_SERVLET_URL_PATTERN, ServletConfig.DEFAULT_URL_PATTERN);
       }
-      RestServletInjector.defaultInject(servletContext);
-      ServletUtils.saveUrlPrefix(servletContext);
+
+      ServletUtils.init(servletContext);
     } catch (IOException e) {
       throw new ServletException(e);
     }
diff --git a/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/CseXmlWebApplicationContext.java b/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/CseXmlWebApplicationContext.java
index ee2fa2c04..59918d524 100644
--- a/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/CseXmlWebApplicationContext.java
+++ b/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/CseXmlWebApplicationContext.java
@@ -53,8 +53,7 @@ protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory b
     super.invokeBeanFactoryPostProcessors(beanFactory);
 
     // inject servlet after config installed and before transport init
-    RestServletInjector.defaultInject(getServletContext());
-    ServletUtils.saveUrlPrefix(getServletContext());
+    ServletUtils.init(getServletContext());
   }
 
   @Override
diff --git a/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/ServletUtils.java b/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/ServletUtils.java
index a73b1499f..94c726f2a 100644
--- a/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/ServletUtils.java
+++ b/transports/transport-rest/transport-rest-servlet/src/main/java/org/apache/servicecomb/transport/rest/servlet/ServletUtils.java
@@ -17,14 +17,18 @@
 
 package org.apache.servicecomb.transport.rest.servlet;
 
+import java.io.File;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import javax.servlet.MultipartConfigElement;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRegistration;
+import javax.servlet.ServletRegistration.Dynamic;
 
+import org.apache.servicecomb.common.rest.UploadConfig;
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
 import org.apache.servicecomb.foundation.common.net.IpPort;
 import org.apache.servicecomb.foundation.common.net.NetUtils;
@@ -75,9 +79,7 @@ static void checkUrlPattern(String urlPattern) {
 
   static String[] filterUrlPatterns(Collection<String> urlPatterns) {
     return urlPatterns.stream()
-        .filter(pattern -> {
-          return !pattern.trim().isEmpty();
-        })
+        .filter(pattern -> !pattern.trim().isEmpty())
         .filter(pattern -> {
           checkUrlPattern(pattern.trim());
           return true;
@@ -86,13 +88,7 @@ static void checkUrlPattern(String urlPattern) {
   }
 
   static String[] collectUrlPatterns(ServletContext servletContext, Class<?> servletCls) {
-    List<ServletRegistration> servlets = servletContext.getServletRegistrations()
-        .values()
-        .stream()
-        .filter(predicate -> {
-          return predicate.getClassName().equals(servletCls.getName());
-        })
-        .collect(Collectors.toList());
+    List<ServletRegistration> servlets = findServletRegistrations(servletContext, servletCls);
     if (servlets.isEmpty()) {
       return new String[] {};
     }
@@ -108,13 +104,22 @@ static void checkUrlPattern(String urlPattern) {
     return filterUrlPatterns(mappings);
   }
 
+  static List<ServletRegistration> findServletRegistrations(ServletContext servletContext,
+      Class<?> servletCls) {
+    return servletContext.getServletRegistrations()
+        .values()
+        .stream()
+        .filter(predicate -> predicate.getClassName().equals(servletCls.getName()))
+        .collect(Collectors.toList());
+  }
+
   static String collectUrlPrefix(ServletContext servletContext, Class<?> servletCls) {
     String[] urlPatterns = collectUrlPatterns(servletContext, servletCls);
     if (urlPatterns.length == 0) {
       return null;
     }
 
-    // even have multiple urlPattern, we only choose a to set as urlPrefix
+    // even have multiple urlPattern, we only choose one to set as urlPrefix
     // only make sure sdk can invoke
     String urlPattern = urlPatterns[0];
     return servletContext.getContextPath() + urlPattern.substring(0, urlPattern.length() - 2);
@@ -130,4 +135,45 @@ public static void saveUrlPrefix(ServletContext servletContext) {
     System.setProperty(Const.URL_PREFIX, urlPrefix);
     LOGGER.info("UrlPrefix of this instance is \"{}\".", urlPrefix);
   }
+
+  static File createUploadDir(ServletContext servletContext, String location) {
+    // If relative, it is relative to TEMPDIR
+    File dir = new File(location);
+    if (!dir.isAbsolute()) {
+      dir = new File((File) servletContext.getAttribute(ServletContext.TEMPDIR), location).getAbsoluteFile();
+    }
+
+    if (!dir.exists()) {
+      dir.mkdirs();
+    }
+
+    return dir;
+  }
+
+  static void setServletParameters(ServletContext servletContext) {
+    UploadConfig uploadConfig = new UploadConfig();
+    MultipartConfigElement multipartConfig = uploadConfig.toMultipartConfigElement();
+    if (multipartConfig == null) {
+      return;
+    }
+
+    File dir = createUploadDir(servletContext, multipartConfig.getLocation());
+    LOGGER.info("set uploads directory to {}.", dir.getAbsolutePath());
+
+    List<ServletRegistration> servlets = findServletRegistrations(servletContext, RestServlet.class);
+    for (ServletRegistration servletRegistration : servlets) {
+      if (!Dynamic.class.isInstance(servletRegistration)) {
+        continue;
+      }
+
+      Dynamic dynamic = (Dynamic) servletRegistration;
+      dynamic.setMultipartConfig(multipartConfig);
+    }
+  }
+
+  public static void init(ServletContext servletContext) {
+    RestServletInjector.defaultInject(servletContext);
+    ServletUtils.saveUrlPrefix(servletContext);
+    setServletParameters(servletContext);
+  }
 }
diff --git a/transports/transport-rest/transport-rest-servlet/src/test/java/org/apache/servicecomb/transport/rest/servlet/TestServletUtils.java b/transports/transport-rest/transport-rest-servlet/src/test/java/org/apache/servicecomb/transport/rest/servlet/TestServletUtils.java
index bf171988c..28506948c 100644
--- a/transports/transport-rest/transport-rest-servlet/src/test/java/org/apache/servicecomb/transport/rest/servlet/TestServletUtils.java
+++ b/transports/transport-rest/transport-rest-servlet/src/test/java/org/apache/servicecomb/transport/rest/servlet/TestServletUtils.java
@@ -17,25 +17,50 @@
 
 package org.apache.servicecomb.transport.rest.servlet;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
+import javax.servlet.MultipartConfigElement;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletRegistration;
+import javax.servlet.ServletRegistration.Dynamic;
+import javax.servlet.http.HttpServlet;
 
+import org.apache.servicecomb.common.rest.RestConst;
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.serviceregistry.api.Const;
 import org.hamcrest.Matchers;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import mockit.Expectations;
+import mockit.Mock;
+import mockit.MockUp;
 import mockit.Mocked;
 
 public class TestServletUtils {
+  @Before
+  public void setUp() {
+    ArchaiusUtils.resetConfig();
+  }
+
+  @After
+  public void tearDown() {
+    ArchaiusUtils.resetConfig();
+  }
+
   @Test
   public void testCheckUrlPatternNormal() {
     ServletUtils.checkUrlPattern("/*");
@@ -179,4 +204,96 @@ public void testSaveUrlPrefixNormal(@Mocked ServletContext servletContext,
     Assert.assertThat(System.getProperty(Const.URL_PREFIX), Matchers.is("/root/rest"));
     System.clearProperty(Const.URL_PREFIX);
   }
+
+  @Test
+  public void createUploadDir_relative(@Mocked ServletContext servletContext) throws IOException {
+    File tempDir = Files.createTempDirectory("temp").toFile();
+    new Expectations() {
+      {
+        servletContext.getAttribute(ServletContext.TEMPDIR);
+        result = tempDir;
+      }
+    };
+
+    File expectDir = new File(tempDir, "upload");
+    Assert.assertFalse(expectDir.exists());
+
+    File dir = ServletUtils.createUploadDir(servletContext, "upload");
+    Assert.assertTrue(expectDir.exists());
+    Assert.assertEquals(expectDir.getAbsolutePath(), dir.getAbsolutePath());
+
+    dir.delete();
+    Assert.assertFalse(expectDir.exists());
+
+    tempDir.delete();
+    Assert.assertFalse(tempDir.exists());
+  }
+
+  @Test
+  public void createUploadDir_absolute(@Mocked ServletContext servletContext) throws IOException {
+    File tempDir = Files.createTempDirectory("temp").toFile();
+
+    File expectDir = new File(tempDir, "upload");
+    Assert.assertFalse(expectDir.exists());
+
+    File dir = ServletUtils.createUploadDir(servletContext, expectDir.getAbsolutePath());
+    Assert.assertTrue(expectDir.exists());
+    Assert.assertEquals(expectDir.getAbsolutePath(), dir.getAbsolutePath());
+
+    dir.delete();
+    Assert.assertFalse(expectDir.exists());
+
+    tempDir.delete();
+    Assert.assertFalse(tempDir.exists());
+  }
+
+  @Test
+  public void setServletParameters_notSupportUpload() {
+    // not support upload will not set parameters to servlet, so servletContext is null will not throw exception
+    ServletUtils.setServletParameters(null);
+  }
+
+  @Test
+  public void setServletParameters_supportUpload(@Mocked ServletContext servletContext, @Mocked Dynamic d1,
+      @Mocked ServletRegistration d2) throws IOException {
+    Map<String, ServletRegistration> servletRegistrations = new HashMap<>();
+    servletRegistrations.put("d1", d1);
+    servletRegistrations.put("d2", d2);
+    new Expectations() {
+      {
+        servletContext.getServletRegistrations();
+        result = servletRegistrations;
+        d1.getClassName();
+        result = RestServlet.class.getName();
+        d2.getClassName();
+        result = HttpServlet.class.getName();
+      }
+    };
+
+    List<MultipartConfigElement> multipartConfigs = new ArrayList<>();
+    new MockUp<Dynamic>(d1) {
+      @Mock
+      void setMultipartConfig(MultipartConfigElement multipartConfig) {
+        multipartConfigs.add(multipartConfig);
+      }
+    };
+
+    File tempDir = Files.createTempDirectory("temp").toFile();
+    File uploadDir = new File(tempDir, "upload");
+    ArchaiusUtils.setProperty(RestConst.UPLOAD_DIR, uploadDir.getAbsolutePath());
+
+    ServletUtils.setServletParameters(servletContext);
+
+    Assert.assertEquals(1, multipartConfigs.size());
+
+    MultipartConfigElement multipartConfigElement = multipartConfigs.get(0);
+    Assert.assertEquals(uploadDir.getAbsolutePath(), multipartConfigElement.getLocation());
+    Assert.assertEquals(-1, multipartConfigElement.getMaxFileSize());
+    Assert.assertEquals(-1, multipartConfigElement.getMaxRequestSize());
+    Assert.assertEquals(0, multipartConfigElement.getFileSizeThreshold());
+
+    uploadDir.delete();
+    tempDir.delete();
+    Assert.assertFalse(tempDir.exists());
+  }
 }
diff --git a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/AbstractVertxHttpDispatcher.java b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/AbstractVertxHttpDispatcher.java
index 7999161a8..5d357c1f8 100644
--- a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/AbstractVertxHttpDispatcher.java
+++ b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/AbstractVertxHttpDispatcher.java
@@ -17,17 +17,14 @@
 
 package org.apache.servicecomb.transport.rest.vertx;
 
-import static io.vertx.ext.web.handler.BodyHandler.DEFAULT_BODY_LIMIT;
-
 import java.util.List;
 
+import org.apache.servicecomb.common.rest.UploadConfig;
 import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
 import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.netflix.config.DynamicPropertyFactory;
-
 import io.vertx.ext.web.handler.BodyHandler;
 
 public abstract class AbstractVertxHttpDispatcher implements VertxHttpDispatcher {
@@ -38,13 +35,15 @@
   protected BodyHandler createBodyHandler() {
     RestBodyHandler bodyHandler = new RestBodyHandler();
 
-    String uploadsDirectory =
-        DynamicPropertyFactory.getInstance().getStringProperty("cse.uploads.directory", null).get();
-    bodyHandler.setUploadsDirectory(uploadsDirectory);
+    UploadConfig uploadConfig = new UploadConfig();
+
+    bodyHandler.setUploadsDirectory(uploadConfig.getLocation());
     bodyHandler.setDeleteUploadedFilesOnEnd(true);
-    bodyHandler.setBodyLimit(
-        DynamicPropertyFactory.getInstance().getLongProperty("cse.uploads.maxSize", DEFAULT_BODY_LIMIT).get());
-    LOGGER.info("set uploads directory to {}.", uploadsDirectory);
+    bodyHandler.setBodyLimit(uploadConfig.getMaxSize());
+
+    if (uploadConfig.toMultipartConfigElement() != null) {
+      LOGGER.info("set uploads directory to {}.", uploadConfig.getLocation());
+    }
 
     return bodyHandler;
   }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services