GH-249, Add full HTTP support to SpringBootApiGatewayRequestHandler
* Add support for handling APIGatewayProxyRequestEvent objects with empty body (should apply to all GET and DELETE requests, which comply with recommandation of RFC-7231) * Add support ReSTful APIs: path and query string parameters as well as the HTTP method are now extracted from the APIGatewayProxyRequestEvent object and forwarded to the function as message headers * Extend unit tests accordingly
This commit is contained in:
committed by
Oleg Zhurakousky
parent
570bbb23b5
commit
01e813ec52
@@ -18,6 +18,7 @@ package org.springframework.cloud.function.adapter.aws;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
@@ -36,6 +37,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Semyon Fishman
|
||||
* @author Markus Gulden
|
||||
*/
|
||||
public class SpringBootApiGatewayRequestHandler extends
|
||||
SpringBootRequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
|
||||
@@ -56,12 +58,22 @@ public class SpringBootApiGatewayRequestHandler extends
|
||||
|
||||
@Override
|
||||
protected Object convertEvent(APIGatewayProxyRequestEvent event) {
|
||||
Object body = deserializeBody(event.getBody());
|
||||
if (functionAcceptsMessage()) {
|
||||
return new GenericMessage<>(body, getHeaders(event));
|
||||
|
||||
if (event.getBody() != null) {
|
||||
if (functionAcceptsMessage()) {
|
||||
return new GenericMessage<>(deserializeBody(event.getBody()), getHeaders(event));
|
||||
}
|
||||
else {
|
||||
return deserializeBody(event.getBody());
|
||||
}
|
||||
}
|
||||
else {
|
||||
return body;
|
||||
if (functionAcceptsMessage()) {
|
||||
return new GenericMessage<Optional<Void>>(Optional.empty(), getHeaders(event));
|
||||
}
|
||||
else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +95,13 @@ public class SpringBootApiGatewayRequestHandler extends
|
||||
if (event.getHeaders() != null) {
|
||||
headers.putAll(event.getHeaders());
|
||||
}
|
||||
if (event.getQueryStringParameters() != null) {
|
||||
headers.putAll(event.getQueryStringParameters());
|
||||
}
|
||||
if (event.getPathParameters() != null) {
|
||||
headers.putAll(event.getPathParameters());
|
||||
}
|
||||
headers.put("httpMethod", event.getHttpMethod());
|
||||
headers.put("request", event);
|
||||
return new MessageHeaders(headers);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.cloud.function.adapter.aws;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@@ -37,7 +38,8 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Dimitry Declercq
|
||||
* @author Markus Gulden
|
||||
*/
|
||||
public class SpringBootApiGatewayRequestHandlerTests {
|
||||
|
||||
@@ -102,6 +104,47 @@ public class SpringBootApiGatewayRequestHandlerTests {
|
||||
.isEqualTo("{\"value\":\"FOO\"}");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void functionMessageBeanWithRequestParameters() {
|
||||
this.handler = new SpringBootApiGatewayRequestHandler(
|
||||
FunctionMessageEchoReqParametersConfig.class);
|
||||
APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent();
|
||||
request.setPathParameters(Collections.singletonMap("path", "pathValue"));
|
||||
request.setQueryStringParameters(Collections.singletonMap("query", "queryValue"));
|
||||
request.setHeaders(Collections.singletonMap("test-header", "headerValue"));
|
||||
request.setHttpMethod("GET");
|
||||
|
||||
Object output = this.handler.handleRequest(request, null);
|
||||
assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class);
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode())
|
||||
.isEqualTo(200);
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("path"))
|
||||
.isEqualTo("pathValue");
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("query"))
|
||||
.isEqualTo("queryValue");
|
||||
assertThat(
|
||||
((APIGatewayProxyResponseEvent) output).getHeaders().get("test-header"))
|
||||
.isEqualTo("headerValue");
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getHeaders().get("httpMethod"))
|
||||
.isEqualTo("GET");
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getBody())
|
||||
.isEqualTo("{\"value\":\"body\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void functionMessageBeanWithEmptyResponse() {
|
||||
this.handler = new SpringBootApiGatewayRequestHandler(
|
||||
FunctionMessageConsumerConfig.class);
|
||||
APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent();
|
||||
|
||||
Object output = this.handler.handleRequest(request, null);
|
||||
assertThat(output).isInstanceOf(APIGatewayProxyResponseEvent.class);
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getStatusCode())
|
||||
.isEqualTo(200);
|
||||
assertThat(((APIGatewayProxyResponseEvent) output).getBody()).isNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ContextFunctionCatalogAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class })
|
||||
@@ -140,6 +183,38 @@ public class SpringBootApiGatewayRequestHandlerTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ContextFunctionCatalogAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class })
|
||||
protected static class FunctionMessageEchoReqParametersConfig {
|
||||
|
||||
@Bean
|
||||
public Function<Message<Foo>, Message<Bar>> function() {
|
||||
return (message -> {
|
||||
Map<String, Object> headers = new HashMap<>();
|
||||
headers.put("path", message.getHeaders().get("path"));
|
||||
headers.put("query", message.getHeaders().get("query"));
|
||||
headers.put("test-header", message.getHeaders().get("test-header"));
|
||||
headers.put("httpMethod", message.getHeaders().get("httpMethod"));
|
||||
return new GenericMessage<>(new Bar("body"), headers);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ContextFunctionCatalogAutoConfiguration.class,
|
||||
JacksonAutoConfiguration.class })
|
||||
protected static class FunctionMessageConsumerConfig {
|
||||
|
||||
@Bean
|
||||
public Consumer<Message<Foo>> function() {
|
||||
return (foo -> {
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class Foo {
|
||||
|
||||
private String value;
|
||||
|
||||
Reference in New Issue
Block a user