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/06/04 06:22:16 UTC

[incubator-servicecomb-java-chassis] branch master updated (272c4e4 -> 517a9ff)

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

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


    from 272c4e4  [SCB-471]watch mode: netty upgrade have add pong response and need to handle it
     new eca4579  [SCB-637] StandardHttpServletRequestEx parse application/x-www-form-urlencoded even not post request (servlet 3.1 defined only parsed for post request)
     new 48db26c  [SCB-637] support getCharsetFromContentType in HttpUtils
     new 517a9ff  [SCB-637] impl getMethod/getContentType/getCharacterEncoding in VertxClientRequestToHttpServletRequest/VertxServerRequestToHttpServletRequest/InvocationToHttpServletRequest

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../foundation/common/http/HttpUtils.java          | 28 +++++++
 .../foundation/common/http/TestHttpUtils.java      | 51 ++++++++++++
 .../vertx/http/StandardHttpServletRequestEx.java   | 90 ++++++++++++++++++++++
 .../VertxClientRequestToHttpServletRequest.java    | 25 ++++++
 .../VertxServerRequestToHttpServletRequest.java    | 37 +++++++--
 .../http/TestStandardHttpServletRequestEx.java     | 54 +++++++++++++
 ...TestVertxClientRequestToHttpServletRequest.java | 51 ++++++++++++
 ...TestVertxServerRequestToHttpServletRequest.java | 16 ++++
 .../common/InvocationToHttpServletRequest.java     | 21 +++++
 .../common/TestInvocationToHttpServletRequest.java | 10 +++
 10 files changed, 376 insertions(+), 7 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.

[incubator-servicecomb-java-chassis] 01/03: [SCB-637] StandardHttpServletRequestEx parse application/x-www-form-urlencoded even not post request (servlet 3.1 defined only parsed for post request)

Posted by li...@apache.org.
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 eca457968972d2636ec5e359f61bace800c160b5
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Jun 4 00:09:58 2018 +0800

    [SCB-637] StandardHttpServletRequestEx parse application/x-www-form-urlencoded even not post request (servlet 3.1 defined only parsed for post request)
---
 .../vertx/http/StandardHttpServletRequestEx.java   | 90 ++++++++++++++++++++++
 .../http/TestStandardHttpServletRequestEx.java     | 54 +++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java
index a6b142d..f9b29ca 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java
@@ -18,12 +18,27 @@
 package org.apache.servicecomb.foundation.vertx.http;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
 import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
 
 import io.netty.buffer.ByteBuf;
@@ -37,6 +52,11 @@ public class StandardHttpServletRequestEx extends HttpServletRequestWrapper impl
 
   private ServletInputStream inputStream;
 
+  // by servlet specification
+  // only parse application/x-www-form-urlencoded of post request automatically
+  // we will parse this even not post method
+  private Map<String, String[]> parameterMap;
+
   public StandardHttpServletRequestEx(HttpServletRequest request) {
     super(request);
   }
@@ -79,4 +99,74 @@ public class StandardHttpServletRequestEx extends HttpServletRequestWrapper impl
   public int getBodyBytesLength() {
     return bodyBuffer.getBodyBytesLength();
   }
