Request package: response.body is not JSON - javascript

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
});

Related

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

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);
});

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);
});
}
);

transform $.get to node.js request

i'm using geolocation, i was handling everything on client side, now I wat to handle this from
Currently using it as;
var url = "youtube.com",
options = {
key: API_KEY,
video: "vid_id"
};
$.get(url, options, function(data) {
console.log(data)
})
I want to use it with nodeJS HTTPS, so i tried;
var https = require("https"),
url = "youtube.com",
options = {
key: API_KEY,
video: "vid_id"
};
https.get(url, options, function(data) {
console.log(data)
})
but i cant get it work I hope someone can convert this.
Try using the request module for node.js. Install it by running:
npm install request.
var request = require('request');
request(`youtube.com/?key=${key}&video=${video_id}`, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('body:', body); // Print body of the response.
});

Specifically add browser to POST request in Node.js

I have a proxy endpoint in a Node.js service that is forwarding POST requests as follows:
request.post(
fullURL,
{ form: req.body },
function (error, response, body) {
if (response){
res.status(response.statusCode).send(body);
}
else {
res.status(500).send("ERROR");
}
}
);
And this is forwarding to a Spring Boot service that is attempting to extract the browser info via:
String browser = request.getHeader("User-Agent");
But this is always empty when being forwarded through the proxy. So how can I specifically set User-Agent in the request?
NOTE: req.headers['user-agent'] from the original incoming request is all present and correct, and ready to be injected into forwarding POST request
From what I can see, your only issue is that you're not actually relaying the user-agent header, but you are reading it. Pass the header object with your POST request like so:
headers: {
'User-Agent': userAgentVariable
}
Haven't tested this myself, but try the following:
request.post(
fullURL,
{
form: req.body,
headers: {
'User-Agent': request.getHeader("User-Agent")
}
},
function (error, response, body) {
if (response){
res.status(response.statusCode).send(body);
}
else {
res.status(500).send("ERROR");
}
}
);

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