POST using multipart/form-data in NodeJS - node.js

I need to essentially POST a local image to Cisco Webex room from my NodeJS service. For local files, you need to do a multipart/form-data request instead of JSON as mentioned in the documentation.
The CURL looks like
curl --request POST \
--header "Authorization: Bearer ACCESS_TOKEN" \
--form "files=#/home/desktop/example.png;type=image/png" \
--form "roomId=Y2lzY2....." \
--form "text=example attached" \
https://api.ciscospark.com/v1/messages
But I am not sure how to convert it to nodeJS request format. I tried to use CURL to Node request converter here but doesn't seem like it is handling the multipart/form-data type. Please suggest.
EDIT: after doing some research, I came up with the below code
var request = require('request');
var fs = require('fs');
var params = { roomId: ROOMID,
text: "hello....",
files: {
value: fs.createReadStream(PATH_WO_FILENAME),
options: {
filename: 'image.jpg',
contentType: 'jpg'
}
}
};
var headersWebex = {
'Authorization': 'Bearer MY_BOT_ACCESS_TOKEN',
'Content-Type': 'multipart/form-data' }
request.post({
headers: headersWebex,
url: 'https://api.ciscospark.com/v1/messages',
method: 'POST',
body: params
}, function(error, response, body){
console.log(body);
});
But it is throwing error
undefined
_http_outgoing.js:642
throw new TypeError('First argument must be a string or Buffer');

Ok so here is how I made it work. I essentially needed to look deeper into the docs that #Evan mentioned
var request = require('request');
var fs = require('fs');
var roomID = 'MY_ROOM_ID'
var params = {
roomId: roomID,
text: "hello....",
files: {
value: fs.createReadStream('./image.jpg'),
options: {
filename: 'image.jpg',
contentType: 'image/jpg'
}
}
};
var headersWebex = {
'Authorization': 'Bearer MY_BOT_ACCESS_TOKEN',
'Content-Type': 'application/json'
}
request.post({
headers: headersWebex,
url: 'https://api.ciscospark.com/v1/messages',
method: 'POST',
formData: params
}, function(error, response, body){
if (error)
console.log(error)
console.log(body);
});

Related

Convert Paypal cURL command to Axios request

