Bobby Bruce
Bobby Bruce

Reputation: 361

Asynchronous HTTP request in AWS Lambda

I am wanting to execute a http request inside of a lambda function, invoked by API Gateway. The problem is, the request takes a bit of time to complete (<20 seconds) and don't want the client waiting for a response. In my research on asynchronous requests, I learned that I can pass the X-Amz-Invocation-Type:Event header to make the request execute asynchronously, however this isn't working and the code still "waits" for the http request to complete.

Below is my lambda code:

'use strict';

const https = require('https');

exports.handler = function (event, context, callback) {
    let requestUrl;
    requestUrl = event.queryStringParameters.url;

    https.get(requestUrl, (res) => {
        console.log('statusCode:', res.statusCode);
        console.log('headers:', res.headers);

        res.on('data', (d) => {
            process.stdout.write(d);
        });
    }).on('error', (e) => {
        console.error(e);
    });

    let response = {
        "statusCode": 200,
        "body": JSON.stringify(event.queryStringParameters)
    };
    callback(null, response);
};

Any help would be appreciated.

Upvotes: 7

Views: 4661

Answers (2)

Warren Parad
Warren Parad

Reputation: 4101

Whatever you do, don't use two lambda functions.

You can't control how lambda is being called, async or sync. The caller of the lambda decides that. For APIGW, it has decided to call lambda sync.

The possible solutions are one of:

  • SQS
  • Step Functions (SF)
  • SNS

In your API, you call out to one of these services, get back a success, and then immediately return a 202 to your caller.

If you have a high volume of single or double action execution use SQS. If you have potentially long running with complex state logic use SF. If you for someone reason want to ignore my suggestions, use SNS.

Each of these can (and should) call back out to a lambda. In the case that you need to run more than 15 minutes, they can call back out to CodeBuild. Ignore the name of the service, it's just a lambda that supports up to 8 hour runs.


Now, why not use two lambdas (L1, L2)? The answer is simple. Once you respond that your async call was queued (SQS, SF, SNS), to your users (202). They'll expect that it works 100%. But what happens if that L2 lambda fails. It won't retry, it won't continue, and you may never know about it.

That L2 lambda's handler no longer exist, so you don't know the state any more. Further, you could try to add logging to L2 with wrapper try/catch but so many other types of failures could happen. Even if you have that, is CloudWatch down, will you get the log? Possible not, it just isn't a reliable strategy. Sure if you are doing something you don't care about, you can build this arch, but this isn't how real production solutions are built. You want a reliable process. You want to trust that the baton was successfully passed to another service which take care of completing the user's transaction. This is why you want to use one of the three services: SQS, SF, SNS.

Upvotes: 3

Noel Llevares
Noel Llevares

Reputation: 16087

You can use two Lambda functions.

Lambda 1 is triggered by API Gateway then calls Lambda 2 asynchronously (InvocationType = Event) then returns a response to the user.

Lambda 2, once invoked, will trigger the HTTP request.

Upvotes: 3

Related Questions