AWS Lambda unable to make external API call

Hi all,

I am trying to access an 3rd party API from my javascript lambda function.

So far I have tried the http standard library, axios and superagent. All do not work, console.logs from within their success or fail callbacks/promises are not being triggered. I am not able to even get a failed or timeout response.

I can confirm that the code and 3rd party API works, as I am able to get a response from a local node instance I have setup.

I have read through http://forum.serverless.com/t/solved-aws-python-call-to-external-apis-from-my-lambda-function/4177 and http://forum.serverless.com/t/how-do-i-grant-internet-access-to-my-function/1275, however my issue appears to be different. I am not getting a null response from the API call and I do not have any VPC configs.

Here is my serverless.yml snippet

myFunc:
    handler:       src/myFunc.main
    events:
      - http:
          path:    myRoute
          method:  get
          cors:    true
          authorizer: aws_iam

and my lambda snippet

export async function main(event, context, callback) {
    console.log('main function triggered') // appears in cloudwatch

    try {
        console.log('try block triggered') // appears in cloudwatch

        const superagent = require('superagent')
        console.log('superagent loaded', superagent) // appears in cloudwatch

        superagent.get('https://api.nasa.gov/planetary/apod')
            .query({
                api_key: 'DEMO_KEY',
                date: '2017-08-02'
            })
            .end((err, res) => {
                console.log('end function triggered') // MISSING in cloudwatch

                if (err) {
                    return console.log(err) // MISSING in cloudwatch
                }
                console.log(res.body.url) // MISSING in cloudwatch
                console.log(res.body.explanation) // MISSING in cloudwatch
                callback(null, success(res.body.explanation))
            })
        console.log('after superagent') // appears in cloudwatch

    } catch (e) {
        console.log('catch block ran') // does not appear in cloudwatch, as expected
        console.log(e) // does not appear in cloudwatch, as expected
        callback(null, failure({
            status: false
        }))
    }
}

Any help will be greatly appreciated.

I think your problem is here:

Try removing the async.

inconceivable…

Yeah removing async resolved the error. Thanks for the good catch.

On a side note, I am under the impression that adding async to functions is generally harmless, it only enables await to work. Any idea why is it tripping up in this case?

relevant stackoverflow - https://stackoverflow.com/questions/45594596/async-function-without-await-in-javascript?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

Functions declared async actually return a Promise so you could think of

async function main(event, context) {
}

as a short way of writing

function main(event, context) {
  return new Promise((resolve) => resolve());
}

My best guess is that AWS is always passing the event, context and callback parameters into your handler (even if callback isn’t documented in the async syntax) then they’re looking to see if you return a Promise or not. If you return a Promise then they call callback() for you once it resolves.

When you had async in your code the main function was returning a Promise that resolved once everything inside main finished running which was happening before the callback passed to end() was executed resulting in the Lambda terminating.

Of course I’m not an expert on the internals of Lambda so I could be completely wrong.

1 Like