Return Body in Azure Function

Viewed 403

I need a little help. I am creating an Azure function to generate a token using NodeJS. Below is the function I have created.

const { response } = require('request');
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');

var request = require('request');
var options = {
    'method': 'POST',
    'url': 'https://abc.onbmc.com/api/jwt/login',
    'headers': {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Connection': 'keep-alive'
    },
    form: {
        'username': 'abc@xyz.com',
        'password': 'password123'
    }
};
request(options, function (error, response) {
    if (error) throw new Error(error);
    console.log(response.body);
    context.res = {
        //status: 200, /* Defaults to 200 */
        body: response.body
    };
}
)
}

I am able to display the required output through console.log but am not able to display it in the response body. Response body just shows the HTTP requested is completed successfully.

HTTP/1.1 200 OK
Connection: close
Date: Tue, 14 Sep 2021 16:32:39 GMT
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Content-Length: 0

Any help is appreciated.

1 Answers

You are not awaiting a response.

By the time you receive a response from "https://abc.onbmc.com/api/jwt/login", the function has already returned the data to the consumer - hence 200 OK, even if you receive an error in a callback. Function instance continues to work after a response is returned, so it logs in callback successfully, but you are assigning the body property into the object that has been already returned.

In order to fix this behaviour (assuming you still want to use request module) you can promisify it with use of util module like below:

const util = require('util')
const { response } = require('request');
const requestPromise = util.promisify(request);

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    var request = require('request');
    var options = {
        'method': 'POST',
        'url': 'https://abc.onbmc.com/api/jwt/login',
        'headers': {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Connection': 'keep-alive'
        },
        form: {
            'username': 'abc@xyz.com',
            'password': 'password123'
        }
    };
    try {
        const response = await requestPromise(options);
        console.log(response.body);
        context.res = {
            //status: 200, /* Defaults to 200 */
            body: response.body
        };
    } catch (error) {
        // Handle your error here
        throw new Error(error);
    }
}

This way you are awaiting a response to come from the desired URL.

Worth to mention: this is a recommended way of handling such cases straight from Microsofts documentation: https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node?tabs=v2#use-async-and-await

Related