curl -d equivalent in Node.js http post request - javascript

I know that the command
curl -X POST -d 'some data to send' http://somehost.com/api
can be emulated in Node.js with some code like
var http = require('http');
var post_data = 'some data to send',
headers = {
host: 'somehost.com',
port: 80,
method: 'POST',
path: '/api',
headers: {
'Content-Length': Buffer.byteLength(post_data)
}
};
var request = http.request(headers, function(response) {
response.on('data', function(d) {
console.log(d);
});
});
request.on('error', function(err) {
console.log("An error ocurred!");
});
request.write(post_data));
request.end();
The question is because I'm looking for the equivalent in node of the cURL command
curl -d name="Myname" -d email="myemail#gmail.com" -X POST http://somehost.com/api
how can i do that?
This is because I wanna do a POST request to a Cherrypy server like this one, and I'm not able to complete the request.
EDIT The solution, as #mscdex said, was with the request library:
I've resolve the problem with the request library. My code for the solution is
var request = require('request');
request.post('http://localhost:8080/api', {
form: {
nombre: 'orlando'
}
}, function(err, res) {
console.log(err, res);
});
Thank you!

You could encode it manually:
var post_data = 'name=Myname&email=myemail#gmail.com';
Or you could use a module like request to handle it for you (becomes especially nice if you have to upload files) since it will handle data escaping and other things for you.

Related

POST request from Node to another server with windows credentials

I am trying to send a post request to a service from my node server.
Node is running on http://localhost:3000. The method I am trying to reach is reachable through http://localhost:80/some/adress/business/layer/myMethod.
var options = {
host: 'localhost',
path: '/some/adress/business/layer/myMethod',
port: '80',
method: 'POST',
headers: {
'Content-type': 'application/json',
'Content-Length': data.length
}
};
var req = http.request(options, function (resu) {
console.log('statusCode: ' + res.statusCode)
resu.on('data', function (d) {
console.log(d);
});
resu.on('error', function (err) {
console.log(err);
});
resu.on('end', function () {
res.jsonp({ result: true });
res.end();
});
});
req.write("data");
req.end();
The request works fine, well more or less. I am getting a 401 status back. The question is: How can I send windows credentials from node to the named server running on localhost:80... ?
Without knowing the exact details of your setup, I can't be sure, but you probably need to use NTLM authentication. There are several libraries that do this for node. Take a look at this question. Hope this helps!

Curl mechanism, inside the expressjs code

