GH-891 Ensure HTTP Request params are mapped even when body is not present
Resolves #891
This commit is contained in:
@@ -85,6 +85,9 @@ public final class FunctionWebRequestProcessingHelper {
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static Publisher<?> processRequest(FunctionWrapper wrapper, Object argument, boolean eventStream) {
|
||||
if (argument == null) {
|
||||
argument = "";
|
||||
}
|
||||
FunctionInvocationWrapper function = wrapper.getFunction();
|
||||
|
||||
if (function == null) {
|
||||
@@ -95,21 +98,18 @@ public final class FunctionWebRequestProcessingHelper {
|
||||
|
||||
Message<?> inputMessage = null;
|
||||
|
||||
if (argument != null) {
|
||||
MessageBuilder builder = MessageBuilder.withPayload(argument);
|
||||
if (!CollectionUtils.isEmpty(wrapper.getParams())) {
|
||||
builder = builder.setHeader(HeaderUtils.HTTP_REQUEST_PARAM, wrapper.getParams().toSingleValueMap());
|
||||
}
|
||||
inputMessage = builder.copyHeaders(headers.toSingleValueMap()).build();
|
||||
|
||||
MessageBuilder builder = MessageBuilder.withPayload(argument);
|
||||
if (!CollectionUtils.isEmpty(wrapper.getParams())) {
|
||||
builder = builder.setHeader(HeaderUtils.HTTP_REQUEST_PARAM, wrapper.getParams().toSingleValueMap());
|
||||
}
|
||||
inputMessage = builder.copyHeaders(headers.toSingleValueMap()).build();
|
||||
|
||||
if (function.isRoutingFunction()) {
|
||||
function.setSkipOutputConversion(true);
|
||||
}
|
||||
|
||||
Object input = argument == null ? "" : (argument instanceof Publisher ? Flux.from((Publisher) argument) : inputMessage);
|
||||
|
||||
Object result = function.apply(input);
|
||||
Object result = function.apply(inputMessage);
|
||||
if (function.isConsumer()) {
|
||||
if (result instanceof Publisher) {
|
||||
Mono.from((Publisher) result).subscribe();
|
||||
|
||||
@@ -18,23 +18,34 @@ package org.springframework.cloud.function.web.function;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.cloud.function.context.FunctionRegistration;
|
||||
import org.springframework.cloud.function.context.FunctionalSpringApplication;
|
||||
import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
@@ -47,6 +58,28 @@ import static org.awaitility.Awaitility.await;
|
||||
*/
|
||||
public class FunctionEndpointInitializerTests {
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testEmptyBodyRequestParameters() throws Exception {
|
||||
int port = startServerAndWaitForPort(BeansConfiguration.class, false);
|
||||
TestRestTemplate testRestTemplate = new TestRestTemplate();
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("fname", "Jim");
|
||||
params.put("lname", "Lahey");
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Accept", "application/json");
|
||||
HttpEntity entity = new HttpEntity(headers);
|
||||
|
||||
String urlTemplate = UriComponentsBuilder.fromHttpUrl("http://localhost:" + port + "/nullPayload")
|
||||
.queryParam("fname", "Jim").queryParam("lname", "Lahey").encode().toUriString();
|
||||
|
||||
ResponseEntity<String> response = testRestTemplate.exchange(urlTemplate, HttpMethod.GET, entity, String.class);
|
||||
String res = response.getBody();
|
||||
assertThat(res).contains("Jim");
|
||||
assertThat(res).contains("Lahey");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonExistingFunction() throws Exception {
|
||||
int port = startServerAndWaitForPort(ApplicationConfiguration.class);
|
||||
@@ -105,8 +138,10 @@ public class FunctionEndpointInitializerTests {
|
||||
assertThat(response.getBody()).isEqualTo("Jim Lahey");
|
||||
}
|
||||
|
||||
private int startServerAndWaitForPort(Class<?> primaryAppConfig) throws InterruptedException {
|
||||
ConfigurableApplicationContext context = FunctionalSpringApplication.run(primaryAppConfig, "--server.port=0");
|
||||
private int startServerAndWaitForPort(Class<?> primaryAppConfig, boolean functional) throws InterruptedException {
|
||||
ConfigurableApplicationContext context = functional
|
||||
? FunctionalSpringApplication.run(primaryAppConfig, "--server.port=0")
|
||||
: SpringApplication.run(primaryAppConfig, "--server.port=0");
|
||||
await()
|
||||
.pollDelay(Duration.ofMillis(500))
|
||||
.pollInterval(Duration.ofMillis(500))
|
||||
@@ -118,6 +153,10 @@ public class FunctionEndpointInitializerTests {
|
||||
return Integer.valueOf(context.getEnvironment().getProperty("local.server.port"));
|
||||
}
|
||||
|
||||
private int startServerAndWaitForPort(Class<?> primaryAppConfig) throws InterruptedException {
|
||||
return this.startServerAndWaitForPort(primaryAppConfig, true);
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
protected static class ConsumerConfiguration
|
||||
implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||
@@ -136,6 +175,17 @@ public class FunctionEndpointInitializerTests {
|
||||
|
||||
}
|
||||
|
||||
@EnableAutoConfiguration
|
||||
@Configuration
|
||||
protected static class BeansConfiguration {
|
||||
@Bean
|
||||
public BiFunction<String, Map<String, Object>, Map<String, Object>> nullPayload() {
|
||||
return (p, h) -> {
|
||||
return h;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SpringBootConfiguration
|
||||
protected static class ApplicationConfiguration
|
||||
|
||||
Reference in New Issue
Block a user