diff --git a/README.md b/README.md index 73315719e..6c088e71a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ To include the library in your Maven project, add the desired implementation to The simplest way to run your application serverlessly is to configure [API Gateway](https://aws.amazon.com/api-gateway/) to use the [`AWS_PROXY`](http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-set-up-lambda-proxy-integration-on-proxy-resource) integration type and configure your desired `LambdaContainerHandler` implementation to use `AwsProxyRequest`/`AwsProxyResponse` readers and writers. Both Spark and Jersey implementations provide static helper methods that -pre-configure this for you. +pre-configure this for you. + +When using a Cognito User Pool authorizer, use the Lambda `RequestStreamHandler` instead of the POJO-based `RequestHandler` handler. An example of this is included at the bottom of this file. The POJO handler does not support Jackson annotations required for the `CognitoAuthorizerClaims` class. ### Jersey support The library expects to receive a valid [JAX-RS](https://jax-rs-spec.java.net) application object. For the Jersey implementation this is the `ResourceConfig` object. @@ -153,3 +155,36 @@ handler.onStartup(c -> { // servlet name mappings are disabled and will throw an exception }); ``` + +# Using the Lambda Stream handler +By default, Lambda does not use Jackson annotations when marshalling and unmarhsalling JSON. This can cause issues when receiving requests that include the claims object from a Cognito User Pool authorizer. To support these type of requests, use Lambda's `RequestStreamHandler` interface instead of the POJO-based `RequestHandler`. This allows you to use a custom version of Jackson with support for annotations. + +This library uses Jackson annotations in the `com.amazonaws.serverless.proxy.internal.model.CognitoAuthorizerClaims` object. The example below shows how to do this with a `SpringLambdaContainerHandler`, you can use the same methodology with all of the other implementations. + +```java +public class StreamLambdaHandler implements RequestStreamHandler { + private SpringLambdaContainerHandler handler; + private static ObjectMapper mapper = new ObjectMapper(); + + @Override + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) + throws IOException { + if (handler == null) { + try { + handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class); + } catch (ContainerInitializationException e) { + e.printStackTrace(); + outputStream.close(); + } + } + + AwsProxyRequest request = mapper.readValue(inputStream, AwsProxyRequest.class); + + AwsProxyResponse resp = handler.proxy(request, context); + + mapper.writeValue(outputStream, resp); + // just in case it wasn't closed by the mapper + outputStream.close(); + } +} +``` \ No newline at end of file diff --git a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/model/ApiGatewayAuthorizerContext.java b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/model/ApiGatewayAuthorizerContext.java index cb51feef6..9cf189a76 100644 --- a/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/model/ApiGatewayAuthorizerContext.java +++ b/aws-serverless-java-container-core/src/main/java/com/amazonaws/serverless/proxy/internal/model/ApiGatewayAuthorizerContext.java @@ -39,7 +39,6 @@ public class ApiGatewayAuthorizerContext { private String principalId; private CognitoAuthorizerClaims claims; - //------------------------------------------------------------- // Methods - Public //------------------------------------------------------------- diff --git a/samples/spring/pet-store/src/main/java/com/amazonaws/serverless/sample/spring/StreamLambdaHandler.java b/samples/spring/pet-store/src/main/java/com/amazonaws/serverless/sample/spring/StreamLambdaHandler.java new file mode 100644 index 000000000..c4bafd058 --- /dev/null +++ b/samples/spring/pet-store/src/main/java/com/amazonaws/serverless/sample/spring/StreamLambdaHandler.java @@ -0,0 +1,45 @@ +package com.amazonaws.serverless.sample.spring; + + +import com.amazonaws.serverless.exceptions.ContainerInitializationException; +import com.amazonaws.serverless.proxy.internal.model.AwsProxyRequest; +import com.amazonaws.serverless.proxy.internal.model.AwsProxyResponse; +import com.amazonaws.serverless.proxy.spring.SpringLambdaContainerHandler; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +/** + * Created by bulianis on 5/2/17. + */ +public class StreamLambdaHandler implements RequestStreamHandler { + private SpringLambdaContainerHandler handler; + private static ObjectMapper mapper = new ObjectMapper(); + + @Override + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) + throws IOException { + if (handler == null) { + try { + handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class); + } catch (ContainerInitializationException e) { + e.printStackTrace(); + outputStream.close(); + } + } + + AwsProxyRequest request = mapper.readValue(inputStream, AwsProxyRequest.class); + + AwsProxyResponse resp = handler.proxy(request, context); + + mapper.writeValue(outputStream, resp); + // just in case it wasn't closed by the mapper + outputStream.close(); + } +}