How do I grant internet access to my function?

My lambda function is making an outbound HTTP request to an external API. I’m getting a 502 Bad Gateway error when I hit my lambda function via REST, and through some research (logs don’t elaborate) I’m thinking it’s probably that it doesn’t have internet access.

I’m just using the default aws-nodejs template, so I don’t have any kind of VPC or gateway settings enabled. Is there an easy way to grant internet access to my function?

Hey Tim,

You will want to expose your lambda function via API gateway with the http event

See https://serverless.com/framework/docs/providers/aws/events/apigateway/ for some examples

Hi @DavidWells, it’s already using HTTP as a trigger - my challenge is outbound HTTP access, so my lambda function can make a request to an external API (ie. Twilio) when it’s called.

Here is a twilio example https://github.com/serverless/examples/blob/master/aws-node-twilio-send-text-message/handler.js#L17

You should also be able to use the ‘request’ module from NPM to make outbound http requests

Wow, that’s odd… it suggests that lambda functions created via serverless automatically have access to make outbound http requests… I can’t imagine why mine wouldn’t work then… I actually am using request to make the request (commented out right now since it doesn’t work), but whenever I try to make an outbound http request, my lambda function throws a 502 bad gateway error when I invoke it. There are no more detailed logs… any idea what else it could be?

Look at the logs of your function.

sls logs -f functionName -t and see what the error is. Cloudwatch should give you some insight into where your function is erroring out.

Yep, all non-VPC Lambda functions have Internet access.

If there’s no other interesting log output (as per @DavidWells’s comment), can you try requesting another URL to confirm basic connectivity? Are you doing anything special with proxies or authentication?

@DavidWells unfortunately the CloudWatch logs (as well as sls logs) just show the START, END, and REPORT logs, none of which appear related. I did console.log the URL being constructed/requested, which worked, and I even console.loged inside request's success callback and that showed in the logs. The issue appears to be that accessing my lambda function over HTTP throws a 502 bad gateway error instantly, before the console.logs of the URL/success message even show up in the logs. Note that I don’t get the 502 error when not making an http request within the lambda function.

@rowanu I did try requesting https://www.google.com with the same result. I’m not doing anything with proxies or authentication.

Thanks for your time.

  1. Add lots of logging (i.e. make the first line a log entry)
  2. Make sure you’re calling the right API GW (it’s wouldn’t be the first time I spent 15 minutes calling the wrong URL)
  3. If your using Babel, TypeScript, etc then make sure you compile before you deploy
  4. Check your return value is what the GW is expecting
  5. Use node locally to make sure you don’t have any syntax errors in your Lambda.
2 Likes

@buggy so I added a bunch of logging and it does in fact complete the request – so apparently it has access to make an outbound request. The problem is that long before the console logs show the request being made or completed, the lambda function has returned a 502 bad gateway error to the requestor. This 502 error is only shown when the lambda function is making an http request. The logs don’t give any indication why it’s happening. Any idea what could be causing it?

As shown in the log below, there’s a log when the function is called, a log of the URL it’s querying, a log when the request is initiated, when it completes, and verifying that err is null. I’ve even tried console.loging the response body in here as well and it shows the expected response. But the initiating http request that kicks off this function errors out 502 long before any of these logs show up in my console.

START RequestId: 70ba7579-ecc1-11e6-856a-79a25d5656e7 Version: $LATEST
2017-02-06 18:10:25.067 (-05:00)	70ba7579-ecc1-11e6-856a-79a25d5656e7	soda function called
2017-02-06 18:10:25.084 (-05:00)	70ba7579-ecc1-11e6-856a-79a25d5656e7	https://phl.carto.com/api/v2/sql?q=SELECT%20*%2C%20ST_AsGeoJSON(the_geom)%3A%3Ajson%20AS%20the_geom%20FROM%20%22incidents_part1_part2%22%20WHERE%20location_b%20%3D%20'800%20BLOCK%20S%20BROAD%20ST'
2017-02-06 18:10:25.084 (-05:00)	70ba7579-ecc1-11e6-856a-79a25d5656e7	requesting
2017-02-06 18:10:25.181 (-05:00)	70ba7579-ecc1-11e6-856a-79a25d5656e7	request completed
2017-02-06 18:10:25.181 (-05:00)	70ba7579-ecc1-11e6-856a-79a25d5656e7	no error on request
END RequestId: 70ba7579-ecc1-11e6-856a-79a25d5656e7
REPORT RequestId: 70ba7579-ecc1-11e6-856a-79a25d5656e7	Duration: 116.97 ms	Billed Duration: 200 ms 	Memory Size: 1024 MB	Max Memory Used: 30 MB

I think I’ve figured it out – the request module callback function signature is (err, response, body). I thought I could simply pass the lambda callback to the request. But request's response object contains a bunch more properties than just statusCode and body, and I think that’s what’s throwing it.

So this works:

  request(cartoUrl, (err, resp, body) => {
    const response = {
      statusCode: resp.statusCode,
      body: resp.body
    }

    callback(null, response)
  })

:-/ thanks though

[ '_readableState',
  'readable',
  'domain',
  '_events',
  '_eventsCount',
  '_maxListeners',
  'socket',
  'connection',
  'httpVersionMajor',
  'httpVersionMinor',
  'httpVersion',
  'complete',
  'headers',
  'rawHeaders',
  'trailers',
  'rawTrailers',
  'upgrade',
  'url',
  'method',
  'statusCode',
  'statusMessage',
  'client',
  '_consuming',
  '_dumped',
  'req',
  'request',
  'toJSON',
  'caseless',
  'read',
  'body' ]
1 Like