How to retrieve response from server using angularjs? - angularjs

I am sending filename to server and trying to get some sort of response to make sure api calls are working but its always returing 404 even though path is correct, I am not sure where i am making mistake , Any idea ?
angularjsFactory.js
getFile:function(file_name){
return $http.get("/file?file_name="+file_name);
}
server.js
var express = require('express');
var app = express();
var fs = require('fs');
app.use(express.static(__dirname + "/public"));
var readDirectory = require('./readDirectory');
app.get('/file', function(req, res) {
var path = './ditLogs';
var fileParam = req.query.file_name;
console.log(fileParam);
fs.readdir(path, function(err, items) {
items.forEach(function(items) {
if (fileParam === items) {
res.sendFile(items);
console.log(items);
}
});
});
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
//console.log('app is printing data',obj);
//ditProducer.startProducer();
setTimeout(function() {
ditconsumer.start();
}, 2000);
});

Your route on server is not correct comparing to the call from angular's side. You are not using route parameters, but query string.
Try this:
app.get('/file', function (req, res) {
// get filename using: req.query.file_name
res.send('FIle data');
});
Or you can try this on angular and keep the server code:
$http.get("/file/"+ encodeURI(file_name));

Server side code looks incorrect.
app.get('/file', function (req, res) {
console.log(req.query.file_name);//This will give you filename passed as url param
res.send('FIle data');
});

Related

socket.io emit not working properly inside express route

I use soket.io in Node.js it's working fine, but there is an issue in the routes files.
Below is my code and flow.
I have server.js file where I define io.
var express = require('express'),
app = express(),
http = require('http').Server(app);
var io = require('socket.io').listen(http);
//io from server.js
io.on('connection', function (socket) {
socket.emit('getDevicePostData', { message : 'Hi from server!!' });
socket.on('sendDevicePostData', function("Hi from server") {});
});
// pass io to routes file
var smart_control = require('./smart_control.js')(io);
app.use('/', smart_control);
And smart_control.js file code is below
module.exports = function(io) {
router.post('/emitdata', function(req, res, next) {
io.sockets.emit('getDevicePostData', { message : 'Hi from route!!' });
});
return router;
}
Above route's emit sometimes work and sometimes does not work.
And this emit is called from angular js. I use https://www.npmjs.com/package/angular-socket-io package in angular
Below code in angular controller:
mySocket.on('getDevicePostData', function(data) {
console.log(data);
});
Here mySocket is factory.
What is wrong in my code. Mainly problem from routes file only.
You just need to replace io.sockets.emit with io.emit.
Here io.sockets.emit will emit to only connected clients and your socket factory might not be up by the time you hit the API.

How to enable CORS on node js?

I am having a problem that I don't really understand. I have a node js server that server simple index.html page (This is actually angular). My server code looks like this:
var express = require('express');
var app = express();
var cors = require('cors')
var port = 4000;
var path = require("path");
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(express.static('.'))
console.log(__dirname + '/.');
app.use(cors({
origin: true,
credentials: true
}));
app.get("/", function(res, req){
req.sendFile(path.join('/index.html'));
});
app.listen(port,'0.0.0.0' , function(){
console.log("listening on * "+ port);
});
I my html page, I have and angularjs service that is accessing localhost:7000 and socket.io that is accessing localhost:7000.
My service look like this :
if(param){
$scope.isloading = true;
$http.post(
'http://' + $location.host() + ':7000/container',
{ "method": "start", "nomber": param } ,
{}
).then(function(err, data){
console.log("No error : ");
console.log(data);
if (err){
console.log(err);
}
$scope.isloading = false;
console.log("end Loading" + $scope.isloading);
}, function(err, data){
$scope.isloading = false;
console.log("error ");
});
}
and the html call to socket.io is this :
<script>var socket = io.connect('http://localhost:7000');
socket.on("news", function(data){
console.log(data);
});</script>
my problem is that I am unable to allow the angular service and socket.io call at the same time. I have installed CORS on chrome. when I enable it, socket.io don't work, but service works.. When I disable it service don't work and socket.io does: . Can you please help me to find a solution ?
Update
I have tried many of the solution proposed here. But they don't work for me.
Try like this,
app.use(cors({
origin: function (origin, callback) {
var allowed = ['http://localhost:7000'].indexOf((origin || '').toLowerCase()) !== -1;
callback(null, allowed);
}
}));
Since the error message says:
A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin'
header when the credentials flag is true
Why don't you try setting your origin instead?
I would use the following middleware:
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:4000");
next();
});
This is assuming that the credentials flag is absolutely necessary.

