HTTP POST is submitting empty JSON array - node.js

$scope.submitBracket = function(item, event){
console.log("submitting form");
var jsonData = '{"userEmail" : "darwood#mail.com","brackets" :' + JSON.stringify($scope.allGames) + '}';
var testJSON = {"Hello": {"id": "file", "value": "WTF"}};
console.log(jsonData);
var responsePromise = $http.post("/api/brackets", jsonData, {});
responsePromise.success(function(dataFromServer,status,headers,config){
console.log(dataFromServer);
});
responsePromise.error(function(data,status,headers,config){
console.log(data);
});
}
I am working on a MEAN stack app which has a form submitting a JSON object to MongoDB. the JSON is valid. It can be submitted to the database manually with no problems. In the above code example I can see the object being output to the console right before being sent to the db via an HTTP post that is the handed off to an express route. Oddly, I had it working and then in testing removed the records from the db to enter new ones and it started submitting a JSON object with an empty array. Sometimes it throws an "empty response message but the POST request does get a 200 response back. I can't for the life of me figure out why the data is not being passed.
If also tried this alternative function on the Angular side to send the data:
$scope.createBracket = function() {
var jsonData = '{"userEmail" : "darwood#mail.com","brackets" :' + JSON.stringify($scope.allGames) + '}';
$http.post('/api/brackets', jsonData)
.success(function(data) {
$scope.brackets = data;
$location.path('/');
})
.error(function(data) {
console.log('Error: ' + data);
});
};
This is the express route that it is passed off to.
app.post('/api/brackets', function(req, res) {
// create a Bracket
Bracket.create({
text : req.body.text,
done : false
}, function(err, Bracket) {
if (err)
res.send(err);
});
});
when using Postman to test with raw JSON. It hangs for a long time and says that the request is pending. This code was modeled after the tutorial found here
http://scotch.io/tutorials/javascript/creating-a-single-page-todo-app-with-node-and-angular
I have this sample code up and running and inserting into my database with no problem.
Stumped I am. Any help would be appreciated. Thanks.

