Skip to content

Commit 4d8494a

Browse files
artembilangaryrussell
authored andcommitted
INT-4462: WebFluxInbound: cope with empty body
JIRA: https://jira.spring.io/browse/INT-4462 When the HTTP request body is empty, the `HttpMessageReader` ends up with the empty `Mono` which can't be evaluated to any reasonable value. * Add fallback to `requestParams` when `Mono` for body is empty and also when `payloadExpression` returns null **Cherry-pick to 5.0.x**
1 parent 48e8b14 commit 4d8494a

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

spring-integration-webflux/src/main/java/org/springframework/integration/webflux/inbound/WebFluxInboundEndpoint.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ public Mono<Void> handle(ServerWebExchange exchange) {
150150
private Mono<Void> doHandle(ServerWebExchange exchange) {
151151
return extractRequestBody(exchange)
152152
.doOnSubscribe(s -> this.activeCount.incrementAndGet())
153+
.switchIfEmpty(Mono.just(exchange.getRequest().getQueryParams()))
153154
.map(body -> new HttpEntity<>(body, exchange.getRequest().getHeaders()))
154155
.map(entity -> buildMessage(entity, exchange))
155156
.flatMap(requestMessage -> {
@@ -267,10 +268,6 @@ private Message<?> buildMessage(HttpEntity<?> httpEntity, ServerWebExchange exch
267268
Object payload;
268269
if (getPayloadExpression() != null) {
269270
payload = getPayloadExpression().getValue(evaluationContext);
270-
if (payload == null) {
271-
throw new IllegalStateException("The payload expression '" + getPayloadExpression().getExpressionString()
272-
+ "' returned null.");
273-
}
274271
}
275272
else {
276273
payload = httpEntity.getBody();
@@ -288,6 +285,10 @@ private Message<?> buildMessage(HttpEntity<?> httpEntity, ServerWebExchange exch
288285
}
289286
}
290287

288+
if (payload == null) {
289+
payload = requestParams;
290+
}
291+
291292
AbstractIntegrationMessageBuilder<?> messageBuilder;
292293

293294
if (payload instanceof Message<?>) {

spring-integration-webflux/src/test/java/org/springframework/integration/webflux/inbound/WebFluxInboundEndpointTests.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017 the original author or authors.
2+
* Copyright 2017-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import org.springframework.context.ApplicationContext;
2626
import org.springframework.context.annotation.Bean;
2727
import org.springframework.context.annotation.Configuration;
28+
import org.springframework.http.HttpMethod;
2829
import org.springframework.http.HttpStatus;
2930
import org.springframework.http.MediaType;
3031
import org.springframework.http.ResponseEntity;
@@ -95,6 +96,16 @@ public void testServerInternalErrorRequest() {
9596
.is5xxServerError();
9697
}
9798

99+
@Test
100+
public void testPostWithEmptyBody() {
101+
this.webTestClient
102+
.post()
103+
.uri("/post?foo=foo")
104+
.exchange()
105+
.expectStatus().isOk()
106+
.expectBody(String.class).isEqualTo("{foo=[foo]}");
107+
}
108+
98109
@Configuration
99110
@EnableWebFlux
100111
@EnableIntegration
@@ -156,6 +167,22 @@ public ResponseEntity<String> processHttpRequest() {
156167
return new ResponseEntity<>("<500 Internal Server Error,{}>", HttpStatus.INTERNAL_SERVER_ERROR);
157168
}
158169

170+
@Bean
171+
public WebFluxInboundEndpoint postInboundEndpoint() {
172+
WebFluxInboundEndpoint endpoint = new WebFluxInboundEndpoint();
173+
RequestMapping requestMapping = new RequestMapping();
174+
requestMapping.setPathPatterns("/post");
175+
requestMapping.setMethods(HttpMethod.POST);
176+
endpoint.setRequestMapping(requestMapping);
177+
endpoint.setRequestChannelName("postServiceChannel");
178+
return endpoint;
179+
}
180+
181+
@ServiceActivator(inputChannel = "postServiceChannel")
182+
String service(Object payload) {
183+
return payload.toString();
184+
}
185+
159186
}
160187

161188

src/reference/asciidoc/webflux.adoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
The WebFlux Spring Integration module (`spring-integration-webflux`) allows for the execution of HTTP requests and the processing of inbound HTTP requests in Reactive manner.
88
The WebFlux support consists of the following gateway implementations: `WebFluxInboundEndpoint`, `WebFluxRequestExecutingMessageHandler`.
9-
The implementation is fully based on the Spring http://docs.spring.io/spring/docs/5.0.0.RC3/spring-framework-reference/web.html#web-reactive[WebFlux] and https://projectreactor.io/[Project Reactor] foundations.
9+
The implementation is fully based on the Spring https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#spring-webflux[WebFlux] and https://projectreactor.io/[Project Reactor] foundations.
1010
Also see <<http>> for more information since many options are shared between reactive and regular HTTP components.
1111

1212
[[webflux-inbound]]
@@ -65,6 +65,8 @@ public IntegrationFlow sseFlow() {
6565

6666
Also see <<http-request-mapping>> and <<http-cors>> for more possible configuration options.
6767

68+
When the request body is empty, or `payloadExpression` returns `null`, the request params `MultiValueMap<String, String>` is used for a `payload` of the target message to process.
69+
6870
[[webflux-outbound]]
6971
=== WebFlux Outbound Components
7072

0 commit comments

Comments
 (0)