POST to PHP from Node.js - javascript

I am trying to POST some data from a Node.js application to a PHP script. For the time being I am just building a proof of concept but I am unable to get the actual data over to the PHP side. The request goes through and I get 200 back but PHP thinks the $_POST array is empty.
Here is my node code:
// simple end point just for testing
exports.testPost = function(request, response) {
data = request.body.data;
postToPHP(data);
response.end(data);
}
function postToPHP (data) {
var http = require('http');
var options = {
host : 'localhost',
port : 8050,
path : '/machines/test/index.php',
method : 'POST',
headers : {
'Content-Type' : 'application/json',
'Content-Length' : Buffer.byteLength(data)
}
};
var buffer = "";
var reqPost = http.request(options, function(res) {
console.log("statusCode: ", res.statusCode);
res.on('data', function(d) {
console.info('POST Result:\n');
//process.stdout.write(d);
buffer = buffer+data;
console.info('\n\nPOST completed');
});
res.on('end', function() {
console.log(buffer);
});
});
console.log("before write: "+data);
reqPost.write(data);
reqPost.end();
}
Again, the request makes it to localhost:8050/machines/test/index.php but when I do a var_dump of $_POST it is an empty array.
[29-Jan-2014 21:12:44] array(0) {
}
I suspect I am doing something wrong with the .write() method but I can't quite figure out what. Any input on what I am missing or doing incorrectly would be greatly appreciated.
* Update:
As some of the comments indicate using file_get_contents('php://input'); does work to get the data on the PHP side but I would still prefer to be able to access the $_POST array directly.

Since you are sending the data with Content-Type: application/json you would need to read the raw input as php does not know how to read json into their globals like _GET and _POST unless you have some php extension that does it.
You can use the querystring library to parse a object into a name-value pair query string that you could than transmit with Content-Type:application/x-www-form-urlencoded so that the data will be parsed into the globals
var data = {
var1:"something",
var2:"something else"
};
var querystring = require("querystring");
var qs = querystring.stringify(data);
var qslength = qs.length;
var options = {
hostname: "example.com",
port: 80,
path: "some.php",
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': qslength
}
};
var buffer = "";
var req = http.request(options, function(res) {
res.on('data', function (chunk) {
buffer+=chunk;
});
res.on('end', function() {
console.log(buffer);
});
});
req.write(qs);
req.end();

Related

Translate Java SOAP Request to Javascript?

I'm working on making a SOAP request in Javascript. I've never done a SOAP request before, and the service provider only has sample code in Java.
Here's their Java sample code:
String applicationPath = "c:\\e-Notify\\";
String inputDirectory = "inputs\\";
String outputDirectory = "outputs\\";
String url = "https://example.com/ENotifyService.svc";
String xml = "";
String resp = "";
String action = "";
String inputFilePath = "";
String outputFilePath = "";
try {
//Encode the URL
URL urlx = new URL(url);
//Instance of connection object
HTTPRequestPoster poster = new HTTPRequestPoster();
//Character stream
Reader data = new StringReader("");
//Get the XML from the input file
inputFilePath = applicationPath + inputDirectory + "manage-consultant-list-input.xml";
xml = FileReader(inputFilePath);
data = new StringReader(xml);
//Set operation
action = "ManageConsultantListRequest";
//Send request to server and get the response.
poster = new HTTPRequestPoster();
resp = poster.postData(data, urlx, action); <==NOTE `ACTION` VARIABLE
//Write the response to the output file
outputFilePath = applicationPath + outputDirectory + "manage-consultant-list-output.xml";
FileWriter(outputFilePath, resp);
}
catch (Exception ex) {
System.out.println(ex.getMessage());
}
Per sample code provided by the SOAP API owner, I need to send the following values:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ManageConsultantListRequest xmlns="http://com.example.services.ServiceModel/2012/eNotifyService">
<Credentials xmlns:a="http://com.example.services.ServiceModel/2012/Credentials" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Username>MyAPIUsername</a:Username>
<a:Password>MyAPIPassword#1</a:Password>
</Credentials>
<Consultants xmlns:a="http://com.example.services.ServiceModel/2012/eNotify" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:Consultant>
<a:SubmissionActionCode>A</a:SubmissionActionCode>
<a:Jurisdiction>IL</a:Jurisdiction>
<a:LicenseNumber>00000001</a:LicenseNumber>
</a:Consultant>
</Consultants>
<TransactionID>12345</TransactionID>
</ManageConsultantListRequest>
</s:Body>
</s:Envelope>
I'm looking at the npm Soap package.
import soap from 'soap'; //https://www.npmjs.com/package/soap
let url = 'https://example.com/ENotifyService.svc';
let args = {name: 'value'};
soap.createClient(url, function(err, client) {
client.MyFunction(args, function(err, result) { <==WHERE TO PUT DATA FROM `ACTION` VARIABLE??
console.log(result);
});
});
I think I can probably get the XML data I need into JSON format using something like the technique described at https://davidwalsh.name/convert-xml-json.
I haven't yet figured out:
How to get the data contained in the Java action variable, into the npm soap package call. It doesn't seem to have a place for it. ???
Thanks very much in advance for any thoughts/advice/info!
UPDATE: If anyone would like to show how to do it using an alternative soap package, that would be an accepted answer as well!
I actually paid somebody on UpWork to help me figure this out! Neither of us could figure out how to get the npm soap package to work on this API. However, he provided this alternative approach, which did work:
var request = require("request");
var rawXML = ''; //your xml goes here
var options = { method: 'POST',
url: 'https://example.com/eNotifyService.svc',
qs: { asmx: '' },
headers:
{ 'cache-control': 'no-cache',
Connection: 'keep-alive',
'content-length': '1960',
'Cache-Control': 'no-cache',
Accept: '*/*',
'User-Agent': 'PostmanRuntime/7.15.0',
Host: 'example.com',
SOAPAction: '"requestedAction"',
'Accept-Encoding': 'gzip,deflate',
'Content-Type': 'text/xml;charset=UTF-8' },
body: rawXML };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});

