Async request module in Node.js - node.js

I am creating a project using Node.js. I want to call my requests in parallel. For achieving this, I have installed the async module. Here is my code:
var requests = [{
url:url,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + req.cookies.apitoken
},
json: finalArr,
}];
async.map(requests, function(obj, callback) {
// Iterator function
request(obj, function(error, response, body) {
if (!error && response.statusCode == 200) {
// Transform data here or pass it on
var body = JSON.parse(body);
callback(null, body);
}
else {
var body = JSON.stringify(body);
console.log(body)
callback(error || response.statusCode);
}
});
})
I got undefined every time in console.log(body). When I am using GET requests using this module for other requests then everything works fine.

It looks like you're using the request module, but didn't tag it as such.
If I'm right, then your options object is incorrect, from the documentation there's not a data key that's respected. Instead, you should use body or formData or json depending on what kind of data you're pushing up. From your headers, I'd go with json.
var requests = [{
url:url,
method: 'POST',
headers: { // Content-Type header automatically set if json is true
'Authorization': 'Bearer ' + req.cookies.apitoken
},
json: finalArr,
}];

Related

Search Contacts with SendGrid API

https://sendgrid.api-docs.io/v3.0/contacts/search-contacts
I'm attempting to search for a contact as shown in SendGrids docs above. In the body section below I'd like to change the hard coded "andrew#gmail.com" to be a variable. Such as email = req.user.email; What is the correct way to do that? Just setting the variable and dropping in 'email' does not work.
var request = require("request");
var options = { method: 'POST',
url: 'https://api.sendgrid.com/v3/marketing/contacts/search',
headers:
{ 'content-type': 'application/json',
authorization: 'Bearer SG.key' },
body: { query: 'email LIKE \'andrew#gmail.com\' AND CONTAINS(list_ids, \'6bcc2d0c-ea17-41ba-a4a1-962badsasdas1\')' },
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
Twilio SendGrid developer evangelist here.
Try using string interpolation using back ticks (which, as an added bonus, means you don't have to escape your single quotes), like below:
const email = req.user.email;
const body = `email LIKE '${email}' AND CONTAINS(list_ids, '6bcc2d0c-ea17-41ba-a4a1-962badsasdas1')`;
const options = {
method: 'POST',
url: 'https://api.sendgrid.com/v3/marketing/contacts/search',
headers: {
'content-type': 'application/json',
authorization: 'Bearer SG.key'
},
body: { query: query },
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});

Node JS Request Printing nothing in console

I'm making an post call using the nodejs requests module. However, the console.log statements seems to be not working for either the error or the response.body that I am trying to get.
My POST request needs the following headers -
Accept : "application/json"
Content-Type : "application/json"
Authorization : Basic + Base64Encoded(username+password)
The post body is something like this
Body:
{
"arg_1" : "a_string_key"
, "arg_2" : "a_string"
, "arg_3" : "a_string"
, "arg_4" : "some_value"
, "arg_5" : "some_string"
, "arg_6" : "<yyyy-mm-dd>"
, "arg_7" : "<yyyy-mm-dd>"
}
My code does nothing but send a POST request and checks if the response.statusCode ==200
Here is what I am doing
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'URL_I_WANT',
// method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
}
console.log('Before request');
request.post(options, function(error, response) {
if (error) {
console.log(error);
}
try {
if (!error && response.statusCode == 200) {
console.log(response.body);
console.log('Success');
}
} catch (error) {
console.log(error)
}
});
console.log('After request');
The code runs without any glitch and I get the before and after request console statements. However the statements inside the requests do not appear in the console, which means my request is not going through. I am not able to understand this. Shouldn't an error come if there is an issue with the request itself? Any if the request is failing, why isn't the error printed out?
This could be because your node process is auto-closed and it will exit before the async request to finishes (haven't looked into it but it might be something configurable). I've seen such set-up on repl.it for example.
To overcome this(if not configurable), you could wrap your code in an async function and use the request-promise to call await request.
var request = require('request-promise-native');
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'https://google.com',
method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
};
console.log('Before request');
async function main() {
try {
const response = await request.post(options);
if (response.statusCode === 200) {
console.log(response.body);
console.log('Success');
process.exit();
}
console.log(`Bad statusCode:${response.statusCode}`);
}
catch (error) {
console.log(error);
}
}
main();
you can check-out the code below
a link to the code above, working on repl.it

NodeJS: uploading file to another server along with other data