+
+  private Map<String, String[]> parseParameterMap() {
+    // 1.post method already parsed by servlet
+    // 2.not APPLICATION_FORM_URLENCODED, no need to enhance
+    if (getMethod().equalsIgnoreCase(HttpMethod.POST)
+        || !StringUtils.startsWithIgnoreCase(getContentType(), MediaType.APPLICATION_FORM_URLENCODED)) {
+      return super.getParameterMap();
+    }
+
+    Map<String, List<String>> listMap = parseUrlEncodedBody();
+    mergeParameterMaptoListMap(listMap);
+    return convertListMapToArrayMap(listMap);
+  }
+
+  private Map<String, String[]> convertListMapToArrayMap(Map<String, List<String>> listMap) {
+    Map<String, String[]> arrayMap = new HashMap<>();
+    for (Entry<String, List<String>> entry : listMap.entrySet()) {
+      arrayMap.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]));
+    }
+    return arrayMap;
+  }
+
+  private void mergeParameterMaptoListMap(Map<String, List<String>> listMap) {
+    for (Entry<String, String[]> entry : super.getParameterMap().entrySet()) {
+      List<String> values = listMap.computeIfAbsent(entry.getKey(), k -> new ArrayList<>());
+      // follow servlet behavior, inherited value first, and then body value
+      values.addAll(0, Arrays.asList(entry.getValue()));
+    }
+  }
+
+  private Map<String, List<String>> parseUrlEncodedBody() {
+    try (InputStream inputStream = getInputStream()) {
+      Map<String, List<String>> listMap = new HashMap<>();
+      String body = IOUtils.toString(inputStream);
+      List<NameValuePair> pairs = URLEncodedUtils
+          .parse(body, getCharacterEncoding() == null ? null : Charset.forName(getCharacterEncoding()));
+      for (NameValuePair pair : pairs) {
+        List<String> values = listMap.computeIfAbsent(pair.getName(), k -> new ArrayList<>());
+        values.add(pair.getValue());
+      }
+      return listMap;
+    } catch (IOException e) {
+      throw new IllegalStateException("", e);
+    }
+  }
+
+  @Override
+  public String[] getParameterValues(String name) {
+    return getParameterMap().get(name);
+  }
+
+  @Override
+  public String getParameter(String name) {
+    String[] values = getParameterMap().get(name);
+    return values == null ? null : values[0];
+  }
+
+  @Override
+  public Enumeration<String> getParameterNames() {
+    return Collections.enumeration(getParameterMap().keySet());
+  }
+
+  @Override
+  public Map<String, String[]> getParameterMap() {
+    if (parameterMap == null) {
+      parameterMap = parseParameterMap();
+    }
+
+    return parameterMap;
+  }
 }
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java
index ed5a884..f87e83c 100644
--- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java
@@ -19,11 +19,19 @@ package org.apache.servicecomb.foundation.vertx.http;
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
 
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.core.MediaType;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
+import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -78,4 +86,50 @@ public class TestStandardHttpServletRequestEx {
     // do not create another one
     Assert.assertSame(cachedInputStream, requestEx.getInputStream());
   }
+
+  @Test
+  public void parameterMap_inherited() {
+    Map<String, String[]> inherited = new HashMap<>();
+    String[] v1 = new String[] {"v1-1", "v1-2"};
+    inherited.put("p1", v1);
+    new Expectations() {
+      {
+        request.getParameterMap();
+        result = inherited;
+        request.getMethod();
+        result = HttpMethod.POST;
+      }
+    };
+
+    Assert.assertSame(inherited, requestEx.getParameterMap());
+    Assert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("p1"));
+    Assert.assertSame(v1, requestEx.getParameterValues("p1"));
+    Assert.assertEquals("v1-1", requestEx.getParameter("p1"));
+  }
+
+  @Test
+  public void parameterMap_merge() throws IOException {
+    Map<String, String[]> inherited = new HashMap<>();
+    String[] v1 = new String[] {"v1-1", "v1-2"};
+    inherited.put("p1", v1);
+
+    Buffer buffer = Buffer.buffer("p1=v1-3;p2=v2");
+    BufferInputStream inputStream = new BufferInputStream(buffer.getByteBuf());
+    new Expectations() {
+      {
+        request.getParameterMap();
+        result = inherited;
+        request.getMethod();
+        result = HttpMethod.PUT;
+        request.getContentType();
+        result = MediaType.APPLICATION_FORM_URLENCODED.toUpperCase(Locale.US) + ";abc";
+        request.getInputStream();
+        result = inputStream;
+      }
+    };
+
+    Assert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("p1", "p2"));
+    Assert.assertThat(requestEx.getParameterValues("p1"), Matchers.arrayContaining("v1-1", "v1-2", "v1-3"));
+    Assert.assertEquals("v1-1", requestEx.getParameter("p1"));
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.

[incubator-servicecomb-java-chassis] 02/03: [SCB-637] support getCharsetFromContentType in HttpUtils

Posted by li...@apache.org.
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 48db26ca9f701f0b6603442c19c339ebb5ff7437
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Jun 4 00:12:06 2018 +0800

    [SCB-637] support getCharsetFromContentType in HttpUtils
---
 .../foundation/common/http/HttpUtils.java          | 28 ++++++++++++
 .../foundation/common/http/TestHttpUtils.java      | 51 ++++++++++++++++++++++
 2 files changed, 79 insertions(+)

diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
index 6edcee4..ed94d76 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java
@@ -81,4 +81,32 @@ public final class HttpUtils {
     fileName = uriDecodePath(fileName);
     return new File(fileName).getName();
   }
