user9687
user9687

Reputation: 91

How to use Nodejs "request" work aysn in AWS Lambda?

When I'm trying to use "request" to access external API and get back the response in AWS Lambda, I don't know how to properly put my "return" code to return the response.

NodeJs 8.10

var request = require('request');

module.exports.sendcode = async (event) => {

  let options = {
    url: 'https://api.netease.im/sms/sendcode.action?' + content, 
    method: 'POST'
  };

  return await request(options, function (error, response, body) {
    console.log(body); 
    return {
      statusCode: 200,
      body: JSON.stringify({
        message: body,
        input: event,
      }),
    };
  });
};

When I run this code in serverless framework, I got a null response, there is nothing in the body, actually it should have at least the "input" attribute.

But console.log already logs the actual response from API.

It looks like my "return" code is not executed at all. (If I remove async and await, then the program hangs until timeout)

Can anyone help how to modify this code to make it work?

Upvotes: 1

Views: 2203

Answers (3)

djheru
djheru

Reputation: 3719

Request does not use promises, so your await keyword is doing nothing. If you want to use promises with request, you need to find a library that supports promises, as noted here: https://www.npmjs.com/package/request#promises--asyncawait A popular option is https://github.com/request/request-promise-native

However, it is a simple matter to simply wrap a request in a promise, so that you don't need to use another dependency

var request = require('request');

const requestHandler = (options) => new Promise((resolve, reject) => {
  request(options, (error, response, body) => {
    if (error) {
      console.error(error);
      reject(error);
    } else {
      console.log(response, body);
      resolve({ response, body });
    }
  });
});

module.exports.sendcode = async (event) => {

  let options = {
    url: 'https://api.netease.im/sms/sendcode.action?' + content, 
    method: 'POST'
  };
  const { response, body } =  await requestHandler(options);
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: body,
      input: event,
    })
  }
};

Upvotes: 5

Sreehari
Sreehari

Reputation: 1370

Use Async/Await with promises. You cannot use Async-Await syntax with callback. Either you must write a promise wrapper for your 'request'callback or you can use request-promise module which is already available.

I have already provided answer for similar problem which you can refer here. Undefined value after returning an array of values from a MySQL query in a different file

Upvotes: 0

1565986223
1565986223

Reputation: 6718

Instead of writing your own promise wrapper, maybe request-promise pacakge with promise wrapper on top of request by the same authors, would be of interest to you.

const rp = require('request-promise')

module.exports.sendcode = async (event) => {

  let options = {
    url: 'https://api.netease.im/sms/sendcode.action?' + content, 
    method: 'POST'
  };

  const body =  await rp(options)
  console.log(body);
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: body,
      input: event,
    }),
  };
};

If you want full response you've to simply set resolveWithFullResponse to true

let options = {
  url: 'https://api.netease.im/sms/sendcode.action?' + content, 
  method: 'POST',
  resolveWithFullResponse: true
};

// now response contains full respose
const response =  await rp(options)
// response.body
// response.statusCode

Upvotes: 2

Related Questions