GH-864 Add support for carying HTTP request parameters in Message headers

Resolves #864
This commit is contained in:
Oleg Zhurakousky
2022-05-03 19:14:00 +02:00
parent fce68b7ae8
commit cef0cb8057
4 changed files with 45 additions and 1 deletions

View File

@@ -650,6 +650,13 @@ When POSTing text the response format might be different with Spring Boot 2.0 an
See <<Testing Functional Applications>> to see the details and example on how to test such application.
==== HTTP Request Parameters
As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., `/{function}/{item}`).
For example, `http://localhost:8080/uppercase/foo` will result in calling `uppercase` function with its input parameter being `foo`.
While this is the recommended approach and the one that fits most use cases cases, there are times when you have to deal with HTTP request parameters.
The framework will treat HTTP request parameters similar to the HTTP headers by storing them in `Message` headers under the header key `http_request_param`
with its value being a `Map` of request parameters, so in order to access them your function input signature should accept `Message` type (e.g., `Function<Message<String>, String>`). For convenience we provide `HeaderUtils.HTTP_REQUEST_PARAM` constant.
=== Function Mapping rules

View File

@@ -89,7 +89,15 @@ public final class FunctionWebRequestProcessingHelper {
HttpHeaders headers = wrapper.getHeaders();
Message<?> inputMessage = argument == null ? null : MessageBuilder.withPayload(argument).copyHeaders(headers.toSingleValueMap()).build();
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();
}
if (function.isRoutingFunction()) {
function.setSkipOutputConversion(true);

View File

@@ -31,6 +31,11 @@ import org.springframework.messaging.MessageHeaders;
*/
public final class HeaderUtils {
/**
* Message Header name which contains HTTP request parameters.
*/
public static final String HTTP_REQUEST_PARAM = "http_request_param";
private static HttpHeaders IGNORED = new HttpHeaders();
private static HttpHeaders REQUEST_ONLY = new HttpHeaders();

View File

@@ -17,6 +17,8 @@
package org.springframework.cloud.function.web.mvc;
import java.net.URI;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
@@ -29,10 +31,12 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.cloud.function.web.RestApplication;
import org.springframework.cloud.function.web.mvc.PrefixTests.TestConfiguration;
import org.springframework.cloud.function.web.util.HeaderUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.Message;
import org.springframework.test.context.ContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
@@ -65,6 +69,15 @@ public class PrefixTests {
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
}
@Test
public void uppercase() throws Exception {
ResponseEntity<String> result = this.rest.exchange(
RequestEntity.get(new URI("/functions/uppercase/foo?nome=Doe&prenome=John")).build(), String.class);
assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(result.getBody()).isEqualTo("[\"foo\",\"bar\"]");
}
@EnableAutoConfiguration
@org.springframework.boot.test.context.TestConfiguration
protected static class TestConfiguration {
@@ -74,6 +87,17 @@ public class PrefixTests {
return () -> Flux.fromArray(new String[] { "foo", "bar" });
}
@Bean
public Function<Message<String>, String[]> uppercase() {
return message -> {
assertThat(message.getPayload().equals("foo"));
Map<String, String> httpParam = (Map<String, String>) message.getHeaders().get(HeaderUtils.HTTP_REQUEST_PARAM);
assertThat(httpParam.get("nome")).isEqualTo("Doe");
assertThat(httpParam.get("prenome")).isEqualTo("John");
return new String[] { "foo", "bar" };
};
}
}
}