I am trying to send some data to another server. This includes a file as well. Here is how I am doing it:
var fs = require("fs");
var request8 = require("request");
var _value = fs.createReadStream(_completefilePath);//File that needs to be sent.
var options = {
method: 'POST',
url: _uploadURL,
headers: {
'content-type': 'multipart/form-data'
},
formData: {
fileName: {
value: _value,
options: { filename: _fileName, contentType: null }
},
data: JSON.stringify(_data)//_data is a JSON object
}
};
request8(options, function (error, response, body) {
if (!error && response.statusCode == 200)
return 1
else
return 0;
});
I have tried many times but the error I get is "ECONNRESET". I have no idea what is wrong with the request above? Is it not properly formed or is there any issue on third party server?
Basically I am trying to upload a file to Eventbrite server. The code in Python is given here under step 2 and that's what I am trying to convert in NodeJS.
[Update 1]: When I changed "formData" to "form" I got statusCode 412(precondition failed).
[Update 2]: Changing the code to below gives "Bad Request" error.
var options = {
method: 'POST',
url: _uploadURL,
headers: {
'content-type': 'multipart/form-data',
'Authorization': 'Bearer ' + _token
},
formData: JSON.stringify({
fileName: {
value: _value,
options: { filename: _fileName, contentType: null }
},
data: _data
})
};

CSRF token validation failed in nodejs while posting data to odata service

var request = require('request');
var username = '';
var password = '';
var url = 'http://207.188.73.88:8000/sap/opu/odata/sap/ZTEE_TIME_SRV/ZTEERESERVESet(Time=time\'PT11H00M00S\',Date=datetime\'2014-03-11T00%3A00%3A00\',Location=\'TAJ\',Number=3)';
var auth = 'Basic ' + new Buffer(username + ':' + password).toString('base64');
// i am trying to post data to odata service but the problem is that i could not get valid token from get service to use it in the post method i am first send get method
request(
{
url: url,
headers: {
'Authorization': auth,
'x-csrf-token': 'Fetch',
},
},
function(error, response, body) {
console.log('JSON data ' + response);
console.log('body' + body);
// trying to get the token to use in post
console.log(response.headers);
request(
{
url: url,
headers: {
here it says invalid token
'Authorization': auth,
'X-CSRF-TOKEN': 'u6piLO58XoK6udOkQ5Naww==',
},
method: 'POST',
//Lets post the following key/values as form
form: {
Time: 'PT11H00M00S',
Date: '2014-03-11T00%3A00%3A00',
Location: 'TAJ',
Number: 3,
},
},
function(error, response, body) {
console.log(body);
},
);
},
);
I got the solution.
I was trying to do this with POSTMAN, and it was working fine.
The thing is that when i was asking for CSRF token it always gave me the same back.
But when i tried with node, every time was different. Then i realized that the cookie was missing.
And thats all, the solution is to send the cookie at least in POST requests.
The set-cookie of the "Fetch" request must be sent in the Post request as Cookie beside the x-csrf-token
I put the example in typescript, but in js doesnt change so much, the idea is the same.
The example is not the best case but is complete to figure out how it works
let headers = {
"Authorization": "Basic " + new Buffer(username + ":" + password).toString("base64"),
"Content-Type":"application/json",
"Accept":"application/json",
"x-csrf-token":"Fetch" // get CSRF Token for post or update
};
// if you are using session vars
if (req.session.headers && req.session.headers.cookie) {
headers['Cookie'] = req.session.headers.cookie;
} else {
req.session.headers = {}; // initialize as object
}
let opts = {
url: "https://{host}:{port}/sap/opu/odata/sap/MD_SUPPLIER_MASTER_SRV",
qs: params1, // params set before, not set in the example
headers: headers,
json: true,
}
request(opts, (error: any, response: any, body: any): any => {
if (!error && response.statusCode === 200) {
if (response.headers["set-cookie"]) {
req.session.headers.cookie = response.headers["set-cookie"]; // store Cookie in session
headers['Cookie'] = req.session.headers.cookie; // set in headers for the next call. I guess this is the part you missed
}
if (response.headers['x-csrf-token']) {
req.session.headers.csrf = response.headers['x-csrf-token']; // store csrf-token in session
headers['x-csrf-token'] = req.session.headers.csrf; // set in headers for the next call
}
let options: request.Options = {
url: "https://{host}:{port}/sap/opu/odata/sap/MD_SUPPLIER_MASTER_SRV/C_BusinessPartnerSupplierEdit",
method: 'POST',
headers: headers,
qs: params2, // params set before
json: true,
}
request(options, (error: any, response: any, body: any): any => {
res.json(body);
});
}
});
Regards

Trying to post api request

I having problem with making a API call to an external site.
I need to send a POST request to http://api.turfgame.com/v4/users with headers Content-type: application/js. But when I run this code it only loads and nothing more.
var request = require('request');
var options = {
uri: 'http://api.turfgame.com/v4/users',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: {
"name": "username"
}
};
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
res.send(response.body);
}
});
The body need to be posted in json formate [{'name': 'username'}].
Can someone tell me what I have done wrong?
There are a few things wrong:
the address property in the "options" object should be "url" not
"uri"
you can use the "json" property instead of body
"res" is undefined in your response handler function
if you want the body to be an array, it needs to be surrounded in square brackets
here's a working sample that just logs the response:
var request = require('request');
var options = {
url: 'http://api.turfgame.com/v4/users',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
json: [{
"name": "username"
}]
};
request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(response.body);
}
});

Resources