Using Nodejs, Express and AngularJS to display IP in the browser - angularjs

I'm learning Nodejs and ExpressJS. I'm trying to use ExpressJS and 2 Node modules (request-ip and geoip2) to get the client IP address for geolocation and then outputting the geolocation in the browser using AngularJS (1.x).
So far for my Nodejs and Expressjs code I have
var express = require('express');
// require request-ip and register it as middleware
var requestIp = require('request-ip');
// to convert the ip into geolocation coords
var geoip2 = require('geoip2');
// Init app
var app = express();
var port = process.env.PORT || 8000;
geoip2.init(); // init the db
//app.use(requestIp.mw({ attributeName: 'myCustomAttributeName'}));
var ip = '207.97.227.239';//67.183.57.64, 207.97.227.239
// respond to homepage req
app.get('/', function (req, res, next) {
//var ip = req.myCustomAttributeName;// use this for live
//var ip = '207.97.227.239';/* use this for testing */
console.log('requestIP is ' + ip);
next();
// geolocation
geoip2.lookupSimple(ip, function(error, result) {
if (error) {
console.log("Error: %s", error);
}
else if (result) {
console.log(result);//ipType was causing console.log duplication, IDK why
}
});
});
// set static folder
app.use('/', express.static(__dirname + '/public'));
app.listen(port, function(){
console.log('user location app is running');
});
And for Angular I have
angular.module('UserLocation', []);
angular.module('UserLocation')
.controller('MainController', MainController);
MainController.$inject = ['$http'];
function MainController($http) {
var vm = this;
vm.result = '';
vm.message = 'Hello World';
vm.getLocation = function() {
console.log();
return $http.get('localhost:8000', {
params: {result: result}
})
.then(function(result){
console.log(result);
})
};
};
vm.result in the Angular controller is for the result from the geoip2 Node module that performs the geolocation.
I can get the result in the console no problem but I'm not to sure how to pass it to Angular. I'm using the $http service but I'm not sure where to go from here...?
How do I pass the result from the geoip2 Node module to my Angular controller with $http?

The problem is that you are calling next before you are even done.
app.get('/', function (req, res, next) {
//next(); this line should be commented
// geolocation
geoip2.lookupSimple(ip, function(error, result) {
if (error)
return res.status(400).json({error: 'Something happened'});
return res.send(result);
});
});
Then on angular
$http({
method: 'GET',
url: '/yourURL'
}).then(function (response) {
console.log(response);
});
If you want to use the user IP to get location:
app.get('/', function (req, res, next) {
//next(); this line should be commented
// geolocation
var ip = req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
geoip2.lookupSimple(ip, function(error, result) {
if (error)
return res.status(400).json({error: 'Something happened'});
return res.send(result);
});
});

Related

Nodejs callback response not working as expected