I am new to most of these concepts, so I apologize if this question is trivial.
I have a script that makes an HTTP POST request in Curl, for sending json file data .
curl https://XXXX.zendesk.com/api/v2/channels/voice/tickets.json ^
-d #C:\Users\Agent\Desktop\json.json ^ -H "Content-Type: application/json" -v -u AAAAA#BBBBB.com/token:99dd6ghxsdrf85fgYdHWb33VYCZXI35fg8w13pfL -X POST
i need to use the mechanism for making HTTP requests of Curl in my code expressjs,
var express = require('express');
var app = express();
app.use(express.static('public'))
app.get('/index.html',function(req,res) {
res.sendFile(__dirname+"/"+'index.html');
})
app.get('/express_get',function(req,res) {
response ={
firstname : req.query.firstname,
lastname: req.query.lastname,
Email: req.query.email
};
console.log(response);
res.end(JSON.stringify(response));
})
var server = app.listen(8000,function() {
var host = server.address().address;
var port = server.address().port;
console.log('App running on http://127.0.0.1:8000')
})
but unfortunately i don't know how to make it !!
so the questions are:
1:
-d #C:\Users\Agent\Desktop\json.json
in the Curl code, is the file that i want use it , it contain data, what do you think about replace it by (JSON.stringify(response)) in the expressjs code !!
2:
and how can i do the same work of curl inside my expressjs code !!!!
Any help, any suggestion is appreciated!
you want to request https://XXXX.zendesk.com/api/v2/channels/voice/tickets.json from one of your express route ?
For that there is Node.js HTTP built-in module (https://nodejs.org/api/http.html#http_http_request_options_callback), which offers the possibility to do a POST request to an host.
There is an example just below on how to use it
// From https://nodejs.org/api/http.html
const postData = querystring.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
You will need to read your JSON file (with Node's FileSystem module) and write it to req after stringifying it :)

Invalid protocol: undefined - NodeJS error on POST request -

I'm getting this error coming from my require.post(error)
its a lambda function deployed from a vagrant box. It is a wrapper for an api, the event.body has the properly formatted post json and everything is working perfectly when the post is done from postman. I have seen a roughly similar problem solved by
npm config set proxy http://usr:pwd#host:port
npm config set https-proxy http://usr:pwd#host:port
Please help! : )
Error: Invalid protocol: undefined
at Request.init (/var/task/node_modules/request/request.js:454:31)
at new Request (/var/task/node_modules/request/request.js:127:8)
at request (/var/task/node_modules/request/index.js:53:10)
at Function.post (/var/task/node_modules/request/index.js:61:12)
at module.exports.startVerifyProcess (/var/task/handler.js:83:13)
my Code:
module.exports.startVerifyProcess = (event, context, callback) => {
var body = JSON.parse(event.body);
const params = querystring.parse(event.body);
console.warn(body);
var Re;
var post_options = {
host: 'api.demo.veri.com',
path: '/api/v1/verify/requests',
port: 443,
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// 'Content-Length': Buffer.byteLength(event.body),
"Authorization": "myValidAuth",
},
}
request.post(post_options, body, function(err, res, resBody) {
if (err){
console.error(err);
}
console.warn("RESPONSE " + resBody);
});
callback(null, {
statusCode: 200,
body: JSON.stringify({
body: Re
})
});
}
The issue here is that request should not take the body as the second parameter.
request.post(post_options, function(err, res, resBody) is correct and the body should be in the post_options object. While your at it chose either camelCase or snake_case for everything in that project. Also check out node-fetch I would consider it a solid upgrade from using request.

Node JS How to POST image along with request data to another server/api

I am trying to POST an image from my Node JS app to another REST API. I have the image in Mongo DB (as binary array data) that is read by Node JS and then is supposed to be POSTed to another API.
The problem I face is how do I send request data along with the image? I have this raw data (that is in JSON format) that should be POSTed along with image:
{"data":{"client":"abc","address": "123"},"meta":{"owner": "yourself","host": "hostishere"}}
I am required to do this using the 'request' module. I can use 'multer' if that helps better. But, I am stuck on how do I send the above request data along with the image stream. Below is my current code. Could you please help me finish it?
var options = {
host: 'hostname.com',
port: 80,
path: '/api/content',
method: 'POST',
headers:{
'Content-Type' : 'multipart/form-data'
}
};
var request = http.request(options, function(response) {
var str = '';
var respTime ='';
response.on('data', function (chunk) {
str = str.concat(chunk);
});
response.on('end', () => {
console.log('No more data in response.');
});
setTimeout(function() {
res.send(JSON.stringify(
{
'imageURL': IMG_URL,
'imageId': IMG_ID,
'body': JSON.parse(str)
}
));
}, 1000);
});
request.on('error', (e) => {
console.error('**** problem with request: ', e);
});
request.write(image.IMG_STR); //image.IMG_STR is the binary array representation of the image.
request.end();
UPDATE: 06/06/2017
So, I happened to talk to the REST team that provides the end point and found out that the data should be sent in the following specific format. Below is a snapshot of the request that succeeded. Could someone help me with the Node code that I should use? I have tried form-data package but have been getting the same error:
if you have control over "the other API" too, you could include the image as base64 representation of the binary data in the post-body (and decode it on the API side)
answer to the update 06/06/2017:
according to the screenshot the API requires multipart/formdata.
such requests with the "request"-module are documented in https://github.com/request/request#multipartform-data-multipart-form-uploads
quick example (not tested):
var formData = {
Data: {data: {client: "abc" ...},
file: fs.createReadStream('testImage_2.jpg'),
};
request.post({url:'<YourUrl>', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
If you add the body to your request with the JSON data, you should be able to send it:
var options = {
host: 'hostname.com',
port: 80,
path: '/api/content',
method: 'POST',
headers:{
'Content-Type' : 'multipart/form-data'
},
body: {
"data": {"client":"abc","address": "123"},
"meta":{"owner": "yourself","host": "hostishere"}
}
};
What I don't understand is why you have a setTimeout with res.send when there is no res variable defined anywhere.

Verifiy iOS Receipt with Node.js

After struggling a few days trying to get something to work and getting no where, I was wondering if someone has gotten iOS Receipt Validation working on Node.js. I have tried the node module iap_verifier found here but I could not get it to work properly for me. the only response I received back form Apples servers is 21002, data was malformed.
One thing that has worked for me was a client side validation request to apples servers that I got directly from the tutorials provided by Apple here, with the code shown below.
// The transaction looks ok, so start the verify process.
// Encode the receiptData for the itms receipt verification POST request.
NSString *jsonObjectString = [self encodeBase64:(uint8_t *)transaction.transactionReceipt.bytes
length:transaction.transactionReceipt.length];
// Create the POST request payload.
NSString *payload = [NSString stringWithFormat:#"{\"receipt-data\" : \"%#\", \"password\" : \"%#\"}",
jsonObjectString, ITC_CONTENT_PROVIDER_SHARED_SECRET];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
// Use ITMS_SANDBOX_VERIFY_RECEIPT_URL while testing against the sandbox.
NSString *serverURL = ITMS_SANDBOX_VERIFY_RECEIPT_URL;
// Create the POST request to the server.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:payloadData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
I have a bunch of different code I have been using to send a wide array of things to my node server. and all of my different attempts have failed. I have even tried just funneling the "payloadData" I constructed in the client side validation example above to my server and sending that to Apples servers with the following code:
function verifyReceipt(receiptData, responder)
{
var options = {
host: 'sandbox.itunes.apple.com',
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptData)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(receiptData);
req.end();
}
Where the function is passed the payloadData. The response received from Apple is always 21002. I'm still basically a node novice,so I can't figure out what exactly is going wrong. I think there might be some data corruption happening when I am sending the data from ObjC to my Node server, so perhaps I am not transmitting right.
If anyone can point me in the right direction, or provide some example of how they got receipt validation to work in node for them, it would be a great help. It would be great if anyone has had any experience with the iap_verifier module, and exactly what data it requires. I'll provide any code example I need to, as I have been fighting this process for a few days now.
Thanks!
For anyone using the npm library "request", here's how to avoid that bothersome 21002 error.
formFields = {
'receipt-data': receiptData_64
'password': yourAppleSecret
}
verifyURL = 'https://buy.itunes.apple.com/verifyReceipt' // or 'https://sandbox.itunes.apple.com/verifyReceipt'
req = request.post({url: verifyURL, json: formFields}, function(err, res, body) {
console.log('Response:', body);
})
This is my working solution for auto-renewable subscriptions, using the npm request-promise library.
Without JSON stringify-ing the body form, I was receiving 21002 error (The data in the receipt-data property was malformed or missing)
const rp = require('request-promise');
var verifyURL = 'https://sandbox.itunes.apple.com/verifyReceipt';
// use 'https://buy.itunes.apple.com/verifyReceipt' for production
var options = {
uri: verifyURL,
method: 'POST',
headers: {
'User-Agent': 'Request-Promise',
'Content-Type': 'application/x-www-form-urlencoded',
},
json: true
};
options.form = JSON.stringify({
'receipt-data': receiptData,
'password': password
});
rp(options).then(function (resData) {
devLog.log(resData); // 0
}).catch(function (err) {
devLog.log(err);
});
Do you have composed correctly receiptData? Accordlying with Apple specification it should have the format
{"receipt-data": "your base64 receipt"}
Modifying your code wrapping the base64 receipt string with receipt-data object the validation should works
function (receiptData_base64, production, cb)
{
var url = production ? 'buy.itunes.apple.com' : 'sandbox.itunes.apple.com'
var receiptEnvelope = {
"receipt-data": receiptData_base64
};
var receiptEnvelopeStr = JSON.stringify(receiptEnvelope);
var options = {
host: url,
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptEnvelopeStr)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
cb(true, chunk);
});
res.on('error', function (error) {
console.log("error: " + error);
cb(false, error);
});
});
req.write(receiptEnvelopeStr);
req.end();
}

Categories

Resources