2.4 Processing Input Data

We just saw how Pulumi Crosswalk allows you to quickly define serverless API endpoints and created a simple get request.

Now, let’s take things a little further.

Step 1 — Add a new API Gateway Route

Create a new route in your API Gateway that accepts post requests. We’ll add this to our already created API Gateway in the routes: [] block. The route should like this this:

{
    path: "encode",
    method: "POST",
    eventHandler: async (event) => {
        console.log("request: " + JSON.stringify(event));
        let body: string
        let responseCode: number

        if (event.body != null) {
            if (event.isBase64Encoded) {
                body = event.body // API gateway will base64 encode for us
                responseCode = 200
            } else {
                body = Buffer.from(event.body).toString('base64')
                responseCode = 200
            }
        } else {
            body = "No data submitted"
            responseCode = 400
        }

        return {
            statusCode: responseCode,
            body: body,
        }
    },
}

This new encode endpoint simply takes some HTTP body data and base64 encodes it for us. Let’s run this program and add the new route to our API gateway.

The index.ts file should now have the following contents:

import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";

const api = new awsx.apigateway.API("hello-world", {
    routes: [{
        path: "/",
        method: "GET",
        eventHandler: async (event) => {
            return {
                statusCode: 200,
                body: "Hello, world!",
            };
        },
    }, {
        path: "encode",
        method: "POST",
        eventHandler: async (event) => {
            console.log("request: " + JSON.stringify(event));
            let body: string
            let responseCode: number

            if (event.body != null) {
                if (event.isBase64Encoded) {
                    body = event.body // API gateway will base64 encode for us
                    responseCode = 200
                } else {
                    body = Buffer.from(event.body).toString('base64')
                    responseCode = 200
                }
            } else {
                body = "No data submitted"
                responseCode = 400
            }

            return {
                statusCode: responseCode,
                body: body,
            }
        },
    }],
})

export const url = api.url;

Deploy the changes:

pulumi up

This will give you a preview and selecting yes will apply the changes:

Previewing update (dev)

View Live: https://app.pulumi.com/jaxxstorm/api-gateway/dev/previews/657bac12-9b9e-4ca8-861e-a014b8e69f79

     Type                                Name                          Plan        Info
     pulumi:pulumi:Stack                 api-gateway-dev
     └─ aws:apigateway:x:API             hello-world
 +      ├─ aws:iam:Role                  hello-world02cbc3ee           create
 +      ├─ aws:iam:RolePolicyAttachment  hello-world02cbc3ee-32be53a2  create
 +      ├─ aws:lambda:Function           hello-world02cbc3ee           create
 ~      ├─ aws:apigateway:RestApi        hello-world                   update      [diff: ~body]
 +-     ├─ aws:apigateway:Deployment     hello-world                   replace     [diff: ~variables]
 +-     ├─ aws:lambda:Permission         hello-world-fa520765          replace     [diff: ~sourceArn]
 +      ├─ aws:lambda:Permission         hello-world-9451c357          create
 ~      └─ aws:apigateway:Stage          hello-world                   update      [diff: ~deployment]

Outputs:
  ~ url: "https://14oplegt8g.execute-api.us-east-1.amazonaws.com/stage/" => output<string>

Resources:
    + 4 to create
    ~ 2 to update
    +-2 to replace
    8 changes. 5 unchanged

Step 2 — Send some data to the echo endpoint

We can post some data to our base64 encoding service using cURL. First, let’s send a simple string:

curl -X POST $(pulumi stack output url)/encode -d foo

The API gateway may take a few moments to provision the endpoint

This should return a small base64 encoded string:

Zm9v

We can also send some JSON data:

curl -X POST $(pulumi stack output url)/encode -d '{"foo": "bar"}'

Step 3 — View the function logs

A nice feature of Pulumi when developing serverless applications is the ability to quickly view the logs from the function within the Pulumi application. Run pulumi logs from without your stack:

pulumi logs