I'm trying to authenticate a user based on values entered in a given form. However, after using res.send(), the function at AngularJS controller is not able to correctly redirect user even if the password and username are correct. Am I handling the callbacks correctly?
Controller
<script>
var app = angular.module('myApp', []);
app.controller("loginController", function($scope,$http) {
$scope.sub = function() {
var config = {
headers : {
'Content-Type': 'application/x-www-form-
urlencoded;charset=utf-8;'
}
}
$http.post('/login', { data:{ username: $scope.username,
password: $scope.password} })
.then(function(response){
if(response.state==0){
console.log('Error!');
} else if(response.state==1){
console.log('action on success');
window.location.href = '/views/success.html';}
}).catch(function(error){
console.log('action on error');
});
Authentication
var db = require('../../config');
exports.login = function(req,res){
var username = req.body.data.username;
var password = req.body.data.password;
db.query('SELECT * FROM users WHERE username = ?',[username], function
(error, results, fields){
var result = "0";
if(error) {
console.log('Code 400, Error ocurred');
}
else{
if(results.length>0){
if(results[0].password == password){
console.log('Code 200, login sucessful');
res.json({ state : 1});
}
}
else{
console.log('Code 400, Password or username invalid');
res.json({ state: 0})
}
}
});
}
server.js
var express = require('express');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var db = require('./config');
var app = express();
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use(express.static(__dirname + '/app'));
require('./app/routes')(app);
app.listen(3000,function(err){
if(err){
console.log(err);
}
else{
console.log("Listening on port 3000");
}
});
Route.js
var auth = require('../app/middleware/authenticateUser');
module.exports = function (app) {
app.get('/',function(req,res){
res.sendFile(__dirname + '/views/index.html');
});
app.post('/login', function(req, res){
auth.login(req,res);
});
}
Thanks in advance!
You need to inject $window in your controller and then in your successful response
$window.location.href = '/views/success.html';
Although using the $window service is considered AngularJS best practice, I don't think this is where the problem is.
Have you tried console.log() the response object of the $http call?
Maybe the problem is because you put if(response.state) instead of if(response.data.state).

How to change my angular controller and node server code to post data into my database

How to change my angular controller and node server code to post data into my database
Controller
var app= angular.module('App',[]);
var PD;
var address=null;
var pid=1;
app.controller("Ctrl",function($scope,$http) {
$http.get('/load').success(function(data) {
$scope.persons= data;
});
$scope.submit=function(){
PD=prompt("Enter person details");
if(PD.localeCompare("")!=0)
{
var data=JSON.stringify({pid:pid,
persondescription:PD,
url:$scope.url,
address:address,
submittedtime:new Date().toLocaleString().replace("/.*(\d{2}:\d{2}:\d{2}).*/", "$1"),
status:'Submitted'
});
console.log(data);
$http.post('/send',data).success(function(data,status) {
console.log(data);
console.log('Data posted successfully');
});
});
Node server code
Server
var express = require('express');
var http=require('http');
var bodyParser= require('body-parser');
var mysql = require('mysql');
var app = express();
app.set('port', 3000);
app.use(express.static(__dirname + "/public"));
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true }));
enter code herevar connection = mysql.createConnection({
host : '-',
user : '-',
password : '-',
database : '-'
});
connection.connect(function(error){
if(error)
{
console.log("Problem with MySQL"+error);
}
else
{
console.log("Connected with Database");
}
});
app.get('/',function(req,res){
res.sendfile('managementt.html');
});
/*
* Here we will call Database.
* Fetch news from table.
* Return it in JSON.
*/
app.get('/load',function(req,res){
connection.query("SELECT * from personactivity",function(err,rows){
if(err)
{
console.log("Problem with MySQL"+err);
}
else
{
res.end(JSON.stringify(rows));
}
});
});
app.post('/send', function(req,res){
console.log(req.body);
var query = connection.query('insert into personactivity set ?',req.body, function(err, res) {
if (err) {
console.error(err);
return res.send(err);
} else {
return res.send('Ok');
}
});
app.listen(3000,function(){
console.log("It's Started on PORT 3000");
});
How to change my angular controller and node server code to post data into my database

How to properly call an external api to use from within express application to build my own restful api?

I'am trying to create a restful api but I need to use an external api quandl to build my api, when i try to use my api from the client(built in angularjs) i get a 500 internal server error and No default engine was specified and no extension was provided in command line. i know my api work cause i tested it with postman, its just not working from the client.
I tried looking at this post : express js 4 how to serve json results without rendering any views /css but it wasnt helpful.
module.exports = function(io){
var q = require('q');
var request = require('request');
var mongoose = require('mongoose');
var Stock = mongoose.model('Stock');
var base_url = "https://www.quandl.com/api/v3/datasets/WIKI/";
var dotjson = ".json"
var apiKey = "?api_key=" + process.env.quandl_apiKey;
function sendJsonResponse(res,status,content){
res.status(status);
res.json(content);
}
// get stock data using quandl api
function stockData(name){
var deferred = q.defer();
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth() + 1;
var date = d.getDate();
request({
url: base_url + name + dotjson + apiKey,
qs:{
start_date:(year-1) + '-' + month + '-' + date,
end_date:year + '-' + month + '-' + date
}
},function(error,response,body){
if(error){
deferred.reject('Error: ' + error);
}else if(response.statusCode !== 200){
deferred.reject('Invalid Status Code: ' + response.statusCode);
}else{
deferred.resolve(body);
}
})
return deferred.promise;
}
// get stock data that is stored in database
function getStockInDatabase(req,res){
Stock.find({},function(err,stock){
if(err){
sendJsonResponse(res,404,err);
} else {
sendJsonResponse(res,200,stock);
}
})
}
// create stock data to be stored in database
function createStockData(req,res){
var stockDatas;
stockData(req.body.name.toUpperCase())
.then(function(stock){
stockDatas = JSON.parse(stock);
Stock.create({
name:stockDatas.dataset.name,
symbol:stockDatas.dataset.dataset_code
},function(err,stk){
if(err){
sendJsonResponse(res,400,err)
}else{
sendJsonResponse(res,201,stk);
io.emit('stock',stockDatas);
}
})
})
.catch(function(err){
sendJsonResponse(res,404,err);
})
}
// delete stock data in database
function deleteStockData(req,res){
Stock
.findByIdAndRemove(req.body._id)
.exec(function(err,stock){
if(err){
sendJsonResponse(res,404,err);
}else {
sendJsonResponse(res,204,null);
}
})
}
return {
getStockInDatabase:getStockInDatabase,
createStockData:createStockData,
deleteStockData:deleteStockData
}
}
angular service to use api:
(function(){
'use strict'
angular
.module('app.common')
.factory('stockService',stockService);
stockService.$inject = ['$http'];
function stockService($http){
function getStock(){
return $http.get('/api/stocks');
}
function getStockInDatabase(){
return $http.get('api/stocks/database');
}
function createStock(data){
return $http.post('/api/stocks',data);
}
function deleteStock(data){
return $http.delete('/api/stocks',data);
}
return{
getStockInDatabase:getStockInDatabase,
createStock:createStock,
deleteStock:deleteStock
}
}
})()
app.js configuration
require('dotenv').load();
var express = require('express');
var socketio = require('socket.io');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var io = socketio();
require('./api/models/db');
var app = express();
app.io = io;
var apiRoute = require('./api/routes/index')(io);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'client')));
app.use('/api', apiRoute);
app.use(function(req, res) {
res.sendFile(path.join(__dirname, 'client', 'index.html'));
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500).send({
message: err.message,
error: {}
})
});
module.exports = app;
No default engine specified error comes when you have not specified any content serving engine in express.. for you views or html files.
Try using
app.set('views', 'html page location');
app.set('view engine', 'jade');
You might have to additionally require jade.