nodejs https request throws error when using Content-Type

The following code is with the Dropbox API, it worked during testing but when I added the "Content-Type":"application/json" in the parameters it broke.
https.request(options, function(resp){
let creds = [];
let ts = "";
resp.on('data', function(body){
creds.push(body);
let jsonarray = Array.prototype.slice.call(creds, 0).toString().split(",");
let token = "Bearer " + jsonarray[0].substring(jsonarray[0].indexOf(':') + 3, jsonarray[0].length - 1);
ts = token;
});
resp.on('end', function(){
let connectfilelist = {
hostname: 'api.dropboxapi.com',
path: '/2/files/list_folder',
method: 'POST',
headers: {Authorization: ts,
"Content-Type", "application/json"}
};
https.request(connectfilelist, function(resp){
let flist = [];
resp.on('data', function(chunk){
flist.push(chunk.toString());
});
resp.on('end', function(){
console.log(flist);
res.render('mydropbox', flist);
});
}).end(bodyParams);
});
}).end(bodyParams);
This is the error I get when i omit that parameter:
[ 'Error in call to API function "files/list_folder": This function requires its argument in the HTTP request body, but your request body is empty.' ]
When I include the Content-Type, it throws this:
[ 'Error in call to API function "files/list_folder": request body: could not decode input as JSON' ]
I think that the way I am stating the parameters might be in a string and not JSON format, but I am not sure where I would change something.

Accessing https response object from external API in a node express application

My code currently makes a request to an external API which then responds with a JSON object. I currently log that to my console so no problems on that end. I need to reference the object externally however so I can display it on my pug page to the client.
The following external javascript file 'server2.js' is in the same location as app.js.
function DemoApiNgClient() {
var FIRST_INDEX = 0;
var DEFAULT_ENCODING = 'utf-8';
var DEFAULT_JSON_FORMAT = '\t';
var options = {
hostname: 'api.betfair.com',
port: 443,
path: '/exchange/betting/json-rpc/v1',
method: 'POST',
headers: {
'X-Application': '',
'Accept': 'application/json',
'Content-type': 'application/json',
'X-Authentication': 'emTox++='
}
}
console.log("Get horse racing event id");
// Define Horse Racing in filter object
var jsonRequest = '{"jsonrpc":"2.0","method":"SportsAPING/v1.0/' + 'listEventTypes' + '", "params": {"filter":{}}, "id": 1}'
var str = '';
var req = https.request(options, function (res) {
res.setEncoding(DEFAULT_ENCODING);
res.on('data', function (chunk) {
str += chunk;
});
res.on('end', function (chunk) {
// On resposne parse Json and check for errors
response = JSON.parse(str);
console.log('Here is our response! ' + util.inspect(response, {showHidden: false, depth: null}))
});
});
// Send Json request object
req.write(jsonRequest, DEFAULT_ENCODING);
req.end();
req.on('error', function (e) {
console.log('Problem with request: ' + e.message);
});
}
I have tried the exports module for nested functions however the res.on block isn't necessarily a function so it won't work doing it that way.
End goal is displaying the response object from the external API in pug on client side, and not being able to reference the object is my only sticky point, everything else works.

Receving POST request from Node JS server on Arduino

