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 <[email protected]> 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
