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:17 UTC
[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)
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.