You’ll get the lambda function output:

 2020-12-01T22:15:00.668-08:00[   hello-world02cbc3ee-f622aef] START RequestId: 4d57a569-cb00-494f-8613-875d6038a979 Version: $LATEST
 2020-12-01T22:15:00.670-08:00[   hello-world02cbc3ee-f622aef] 2020-12-02T06:15:00.670Z	4d57a569-cb00-494f-8613-875d6038a979	INFO	request: {"resource":"/encode","path":"/encode","httpMethod":"POST","headers":{"Accept":"*/*","CloudFront-Forwarded-Proto":"https","CloudFront-Is-Desktop-Viewer":"true","CloudFront-Is-Mobile-Viewer":"false","CloudFront-Is-SmartTV-Viewer":"false","CloudFront-Is-Tablet-Viewer":"false","CloudFront-Viewer-Country":"US","content-type":"application/x-www-form-urlencoded","Host":"8i41k0ifjd.execute-api.us-east-1.amazonaws.com","User-Agent":"curl/7.64.1","Via":"2.0 3dcf7c8001b07734617b28e9bacc90ad.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"Xmm43gQdDAsIGfQrrePMTkNfakJild8CwLi5Ueq0CArYFWwlqB42hw==","X-Amzn-Trace-Id":"Root=1-5fc730e4-5a1e0d750d6f40c80527173e","X-Forwarded-For":"24.56.241.187, 130.176.132.123","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"multiValueHeaders":{"Accept":["*/*"],"CloudFront-Forwarded-Proto":["https"],"CloudFront-Is-Desktop-Viewer":["true"],"CloudFront-Is-Mobile-Viewer":["false"],"CloudFront-Is-SmartTV-Viewer":["false"],"CloudFront-Is-Tablet-Viewer":["false"],"CloudFront-Viewer-Country":["US"],"content-type":["application/x-www-form-urlencoded"],"Host":["8i41k0ifjd.execute-api.us-east-1.amazonaws.com"],"User-Agent":["curl/7.64.1"],"Via":["2.0 3dcf7c8001b07734617b28e9bacc90ad.cloudfront.net (CloudFront)"],"X-Amz-Cf-Id":["Xmm43gQdDAsIGfQrrePMTkNfakJild8CwLi5Ueq0CArYFWwlqB42hw=="],"X-Amzn-Trace-Id":["Root=1-5fc730e4-5a1e0d750d6f40c80527173e"],"X-Forwarded-For":["24.56.241.187, 130.176.132.123"],"X-Forwarded-Port":["443"],"X-Forwarded-Proto":["https"]},"queryStringParameters":null,"multiValueQueryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"resourceId":"10gsf9","resourcePath":"/encode","httpMethod":"POST","extendedRequestId":"W6STvFSJoAMFeYA=","requestTime":"02/Dec/2020:06:15:00 +0000","path":"/stage//encode","accountId":"616138583583","protocol":"HTTP/1.1","stage":"stage","domainPrefix":"8i41k0ifjd","requestTimeEpoch":1606889700655,"requestId":"e62303e4-684b-4f96-a319-f143cdaa07aa","identity":{"cognitoIdentityPoolId":null,"accountId":null,"cognitoIdentityId":null,"caller":null,"sourceIp":"24.56.241.187","principalOrgId":null,"accessKey":null,"cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,"userAgent":"curl/7.64.1","user":null},"domainName":"8i41k0ifjd.execute-api.us-east-1.amazonaws.com","apiId":"8i41k0ifjd"},"body":"eyJmb28iOiAiYmFyIn0=","isBase64Encoded":true}
 2020-12-01T22:15:00.671-08:00[   hello-world02cbc3ee-f622aef] END RequestId: 4d57a569-cb00-494f-8613-875d6038a979
 2020-12-01T22:15:00.671-08:00[   hello-world02cbc3ee-f622aef] REPORT RequestId: 4d57a569-cb00-494f-8613-875d6038a979	Duration: 1.24 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 66 MB

This is being returned from the console.log statement in our function.

Step 4 — Destroy Everything

Finally, destroy the resources and the stack itself:

pulumi destroy
pulumi stack rm