From 120d2da496a232d9b1beac2f48e87310a7103662 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 16 May 2017 10:26:10 +0100 Subject: [PATCH] Add support for POSTing a single POJO You need to cache the request body so it can be read twice, once to see if it's an array, and again to turn it into a POJO. --- .../FluxHandlerMethodArgumentResolver.java | 20 +++++++++++-------- .../function/web/RestApplicationTests.java | 10 ++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java index a2e27b66f..a14902229 100644 --- a/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java +++ b/spring-cloud-function-web/src/main/java/org/springframework/cloud/function/web/flux/request/FluxHandlerMethodArgumentResolver.java @@ -23,6 +23,7 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cloud.function.context.FunctionInspector; @@ -34,6 +35,7 @@ import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; +import org.springframework.web.util.ContentCachingRequestWrapper; /** * Converter for request bodies of type Flux. @@ -72,24 +74,26 @@ public class FluxHandlerMethodArgumentResolver type = Object.class; } List body; + ContentCachingRequestWrapper nativeRequest = new ContentCachingRequestWrapper( + webRequest.getNativeRequest(HttpServletRequest.class)); if (isPlainText(webRequest) && CharSequence.class.isAssignableFrom(type)) { - body = Arrays.asList(StreamUtils.copyToString(webRequest - .getNativeRequest(HttpServletRequest.class).getInputStream(), + body = Arrays.asList(StreamUtils.copyToString(nativeRequest.getInputStream(), Charset.forName("UTF-8"))); } else { - body = mapper.readValue( - webRequest.getNativeRequest(HttpServletRequest.class) - .getInputStream(), - mapper.getTypeFactory().constructCollectionLikeType(ArrayList.class, - type)); + try { + body = mapper.readValue(nativeRequest.getInputStream(), mapper + .getTypeFactory().constructCollectionLikeType(ArrayList.class, type)); + } catch (JsonMappingException e) { + body = Arrays.asList(mapper.readValue(nativeRequest.getContentAsByteArray(), type)); + } } return new FluxRequest(body); } private boolean isPlainText(NativeWebRequest webRequest) { String value = webRequest.getHeader("Content-Type"); - if (value!=null) { + if (value != null) { return MediaType.valueOf(value).isCompatibleWith(MediaType.TEXT_PLAIN); } return false; diff --git a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java index 42acbd908..0a28c0b71 100644 --- a/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java +++ b/spring-cloud-function-web/src/test/java/org/springframework/cloud/function/web/RestApplicationTests.java @@ -273,6 +273,16 @@ public class RestApplicationTests { .isEqualTo("[{\"value\":\"FOO\"},{\"value\":\"BAR\"}]"); } + @Test + public void uppercaseFoo() throws Exception { + // Single Foo can be parsed + ResponseEntity result = rest.exchange(RequestEntity + .post(new URI("/upFoos")).contentType(MediaType.APPLICATION_JSON) + .body("{\"value\":\"foo\"}"), String.class); + assertThat(result.getBody()) + .isEqualTo("[{\"value\":\"FOO\"}]"); + } + @Test public void bareUppercase() throws Exception { ResponseEntity result = rest.exchange(RequestEntity