I would use socket.io in my routes file.
I have found multiple methods but no one worked for me.
Now I'm trying this solution
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var server = app.listen(port);
var io = require("socket.io")(server);
var routerProj = require("./routes/routes")(io);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
XXX
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use("/v1", routerProj);
//Create HTTP server and listen on port 8000 for requests
// Print URL for accessing server
console.log("Server running at http://127.0.0.1:8080/");
io.sockets.on("connection", function (socket) {
console.log("a user is connected");
});
Routes.js
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
module.exports = function (io) {
/*router.use(function (req, res, next) {
// do logging
io.on('connection', function (socket) {
console.log('User has connected to Index');
});
});*/
router.use(function (req, res, next) {
io.on('save-message', function (socket) {
console.log('User has connected to Index');
});
});
router
.route("/")
.get(function (req, res, err) {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.once("value", function (snapshot) {
var list = [];
snapshot.forEach(function (elem) {
list.push(elem.val());
})
list = JSON.stringify(list);
//list = JSON.parse(list)
//console.log(JSON.stringify(list))
res.send(list);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
res.status(500).send(errorObject.code);
});
});
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body.text
}
);
});
return router
}
sockets are working in my server.js file , in console I get the message :"a user is connected" when I run my angular app.
But in my browser I run http://127.0.0.1:8080/v1in router.js console.log is not working, so sockets is not getting passed.
I have tried to emit an event :
ngOnInit() {
this.socket.emit('save-message', { room: "hello" });
}
In my router.js :
router.use(function (req, res, next) {
io.on('save-message', function (socket) {
console.log('User has connected to Index');
});
});
console.log don't print anything.
Related
I would update my client side view every insert in the database.
In y angular application I have a function that adds text to database :
ajoutText(newtext: String) {
this.dataService.sendtext(newtext)
.subscribe(res => this.socket.emit('save-message', { data: "hello" }));
}
after posting message to database I emit a socket. the idea is to trigger a get route to update my observable in Angular side with the new data, and create a data stream.
Here's my server configuration :
server.js:
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var server = app.listen(port);
var io = require("socket.io")(server);
var routerProj = require("./routes/routes");
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
... configuration...
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use(function (req, res, next) {
req.io = io; // pass socket to route
next();
});
app.use("/v1", routerProj);
and routes.js file :
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
//module.exports = function (req) {
//router.route("/")
router.use(function (req, res, next) {
// Test
console.log(req.io.sockets)
next();
});
router
.route("/")
.get(function (req, res, err) {
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.once("value", function (snapshot) {
var list = [];
snapshot.forEach(function (elem) {
list.push(elem.val());
})
list = JSON.stringify(list);
res.send(list);
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
res.status(500).send(errorObject.code);
});
});
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body.text
}
);
});
//return router;
//}
module.exports = router;
How can I run post route on save-message emit from client side ?
I would send data from angular to Express.
in my service ;
sendtext(text): Observable<any> {
console.log(text);
return this.http.post<string>(this.url, text, httpOptions);
}
I configure headers
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
my console.log(text) prints me the right text typed in an input.
In my server side I have created my server.js file
var http = require("http");
var admin = require('firebase-admin');
var firebase = require("firebase");
var express = require("express");
var app = express();
var routerProj = require("./routes/routes");
var bodyParser = require("body-parser");
var port = process.env.app_port || 8080; // set our port
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
var server = app.listen(port);
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,*");
next();
});
var config = {
......configuration...
};
firebase.initializeApp(config);
var serviceAccount = require("./ServiceAcountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://datatable-18f93.firebaseio.com"
});
app.use("/v1", routerProj);
//Create HTTP server and listen on port 8000 for requests
// Print URL for accessing server
console.log("Server running at http://127.0.0.1:8080/");
And I have created my router file:
var express = require("express"); // call express
var router = express.Router(); // get an instance of the express Router
var admin = require("firebase-admin");
router
.route("/")
.post(function (req, res, err) {
console.log(req.body);
// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("/");
// Attach an asynchronous callback to read the data at our posts reference
ref.push(
{
"text": req.body
}
);
});
module.exports = router;
Here console.log(req.body) prints an empty object {}
Is it because of the headers ? if yes how can I configure them ? I have already tried'Content-Type': 'application/json', and without headers, no result.
I have the following file: (auth.js)
module.exports = function (express, mongoose, router) {
router.route('/setup')
.get(function (req, res) {
var salt = bcrypt.genSaltSync(10);
var hashed = bcrypt.hashSync(req.query.password, salt);
// create a sample user
mongoose.models.playlist.create({username: 'Hieratic', password: hashed}, function (err, item) {
if (err) throw err;
console.log('User saved successfully');
res.json({ success: true });
});
});
return router;
};
And the current server file: (server.js)
"use strict";
var url = require('url');
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var crypto = require('crypto');
//npm install request
var request = require('request');
var config = require('./config/access.json');
var admin = require("firebase-admin");
var fireBaseConfig = require('./config/firebase.config.json');
var mongoose = require('mongoose');
var MongoClient = require('mongodb').MongoClient;
var mongodbConfig = require('./config/database.json');
var exec = require('child-process-promise').exec;
var app = express();
/**
* Schemas
*/
var UserModel = require('./schemas/user.schema.js')(mongoose);
var PlayListModel = require('./schemas/playlist.schema.js')(mongoose);
app.use(function (req, res, next) {
// CORS headers
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, x-access-token, Cache-Control, Pragma"
);
next();
});
var router = express.Router();
app.use(bodyParser.json({limit: '4mb'}));
app.use(bodyParser.urlencoded({
extended: true,
limit: '4mb'
}));
if (mongodbConfig.username && mongodbConfig.password) {
mongoose.connect(`mongodb://${mongodbConfig.username}:${mongodbConfig.password}#${mongodbConfig.host}:${mongodbConfig.port}/${mongodbConfig.database}`);
}
else {
mongoose.connect(`mongodb://${mongodbConfig.host}:${mongodbConfig.port}/${mongodbConfig.database}`);
}
process.on('disconnect', function () {
// If mongodb connection is not terminated child process never dies
mongoose.disconnect();
});
require('./auth.js')(express, mongoose, router);
var port = 51000;
app.listen(port);
console.log('Magic happens at http://localhost:' + port);
When i attempt to access the /setup route it does hit the server however it throws an html page:
(http://localhost:51000/setup):
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /setup</pre>
</body>
Can anyone see what ive done wrong?
You have created router, but not registered it as a middleware:
var router = express.Router();
require('./auth.js')(express, mongoose, router);
app.use(router);
Refer to Cannot GET / Nodejs Error
You have no route set up.
Serve your page like this:
app.get('/', function (req, res) {
res.render('index', {});
});
var search = 1 + req.url.indexOf('?'); throws an error saying the statement to my left is undefined. Im using passportjs to create a login/registration page on my angular frontend. trying to make a post request to nodejs results in the above error. Im entirely new to the mean stack and ive tried several different tutorials to get myself up and running but have had some road blocks. can someone point in the right direction?
I've played around with just about every file moving around code and trying different solutions but nothing works, or one problem is solved but another occurs.
server.js
// set up ========================
var DATABASE = "mongodb://localhost:27017/smartHomeDevices";
var express = require("express");
var mongoose = require("mongoose"); //require monogDB Driver
var morgan = require("morgan"); // log requests to the console (express4)
var bodyParser = require("body-parser"); // pull information from HTML POST (express4)
var methodOverride = require("method-override"); // simulate DELETE and PUT (express4)
var passport = require("passport");
//var _ = require("lodash");
var http = require('http');
//setup
//app.models =
require("./Models/moduleIndex");
// Bring in the Passport config after model is defined
require('./config/passport');
//registering routes
var routes = require("./routes");
//Create App
var app = express();
app.use(passport.initialize());
//Add Middleware for REST API
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json);
app.use(bodyParser.json({
type: 'application/vnd.api+json'
}));
app.use(methodOverride("X-HTTP-Method-Override"));
app.use(morgan("dev"));
//CORS Support, makes API Public
app.use(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,Authorization");
next();
});
app.use("/", routes);
// Connect to the db
mongoose.connect(DATABASE);
mongoose.connection.once("open", function() {
var serv = http.createServer(function(req, res) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE");
res.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization");
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end();
console.log(routes(req.method, req.url));
}).listen(3000);
//module.exports = app;
console.log("Listening on 3000");
});
routes.js
//setup
var express = require('express');
var router = express.Router();
var jwt = require('express-jwt');
var auth = jwt({
secret: 'MY_SECRET',
userProperty: 'payload'
});
var ctrlProfile = require('./Controllers/ProfileController');
var ctrlAuth = require('./Controllers/RegisterUserController');
// profile
router.get('/profile', auth, ctrlProfile.profileRead);
// authentication
router.post('/register', ctrlAuth.register);
router.post('/login', ctrlAuth.login);
module.exports = router;
/*module.exports = {
"/smartDevices" : require("./Controllers/SmartDeviceController"),
"/registeredUsers": require("./Controllers/RegisterUserController")
};*/
resgisteredUsersControllers.js
//setup
//var Resource = require("resourcejs");
var restful = require("node-restful");
var passport = require('passport');
var mongoose = require('mongoose');
var User = mongoose.model('registeredUserModel');
var sendJSONresponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.register = function(req,res) {
console.log(req);
console.log("nw logging res");
console.log(res);
var user = new User();
user.name = req.body.name;
user.email = req.body.email;
user.username = req.body.username;
user.setPassword(req.body.password);
user.save(function(err) {
if(err)
console.log(err);
var token;
token = user.generateJwt();
res.status(200);
res.json({
"token" : token
});
});
next();
};
module.exports.login = function(req, res) {
passport.authenticate('local', function(err, user, info) {
var token;
// If Passport throws/catches an error
if (err) {
res.status(404).json(err);
return;
}
// If a user is found
if (user) {
token = user.generateJwt();
res.status(200);
res.json({
"token": token
});
} else {
// If user is not found
res.status(401).json(info);
}
})(req, res);
next();
};
/*module.exports = function(app, route) {
//setup controller for restful
// Resource(app,"",route,app.models.registeredUserModel).rest();
var rest = restful.model("registeredUserModel",
app.models.registeredUserModel
).methods(["get", "put", "post", "delete"]);
rest.register(app, route);
//return Middleware
return function(req, res, next) {
next();
};
};
*/
ProfileController.js
var mongoose = require('mongoose');
var User = mongoose.model('registeredUserModel');
module.exports.profileRead = function(req, res) {
// If no user ID exists in the JWT return a 401
if (!req.payload._id) {
res.status(401).json({
"message" : "UnauthorizedError: private profile"
});
} else {
// Otherwise continue
User
.findById(req.payload._id)
.exec(function(err, user) {
res.status(200).json(user);
});
}
};
Request object does not have url field.
i have the following method to auth my users:
app.all('/*', function(req, res, next) {
// CORS headers
res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// Set custom headers for CORS
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
if (req.method == 'OPTIONS') {
res.status(200).end();
} else {
next();
}
});
var auth = require('./auth.js');
router.post('/login', auth.login);
app.all('/api/*', [require('./middlewares/validateRequest')]);
// If no route is matched by now, it must be a 404
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
And my Auth.js
var jwt = require('jwt-simple');
var auth = {
login: function(req, res) {
var username = req.body.username || '';
var password = req.body.password || '';
if (username == '' || password == '') {
res.status(401);
res.json({
"status": 401,
"message": "Invalid credentials"
});
return;
}
// Fire a query to your DB and check if the credentials are valid
var dbUserObj = auth.validate(username, password);
if (!dbUserObj) { // If authentication fails, we send a 401 back
res.status(401);
res.json({
"status": 401,
"message": "Invalid credentials"
});
return;
}
if (dbUserObj) {
// If authentication is success, we will generate a token
// and dispatch it to the client
res.json(genToken(dbUserObj));
}
},
validate: function(username, password) {
// spoofing the DB response for simplicity
var dbUserObj = { // spoofing a userobject from the DB.
name: 'arvind',
role: 'admin',
username: 'arvind#myapp.com'
};
return dbUserObj;
},
validateUser: function(username) {
// spoofing the DB response for simplicity
var dbUserObj = { // spoofing a userobject from the DB.
name: 'arvind',
role: 'admin',
username: 'arvind#myapp.com'
};
return dbUserObj;
}
}
// private method
function genToken(user) {
var expires = expiresIn(7); // 7 days
var token = jwt.encode({
exp: expires
}, require('../config/secret')());
return {
token: token,
expires: expires,
user: user
};
}
function expiresIn(numDays) {
var dateObj = new Date();
return dateObj.setDate(dateObj.getDate() + numDays);
}
module.exports = auth;
This server runs on port 8080.
So when i attempt to go to http://localhost:8080/login i get the following error message:
Error: Not Found
at app.use.bodyParser.urlencoded.extended (/var/www/example/backend/server.js:34:15)
at Layer.handle [as handle_request] (/var/www/example/backend/node_modules/express/lib/router/layer.js:82:5)
at trim_prefix (/var/www/example/backend/node_modules/express/lib/router/index.js:302:13)
at /var/www/example/backend/node_modules/express/lib/router/index.js:270:7
at Function.proto.process_params (/var/www/example/backend/node_modules/express/lib/router/index.js:321:12)
at next (/var/www/example/backend/node_modules/express/lib/router/index.js:261:10)
at next (/var/www/example/backend/node_modules/express/lib/router/route.js:100:14)
at next (/var/www/example/backend/node_modules/express/lib/router/route.js:104:14)
at next (/var/www/example/backend/node_modules/express/lib/router/route.js:104:14)
at next (/var/www/example/backend/node_modules/express/lib/router/route.js:104:14)
However it seems that the rest of my auth is working because if i go to:
http://localhost:8080/api/user
I get: {"status":401,"message":"Invalid Token or Key"}
Can anyone tell me why my login does not work?
Full server script:
// BASE SETUP
// =============================================================================
var express = require('express'),
bodyParser = require('body-parser');
var app = express();
var router = express.Router();
var es = require('express-sequelize');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// =============================================================================
//Secure
app.all('/*', function(req, res, next) {
// CORS headers
res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// Set custom headers for CORS
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
if (req.method == 'OPTIONS') {
res.status(200).end();
} else {
next();
}
});
var auth = require('./auth.js');
router.post('/login', auth.login);
app.all('/api/*', [require('./middlewares/validateRequest')]);
// If no route is matched by now, it must be a 404
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
var env = app.get('env') == 'development' ? 'dev' : app.get('env');
var port = process.env.PORT || 8080;
var Sequelize = require('sequelize');
// db config
var env = "dev";
var config = require('./database.json')[env];
var password = config.password ? config.password : null;
// initialize database connection
var sequelize = new Sequelize(
config.database,
config.user,
config.password,
{
logging: console.log,
define: {
timestamps: false
}
}
);
//Init models
var division_model = require('./lb_models/division/division_model')(express,sequelize,router);
var user_model = require('./lb_models/user/user_model')(express,sequelize,router);
var team_model = require('./lb_models/Team')(express,sequelize,router);
app.use('/api', router);
app.use(division_model);
app.use(user_model);
app.use(team_model);
// START THE SERVER
app.listen(port);
console.log('Magic happens on port ' + port);
Try moving your app.use(bodyParser…) statements above the login route. The order of middleware matters. At the time login is called the req object hasn't run through the bodyParser middleware yet.
Also, your router instance is mounted at "/api" so the router methods will never get called for "/login". The following line should be place above your 404 catchall:
app.use('/', router);
Before, you had used app.use('/api', router), which means that your router routes will only be looked at for any request that starts with '/api'. Also, you had place the 'use' statement too far down.
When setting up middleware, the order in which you call app.use() is key. In your server.js, you're setting up your application routes before you set up body parser. Meaning, when the request comes in, is is not parsed before hitting your application logic. You need to move the app.use(bodyParser) parts to the top of your code.
var express = require('express'),
bodyParser = require('body-parser');
var app = express();
var router = express.Router();
var es = require('express-sequelize');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
perphaps you have to move the
app.use("/", (req, res, next) => {
res.status("404").json({message: "Not found"})
})
to the bottom of your code, but before "app.listen()", The order you declare the routes in the router are important, so putting the "app.use" after you declare all theses routes, would search a match with all the previous route and if none is found then it will enter in that last one
Like this:
.
..
...
app.use('/api', router);
app.use(division_model);
app.use(user_model);
app.use(team_model);
app.use("/", (req, res, next) => {
res.status("404").json({message: "Not found"})
})
// START THE SERVER
app.listen(port);
console.log('Magic happens on port ' + port);