Cannot read POST response body from external api in firebase cloud functions - javascript

I have a cloud function which makes an http POST request to the LinkedIn API in order to retrieve an access token. The problem is that I cannot read the body of the response, it's always undefined.
Here's the code
exports.linkedinToken = functions.https.onRequest((req, res) => {
let url = "https://linkedin.com/oauth/v2/accessToken?...REQUIRED_PARAMS...";
request.post(url, {json: true}, (err, response, body) => {
if (!!err) { // this is never happening
console.log(err);
throw err;
} else {
console.log(response.body); // this is always undefined
console.log(body); // this is always undefined
}
});
If I try the same request with Postman or curl it works perfectly, and I cannot really understand why.
Before this request, I made another GET request to the linkedin API and it works normally. Maybe there's a problem with POST requests.

I think you are missing headers.
var request = require('request');
request.post({
headers: {
'content-type' : 'application/x-www-form-urlencoded',
'cache-control' : 'no-cache'
},
url: url
}, function(error, response, body){
console.log(body);
});

Related

Storing API response in session

On POST of a page I'm trying to GET information from an API, return the output and store the results so it can be used across all pages. The method in which the API is called isn't the best but it's just for proof of concept rather than production quality. So here is the code at the moment:
router.post('/page-one/', function (req, res) {
var options = {
'method': 'GET',
'url': 'https://api.information.service.com/company/<value>',
'headers': {
'Authorization': 'Basic <key>'
}
}
request(options, function (error, response) {
if (error) throw new Error(error)
console.log(response.body)
})
res.redirect('/page-two/')
})
So this works fine, the console returns the right information. How would I then take this and use it across all pages? Say on page 2 my get is:
router.get('/page-two/', function (req, res) {
res.render('/page-two/', {
})
})
I'm using Express, Express Session, Express Writer and Nunjucks.

Request package: response.body is not JSON

I am using nodejs request module to fetch data from stackexchange api. However, I do not understand the body of the response
��V�n�6������$_��Ң�C��MQc�Ԓ���wHɉs�.l��s�>��㆕ڋ�
<C2��ݓ-�T��x]OȄ���T���Y�Z��2Cs�{ד;��<Ū�å��Ѭ�՚�O�x����i��+��x:��0�d$��ʬ1(��z]�R2�[�d�xnL��0��� %����T�a���f��hM�wV��Z�߭���($�z �UA�+AJ�w�P;'�BY���L�6�n䖩��;����֏��X?��"B�'�Q5�z[�v+*ka0�(B݉�ޠ�i�)�1D�D���o�ٯ�&��d:FgPNsA}E�`:�
1H?j���Fy4O�h��;'�O����#2�H�=`Z)|Rq��J�o+�_�����I��~�d�[TI��pSظ�}��y�H8����-4
<p���#�X�{�Y�d�4�jq��Z;����K�����}��:pu���NGt��ԟDӉ%l��M��8�&4������#d*� �Eʔbj�-, �u��
IpE��!Y�� `;�5��yX-�b)N&S)0�6�-���f��Q��8��f"i�+m�6.�M�sr�B�ST�x��y�6���l�3����
<a[48�Mp#��(���b�'���RA�D�m���n\4.8�.��.���v5jjU���Y��25S�-�]���z�T��'�:�޲�d&�I[��7pv�:��Ф(�3���$g$�1��׮z`�0��=�+���5px��x����r��u�-�������V�}ڼ����,8L��o�%�ږ��wc�#mM��&v�N|���Z�q�pZ?J������K[���Rd��BfX/�O�#ֿ���˷
��3T�mGa�`۴�7�ƕ"[���T�}�����v_�T�#��A����g}����ӌN�]��K�,$΁gJ<��z?���ђ
k��Q�a ����$V66�g�? �H�����1��5�c�Xi���0[i��܍�
�̞Ϝl�*��8d�����C����R0�i3��dfI�b�k]��^he�QX3�Ҏ ;�5/���X�r(��7Z�A.���tR�9D*�F�ű���V�w�o.�ɪt))4�_ҐUI<��ӻb%���'�d|��3���
I want the body to be in JSON format.
I tried using JSON.parse(body) but it throws this error
undefined:1
� ^
SyntaxError: Unexpected token in JSON at position 0
Here is the code on my nodeJS app
var questionId = req.params.id
request.get('https://api.stackexchange.com/2.2/questions/'+questionId+'?order=desc&sort=activity&site=stackoverflow&filter=!9Z(-wwYGT',
{json:true}, (error, response, body) => {
if(error) res.status(500).json(error)
else{
res.status(200).send(body)
}
})
Stack Exchange is requiring gzip. The request module isn't requesting it by default, so it assumes that it doesn't need to decode it.
Enable gzip on the request:
const request = require('request');
request.get(
{
url: 'https://api.stackexchange.com/2.2/questions/53684484?order=desc&sort=activity&site=stackoverflow&filter=!9Z(-wwYGT',
json:true,
gzip: true
}, (error, response, body) => {
console.log({error, response, body});
}
);
https://repl.it/repls/AppropriateSarcasticFilesize
Assuming request is the npm request module, the get method allows only two parameters (URL or options with URL, and callback) while you are passing URL and options separately.
For example:
request.get({
uri: 'https://api.stackexchange.com/2.2/questions/'+questionId+'?order=desc&sort=activity&site=stackoverflow&filter=!9Z(-wwYGT',
json: true,
},(error, response, body) => {
// ... callback here
});

How to consume a REST api that needs username/password authentication in node.js

I want to consume a REST api that needs a username/password authentication in node.js. The code that consumes the api is as follows:
var request = require('request');
var url = 'http://localhost:3000/api/v1/login/'
request.get(url,{'auth': {'user': 'test35','pass': 'mypassword','sendImmediately': false}},function(err, httpResponse, body) {
if (err) {
return console.error('post failed:', err);
}
console.log('Post successful! Server responded with:', body);
});
With the above code, the error I get is:
{
"status": "error",
"message": "API endpoint does not exist"
}
The api is written in meteor restivus and you can see it in the following question's answer here
In the API, when I remove the api's authRequired: true, i.e, remove
{
routeOptions: {
authRequired: true
}
}
and in the code that consumes the API above, change url from
'http://localhost:3000/api/v1/login/
to:
http://localhost:3000/api/v1/articles/
and run "node accessRESTapi.js", I am able to consume the REST api! What I am not able to do correctly is the authentication when "authRequired: true" is set as per above! Please help
EDIT: Updated based on info from comments
The style of request is quite different between logging in to get a token and the subsequent requests:
For login
The docs specify that login actions must be done with a POST request to /api/login/ with a body that contains username or email and password as url-encoded params
var request = require('request');
var url = 'http://localhost:3000/api/v1/login/'
var user = 'test35';
var pass = 'mypassword';
// Save these for future requests
var userId;
var authToken;
// Use POST instead of GET
request.post(
{
uri: url,
// I'm using form because it matches the urlEncoding behaviour expected by `restivus`
form: { username: user, password: pass }
},
function(err, httpResponse, body) {
if (err) {
return console.error('post failed:', err);
}
var json = JSON.parse(body);
authToken = json.data.authToken;
userId = json.data.userId;
console.log('Post successful! Server responded with:', body);
}
);
For future requests
Now you need to set the correct headers with the previously saved userId and authToken
According to the docs, that means X-User-Id and X-Auth-Token headers on all subsequent requests
var request = require('request');
var url = 'http://localhost:3000/api/v1/articles/'
request.get({
uri: url,
headers: {
'X-User-Id': userId,
'X-Auth-Token': authToken
}
}, function(err, httpResponse, body) {
if (err) {
return console.error('get failed:', err);
}
console.log('Get successful! Server responded with:', body);
});
Putting it together:
We want to make sure we get the authToken before making any further requests.
This means making the second request in the callback of the first function like so:
var request = require('request');
var url = 'http://localhost:3000/api/v1/login/';
var user = 'test35';
var pass = 'mypassword';
// Save these for future requests
var userId;
var authToken;
// Use POST instead of GET
request.post(
{
uri: url,
// I'm using form because it matches the urlEncoding behaviour expected by `restivus`
form: { username: user, password: pass }
},
function(err, httpResponse, body) {
if (err) {
return console.error('post failed:', err);
}
var json = JSON.parse(body);
authToken = json.data.authToken;
userId = json.data.userId;
console.log('Post successful! Server responded with:', body);
// And now we make the second request
// Welcome to callback hell
var articlesUrl = 'http://localhost:3000/api/v1/articles/';
request.get({
uri: articlesUrl,
headers: {
'X-User-Id': userId,
'X-Auth-Token': authToken
}
}, function(err, httpResponse, body) {
if (err) {
return console.error('post failed:', err);
}
console.log('Get successful! Server responded with:', body);
});
}
);

MYSQL + Node.JS Post Request Confusion

I am very new to networking and I have this code which, when I use a REST API like Postman, does exactly what I want it to do:
router.post('/', function(req,res,next){
var reqObj = req.body;
console.log(reqObj);
req.getConnection(function(err, conn){
if(err)
{
console.error('SQL Connection error: ', err);
return next(err);
}
else
{
var query = conn.query("INSERT INTO coordinates (id,lat,lon) VALUES(3,2,1);");
if(err)
{
console.error('SQL error: ', err);
return next(err);
}
res.json("Coordinates sent.");
}
})
} );
That is, it sends the query request to the MYSQL database. My question is, how do I do this without using Postman to send the POST request?
Thank you.
You can't unless you make a post request from within your application or something. If you don't intend on sending data, you can just make it a GET request by changing
router.post('/', function(req,res,next){
to
router.get('/', function(req,res,next){
Then you can just go to the relevant URL from your browser. If you're using chrome and you just wanna see the JSON data, I'd also recommend installing the JSONView chrome extension.
EDIT
Here's the example request using request-promise
var request = require('request-promise');
var objectData = {
name: 'Bruce',
alias: 'Batman'
};
var options = {
method: 'POST',
uri: 'http://your.api/endpoint/',
body: objectData,
json: true // Automatically stringifies the body to JSON
};
request(options).then(function(response){
// handle success response
}, function(error){
// handle error response
})

Sending parameters to an API using node.js

I have worked with REST APIs in Python but have no idea how to use them in node.js. I'm trying to build an application that pulls data from a user's smartsheet account. The smartsheet API page gives cURL examples. Could you please tell me how to call this API and pass parameters to it in node.js?
Thanks in advance.
You can use request module. Since I don't have an access token I am getting {"errorCode":1002,"message":"Your Access Token is invalid."}
var request = require('request');
var options = {
url: 'https://api.smartsheet.com/1.1/sheets',
headers: {
'Authorization': 'Bearer ACCESS_TOKEN'
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log(info);
} else {
console.log(error);
console.log(body);
}
}
request(options, callback);

Categories