1
votes

I'm new to AWS lambda functions and NodeJS. I'm trying to create an API Gateway call to a Lambda function that calls an external API and return some JSON data. It took me a while but I was finally able to get something to work based on this post: AWS Lambda HTTP POST Request (Node.js)

The problem was the API Gateway kept erroring with a 502 Bad Gateway; which turns out to be that the JSON response was malformed. In the post I referenced above everyone seem to have success with just returning the JSON as-is, but I had to follow the instructions here to fix my issue: https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/

My question is: if you look at the last 10 lines of my code that finally worked I had to reformat my response, as well as use a callback in a async function. I am new to nodeJS and Lambda but it looks wrong to me, even though it works. The post I referenced seem to have much more elegant code, and I hope someone can tell me what I am doing wrong.

const https = require('https');
var responseBody = {"Message": "If you see this then the API call did not work"};

const doGetRequest = () => {

  return new Promise((resolve, reject) => {
    const options = {
      host: 'my.host.com',
      path: '/api/v1/path?and=some&parameters=here',
      method: 'GET',
      headers: {
        'Authorization': 'Bearer token for testing',
        'X-Request-Id': '12345',
        'Content-Type': 'application/json'
      }
    };
    var body='';
    //create the request object with the callback with the result
    const req = https.request(options, (res) => {

      res.on('data', function (chunk) {
            body += chunk;
        });
      res.on('end', function () {
         console.log("Result", body.toString());
         responseBody = body;
      });
      resolve(JSON.stringify(res.statusCode));
    });

    // handle the possible errors
    req.on('error', (e) => {
      reject(e.message);
    });
    //finish the request
    req.end();
  });
};

exports.handler = async (event, context, callback) => {
await doGetRequest();

    var response = {
        "statusCode": 200,
        "headers": {
            "my_header": "my_value"
        },
        "body": JSON.stringify(responseBody),
        "isBase64Encoded": false
    };
    callback(null, response);
};
1

1 Answers

0
votes

I see couple of things.

  • We need to get the values from method doGetRequest and use the response, we can do that by await response = doGetRequest() or doGetRequest.then(), since we ant to capture errors as well, i went with second method.
  • We also need to resolve or reject the actual response from within promise.

I tested with a different api(with url of this question). Here is the updated code.

const https = require('https');
var responseBody = {"Message": "If you see this then the API call did not work"};
const doGetRequest = () => {

  return new Promise((resolve, reject) => {
    const options = {
      host: 'stackoverflow.com',
      path: '/questions/66376601/aws-api-gateway-with-lambda-http-get-request-node-js-502-bad-gateway',
      method: 'GET'
    };
    var body='';
    //create the request object with the callback with the result
    const req = https.request(options, (res) => {

      res.on('data', function (chunk) {
            body += chunk;
        });
      res.on('end', function () {
         console.log("Result", body.toString());
         resolve(body);
      });
      
    });

    // handle the possible errors
    req.on('error', (e) => {
      reject(e.message);
    });
    //finish the request
    req.end();
  });
};

exports.handler =   (event, context, callback) => {
    console.log('event',event, 'context',context);
    

    doGetRequest().then(result => {
    var response = {
        "statusCode": 200,
        "headers": {
            "my_header": "my_value"
        },
        "body": JSON.stringify(result),
        "isBase64Encoded": false
    };
      callback(null, response);
    }).catch(error=> {
        callback(error);
    })
};