Eric
Eric

Reputation: 2076

AWS Java Lambda Function with API Gateway - POJO input and OutputStream output

I'm creating a simple AWS Lambda Function in Java that creates and returns a PDF. The function is invoked by an API Gateway. The input is a simple POJO class, but the output should be an OutputStream for the file.

For the input, I've tried creating a POJO class and just using the APIGatewayProxyRequestEvent and either works fine. Below is a simple example I used that takes in a input and prints back the query string parameters.

public class LambdaFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest( APIGatewayProxyRequestEvent input, Context context ) {

        return new APIGatewayProxyResponseEvent()
            .withStatusCode(200)
            .withHeaders(Collections.emptyMap())
            .withBody("{\"input\":\"" + input.getQueryStringParameters() + "\"}");
    }

}

That works fine, but now I need to alter it to use an OutputStream as the the output. How can this be done? I see that I can use the RequestStreamHandler and AWS has some documentation on implementing this. However, that would force my input to be an InputStream, which I'm not sure how that would work with the API Gateway.

How can I serve this PDF back to the client requesting it?

Upvotes: 2

Views: 2189

Answers (1)

stdunbar
stdunbar

Reputation: 17435

Remember that the POJO method of the Lambda handler is a convenience only. Ultimately, you could do this yourself and use the InputStream/OutputStream Lambda pattern. Something like:

public void handleRequest(InputStream inputStream,
                          OutputStream outputStream,
                          Context context) throws IOException {
    String inputString = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));

    ObjectMapper objectMapper = new ObjectMapper();
    APIGatewayProxyRequestEvent request = objectMapper.readValue(inputString, APIGatewayProxyRequestEvent.class);

    // do your thing, generate a PDF
    byte[] thePDF = ...
    // create headers
    Map<String, String> headers = new HashMap<>();
    headers.put("Content-type", "application/pdf");

    APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent().
             .withStatusCode(200)
             .withHeaders(headers)
             .withBody(Base64.Encoder.encode(thePDF))
             .withIsBase64Encoded(Boolean.TRUE);

    outputStream.write(objectMapper.writeValueAsString(response)
                                   .getBytes(StandardCharsets.UTF_8));
}

However, I'm not convinced that this is really any better. If you want to return just the PDF without the APIGatewayProxyResponseEvent you can but now you'll have to update API Gateway to correctly send the Content-Type header.

Upvotes: 1

Related Questions