Following Paypal cURL command works as it supposed to be but unfortunately I couldn't convert to axios code to work same. Paypal Documentation doesn't have form data example but it allows that if you need to optional message_document file.
curl --request POST \
--url https://api-m.sandbox.paypal.com/v1/customer/disputes/12345/send-message` \
--header 'authorization: Bearer --token--' \
--header 'content-type: multipart/form-data' \
-F "input={\"message\":\"sample message\"};type=application/json" \
-F "message_document=#sample.pdf"
I tried that Node.js code even without sending file but not successful:
const FormData = require('form-data');
const form = new FormData();
form.append('input', JSON.stringify({ message: 'sample message' }), { contentType: 'application/json' });
const result = await axios({
url: 'https://api-m.sandbox.paypal.com/v1/customer/disputes/12345/send-message',
method: 'post',
data: form,
headers: {
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer --token--'
}
}).catch(err => {
throw new Error(err);
});
I can't see that where is the problem. Please enlighten me. Thanks in advance.
I wasn't expecting but it is solved with missing boundary information. These can be used:
const result = await axios({
url: 'https://api-m.sandbox.paypal.com/v1/customer/disputes/12345/send-message',
method: 'post',
data: form,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`,
Authorization: 'Bearer --token--'
}
})
or
const result = await axios({
url: 'https://api-m.sandbox.paypal.com/v1/customer/disputes/12345/send-message',
method: 'post',
data: form,
headers: {
Authorization: 'Bearer --token--',
...form.getHeaders()
}
})

what is the nodejs code for this curl command

I can successfully execute this curl command from a Unix shell script and I can see output in C:\Users\OutputFile.csv. What is the equivalent code in NodeJS
curl -k -v --user 'helloworld:hello_password'
--header 'Accept: application/vnd.myDMS-dms-api+json; version=1'
-X POST 'https://DMS.com:3001/download/csv'
--data header=true -o C:\Users\OutputFile.csv
I tried using the Online curl to nodeJS converter and it has generated the following NodeJs code:-
var request = require('request');
var headers = {
'Accept': 'application/vnd.myDMS-dms-api+json; version=1'
};
var options = {
url: 'https://DMS.com:3001/download/csv',
method: 'POST',
headers: headers,
auth: {
'user': 'helloworld',
'pass': 'hello_password'
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
}
request(options, callback);
However, when I run this NodeJS code it does not show any output. Also how can I get this output to C:\Users\OutputFile.csv
Maybe the response isn't return before the script is terminated. You would want the request to be asynchronous:
You can use request-promise
Here's an example
var rp = require('request-promise');
function someFunction() {
let options = {
url: `someURL`,
method: 'POST',
body: {
some: 'payload'
},
json: true
};
return rp(options);
}
This will await the response.
A simple version of your API parameters using request-promise:
var rp = require('request-promise');
function downloadFile() {
var options = {
uri: 'https://DMS.com:3001/download/csv',
method: 'POST',
auth: {
user: 'helloworld',
pass: 'hello_password',
sendImmediately: true
},
headers: {
Accept:'application/vnd.myDMS-dms-api+json; version=1'
},
form: {
'header': 'true'
}
};
rp(options)
.then(function (body) {
console.log('Downloaded body was %d long', repos.length);
})
.catch(function (err) {
console.log(err)
});
}
downloadFile()

Nodejs - Rest api call with option --data from a file

I am making rest api calls from a nodejs application.
My curl calls looks like this:
curl -X PUT -iv -H "Authorization: bearer <token>" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Spark-Service-Instance: <spark-instance>" --data "#pipeline.json" -k https://<url>
I want to have a similar call in Nodejs. I am unable to understand how to have the data sent which is in a json file which in curl call was --data "#pipeline.json".
My Nodejs code looks like this:
var token = req.body.mlToken;
var urlToHit = req.body.url;
var SPARKINSTANCE = req.body.sparkInstance;
var b = "bearer ";
var auth = b.concat(token);
var headers = {
'Content-Type': 'application/json',
'Authorization': auth,
'Accept': 'application/json',
'X-Spark-Service-Instance': SPARKINSTANCE
}
var options= {
url: urlToHit,
method: 'PUT',
headers: headers
}
console.log(urlToHit);
request(options, callback);
function callback(error, response, body) {...}
You can either use the request library to pipe the request as so:
var fs = require('fs');
var options= {
url: urlToHit,
method: 'PUT',
headers: headers
}
fs.createReadStream('./pipeline.json')
.pipe(request.put(options, callback))
Or, using plain Node.js, read the file in to memory asynchronously and the once loaded, make a put request like this:
var fs = require('fs');
// Will need this for determining 'Content-Length' later
var Buffer = require('buffer').Buffer
var headers = {
'Content-Type': 'application/json',
'Authorization': auth,
'Accept': 'application/json',
'X-Spark-Service-Instance': SPARKINSTANCE
}
var options= {
host: urlToHit,
method: 'PUT',
headers: headers
}
// After readFile has read the whole file into memory, send request
fs.readFile('./pipeline.json', (err, data) => {
if (err) throw err;
sendRequest(options, data, callback);
});
function sendRequest (options, postData, callback) {
var req = http.request(options, callback);
// Set content length (RFC 2616 4.3)
options.headers['Content-Length'] = Buffer.byteLength(postData)
// Or other way to handle error
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
}

Simple NodeJS http request equivalent for curl

I'm having trouble converting a curl that works to an equivalent http request through nodeJS. I'm using the Request module, but I seem to be doing something wrong when making the request. When I run it, it gives me
body: Cannot POST /path
Not really sure how to debug this, any ideas?
var data = JSON.stringify({
'sender': {
'name': 'name',
'handle': 'handle'
},
'subject': 'Title here',
'body': 'something something',
'metadata': {}
});
var options = {
host: 'website.com',
path: '/path',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer <token>',
'Accept': 'application/json',
'Content-Length': Buffer.byteLength(data)
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(data);
req.end();
Below is the equivalent curl (that works) that I'm trying to make for the above nodejs.
curl --include \
--request POST \
--header "Content-Type: application/json" \
--header "Authorization: Bearer <token>" \
--header "Accept: application/json" \
--data-binary "{
\"sender\": {
\"name\": \"name\",
\"handle\": \"handle\"
},
\"subject\": \"Title here\",
\"body\": \"something something\",
\"metadata\": {}
}" \
'website.com/path"
You can include your JSON data directly with json parameter with request library :
var request = require('request');
var options = {
uri: 'http://website.com/path',
method: 'POST',
headers: {
'Authorization': 'Bearer <token>',
'Accept': 'application/json'
},
json: {
'sender': {
'name': 'name',
'handle': 'handle'
},
'subject': 'Title here',
'body': 'something something',
'metadata': {}
}
};
var req = request(options, function(error, response, body) {
if (error) {
console.log(error);
return;
}
if (response.statusCode == 200) {
console.log(body);
} else {
console.log("receive status code : " + response.statusCode);
}
});
From request options doc :
json - sets body to JSON representation of value and adds
Content-type: application/json header. Additionally, parses the
response body as JSON.

cURL call to API in NodeJS Request

it's me again with another lame question. I have the following call to a Rattic password database API which works properly:
curl -s -H 'Authorization: ApiKey myUser:verySecretAPIKey' -H 'Accept: text/json' https://example.com/passdb/api/v1/cred/\?format\=json
I tried to replicate this call in NodeJS, however the following returns blank:
var request = require('request');
url='https://example.com/passdb/api/v1/cred/?format=json';
request({
url: url,
method: 'POST',
headers: [
{ 'Authorization': 'ApiKey myUser:verySecretAPIKey' }
],
},
function (error, response, body) {
if (error) throw error;
console.log(body);
}
);
Any help is appreciated.
As pointed out in the comments already, use GET, not POST;
headers should be an object, not an array;
You're not adding the Accept header.
All combined, try this:
request({
url : url,
method : 'GET',
headers : {
Authorization : 'ApiKey myUser:verySecretAPIKey',
Accept : 'text/json'
}, function (error, response, body) {
if (error) throw error;
console.log(body);
}
});
One thing you can do is import a curl request into Postman and then export it into different forms. for example, nodejs:
var http = require("https");
var options = {
"method": "GET",
"hostname": "example.com",
"port": null,
"path": "/passdb/api/v1/cred/%5C?format%5C=json",
"headers": {
"authorization": "ApiKey myUser:verySecretAPIKey",
"accept": "text/json",
"cache-control": "no-cache",
"postman-token": "c3c32eb5-ac9e-a847-aa23-91b2cbe771c9"
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.end();
Headers should be an object.
var request = require('request');
url='https://example.com/passdb/api/v1/cred/?format=json';
request({
url: url,
method: 'POST',
headers: {
'Authorization': 'ApiKey myUser:verySecretAPIKey'
}
}, function (error, response, body) {
if (error) throw error;
console.log(body);
});

Resources