From 9d04c0424dff50d02dfcd3bf3786ebe9194680c8 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 14 Jul 2017 14:38:42 +0200 Subject: [PATCH] Allow empty body with no content type in BodyExtractors Issue: SPR-15758 --- .../web/reactive/function/BodyExtractors.java | 17 ++++++++++++++--- .../reactive/function/BodyExtractorsTests.java | 15 ++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java index acb0dab440..2f86ea9c8e 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/BodyExtractors.java @@ -103,7 +103,8 @@ public abstract class BodyExtractors { return reader.readMono(elementType, inputMessage, context.hints()); } }, - Mono::error, + ex -> (inputMessage.getHeaders().getContentType() == null) ? + Mono.from(permitEmptyOrFail(inputMessage, ex)) : Mono.error(ex), Mono::empty); } @@ -138,6 +139,7 @@ public abstract class BodyExtractors { return toFlux(ResolvableType.forType(typeReference.getType())); } + @SuppressWarnings("unchecked") static BodyExtractor, ReactiveHttpInputMessage> toFlux(ResolvableType elementType) { Assert.notNull(elementType, "'elementType' must not be null"); return (inputMessage, context) -> readWithMessageReaders(inputMessage, context, @@ -152,10 +154,18 @@ public abstract class BodyExtractors { return reader.read(elementType, inputMessage, context.hints()); } }, - Flux::error, + ex -> (inputMessage.getHeaders().getContentType() == null) ? + permitEmptyOrFail(inputMessage, ex) : Flux.error(ex), Flux::empty); } + @SuppressWarnings("unchecked") + private static Flux permitEmptyOrFail(ReactiveHttpInputMessage message, UnsupportedMediaTypeException ex) { + return message.getBody().doOnNext(buffer -> { + throw ex; + }).map(o -> (T) o); + } + /** * Return a {@code BodyExtractor} that reads form data into a {@link MultiValueMap}. * @return a {@code BodyExtractor} that reads form data @@ -225,7 +235,8 @@ public abstract class BodyExtractors { private static > S readWithMessageReaders( ReactiveHttpInputMessage inputMessage, BodyExtractor.Context context, ResolvableType elementType, - Function, S> readerFunction, Function unsupportedError, + Function, S> readerFunction, + Function unsupportedError, Supplier empty) { if (VOID_TYPE.equals(elementType)) { diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java index ce5b64e60f..e1627f3dca 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/BodyExtractorsTests.java @@ -56,7 +56,9 @@ import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.util.MultiValueMap; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.springframework.http.codec.json.Jackson2CodecSupport.JSON_VIEW_HINT; /** @@ -169,6 +171,17 @@ public class BodyExtractorsTests { .verify(); } + @Test // SPR-15758 + public void toMonoWithEmptyBodyAndNoContentType() throws Exception { + BodyExtractor>, ReactiveHttpInputMessage> extractor = + BodyExtractors.toMono(new ParameterizedTypeReference>() {}); + + MockServerHttpRequest request = MockServerHttpRequest.post("/").body(Flux.empty()); + Mono> result = extractor.extract(request, this.context); + + StepVerifier.create(result).expectComplete().verify(); + } + @Test public void toFlux() throws Exception { BodyExtractor, ReactiveHttpInputMessage> extractor = BodyExtractors.toFlux(String.class); -- GitLab