How did you send the JSON object to MongoDB manually? Was it using command line or with tool like Robomongo?
I would try the following.
No 1. WHAT EXACTLY ARE WE SENDING TO SERVER?
$scope.createBracket = function() {
var jsonData = '{"userEmail" : "darwood#mail.com","brackets" :' +
JSON.stringify($scope.allGames) + '}';
console.info("In Controller-> jsonData = " + JSON.stringify(jsonData)); //**TEST**
//Is jsonData shown as expected?
$http.post('/api/brackets', jsonData)
.success(function(data, status, headers, config) {
$scope.brackets = data;
console.info("Status: " + status);
console.info("Data: " + data);
console.info("Config: " + JSON.stringify(config));
//$location.path('/');
})
.error(function(data) {
console.log('Error: ' + data);
});
No 2. ARE WE GETTING POST REQ DATA AT SERVER?
app.post('/api/brackets', function(req, res) {
console.info("Body: " + JSON.stringify(req.body)); //TEST
console.info("Text: " + JSON.stringify(req.body.text)); //TEST
console.info("Done: " + JSON.stringify(req.body.done)); //TEST
//Have we got the data from the client?
//If so need to check Mongoose Schema/Model MongoDB settings etc
//create a Bracket
//I take it you are using Mongoose and Bracket is the name of the Mongoose Model?
//
Bracket.create({
text : req.body.text,
done : false
}, function(err, bkt) //I would remove Bracket from fn argument as its your Mongoose M
//model name
{
if (err)
res.send(err);
});
});

I had a similar problem using Grails as the backend, so this might not help you. I had to explicitly set the Content-Type.
$http({
method: 'POST',
url: serverURL + '/' + scope.controller + '/save',
data: $form.serializeObject(),
headers: {'Content-Type': 'application/json'}
})
I would have simply commented, but I don't have the reputation to allow that.

Related

softlayer-client: unable to update VPN for User_Customer via REST API

I am experimenting with the softlayer-client api wrapper in my Node Express application. My goal is to update the VPN password of a User_Customer by calling the updateVpnPassword method on a specific user.
I can construct a call to achieve a VPN password update using request, but I'm not sure it's the best way to achieve the desired result.
Can the softlayer-client module be used to make an similar call to this:
function updateVpnPassword(req, res, next) {
// Construct URL to update VPN
myURL = 'https://' + <userIDAdmin> + ':' + <apiKeyAdmin> + '#api.softlayer.com/rest/v3/SoftLayer_User_Customer/' + <softLayerID> + '/updateVpnPassword/' + <newPassword> + '.json';
request.get({url: myURL}, function (error, response, body) {
console.log('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log('body:', body);
});
next();
}
My initial attempts have been to try variations on this:
function updateVpnPassword(req, res, next) {
// Assuming var client = new SoftLayer();
client
.auth(<userIDAdmin>, <apiKeyAdmin>)
.path('User_Customer', <softLayerID>,'updateVpnPassword')
.parameters(<newPassword>)
.put(function(err,result){
console.log(result);
if (err) {
next(err); // Pass errors to Express.
}
else {
// update successful
}
});
next();
}
But the console log gives an error response like
{ message: { error: 'Internal Error', code: 'SoftLayer_Exception_Public' } }.
I expect a TRUE or FALSE response, to indicate the whether the update is successful.
A similar python client can be found here but I require an implementation in JS.
I'm not familiar with nodejs but I installed the package softlayer-node and run your second code and it worked.
I also created the following script and I got TRUE
var username = 'set me';
var apikey = 'set me';
var userId = 1111111;
var SoftLayer = require('softlayer-node');
var client = new SoftLayer();
client
.auth(username, apikey)
.path('User_Custome', userId, 'updateVpnPassword')
.parameters('P#ssword123')
.put()
.then(function(result) {
console.log(result);
}, function(error) {
console.log(error);
});
node command:
$ node updateVpnPassword.js
true
Did you tried by sending that request using curl or any other REST client like postman?
If you get the same error then I recommend you submit a ticket and provide information like the id of users you are trying to update the vpn password and the user with which you are sending the request.

Design a REST api which will fetch results from multiple apis using Nodejs

Am trying to design a REST api which will throw an aggregated response from multiple apis.
Following is the NodeJS code am trying to execute -
Pseudo Code start
//endpoint to be called from a browser / REST client
router.get('/api/v1/getItems', (req, response, next) => {
var result = {} // hold the aggregated response from multiple apis
//internally fire another endpoint & add the response over to the var result
http.get(endpoint 1, function(resp){
add response to result})
http.get(endpoint 2, function(resp){
add response to result
})
return response.json(result);
}
Pseudo Code end
// endpoint to be called from the browser or REST Client.
router.get('/api/v1/getItems', (req, response, next) => {
var results = {};
// Nested Endpoint 1
var optionsgetmsg = {
host : 'host.domain.com', // tthe domain name
port : 9043,
path : '/services/itemdata', // the rest of the url
method : 'GET' // do GET
};
//child endpoint
var reqGet = http.request(optionsgetmsg, function(res) {
res.on('data', function(d) {
console.log("d "+ d); // child response
results.itemdata = d;
return response.send(results);
//process.stdout.write(d);
});
res.on('end', function(d){
})
});
reqGet.end();
reqGet.on('error', function(e) {
console.error(e);
});
});
The result in the above case should be the output 'd'. The output 'd' is the response from the child endpoint.
Actual result am getting is an empty object. {}
If you are sending JSON, you must set the headers correctly and the response:
//child endpoint
var reqGet = http.request(optionsgetmsg, function(res) {
res.on('data', function(d) {
res.setHeader('Content-Type', 'application/json');
var results = d;
response.send(JSON.stringify(results));
});
It is unclear as to what exactly you are asking for.

Not able to get the value from node.js backend back to my $http angular ajax call success block.when alerted the value of data it is empty

When posting data from angular passing the data to nodejs server and data is getting successfully inserted in mongodb.
data is requested from angular using $http call to the node.js server but the node.js server inspite of successful fetching of data from database is unable to send the data to the angular js controller.Does res.send(str) mentioned below send back the response with the content to the controller?
In the response used for node.js used str is the data fetched from the mongodb successfully
res.end(str);
In the controller I used
$http.get(url).success(function(data) {
I am not receiving any value for data and it is returning and going to the error block rather than success.
angularjscontroller:
$scope.list = function() {
var url = 'http://192.168.0.104:1212/getangularusers';
$http.get(url).success(function(data) {
$scope.users = data;
}).
error(function(data){
alert('moving into error block');
});
};
$scope.list();
}
appmongodbangulr.js(node.js server)
app.get('/getangularusers', function (req, res) {
res.header("Access-Control-Allow-Origin", "http://localhost");
res.header("Access-Control-Allow-Methods", "GET, POST");
db.things.find('', function(err, users) {
if( err || !users) console.log("No users found");
else
{
res.writeHead(200, {'Content-Type': 'application/json'});
str='[';
users.forEach( function(user) {
str = str + '{ "name" : "' + user.username + '"},' +'\n';
});
str = str.trim();
str = str.substring(0,str.length-1);
str = str + ']';
res.end( str);
}
});
});
app.listen(1212);
Please provide me with the solution how to pass the data that is fetched back to the controller?
You should NOT create JSON manually in any case. You need to use JSON.stringify method.
From the other hand, if you need to convert array of objects into array of other objects, then you definitely need to use map method.
As the result you can see something like the following:
res.writeHead(200, {'Content-Type': 'application/json'});
var usersNames = users.map(function(user){
return user.username;
});
res.end(JSON.stringify(usersNames));
P.S. don't use global scope for names, as you do with str variable.

How can I pass an array to the server when using $http?

I have an array of ids that I want to pass to the server. The other answers I have seen online describe how to pass these ids as query parameters in the url. I prefer not to use this method because there may be lots of ids. Here is what I have tried:
AngularJS:
console.log('my ids = ' + JSON.stringify(ids)); // ["482944","335392","482593",...]
var data = $.param({
ids: ids
});
return $http({
url: 'controller/method',
method: "GET",
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function (result, status, headers, config) {
return result;
})
Node.js:
app.get('/controller/method', function(req, res) {
console.log('my ids = ' + JSON.stringify(req.body.ids)); // undefined
model.find({
'id_field': { $in: req.body.ids }
}, function(err, data){
console.log('ids from query = ' + JSON.stringify(data)); // undefined
return res.json(data);
});
});
Why am I getting undefined on the server side? I suspect it's because of my use of $.params, but I'm not sure.
In Rest GET methods uses the URL as the method to transfer information if you want to use the property data in your AJAX call to send more information you need to change the method to a POST method.
So in the server you change your declaration to:
app.post( instead of app.get(
If you're using ExpressJS server-side, req.body only contains data parsed from the request's body.
With GET requests, data is instead sent in the query-string, since they aren't expected to have bodies.
GET /controller/method?ids[]=482944&ids[]=...
And, the query-string is parsed and assigned to req.query instead.
console.log('my ids = ' + JSON.stringify(req.query.ids));
// ["482944","335392","482593",...]

How do I use Blockchain.info's Receive Payments API with node JS / Express?

They have great documentation for PHP, but nothing really for node!
Does anyone here have any projects,where they used the blockchain.info Receive Payments API, in their node apps, to receive money / check for confirmations?
I learn a lot better by viewing / recreating example code so any you have would help me out tons!
-Thanks for your time
To create the address you can use something like this:
app.js:
api = require('blockchain')
app.post('/api/blockchain/createAddress', api.blockchainCreateAddress);
blockchain.js:
exports.blockchainCreateAddress = function(req, res) {
var btc_address = '<you-destination-btc-address>';
var api_url = 'https://blockchain.info/api/receive';
var callback_url = '<your-callback-url>';
var url = api_url + '?method=create&address=' + btc_address + '&callback=' + encodeURIComponent(callback_url);
if (btc_address)
{
https.get(url, function(resp) {
console.log("Calling Blockchain API at " + url)
var body = '';
resp.on('data', function(chunk) {
body += chunk;
});
resp.on('end', function() {
try
{
console.log('Blockchain returns: ' + body);
res.json(JSON.parse(body));
}
catch(e)
{
msg.error = e;
}
});
}).on('error', function(e) {
msg.error = e;
});
}
};
This is the first part, blockchain will respond you with some data, you should store the input_address returned and send payment to that (expose it to the public).
After you send a payment to input_address you should create a new module to handle the Blockchain callback.
Create something like this and go on following the doc at https://blockchain.info/api/api_receive (Implementing The Callback)
app.js
[...]
app.get('<your-callback-path>/:value/:input_address/:confirmations/:transaction_hash/:input_transaction_hash/:destination_address', api.blockchainCallback);
[...]
blockchain.js:
exports.blockchainCallback = function(req, res) {
// Go on and save/store the payment
// remember to send *ok* result string when you are done
res.send("*ok*");
});
Hope this can help you.

Resources