I've got such a code in node.js:
var requestData = JSON.stringify({ id : data['user_id'] });
var options = {
hostname: 'localhost',
port: 80,
path: '/mypath/index.php',
method: 'POST',
headers: {
"Content-Type": "application/json",
'Content-Length': requestData.length
}
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write(requestData);
req.end();
and PHP code:
<?php
$data = $_POST;
define('DS', '/');
umask(000);
file_put_contents(dirname( __FILE__ ).DS.'log.txt', json_encode($data), FILE_APPEND);
echo json_encode($data);
?>
quite simple... but after making node.js POST request - PHP is not obtaining any data. I've tried many other ways of making that POST message to PHP but nothing works for me. I mean, $_POST is always empty.
Tried also request nodejs library:
request.post({
uri : config.server.protocol + '://localhost/someurl/index.php',
json : JSON.stringify({ id : data['user_id'] }),
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log('returned BODY:', body);
}
def.resolve(function() {
callback(error);
});
});
There should be really simple solution for my problem but I can't find one.
The $_POST array is only populated with HTML form POST submits. To emulate such a form submit, you need to:
Set the request Content-Type header exactly to application/x-www-form-urlencoded
Use the form encoding in the request body... I.E key=value&key2=value2 with percent-encoding where necessary.
Calculate the Content-Length header's value exactly to the length of bytes that are being sent. You can only do this after having the fully encoded string, though byte conversion is not necessary in order to calculate the Content-Length since 1 character = 1 byte in urlencoded string.
However, with your current code (provided all you have is ASCII), you can also do this:
<?php
$data = json_decode(file_get_contents("php://input"));
$error = json_last_error();
if( $error !== JSON_ERROR_NONE ) {
die( "Malformed JSON: " . $error );
}
define('DS', '/');
umask(000);
file_put_contents(dirname( __FILE__ ).DS.'log.txt', json_encode($data), FILE_APPEND);
echo json_encode($data);
?>
Related
I have to send a post request with a body containing russian characters to a service which seems to only accept win1251 encoding. I am doing this in node.js using the request module.
This is how I am sending the request
var rawbody = "i1=&i2=&i3=" + query + "&i4=&i5=&i8=";
var options = {
url: this.initiate_endpoint,
jar: this.session,
cert: this.fs.readFileSync('resources/r.crt.pem', 'utf-8'),
key: this.fs.readFileSync('resources/r.key.pem', 'utf-8'),
timeout: 20000,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: rawbody
};
let cookie = this.session;
request.post(options,
function (error, response, body) {
if( error ) {
callback(cookie, error);
}
else if( response.statusCode !== 200 ) {
callback(cookie, 'Responded with status code: ' + response.statusCode);
}
else {
callback(cookie, false);
}
});
Whenever the query variable is containing russian letters the request will fail.
For example:
var query = 'Путин';
So my questions are how to actually convert the encoding from the query variable to win1251 and furthermore how to set the encoding of the actual raw postbody, because I think those two things could be the cause of the issue.
I want to send form data to web-server by using Node.js, So I use "request" module that is very famous in nodeland. And It's cool, There is no problem, But because of some reason (write-stream encoding non-supported), I have to change it to built-in module, "http".
I think beneath codes are same to post some data to web-server, When I using "request" module, There is no problem so can get 200 response, success to sending data.
But in "http" module, I got a 302 response that redirects to another page. and failed post data. I don't know what is problem with, maybe it is something URL trouble, http use 'host and path' on the other hand, request use 'url' . I don't know how can I solve this, I stucked 2 days, please let me know If you have some hints..
Thanks.
By Using "Request" Module
function postFormByRequestModule() {
request({
url: 'http://finance.naver.com/item/board_act.nhn',
headers: { 'Content-Type': 'text/plain' },
method: 'POST',
form: {
code:'000215',
mode: 'write',
title: 'This is Title',
body:'This is body'
}
}, function (error, response, body) {
if (error) {
console.log(error);
} else {
console.log(response.statusCode, response.body);
}
});
}
By Using "Http" Module
var postData = querystring.stringify({
code:'000215',
mode: 'write',
title: 'This is Title',
body:'This is body'
});
var options = {
host: 'finance.naver.com',
path: '/item/board_act.nhn',
method: 'POST',
headers: { 'Content-Type': 'text/plain', }
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
res.on('end', function() {
console.log('No more data in response.')
})
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
function postFormByBuiltInHttpModule() {
req.write(postData);
req.end();
}
The built-in http client does not automatically follow forwards, whereas the request module does (and has many other "high level" features). So if you want to continue using the built-in client, you will need to manually check res.headers.location and retry the request at that url.
I'm learning how to process credit card payments.. Here is the test CURL...
curl -k -v -X POST -H "Content-Type:application/json" -H "Authorization: Basic Mxxxxxxxxxxxxxxxxxx=" -d "#json_file.txt" -o output.txt https://w1.xxxxxxxxxxxx.net/PaymentsAPI/Credit/Sale
Where json_file.txt contains
{
"InvoiceNo":"1",
"RefNo":"1",
"Memo":"TEST_TEST_PHONY",
"Purchase":"1.00",
"AccountSource":"Swiped",
"AcctNo":"5xxxxxxxxxxxxxxxxx1",
"ExpDate":"0816",
"OperatorID":"xxxxxxxxxx",
}
I converted over to node module HTTPS
var https = require("https");
var options = {
host: 'w1.xxxxxxxxxxxxxx.net',
port: 443,
path: '/PaymentsAPI/Credit/Sale',
headers: { "Content-Type" :"application/json",
"Authorization" : "Basic Mxxxxxxxxxxxxxxxxxxxxxxxxxxx="} ,
data: {
"InvoiceNo":"1",
"RefNo":"1",
"Memo":"xxxxxxxxxxxxxxx",
"Purchase":"1.00",
"AccountSource":"Swiped",
"AcctNo":"5xxxxxxxxxxxxxxxxx1",
"ExpDate":"0816",
"OperatorID":"xxxxxxxxxxxx",
},
method: 'POST'
};
// oops... 400 Bad Request
// The request could not be understood by the server due to malformed syntax.
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk.toString() );
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
Problem is on the original curl request, the data contained within the JSON text file is submitted as a POST attachment. Curl request works fine. On the other hand its not clear to me on how to do that from a node.js server. The response headers come back fine, but I get a 400 response (malformed syntax). Anybody know how to attach JSON data as a post attachment to a HTTPS request?
Oops. I totally didn't understand how the req.write() stuff works.. This code is successful. Thanks to Dan Ourada # Mercury Payments for his assistance. Note, all code here is pure sandbox. No real $$ going buy buy.
var https = require("https");
var options = {
host: 'w1.mercurycert.net',
port: '443',
path: '/PaymentsAPI/Credit/Sale',
headers: { "Content-Type" :"application/json", "Authorization" : "Basic MDAzNTAzOTAyOTEzMTA1Onh5eg=="},
method: 'POST'
};
var inputdata = JSON.stringify( {
"InvoiceNo":"1",
"RefNo":"1",
"Memo":"XXXXX",
"Purchase":"1.00",
"AccountSource":"Swiped",
"AcctNo":"5499990123456781",
"ExpDate":"0816",
"OperatorID":"money2020",
} );
var req = https.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('Return info: ' + chunk); // output the return raw data
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// attach input data to request body
req.write(inputdata);
req.end();
Info offered here in case anybody else gets stuck converting from a CURL command over to a Node.js http request...
And hey, after playing around with this, I'm amazed on how truly easy it is to incorporate a real (and secure) payments system into any merchant website. (Obviously Https site required.)
I am trying to send a simple HTTP POST request, retrieve the response body.Following is my code. I am getting
Error: Incorrect header check
inside the "zlib.gunzip" method. I am new to node.js and I appreciate any help.
;
fireRequest: function() {
var rBody = '';
var resBody = '';
var contentLength;
var options = {
'encoding' : 'utf-8'
};
rBody = fSystem.readFileSync('resources/im.json', options);
console.log('Loaded data from im.json ' + rBody);
contentLength = Buffer.byteLength(rBody, 'utf-8');
console.log('Byte length of the request body ' + contentLength);
var httpOptions = {
hostname : 'abc.com',
path : '/path',
method : 'POST',
headers : {
'Authorization' : 'Basic VHJhZasfasNWEWFScsdfsNCdXllcjE6dHJhZGVjYXJk',
'Content-Type' : 'application/json; charset=UTF=8',
// 'Accept' : '*/*',
'Accept-Encoding' : 'gzip,deflate,sdch',
'Content-Length' : contentLength
}
};
var postRequest = http.request(httpOptions, function(response) {
var chunks = '';
console.log('Response received');
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
// response.setEncoding('utf8');
response.setEncoding(null);
response.on('data', function(res) {
chunks += res;
});
response.on('end', function() {
var encoding = response.headers['content-encoding'];
if (encoding == 'gzip') {
zlib.gunzip(chunks, function(err, decoded) {
if (err)
throw err;
console.log('Decoded data: ' + decoded);
});
}
});
});
postRequest.on('error', function(e) {
console.log('Error occured' + e);
});
postRequest.write(rBody);
postRequest.end();
}
response.on('data', ...) can accept a Buffer, not just plain strings. When concatenating you are converting to string incorrectly, and then later can't gunzip. You have 2 options:
1) Collect all the buffers in an array, and in the end event concatentate them using Buffer.concat(). Then call gunzip on the result.
2) Use .pipe() and pipe the response to a gunzip object, piping the output of that to either a file stream or a string/buffer string if you want the result in memory.
Both options (1) and (2) are discussed here: http://nickfishman.com/post/49533681471/nodejs-http-requests-with-gzip-deflate-compression
In our case we added 'accept-encoding': 'gzip,deflate' to the headers and code started working (solution credited to Arul Mani):
var httpOptions = {
hostname : 'abc.com',
path : '/path',
method : 'POST',
headers : {
...
'accept-encoding': 'gzip,deflate'
}
};
I had this error trying to loop with fs.readdirSync but there is a .Dstore file so the unzip function was applied to it.
Be careful to pass only .zip/gz
import gunzip from 'gunzip-file';
const unzipAll = async () => {
try {
const compFiles = fs.readdirSync('tmp')
await Promise.all(compFiles.map( async file => {
if(file.endsWith(".gz")){
gunzip(`tmp/${file}`, `tmp/${file.slice(0, -3)}`)
}
}));
}
catch(err) {
console.log(err)
}
}
In addition to #Nitzan Shaked's answer, this might be related to the Node.js version.
What I experienced is that https.request (OP uses http.request, but it may behave the same) already decompresses the data under the hood, so that once you accumulate the chunks into a buffer, all you're left with is to call buffer.toString() (assuming utf8 as an example). I myself experienced it in this other answer and it seems to be related to Node.js version.
I'll end up this answer with a live demo of a similar working code which may come handy for future readers (it queries StackExchange API, gets a gzip compressed chunks, and then decompress it):
It includes a code that works on 14.16.0 (current StackBlitz version) - which, as I described, already decompresses the data under the hood - but not on Node.js 15.13.0,
It includes a commented-out code that works for Node.js 15.13.0 the latter but not for 14.16.0.
first question here, so apologies if it turns out to be something very obvious
I am trying to call the paypal adaptive payments api via node.js and am getting a 580001 invalid request error. I can make a successfull call via curl with the below message and headers, but not through node.
any help would be much appreciated.
var API_endpoint = "svcs.sandbox.paypal.com";
var API_user = '';
var API_pass = '';
var API_sig = '';
message='requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per#gmail.com&receiverList.receiver(0).email=test2_1320887729_biz#gmail.com& receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http://your_cancel_url& returnUrl=http://your_return_url'
//var params = qs.parse(message);
//params = qs.stringify(params);
var req_options = {
host: API_endpoint,
method: 'POST',
path: '/AdaptivePayments/Pay',
headers: {
'Host': API_endpoint,
'Content-Type': 'application/x-www-form-urlencoded',
//'Content-Type': 'text/namevalue',
'Content-Length': message.length,
'X-PAYPAL-REQUEST-DATA-FORMAT:':'NV',
'X-PAYPAL-RESPONSE-DATA-FORMAT':'NV',
'X-PAYPAL-SECURITY-USERID':API_user,
'X-PAYPAL-SECURITY-PASSWORD':API_pass,
'X-PAYPAL-SECURITY-SIGNATURE':API_sig,
'X-PAYPAL-APPLICATION-ID':'APP-80W284485P519543T'
}
}
fs.readFile('/home/dev/.ssh/sandbox-paypal-private.pem', 'ascii', function(err, key){
fs.readFile('/home/dev/.ssh/sandbox-paypal-public.pem', 'ascii', function(err, cert){
req_options.key=key
req_options.cert=cert
var req = https.request(req_options, function(res){
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function(d){
var response = d.toString();
console.log(response)
});
});
req.write(message);
req.end();
req.on('error', function request_error(e) {
console.log(e);
});
});
});
I'm not sure if it's only a copy paste problem, but your message variable does not seem to contain properly formatted string. It has white spaces and the special characters are not encoded.
requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per#gmail.com&receiverList.receiver(0).email=test2_1320887729_biz#gmail.com&receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http://your_cancel_url& returnUrl=http://your_return_url'.
It should look like this:
requestEnvelope.errorLanguage=en_US&actionType=PAY&senderEmail=test_1320882990_per%40gmail.com&receiverList.receiver(0).email=test2_1320887729_biz%40gmail.com& receiverList.receiver(0).amount=100.00¤cyCode=USD&cancelUrl=http%3A%2F%2Fyour_cancel_url&returnUrl=http%3A%2F%2Fyour_return_url
There's a trailing colon in one of your header fields; Rather than:
'X-PAYPAL-REQUEST-DATA-FORMAT:'
You should have:
'X-PAYPAL-REQUEST-DATA-FORMAT'