success function is not working angular

I am sending http request and when that request is finished I am trying to go to another state but the problem is it does not goes in the success callback I thought my be I'm getting an error so I wrote the error callback it does not goes in that to. Can anybody tell me what am I doing wrong
$scope.submitUpdatedData= function(user){
debugger;
// $http.post('/url',{params: value}).sucess(function(){
API.updateRecord(user).success(function(res){
$state.go('app' ,{} , {reload: true });
console.log("Hello");
});
}
The API code is given below. Here I invoke the http call
.factory('API', function($http) {
var api = {};
var baseURL = 'http://localhost:3000';
api.addRecord = function(record) {
console.log(record);
// $http.post(baseURL + '/addData', {name: record.name}.);
return $http.post(baseURL + '/addData', {rec:record});
};
api.deleteRecord = function(id){
return $http.get(baseURL +'/delete/' + id );
};
api.updateRecord = function(user){
return $http.post(baseURL + "/update/" ,{rec:user});
};
api.getAllRecord = function(){
return $http.get(baseURL+'/getAll');
};
api.getOneRecord = function(id){
return $http.get(baseURL + '/getOne/' + id)
};
return api;
})
UPDATE
I have replaced the .success part with then but it still not works
Second Update
This is my server side code
var express = require('express');
var mongoose = require('mongoose');
var util = require('util');
var bodyParser = require('body-parser')
var app = express();
var Schema = mongoose.Schema;
require('node-monkey').start({host: "127.0.0.1", port:"50500"});
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
};
app.use( bodyParser.json() );
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
// app.use(express.json()); // to support JSON-encoded bodies
// app.use(express.urlencoded()); // to support URL-encoded bodies
app.use(allowCrossDomain);
// app.use('/' , require('./index'))
mongoose.connect('mongodb://localhost:27017/myappdatabase');
var userSchema = new Schema({
name: String,
password: String
});
var Todo = mongoose.model('Todo', userSchema);
app.get('/getAll' , function(req, res){
Todo.find({} , function(err , todos){
if (err){
res.send(err);
}
console.log(todos);
res.send(todos);
});
});
app.get('/delete/:name' , function(req , res){
console.log(req.params);
console.log(req.params.name);
Todo.remove({
name : req.params.name
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
app.get('/getOne/:id' , function(req , res){
Todo.find({name : req.params.id}, function(err, todo) {
if (err)
res.send(err);
res.send (todo[0]);
// get and return all the todos after you create another
});
});
app.post('/update', function(req , res){
console.log(req.param('rec').name);
Todo.update({_id:req.param('rec').id} , {$set : {name:req.param('rec').name , password:req.param('rec').password}} , function(err){
if(err)
res.send("Error occured");
res.send("true");
});
});
app.post('/addData' , function(req , res){
console.log( req.param('rec').name);
var p = new Todo({name: req.param('rec').name , password: req.param('rec').password});
p.save(function(err){
if(err){
res.send(err);
console.log(error);
}
res.json(p);
});
});
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
// module.exports = app;
Seems like success and error are deprecated, you should use then instead:
API.updateRecord(user).then(function(res){
$state.go('app' ,{} , {reload: true });
console.log("Hello");
});
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
Source here
Seems like your request is never answered by the API Server. Maybe you can set a timeout for your request. Here it says you can do:
$http.post(url, data, {timeout: 100});
That should timeout your request after 100ms.

AngularJS - Socket.io - ExpressJS : How to set up a realtime counter?

My purpose is to create a realtime counter. Actually I'm creating files with my server. And I want for every created file, the counter to be incremented (the client should see the number of files in the browser growing...)
How can I exactly do that using Socket.io, AngularJS and Express.js ?
P.S : I have already written some code, but vainly.
EDIT 1 :
public/core.js
var app = angular.module('app', []);
app.factory('socket', function($rootScope){
var socket = io.connect();
return{
on: function(eventName, callback){
socket.on(eventName, function(){
var args = arguments;
$rootScope.$apply(function(){
callback.apply(socket, args);
});
});
},
emit: function(eventName, data, callback){
socket.emit(eventName, data, function(){
var args = arguments;
$rootScope.$apply(function(){
if(callback){
callback.apply(socket.args);
}
});
})
}
};
});
function mainController($scope, $http, socket) {
$scope.formData = {};
socket.on('number', function (data) {
console.log("Socket on number core.js !");
$scope.number = data.numberOfFiles;
});
$scope.initialize = function() {
$scope.formData.search = "";
console.log("initialize() body !");
};
$scope.search = function() {
socket.emit('next', {
message: "next"
});
console.log("search() body !");
$http.post('/search', $scope.formData)
.success(function() {
$('input').val('');
})
.error(function(data) {
console.log('Error: ' + data);
});
};
}
app.js
/**
* Module dependencies.
*/
var express = require('express');
var request = require('request');
var http = require('http');
var path = require('path');
var url = require('url');
var cheerio = require('cheerio'); // builds the DOM tree
var fs = require('fs');
var app = express();
// all environments
app.configure(function() {
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(express.logger('dev')); // log every request to the console
app.use(express.bodyParser()); // pull information from html in POST
app.use(express.methodOverride()); // simulate DELETE and PUT
app.use(express.json());
app.use(express.urlencoded());
app.use(app.router);
});
// app.listen(8080);
// console.log("App listening on port 8080");
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8080);
var numberFiles = 1;
app.post('/search', function(req, res){
var keyword = req.body.search;
for(var i = 0; i < 100; i++) {
// The results' page URL
// some long logic that creates files and increments numberFiles
numberFiles++;
}
});
io.sockets.on('connection', function (socket) {
socket.on('next', function (data) {
socket.emit('number', {
numberOfFiles: numberFiles
});
});
});
app.get('/', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
Have you tried:
SERVER
io.sockets.on('connection', function (socket) {
socket.on('next', function (data, respond) {
respond({
numberOfFiles: numberFiles
});
});
});
CLIENT
socket.emit('next', {
message: "next"
}, function(data){ // data.numberOfFiles ... };

Resources