Asynchronous calls with AngularJS and Node.js

New to AngularJS and Node.js. Please advise.
Because the data I want to display on the page takes quite some time to load. I decide to load the fast data from database_1 first, and then get the slow response from database_2 later. Here is my AngularJS:
var app = angular.module('myApp', [
]);
app.factory('rateFactory', function ($http) {
return $http.get("localhost/rate"); // api or node.js to return only issueId and rate
})
app.controller('SignupController', function ($scope, $http, $filter, rateFactory) {
// Display most of the content first
$scope.showData = function () {
$http.get("localhost/signup") // api or node.js
.success(function (response) {
$scope.Signups = response;
$scope.curPage = 0;
$scope.pageSize = 25;
$scope.numberOfPages = function () {
return Math.ceil($scope.Signups.length / $scope.pageSize);
};
})
.error(function (data, status, headers, config) {
alert(status);
});
}
// Display slow response, Rate, later based on the issueId
$scope.showRate = function (issueId) {
rateFactory
.success(function (data) {
document.getElementById(issueId).innerHTML = data.find(x => x.IssueID === issueId).Rate;
})
.error(function (data, status, headers, config) {
//alert(status);
});
}
});
I wonder whether there is any better way to do it. This my first question.
Next question is about Node.js. If I get the data from ashx or api, it returns the data without any problem. But when using Node.js for both calls, it's a hit and miss. Sometimes it works fine, but most of the time, the 2nd call fails. Am I doing something wrong? Both returns the data perfectly if calling individually. Here is the node.js code:
var express = require('express');
var http = require('http');
var app = express();
var usp2Json = require('./lib/usp2Json.js');
app.get('/iisnode/myApp/signup', function(req, res) {
usp2Json.getJsonFromStoredProc('stroedprocToGetSignup', req, res);
});
app.get('/iisnode/myApp/rate', function(req, res) {
usp2Json.getJsonFromStoredProc('stroedprocToGetRate', req, res);
})
var server = http.createServer(app);
var port = process.env.PORT || 593;
server = app.listen(port, function() {
console.log('Server is running...');
});
usp2Json.js is a custom module to get data from SQL Server with a stored procedures:
exports.getJsonFromStoredProc = function(storedproc, req, res) {
var sql = require("mssql");
var express = require('express');
var app = express();
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
// config database
var config = {
user: 'username',
password: 'password',
server: 'servername',
database: 'databasename',
};
// connect to database
sql.connect(config, function(err) {
if(err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query(storedproc, function(err, recordset) {
if(err)
console.log(err);
// send records as a response
res.send(recordset);
});
});
}
One suggestion I have is to get rid of:
document.getElementById(issueId).innerHTML = data.find(x => x.IssueID === issueId).Rate;
And use regular Angular 2 way data binding, and bind your #issueId element to a $scope.issueId scope variable, and update the scope variable on call success. The way it is done right now is sort of an anti-pattern.
In terms of the NodeJS API call, you will need to show us what the route handler i.e. usp2Json.getJsonFromStoredProc does in it's code. Otherwise your code looks perfectly fine
In terms of the NodeJS API call, the issue is actually the SQL Server connection. When I looked at console.log, it doesn't give me enough information, but simply says "Server is running". I had to add a line to get the details of error:
request.query(storedproc, function (err, recordset) {
if (err) {
fs.appendFile("path"+ datetime+".txt", time + " Error on executing " + storedproc + " - " + err + " \r\n")
//throw (err);
}
// send records as a response
res.send(recordset);
});
This gives me "ConnectionError: Connection is closed.". With this information, I was able to find the solution from here:
https://github.com/patriksimek/node-mssql/issues/138
and answer from Stackoverflow: How can I use a single mssql connection pool across several routes in an Express 4 web application?

XMLHttpRequest cannot load [url] Response for preflight is invalid (redirect)

I'm making an ionic app for android and today I implemented a server side nodejs (express) Restful API with mongodb on cloud9.
But when I trigger a http request to the url, I keep getting the error mentioned in the title:
This is my angular http request on ionic (simply to test first):
app.controller('DashCtrl', function($scope, $http, $q) {
$http.get('https://[workspace]-[user].c9users.io/api/capture')
.then(function(result) {
console.log(result);
});
});
This is an image of my workspace:
I used the following code to make the database:
api.js
var Capture = require('../models/capture');
module.exports = function(router) {
router.get('/capture', function(req, res){
var capture = new Capture();
// capture.birdname = req.body.birdname;
// capture.place.city = req.place.body.city;
// capture.place.country = req.place.body.country;
capture.birdname = "Pigeon";
capture.save(function(err, data){
if(err)
throw err;
res.json(data);
});
});
router.get('/captures', function(req, res){
Customer.find({}, function(err, data){
res.json(data);
})
})
}
capture.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var captureSchema = mongoose.Schema({
birdname: String,
place: {
city: String,
country: String
}
});
module.exports = mongoose.model('Capture', captureSchema)
database.js
module.exports = {
'url': 'mongodb://' + process.env.IP
}
server.js
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var configDB = require('./server/config/database.js');
mongoose.connect(configDB.url);
var api = express.Router();
require('./server/routes/api')(api);
app.use('/api', api);
app.listen(process.env.PORT, process.env.IP);
console.log('Listening on port ' + process.env.PORT)
Anyone have an idea why I'm getting this error and what I need to do to fix this?
I'm guessing it has something to do with the server allowing me to send requests to the API though I don't know how to implement that.
Is there also a way to secure my database (API key maybe) and how would I implement this?
Thanks in advance

In Express.js with body-parser the value of request.body is undefined

I'm having a problem I cannot diagnose.
On a server, I have a simple URL handler using Express.js:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
app.configure(function() {
app.use(app.router);
app.use(bodyParser.json()); // see: http://expressjs.com/api.html#req.body
app.use(bodyParser.urlencoded({
extended: true
}));
});
app.post('/submit', function (req, res) {
console.log(req.body);
});
On client side, there's a form which is handled with Angular controller:
$scope.submit = function () {
// $http.post('/submit', $scope.data); // POST request to send data to the server
$http({
method: 'POST',
url: '/submit',
data: $scope.data
});
console.log('POST /submit ' + JSON.stringify($scope.data));
};
In browser's console everything is fine: $scope.data is valid; Node.js also responds with console.log, as expected, but writes undefined which means that, well, request.body is undefined.
What do I do wrong? How can I fix it?
If you're using Express 3 you shouldn't have to use the body-parser module as it is already bundled with Express 3 as express.bodyParser. You're getting an empty body because you're putting app.use(app.router) before the body parser.
app.configure(function() {
app.use(express.bodyParser());
app.use(app.router);
});
Which is why your other solution is working:
app.post('/submit', bodyParser.json(), function (req, res) {
Well, I just came up with solution, and it works. Here the app.post using body-parser is explained in few words. So I changed POST request handler definition to:
app.post('/submit', bodyParser.json(), function (req, res) {
console.log(req.body);
});
And now not only console.log(req.body) returns valid data, but it's deserialized into JSON correctly on the server without any extra code (which is, well, expected from Angular+Node pair).

Resources