+
+  /**
+   * Parse the character encoding from the specified content type header.
+   * If the content type is null, or there is no explicit character encoding,
+   * <code>null</code> is returned.
+   *
+   * @param contentType a content type header
+   */
+  public static String getCharsetFromContentType(String contentType) {
+    if (contentType == null) {
+      return null;
+    }
+    int start = contentType.indexOf("charset=");
+    if (start < 0) {
+      return null;
+    }
+    String encoding = contentType.substring(start + 8);
+    int end = encoding.indexOf(';');
+    if (end >= 0) {
+      encoding = encoding.substring(0, end);
+    }
+    encoding = encoding.trim();
+    if ((encoding.length() > 2) && (encoding.startsWith("\""))
+        && (encoding.endsWith("\""))) {
+      encoding = encoding.substring(1, encoding.length() - 1);
+    }
+    return encoding.trim();
+  }
 }
diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
index 5fbd603..6fc0c8c 100644
--- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
+++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java
@@ -18,6 +18,8 @@ package org.apache.servicecomb.foundation.common.http;
 
 import java.net.URISyntaxException;
 
+import javax.ws.rs.core.MediaType;
+
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Rule;
@@ -111,4 +113,53 @@ public class TestHttpUtils {
   public void parseFileNameFromHeaderValue_ignorePath() {
     Assert.assertEquals("a.txt", HttpUtils.parseFileNameFromHeaderValue("xx;filename=../../a.txt"));
   }
+
+  @Test
+  public void getCharsetFromContentType_noContentType() {
+    String character = HttpUtils.getCharsetFromContentType(null);
+
+    Assert.assertNull(character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_noCharset() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON);
+
+    Assert.assertNull(character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_noSemicolonEnd() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=utf-8");
+
+    Assert.assertEquals("utf-8", character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_semicolonEnd() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=utf-8;");
+
+    Assert.assertEquals("utf-8", character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_needTrim() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset= utf-8 ;");
+
+    Assert.assertEquals("utf-8", character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_quotationMarks() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=\"utf-8\";");
+
+    Assert.assertEquals("utf-8", character);
+  }
+
+  @Test
+  public void getCharsetFromContentType_quotationMarks_needTrim() {
+    String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=\" utf-8 \";");
+
+    Assert.assertEquals("utf-8", character);
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.

[incubator-servicecomb-java-chassis] 03/03: [SCB-637] impl getMethod/getContentType/getCharacterEncoding in VertxClientRequestToHttpServletRequest/VertxServerRequestToHttpServletRequest/InvocationToHttpServletRequest

Posted by li...@apache.org.
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 517a9ff762f8c5f969ed7dee834a6fc88c32e340
Author: wujimin <wu...@huawei.com>
AuthorDate: Mon Jun 4 00:24:58 2018 +0800

    [SCB-637] impl getMethod/getContentType/getCharacterEncoding in VertxClientRequestToHttpServletRequest/VertxServerRequestToHttpServletRequest/InvocationToHttpServletRequest
---
 .../VertxClientRequestToHttpServletRequest.java    | 25 +++++++++++
 .../VertxServerRequestToHttpServletRequest.java    | 37 +++++++++++++---
 ...TestVertxClientRequestToHttpServletRequest.java | 51 ++++++++++++++++++++++
 ...TestVertxServerRequestToHttpServletRequest.java | 16 +++++++
 .../common/InvocationToHttpServletRequest.java     | 21 +++++++++
 .../common/TestInvocationToHttpServletRequest.java | 10 +++++
 6 files changed, 153 insertions(+), 7 deletions(-)

diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java
index 3563d4d..72fd366 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java
@@ -20,12 +20,18 @@ package org.apache.servicecomb.foundation.vertx.http;
 import java.util.Collections;
 import java.util.Enumeration;
 
+import javax.ws.rs.core.HttpHeaders;
+
+import org.apache.servicecomb.foundation.common.http.HttpUtils;
+
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.http.HttpClientRequest;
 
 public class VertxClientRequestToHttpServletRequest extends AbstractHttpServletRequest {
   private HttpClientRequest clientRequest;
 
+  private String characterEncoding;
+
   public VertxClientRequestToHttpServletRequest(HttpClientRequest clientRequest, Buffer bodyBuffer) {
     this.clientRequest = clientRequest;
     setBodyBuffer(bodyBuffer);
@@ -70,4 +76,23 @@ public class VertxClientRequestToHttpServletRequest extends AbstractHttpServletR
   public String getContextPath() {
     return "";
   }
+
+  @Override
+  public String getMethod() {
+    return clientRequest.method().name();
+  }
+
+  @Override
+  public String getContentType() {
+    return clientRequest.headers().get(HttpHeaders.CONTENT_TYPE);
+  }
+
+  @Override
+  public String getCharacterEncoding() {
+    if (characterEncoding == null) {
+      characterEncoding = HttpUtils.getCharsetFromContentType(getContentType());
+    }
+
+    return characterEncoding;
+  }
 }
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
index 47e9d4d..f198587 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java
@@ -31,6 +31,7 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.Part;
 import javax.ws.rs.core.HttpHeaders;
 
+import org.apache.servicecomb.foundation.common.http.HttpUtils;
 import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,6 +61,11 @@ public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletR
 
   private SocketAddress socketAddress;
 
+  // cache from convert vertx parameters to servlet parameters
+  private Map<String, String[]> parameterMap;
+
+  private String characterEncoding;
+
   public VertxServerRequestToHttpServletRequest(RoutingContext context, String path) {
     this(context);
     this.path = path;
@@ -106,19 +112,27 @@ public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletR
 
   @Override
   public String[] getParameterValues(String name) {
+    if (parameterMap != null) {
+      return parameterMap.get(name);
+    }
+
     List<String> paramList = this.vertxRequest.params().getAll(name);
-    return (String[]) paramList.toArray(new String[paramList.size()]);
+    return paramList.toArray(new String[paramList.size()]);
   }
 
   @Override
   public Map<String, String[]> getParameterMap() {
-    Map<String, String[]> paramMap = new HashMap<>();
-    MultiMap map = this.vertxRequest.params();
-    for (String name : map.names()) {
-      List<String> valueList = map.getAll(name);
-      paramMap.put(name, (String[]) map.getAll(name).toArray(new String[valueList.size()]));
+    if (parameterMap == null) {
+      Map<String, String[]> paramMap = new HashMap<>();
+      MultiMap map = this.vertxRequest.params();
+      for (String name : map.names()) {
+        List<String> valueList = map.getAll(name);
+        paramMap.put(name, map.getAll(name).toArray(new String[valueList.size()]));
+      }
+      parameterMap = paramMap;
     }
-    return paramMap;
+
+    return parameterMap;
   }
 
   @Override
@@ -240,4 +254,13 @@ public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletR
   public RoutingContext getContext() {
     return context;
   }
+
+  @Override
+  public String getCharacterEncoding() {
+    if (characterEncoding == null) {
+      characterEncoding = HttpUtils.getCharsetFromContentType(getContentType());
+    }
+
+    return characterEncoding;
+  }
 }
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java
index 71908f1..271a0c08 100644
--- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java
@@ -19,6 +19,9 @@ package org.apache.servicecomb.foundation.vertx.http;
 
 import java.util.Collections;
 
+import javax.ws.rs.core.HttpHeaders;
+
+import org.apache.servicecomb.foundation.common.http.HttpUtils;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Before;
@@ -27,6 +30,7 @@ import org.junit.Test;
 import io.vertx.core.MultiMap;
 import io.vertx.core.buffer.Buffer;
 import io.vertx.core.http.HttpClientRequest;
+import io.vertx.core.http.HttpMethod;
 import mockit.Expectations;
 import mockit.Mocked;
 
@@ -143,4 +147,51 @@ public class TestVertxClientRequestToHttpServletRequest {
   public void testGetContextPath() {
     Assert.assertEquals("", request.getContextPath());
   }
+
+  @Test
+  public void getMethod() {
+    new Expectations() {
+      {
+        clientRequest.method();
+        result = HttpMethod.GET;
+      }
+    };
+
+    Assert.assertEquals("GET", request.getMethod());
+  }
+
+  @Test
+  public void getContentType() {
+    MultiMap headers = MultiMap.caseInsensitiveMultiMap();
+    new Expectations() {
+      {
+        clientRequest.headers();
+        result = headers;
+      }
+    };
+
+    request.addHeader(HttpHeaders.CONTENT_TYPE, "ct");
+
+    Assert.assertEquals("ct", request.getContentType());
+  }
+
+  @Test
+  public void getCharacterEncoding() {
+    String contentType = "ct";
+    String characterEncoding = "ce";
+
+    MultiMap headers = MultiMap.caseInsensitiveMultiMap();
+    new Expectations(HttpUtils.class) {
+      {
+        HttpUtils.getCharsetFromContentType(contentType);
+        result = characterEncoding;
+        clientRequest.headers();
+        result = headers;
+      }
+    };
+
+    request.addHeader(HttpHeaders.CONTENT_TYPE, contentType);
+
+    Assert.assertEquals("ce", request.getCharacterEncoding());
+  }
 }
diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java
index 2e2f0f8..df72215 100644
--- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java
+++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java
@@ -29,6 +29,7 @@ import javax.servlet.http.Cookie;
 import javax.ws.rs.core.HttpHeaders;
 import javax.xml.ws.Holder;
 
+import org.apache.servicecomb.foundation.common.http.HttpUtils;
 import org.hamcrest.Matchers;
 import org.junit.Assert;
 import org.junit.Before;
@@ -182,6 +183,7 @@ public class TestVertxServerRequestToHttpServletRequest {
     Map<String, String[]> result = request.getParameterMap();
     Assert.assertThat(result.keySet(), Matchers.contains("name"));
     Assert.assertThat(result.get("name"), Matchers.arrayContaining("value"));
+    Assert.assertSame(result, request.getParameterMap());
   }
 
   @Test
@@ -436,4 +438,18 @@ public class TestVertxServerRequestToHttpServletRequest {
 
     Assert.assertSame(asyncContext, request.getAsyncContext());
   }
+
+  @Test
+  public void getCharacterEncoding() {
+    new Expectations(HttpUtils.class) {
+      {
+        vertxRequest.getHeader(HttpHeaders.CONTENT_TYPE);
+        result = "ct";
+        HttpUtils.getCharsetFromContentType("ct");
+        result = "ce";
+      }
+    };
+
+    Assert.assertEquals("ce", request.getCharacterEncoding());
+  }
 }
diff --git a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/InvocationToHttpServletRequest.java b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/InvocationToHttpServletRequest.java
index c3585bb..eb126d4 100644
--- a/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/InvocationToHttpServletRequest.java
+++ b/providers/provider-rest-common/src/main/java/org/apache/servicecomb/provider/rest/common/InvocationToHttpServletRequest.java
@@ -30,6 +30,9 @@ import org.apache.servicecomb.foundation.vertx.http.AbstractHttpServletRequest;
 
 import io.vertx.core.net.SocketAddress;
 
+/**
+ * when transport is not over http, mock a HttpServletRequest from Invocation
+ */
 public class InvocationToHttpServletRequest extends AbstractHttpServletRequest {
   private RestOperationMeta swaggerOperation;
 
@@ -126,4 +129,22 @@ public class InvocationToHttpServletRequest extends AbstractHttpServletRequest {
   public String getContextPath() {
     return "";
   }
+
+  /**
+   * it's a mock httpServletRequest, contentType is unknown
+   * @return contentType
+   */
+  @Override
+  public String getContentType() {
+    return null;
+  }
+
+  /**
+   * it's a mock httpServletRequest, characterEncoding is unknown
+   * @return characterEncoding
+   */
+  @Override
+  public String getCharacterEncoding() {
+    return null;
+  }
 }
diff --git a/providers/provider-rest-common/src/test/java/org/apache/servicecomb/provider/rest/common/TestInvocationToHttpServletRequest.java b/providers/provider-rest-common/src/test/java/org/apache/servicecomb/provider/rest/common/TestInvocationToHttpServletRequest.java
index b29f329..79c1c90 100644
--- a/providers/provider-rest-common/src/test/java/org/apache/servicecomb/provider/rest/common/TestInvocationToHttpServletRequest.java
+++ b/providers/provider-rest-common/src/test/java/org/apache/servicecomb/provider/rest/common/TestInvocationToHttpServletRequest.java
@@ -322,4 +322,14 @@ public class TestInvocationToHttpServletRequest {
     InvocationToHttpServletRequest request = new InvocationToHttpServletRequest(invocation);
     Assert.assertEquals("", request.getContextPath());
   }
+
+  @Test
+  public void getContentType() {
+    Assert.assertNull(request.getContentType());
+  }
+
+  @Test
+  public void getCharacterEncoding() {
+    Assert.assertNull(request.getCharacterEncoding());
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
liubao@apache.org.