You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by wu...@apache.org on 2018/12/05 06:32:53 UTC

[servicecomb-java-chassis] branch master updated: [SCB-1054]when download file, we should ignore consumer acceptType (#1016)

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

wujimin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 6025b0d  [SCB-1054]when download file, we should ignore consumer acceptType (#1016)
6025b0d is described below

commit 6025b0dc55c980a80b096c3b2a39b1e5fcbd6052
Author: heyile <25...@qq.com>
AuthorDate: Wed Dec 5 14:32:48 2018 +0800

    [SCB-1054]when download file, we should ignore consumer acceptType (#1016)
    
    * [SCB-1054]when download file, we should ignore consumer acceptType
    
    * [SCB-1054]when download file, we should ignore consumer acceptType: fix as review
---
 .../common/rest/definition/RestOperationMeta.java  | 30 +++++++++++++---
 .../rest/definition/TestRestOperationMeta.java     | 14 ++++++++
 .../servicecomb/it/testcase/TestDownload.java      | 41 ++++++++++++++++++++++
 .../servicecomb/it/schema/DownloadSchema.java      |  3 +-
 4 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
index 36979ea..a417ef2 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
+import javax.servlet.http.Part;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 
@@ -35,9 +36,12 @@ import org.apache.servicecomb.common.rest.definition.path.PathRegExp;
 import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.swagger.invocation.response.ResponseMeta;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.databind.JavaType;
+
 import io.swagger.models.Operation;
 import io.swagger.models.Swagger;
 import io.swagger.models.parameters.Parameter;
@@ -52,6 +56,9 @@ public class RestOperationMeta {
 
   protected boolean formData;
 
+  // make sure if response is file
+  protected boolean downloadFile;
+
   protected List<RestParam> paramList = new ArrayList<>();
 
   // key为参数名
@@ -80,13 +87,14 @@ public class RestOperationMeta {
       this.produces = swagger.getProduces();
     }
 
+    this.downloadFile = checkDownloadFileFlag();
     this.createProduceProcessors();
 
     Method method = operationMeta.getMethod();
     Type[] genericParamTypes = method.getGenericParameterTypes();
     if (genericParamTypes.length != operation.getParameters().size()) {
       throw new Error("Param count is not equal between swagger and method, path=" + absolutePath
-        + ";operation=" + operationMeta.getMicroserviceQualifiedName());
+          + ";operation=" + operationMeta.getMicroserviceQualifiedName());
     }
 
     // 初始化所有rest param
@@ -105,6 +113,15 @@ public class RestOperationMeta {
     setAbsolutePath(concatPath(swagger.getBasePath(), operationMeta.getOperationPath()));
   }
 
+  private boolean checkDownloadFileFlag() {
+    ResponseMeta responseMeta = operationMeta.findResponseMeta(200);
+    if (responseMeta != null) {
+      JavaType javaType = responseMeta.getJavaType();
+      return javaType.getRawClass().equals(Part.class);
+    }
+    return false;
+  }
+
   public boolean isFormData() {
     return formData;
   }
@@ -217,12 +234,17 @@ public class RestOperationMeta {
   }
 
   public ProduceProcessor ensureFindProduceProcessor(String acceptType) {
+    if (downloadFile) {
+      //do not check accept type, when the produces of provider is text/plain there will return text/plain processor
+      //when the produces of provider is application/json there will return the application/json processor
+      //so do not care what accept type the consumer will set.
+      return this.produceProcessorMap.get(MediaType.WILDCARD);
+    }
     if (StringUtils.isEmpty(acceptType)) {
       return defaultProcessor;
     }
-
-    List<String> mimeTyps = MimeTypesUtils.getSortedAcceptableMimeTypes(acceptType.toLowerCase(Locale.US));
-    for (String mime : mimeTyps) {
+    List<String> mimeTypes = MimeTypesUtils.getSortedAcceptableMimeTypes(acceptType.toLowerCase(Locale.US));
+    for (String mime : mimeTypes) {
       ProduceProcessor processor = this.produceProcessorMap.get(mime);
       if (null != processor) {
         return processor;
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
index 6103df9..fa46651 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java
@@ -184,6 +184,20 @@ public class TestRestOperationMeta {
   }
 
   @Test
+  public void testEnsureFindProduceProcessorWithDownload() {
+    RestOperationMeta operationMeta = new RestOperationMeta();
+    operationMeta.produces = Arrays.asList(MediaType.APPLICATION_JSON);
+    operationMeta.downloadFile = true;
+    operationMeta.createProduceProcessors();
+
+    Assert.assertSame(ProduceProcessorManager.JSON_PROCESSOR,
+        operationMeta.ensureFindProduceProcessor("text/plain"));
+
+    operationMeta.downloadFile = false;
+    Assert.assertNull(operationMeta.ensureFindProduceProcessor("text/plain"));
+  }
+
+  @Test
   public void testEnsureFindProduceProcessorAcceptNotFound() {
     RestOperationMeta operationMeta = new RestOperationMeta();
     operationMeta.produces = Arrays.asList(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN);
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownload.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownload.java
index 9a3947c..a370e49 100644
--- a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownload.java
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownload.java
@@ -32,6 +32,11 @@ import org.apache.servicecomb.it.Consumers;
 import org.apache.servicecomb.it.testcase.support.DownloadSchemaIntf;
 import org.junit.Assert;
 import org.junit.Test;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 
 import com.google.common.collect.Iterables;
 
@@ -96,17 +101,35 @@ public class TestDownload {
             content);
   }
 
+  private ReadStreamPart templateExchange(String methodPath, String type) {
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("accept", type);
+    HttpEntity<?> entity = new HttpEntity<>(headers);
+    ResponseEntity<ReadStreamPart> response = consumers.getSCBRestTemplate()
+        .exchange("/" + methodPath + "?content={content}",
+            HttpMethod.GET,
+            entity,
+            ReadStreamPart.class, content);
+    return response.getBody();
+  }
+
   @Test
   @SuppressWarnings("unchecked")
   public void runRest() {
     futures.add(checkFile(consumers.getIntf().tempFileEntity(content)));
     futures.add(checkFuture(templateGet("tempFileEntity").saveAsBytes()));
+    futures.add(checkFuture(templateExchange("tempFileEntity", MediaType.TEXT_PLAIN_VALUE).saveAsBytes()));
+    futures.add(checkFuture(templateExchange("tempFileEntity", MediaType.APPLICATION_JSON_VALUE).saveAsBytes()));
 
     futures.add(checkFile(consumers.getIntf().tempFilePart(content)));
     futures.add(checkFuture(templateGet("tempFilePart").saveAsString()));
+    futures.add(checkFuture(templateExchange("tempFilePart", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("tempFilePart", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     futures.add(checkFile(consumers.getIntf().file(content)));
     futures.add(checkFuture(templateGet("file").saveAsString()));
+    futures.add(checkFuture(templateExchange("file", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("file", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     {
       ReadStreamPart part = consumers.getIntf().chineseAndSpaceFile(content);
@@ -116,22 +139,40 @@ public class TestDownload {
       part = templateGet("chineseAndSpaceFile");
       Assert.assertEquals("测 试.test.txt", part.getSubmittedFileName());
       futures.add(checkFuture(part.saveAsString()));
+
+      ReadStreamPart part2 = templateExchange("chineseAndSpaceFile", MediaType.TEXT_PLAIN_VALUE);
+      Assert.assertEquals("测 试.test.txt", part2.getSubmittedFileName());
+      futures.add(checkFuture(part2.saveAsString()));
+
+      ReadStreamPart part3 = templateExchange("chineseAndSpaceFile", MediaType.APPLICATION_JSON_VALUE);
+      Assert.assertEquals("测 试.test.txt", part3.getSubmittedFileName());
+      futures.add(checkFuture(part3.saveAsString()));
     }
 
     futures.add(checkFile(consumers.getIntf().resource(content)));
     futures.add(checkFuture(templateGet("resource").saveAsString()));
+    futures.add(checkFuture(templateExchange("resource", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("resource", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     futures.add(checkFile(consumers.getIntf().entityResource(content)));
     futures.add(checkFuture(templateGet("entityResource").saveAsString()));
+    futures.add(checkFuture(templateExchange("entityResource", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("entityResource", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     futures.add(checkFile(consumers.getIntf().entityInputStream(content)));
     futures.add(checkFuture(templateGet("entityInputStream").saveAsString()));
+    futures.add(checkFuture(templateExchange("entityInputStream", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("entityInputStream", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     futures.add(checkFile(consumers.getIntf().bytes(content)));
     futures.add(checkFuture(templateGet("bytes").saveAsString()));
+    futures.add(checkFuture(templateExchange("bytes", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("bytes", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     futures.add(checkFile(consumers.getIntf().netInputStream(content)));
     futures.add(checkFuture(templateGet("netInputStream").saveAsString()));
+    futures.add(checkFuture(templateExchange("netInputStream", MediaType.TEXT_PLAIN_VALUE).saveAsString()));
+    futures.add(checkFuture(templateExchange("netInputStream", MediaType.APPLICATION_JSON_VALUE).saveAsString()));
 
     try {
       CompletableFuture
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
index 5ba7d8b..2f3ba54 100644
--- a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
@@ -192,12 +192,11 @@ public class DownloadSchema implements BootListener {
     URL url = new URL("http://localhost:" + server.getLocalPort() + "/download/netInputStream?content="
         + URLEncoder.encode(content, StandardCharsets.UTF_8.name()));
     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-    ResponseEntity<InputStream> responseEntity = ResponseEntity
+    return ResponseEntity
         .ok()
         .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
         .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=netInputStream.txt")
         .body(conn.getInputStream());
-    return responseEntity;
   }
 
   private Thread slowInputStreamThread;