You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/08/29 02:56:28 UTC

[incubator-servicecomb-java-chassis] 02/03: [SCB-206] allow users to specify request Content-Type

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

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

commit cabebee4552cb8d170b993ca7a317cd1a4f1052f
Author: yaohaishi <ya...@huawei.com>
AuthorDate: Fri Aug 24 00:28:17 2018 +0800

    [SCB-206] allow users to specify request Content-Type
---
 .../common/rest/codec/RestClientRequest.java       |  3 ++
 .../rest/codec/param/BodyProcessorCreator.java     | 43 +++++++++++++++++--
 .../rest/codec/param/RestClientRequestImpl.java    |  6 +++
 .../common/rest/codec/param/TestBodyProcessor.java | 50 ++++++++++++++++++++--
 4 files changed, 94 insertions(+), 8 deletions(-)

diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
index f70c7c7..a300273 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.common.rest.codec;
 
 import javax.servlet.http.Part;
 
+import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
 
 /**
@@ -34,6 +35,8 @@ public interface RestClientRequest {
 
   void putHeader(String name, String value);
 
+  MultiMap getHeaders();
+
   void addForm(String name, Object value);
 
   Buffer getBodyBuffer() throws Exception;
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
index ff5f587..e3016a0 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.common.rest.codec.param;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Type;
 import java.util.Locale;
@@ -33,6 +34,7 @@ import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream;
 import org.apache.servicecomb.swagger.generator.core.utils.ClassUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.util.StringUtils;
 
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
@@ -40,6 +42,7 @@ import com.fasterxml.jackson.databind.type.TypeFactory;
 
 import io.swagger.models.parameters.Parameter;
 import io.vertx.core.buffer.Buffer;
+import io.vertx.core.buffer.impl.BufferImpl;
 
 public class BodyProcessorCreator implements ParamValueProcessorCreator {
   private static final Logger LOGGER = LoggerFactory.getLogger(BodyProcessorCreator.class);
@@ -99,12 +102,44 @@ public class BodyProcessorCreator implements ParamValueProcessorCreator {
 
     @Override
     public void setValue(RestClientRequest clientRequest, Object arg) throws Exception {
+      ensureContentType(clientRequest);
+      if (arg != null) {
+        Buffer buffer = createBodyBuffer(
+            clientRequest.getHeaders().get(HttpHeaders.CONTENT_TYPE),
+            arg);
+        clientRequest.write(buffer);
+      }
+    }
+
+    /**
+     * Deserialize body object into body buffer, according to the Content-Type.
+     *
+     * @param contentType the Content-Type of request
+     * @param arg body param object
+     * @return the deserialized body buffer
+     * @throws IOException
+     */
+    private Buffer createBodyBuffer(String contentType, Object arg) throws IOException {
+      if (MediaType.TEXT_PLAIN.equals(contentType)) {
+        if (!String.class.isInstance(arg)) {
+          throw new IllegalArgumentException("Content-Type is text/plain while arg type is not String");
+        }
+        return new BufferImpl().appendBytes(((String) arg).getBytes());
+      }
+
       try (BufferOutputStream output = new BufferOutputStream()) {
-        clientRequest.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
         RestObjectMapperFactory.getConsumerWriterMapper().writeValue(output, arg);
-        if (arg != null) {
-          clientRequest.write(output.getBuffer());
-        }
+        return output.getBuffer();
+      }
+    }
+
+    /**
+     * If the Content-Type has not been set yet, set application/json as default value.
+     */
+    private void ensureContentType(RestClientRequest clientRequest) {
+      if (null == clientRequest.getHeaders()
+          || StringUtils.isEmpty(clientRequest.getHeaders().get(HttpHeaders.CONTENT_TYPE))) {
+        clientRequest.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
       }
     }
 
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 9116d3f..8b124ec 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
@@ -40,6 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import io.vertx.core.Context;
+import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.http.HttpClientRequest;
 import io.vertx.core.http.HttpHeaders;
@@ -272,4 +273,9 @@ public class RestClientRequestImpl implements RestClientRequest {
   public void putHeader(String name, String value) {
     request.putHeader(name, value);
   }
+
+  @Override
+  public MultiMap getHeaders() {
+    return request.headers();
+  }
 }
diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java
index 0b9fb1f..a7afaa5 100644
--- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java
+++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java
@@ -17,8 +17,11 @@
 
 package org.apache.servicecomb.common.rest.codec.param;
 
+import static org.junit.Assert.fail;
+
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -32,13 +35,16 @@ import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.BodyP
 import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.RawJsonBodyProcessor;
 import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
+import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
+import io.vertx.core.http.impl.headers.VertxHttpHeaders;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
@@ -48,7 +54,7 @@ public class TestBodyProcessor {
   @Mocked
   HttpServletRequest request;
 
-  Map<String, String> headers = new HashMap<>();
+  MultiMap headers;
 
   RestClientRequest clientRequest;
 
@@ -72,13 +78,18 @@ public class TestBodyProcessor {
     clientRequest = new MockUp<RestClientRequest>() {
       @Mock
       void putHeader(String name, String value) {
-        headers.put(name, value);
+        headers.add(name, value);
       }
 
       @Mock
       void write(Buffer bodyBuffer) {
         outputBodyBuffer = bodyBuffer;
       }
+
+      @Mock
+      MultiMap getHeaders() {
+        return headers;
+      }
     }.getMockInstance();
   }
 
@@ -96,6 +107,11 @@ public class TestBodyProcessor {
     initInputStream();
   }
 
+  @Before
+  public void before() {
+    headers = new VertxHttpHeaders();
+  }
+
   @Test
   public void testGetValueHaveAttr() throws Exception {
     int body = 10;
@@ -122,7 +138,7 @@ public class TestBodyProcessor {
     };
 
     Object result = processor.getValue(request);
-    Assert.assertEquals(null, result);
+    Assert.assertNull(result);
   }
 
   @Test
@@ -174,6 +190,32 @@ public class TestBodyProcessor {
   }
 
   @Test
+  public void testSetValueTextPlain() throws Exception {
+    createClientRequest();
+    createProcessor(String.class);
+    headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+
+    processor.setValue(clientRequest, "value");
+    Assert.assertEquals(MediaType.TEXT_PLAIN, headers.get(HttpHeaders.CONTENT_TYPE));
+    Assert.assertEquals("value", outputBodyBuffer.toString());
+  }
+
+  @Test
+  public void testSetValueTextPlainTypeMismatch() {
+    createClientRequest();
+    createProcessor(String.class);
+    headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN);
+
+    try {
+      processor.setValue(clientRequest, new Date());
+      fail("an exception is expected!");
+    } catch (Exception e) {
+      Assert.assertEquals(IllegalArgumentException.class, e.getClass());
+      Assert.assertEquals("Content-Type is text/plain while arg type is not String", e.getMessage());
+    }
+  }
+
+  @Test
   public void testGetParameterPath() {
     createProcessor(String.class);
     Assert.assertEquals("", processor.getParameterPath());
@@ -220,7 +262,7 @@ public class TestBodyProcessor {
     };
 
     Object result = processor.getValue(request);
-    Assert.assertEquals(null, result);
+    Assert.assertNull(result);
   }
 
   @Test