Im trying to send a post request to an arduino with Node JS and the Request package:
var body = {
d:"5",
l:"6",
TOTAL_VOLUME: "75",
meterId: "9"
};
var options = {
url: 'http://'+'192.168.1.102'+'/configData',
timeout: 7000,
headers: {
'Content-type' : 'application/json',
'Content-length': JSON.stringify(body).length
},
json:true,
body: JSON.stringify(body)
};
request.post(options, function (error, response, body) {
//console.log(error);
//console.log(response);
console.log(body);
if (!error && response.statusCode == 200) {
console.log("Changed configuration succesfully. ");
// Request to enpoint to save changes in database
var options = {
url: 'http://'+'8.8.8.8:4000'+'/meter/'+meter.id+'/',
method: 'PUT',
timeout: 10000,
body: {
'tank_diameter': tank_diameter,
'tank_length':tank_length,
'tank_capacity': tank_capacity
}
};
/*request(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
}
});*/
}
done();
}).on('error', function(err) {
console.log(err);
done();
});
The above code is how I send the data, However Im not able to get the data on the arduino.
This is the code on arduino:
server.on("/configData", HTTP_POST, [](){ // configData Seteo de Valores desde POST
StaticJsonBuffer<200> configBuffer;
JsonObject& configJson= configBuffer.parseObject(server.arg("plain"));
String l = configJson["l"];
String d = configJson["d"];
String meterId2 = configJson["meterId"];
String volumenTotal = configJson["TOTAL_VOLUME"];
LENGTH = l.toFloat();
HEIGHT = d.toFloat();
meterId = meterId2.toInt();
TOTAL_VOLUME = volumenTotal.toFloat();
// GUARDAR EN LA EEPROM
int EEadr = 0;
EEPROM.write(EEadr, HEIGHT);
EEPROM.commit();
EEadr = 10;
EEPROM.write(EEadr, LENGTH);
EEPROM.commit();
EEadr = 20;
EEPROM.write(EEadr, TOTAL_VOLUME);
EEPROM.commit();
EEadr = 30;
EEPROM.write(EEadr, meterId);
EEPROM.commit();
//SHOW ON SERIAL MONITOR
Serial.println("l= "+l);
Serial.println("d= "+d);
Serial.println("meterId2= "+meterId2);
Serial.println("TOTAL_VOLUME= "+volumenTotal);
server.send ( 200, "text/json", "{success:true}" );
});
The weird thing is that if I use curl like this:
curl -H "Content-type: application/json" -X POST -d "{l:\"55\", r:\"10\", meterId: \"2\"}" http://192.168.1.2
The arduino does receive the data correctly, so the problem is most likely on my Node JS request. Can anyone tell me what Im I doing wrong here?
UPDATE:
Ive checked the requests with wireshark, and it results that the curl request (the one that is working) is being sent as Line based text data. Can anyone tell me how can I send it the same way using Node JS and request?
In these type of situations you can check your request structure with applications like wireshark.
In this problem if you can see that you attach your hole json as a single string, because when you set json flag of request in request library it convert your body into json for you so now you have something like:
var options = {
body: JSON.stringfy(JSON.stringfy(body))
};
so you can correct your application by simply set following options:
var options = {
url: 'http://'+'www.goole.com'+'/configData',
timeout: 7000,
json:true,
body: body
};

Post Method works using https.request but not with Needle or Request libraries

I have nodeApp. It does stuff.
At a particular time I need to communicate with an API that out there in the wild. Using the API in rest tool like Postman is straight forward:
Postman
Url:
https://epicurl
Headers:
Content-Type : application/json
Accept : application/json
x-key : secret
Body:
{
"some":"kickass"
"data":"here"
}
Sending the above in Postman I get a nice quick response! Yay for rest tools.
So their API works, now I need to make that same response in my Node.js application.
This is where things get odd...
Request Module: FAILS
var request = require('request')
...lots_of_other_stuff...
var options = {
uri: 'https://epicURL',
method: 'POST',
json: true,
headers : {
"Content-Type":"application/json",
"Accept":"application/json",
"x-key":"secretbro"
},
body : JSON.stringify(bodyModel)
};
request(options, function(error, response, body) {
if (!error) {
console.log('Body is:');
console.log(body);
} else {
console.log('Error is:');
logger.info(error);
}
cb(body); //Callback sends request back...
});
The above fails.. It throws the good'ol ECONNRESET error that we all love! Why? Who knows?
https.request() - WORKS!
var https = require("https");
https.globalAgent.options.secureProtocol = 'SSLv3_method';
var headers = {
"Content-Type":"application/json",
"Accept":"application/json",
"x-key":"nicetrybro"
}
var options = {
host: 'www.l33turls.com',
port:443,
path: "/sweetpathsofjebus",
method: 'POST',
headers: headers
};
var req = https.request(options, function(res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function(data) {
responseString += data;
});
res.on('end', function() {
var resultObject = responseString;
//Call the callback function to get this response object back to the router.
cb(resultObject);
});
});
req.on('error', function(e) {
console.log(e);
});
req.write(bodyString);
req.end();
But then I notice...
If i leave this line of code in place when using the Request Module it then works...
var https = require("https");
https.globalAgent.options.secureProtocol = 'SSLv3_method';
Is this documented somewhere and I am missing it? Anyone explain this to me?

Categories