I'm new to mean-stack and I followed some instruction on how to get real-time data. I tried every single steps but none of it is working, how can I use socket.io correctly? I provided my code here for getting users from mongodb, please do correct my code
server.js
var express = require ('express');
var app = express();
var server = require('http').Server(app);
var http = require('http').Server(app);
var io = require('socket.io')(http);
var morgan = require ('morgan');
var mongoose = require('mongoose');
var appRoutes = require('./app/routes/api');
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use('/api',appRoutes);
mongoose.connect('mongodb://localhost:27017/testing', function(err){
if(err){
console.log('Not connected' + err);
} else
{
console.log('Connected');
}
});
Then here is the part where I get the users from the table, I don't know how to get the the data real-time:
api.js
var User = require('../models/user');
const router = express.Router();
router.get('/management', function(req, res) {
User.find({}, function(err, users) {
if (!users) {
res.json({ success: false, message: 'Users not found' });
} else {
res.json({ success: true, users: users,});
}
});
});
userCtrl.js
.controller('managementCtrl', function(User, $scope) {
function getUsers() {
User.getUsers().then(function(data) {
if (data.data.success) {
app.users = data.data.users;
} else {
app.errorMsg = data.data.message;
}
});
}
});
users.html
<tbody>
<tr ng-repeat="person in management.users">
<td align="center">{{ person.name }}</td>
<td align="center">{{ person.email }}</td>
</tr>
</tbody>
First of all you need to get a socket with connection event:
io.on('connect', function(socket){
than you need to set a "listener" on specific event you want to reply with data
Together it will be:
io.on('connect', function(socket){
socket.on('eventYouGet', function(eventData) {
User.find({}, function(err, users) {
if (!users) {
socket.emit('eventAnswer', {success: false, message: 'Users not found'});
} else {
socket.emit('eventAnswer', {success: true, users: users)};
}
});
});
});
Where eventYouGet is event which you (from server perspective) are waiting for (kind of like request in REST); eventAnswer is event you send as answer (to the client).
Note:
socket.emit sends an event to sender and no one else (one socket)
On the server -
I generally check for connections:
io.on('connection', function(socket){
console.log('a user connected');
});
You'll need for the client and the server to agree on some sort of token to listen to for socket. In this case, I am hardcoding in '123123123'
var User = require('../models/user');
const router = express.Router();
router.get('/management', function(req, res) {
User.find({}, function(err, users) {
if (!users) {
io.emit("123123123", { success: false, message: 'Users not found' });
} else {
io.emit("123123123", { success: true, users: users,});
}
});
});
In angular -
var socket = io.connect(<url>); //url from server
socket.on('123123123', function (user) {
let user = json.parse(user)
});
Related
I have a form where a user is supposed to put in there nickname, the issue is I need the nickname to be unique, in that no one else should be able to make there nickname the same as someone elses. Is there a fix for this using only mongoDB and not mongoose?
var bodyParser = require("body-parser");
var express = require("express");
var app = express();
var PORT = 3332;
app.use("/", express.static(__dirname));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect("mongodb://localhost/gtra", {
useNewUrlParser: true
});
var db = mongoose.connection;
db.once("open", function(cb) {
console.log("connection established");
});
app.post("/addname", (req, res) => {
var name = req.body.pickname;
var data = {
nickname: name
};
db.collection("dat").insertOne(data, function(err, coll) {
if (err) throw err;
console.log("rec estab");
res.redirect("/");
});
});
app.listen(PORT, function() {
console.log("server is up and running using port " + PORT);
});
You can check if there is already a username in the collection, if exists you can throw exception.
app.post("/addname", (req, res) => {
var data = {
nickname: req.body.pickname
};
db.collection("dat").findOne({ nickname: data.nickname }, function(err, doc) {
if (err) throw err;
if (doc) {
return res.status(400).send("Nickname already taken"); //or throw whatever you want
} else {
db.collection("dat").insertOne(data, function(err, coll) {
if (err) throw err;
console.log("rec estab");
res.redirect("/");
});
}
});
});
Another option is creating a unique index on the nickname field.
db.users.createIndex( { "nickname": 1 }, { unique: true } )
Change users to your collection name.
I have some code to create an account and have a login page and say true or false if you entered the correct details but instead it says 'Cannot post /membership/login/submit'.
my main.js code (the html files are basic and the forms are just standard tags with an action and a method, tell me if you want these)
var app = require('express')();
var http = require('http').Server(app);
var httpuse = require('http');
var io = require('socket.io')(http);
var MongoClient = require('mongodb').MongoClient;
var users = require(__dirname + '/local_js/users.js');
var public = __dirname + "/www/";
var bodyParser = require('body-parser')
var url = "mongodb://localhost:27017/";
const bcrypt = require('bcrypt');
var needle = require('needle');
const saltRounds = 10;
app.use(bodyParser.urlencoded({ extended: false }));
function rand(n) {
Math.floor(Math.random() * (n+1));
}
function getToken(hashedpass, user) {
return hashedpass+"_._"+user;
}
app.get('/', function(req, res){
res.sendFile(public + 'index.html');
});
app.get('/membership/create/form', function(req, res){
res.sendFile(public + 'user/create.html');
});
app.post('/membership/create/submit', function(req, res){
MongoClient.connect(url, function(errdd, db) {
if (errdd) throw errdd;
var dbo = db.db("boaichat");
bcrypt.hash(req.body.password, saltRounds, function(err, hash) {
if (err) {throw err;}
var newUser = { nickname: req.body.nickname, password: hash };
dbo.collection("users").insertOne(newUser, function(errd, ress) {
if (errd) throw errd;
console.log("1 user document inserted");
db.close();
res.send("200 OK");
});
});
});
});
app.get('/membership/login/form', function(req, res) {
res.sendFile(public + 'user/login.html');
});
app.post('membership/login/submit', function(req, res) {
MongoClient.connect(url, function(errdd, db) {
if (errdd) throw errdd;
var dbo = db.db("boaichat");
dbo.collection("users").findOne({nickname: req.body.nickname}, function(err, result) {
if (err) throw err;
if (result) {
bcrypt.compare(req.body.password, result.password, function(err, ress) {
console.log(ress);
res.send(ress);
});
}
});
db.close();
});
});
// IGNORE THIS
app.post('api/v1/getSessionValid', function(req, res) {
let token = req.body.token;
let userInfo = token.split('_._');
if (userInfo[0] && userInfo[1]) {
}
});
io.on('connection', function(socket){
console.log('connection');
socket.on('disconnect', function(){
console.log("disconnection");
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
it says 'Cannot post /membership/login/submit'.
Don't forget the / at the beginning of your route.
// Try this
app.post('/membership/login/submit', ...)
// Instead of
app.post('membership/login/submit', ...)
I'm new to mean-stack and I followed some instruction on how to get real-time data. I tried every single steps but none of it is working, how can I use socket.io correctly? I provided my code here for getting users from mongodb, please do correct my code
server.js
var express = require ('express');
var app = express();
var server = require('http').Server(app);
var http = require('http').Server(app);
var io = require('socket.io')(http);
var morgan = require ('morgan');
var mongoose = require('mongoose');
var appRoutes = require('./app/routes/api');
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use('/api',appRoutes);
mongoose.connect('mongodb://localhost:27017/testing', function(err){
if(err){
console.log('Not connected' + err);
} else
{
console.log('Connected');
}
});
Then here is the part where I get the users from the table, I don't know how to get the the data real-time:
api.js
var User = require('../models/user');
const router = express.Router();
router.get('/management', function(req, res) {
User.find({}, function(err, users) {
if (!users) {
res.json({ success: false, message: 'Users not found' });
} else {
res.json({ success: true, users: users,});
}
});
});
userCtrl.js
.controller('managementCtrl', function(User, $scope) {
function getUsers() {
User.getUsers().then(function(data) {
if (data.data.success) {
app.users = data.data.users;
} else {
app.errorMsg = data.data.message;
}
});
}
});
userServices.js
angular.module('userServices', [])
.factory('User', function($http) {
var userFactory = {};
userFactory.getUsers = function() {
return $http.get('/api/management/');
};
return userFactory;
});
};
users.html
<tbody>
<tr ng-repeat="person in management.users">
<td align="center">{{ person.name }}</td>
<td align="center">{{ person.email }}</td>
</tr>
</tbody>
You have to make establish persistent socket connection with the frontEnd. After making the persistent connection you have to listen for the particular event and then send the realtime user Data.
You can achieve this by:
server.js
var express = require ('express');
var app = express();
var server = require('http').Server(app);
var http = require('http').Server(app);
var io = require('socket.io')(http);
var morgan = require ('morgan');
var mongoose = require('mongoose');
var appRoutes = require('./app/routes/api');
var User = require('../models/user');
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));
app.use('/api',appRoutes);
mongoose.connect('mongodb://localhost:27017/testing', function(err){
if(err){
console.log('Not connected' + err);
} else
{
console.log('Connected');
}
});
io.on('connection', function(socket) {
console.log('New Socket has been connected');
socket.on('getUserDetails', function() {
User.find({}).then(function(data){
socket.emit('userDetails', data)
})
})
})
In fronEnd you can emit the event getUserDetails for getting the data from the server and listen on userDetails for getting the response from the server.
Something like this can be implemented in front end
angular
I have a Express server resolving GET /companies/:id/populate/. Now, I would like to setup GET /companies/populate/ (without the :id). However, I can't make this route to work. If I try, for example, GET /companies/all/populate/, it works, so it seems the pattern for an Express route is path/:key/path/:key.
Is this true? Thanks!
Edit: Adding code.
server.js
'use strict';
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cors = require('cors');
var mongoUri = 'mongodb://localhost:27017';
mongoose.connect(mongoUri);
var db = mongoose.connection;
db.on('error', function() {
throw new Error('Unable to connect to database at' + mongoUri);
});
// runs Express
var app = express();
// uses Cors
app.use(cors());
// uses bodyParser
app.use(bodyParser.json());
// requires Mongo models
require('./models');
// includes routes.js, passing the object 'app'
require('./routes')(app);
// listens for connections on port 3000
app.listen(3000, function() {
console.log("Express started on Port 3000");
});
routes.js
module.exports = function(app) {
// thumbs up if everything is working
app.get('/', function(req, res, next) {
res.send('👍');
console.log('Server Running');
res.end();
});
// companies
var companies = require('./controllers/companies');
app.get('/companies', companies.findAll);
app.get('/companies/:id', companies.findById);
app.get('/companies/:id/populate', companies.populate);
app.get('/companies/populate', companies.populateAll);
app.post('/companies', companies.add);
app.patch('/companies/:id', companies.patch);
app.delete('/companies/:id', companies.delete);
};
/controllers/companies.js
var mongoose = require('mongoose');
Company = mongoose.model('Company');
// GET /companies
// status: works, needs error handling
exports.findAll = function(req, res) {
Company.find({}, function(err, results) {
return res.send(results);
});
};
// GET /companies/:id
// status: works, needs to check error handling
exports.findById = function(req, res) {
var id = req.params.id;
Company.findById(id, function(err, results) {
if (results) res.send(results);
else res.send(204);
});
};
// POST /companies
// status: works, needs error handling
exports.add = function(req, res) {
Company.create(req.body, function(err, results) {
if (err) {
return console.log(err)
} else {
console.log('company created');
}
return res.send(results);
});
};
// PATCH /companies/:id
// status: works, needs error handling
exports.patch = function(req, res) {
var id = req.params.id;
var data = req.body;
Company.update( { '_id' : id }, data, function(err, numAffected) {
if (err) return console.log(err);
return res.send(200);
});
};
// DELETE /companies/:id
// status: works, needs error handling, make sure that we are sending a 204 error on delete
exports.delete = function(req, res) {
var id = req.params.id;
Company.remove({ '_id': id }, function(results) {
console.log('deleted ' + id); // tester
return res.send(results);
});
};
// GET /companies/:id/populate
exports.populate = function(req, res) {
var id = req.params.id;
Company
.findOne({ _id: id })
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};
// GET /companies/populate
exports.populateAll = function(req, res) {
Company
.find({})
.populate('contacts country')
.exec(function (err, results) {
if (err) return handleError(err);
else res.send(results);
});
};
Hi I am new to backend node applications and I am trying to create a clean API driven node.js app without frameworks by working with scripts and pug template engine.
I have created a serve.js file with all the necessary code:
var express = require('express');
var app = express();
var path = require('path');
var favicon = require('serve-favicon');
const bodyParser = require("body-parser");
var mongodb = require("mongodb");
const MongoClient = require('mongodb').MongoClient
var ObjectID = mongodb.ObjectID;
var indexRoutes = require('./routes/index');
var thePort = process.env.PORT || 5000;
var SECTIONS_COLLECTION = "sections";
//make results available as json
app.use(bodyParser.json());
//External database identifier
var db;
//Path to the database with URI
var dbpath = process.env.MONGODB_URI || 'mongodb://heroku_fmvc5nhk:5rqdhjqc2orjhen7knanjpfmd7#ds014586.mlab.com:19986/heroku_fmvc5nhk';
// Connect to the database before starting the application server.
mongodb.MongoClient.connect(dbpath, function (err, database) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
db = database;
console.log("Database connection ready");
//static folder directory
app.use(express.static(__dirname + '/dist'));
// Initialize the app.
var server = app.listen(process.env.PORT || thePort, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
});
// Generic error handler used by all endpoints.
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({"error": message});
}
//set up routes directory
app.use('/', indexRoutes);
// Views and Template Engine
//app.set('views', __dirname + './views');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// sections API ROUTES:
/* "/api/sections"
* GET: finds all sections
* POST: creates a new contact
*/
app.get("/api/sections", function(req, res) {
db.collection(SECTIONS_COLLECTION).find({}).toArray(function(err, docs) {
if (err) {
handleError(res, err.message, "Failed to get sections.");
} else {
res.status(200).json(docs);
}
});
});
app.post("/api/sections", function(req, res) {
var newContact = req.body;
if (!req.body.name) {
handleError(res, "Invalid user input", "Must provide a name.", 400);
}
db.collection(sections_COLLECTION).insertOne(newContact, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new contact.");
} else {
res.status(201).json(doc.ops[0]);
}
});
});
/* "/api/sections/:id"
* GET: find contact by id
* PUT: update contact by id
* DELETE: deletes contact by id
*/
app.get("/api/sections/:id", function(req, res) {
db.collection(SECTIONS_COLLECTION).findOne({ _id: new ObjectID(req.params.id) }, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to get contact");
} else {
res.status(200).json(doc);
}
});
});
app.put("/api/sections/:id", function(req, res) {
var updateDoc = req.body;
delete updateDoc._id;
db.collection(SECTIONS_COLLECTION).updateOne({_id: new ObjectID(req.params.id)}, updateDoc, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to update contact");
} else {
updateDoc._id = req.params.id;
res.status(200).json(updateDoc);
}
});
});
app.delete("/api/sections/:id", function(req, res) {
db.collection(SECTIONS_COLLECTION).deleteOne({_id: new ObjectID(req.params.id)}, function(err, result) {
if (err) {
handleError(res, err.message, "Failed to delete contact");
} else {
res.status(200).json(req.params.id);
}
});
});
In my views\about.pug template I reference my JSON object's contents.
//--about.pug
extends index.pug
block div.root
h2= #{about.heading}
h3= #{about.summary}
p #{about.content}
In my routesroutes/index.js I have pre-existing "flat" examples with pug then one dynamic about example:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res) {
res.render(
'index',
{
title: 'Welcome to Awesome Place',
header: 'Home',
summary: 'This is my home. It can\'t be any simpler'
}
)
})
Dynamic example:
//About
router.get('/about', function (req, res) {
//retrieve all home from Mongo
db.collection(SECTIONS_COLLECTION).find({"name": "about"}), function (err, about) {
if (err) {
handleError(res, err.message, "Failed to get sections.");
} else {
res.render('about', {})
console.log(result)
}
}
})
The above is returning a db is not defined error.
If var indexRoutes = require('./routes/index'); is required as part of my server.js file, why can't it find the value of db?
UPDATED CODE (TOO MANY ERRORS)
//server.js
//APP Dependences
var express = require('express');
var app = express();
var path = require('path');
var favicon = require('serve-favicon');
var indexRoutes = require('./routes/index');
var bodyParser = require("body-parser");
//PORT
var thePort = process.env.PORT || 5000;
// Views and Template Engine
//app.set('views', __dirname + './views');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
//Documents
app.use(bodyParser.json());
//static folder directory
app.use(express.static(__dirname + '/dist'));
//set up routes directory
app.use('/', indexRoutes);
// Catch errors
app.use(function(req, res, next) {
res.status(404).sendFile(process.cwd() + '/app/views/404.htm');
});
// Initialize the app.
var server = app.listen(process.env.PORT || thePort, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
});
var mongodb = require("mongodb");
const MongoClient = require('mongodb').MongoClient
var ObjectID = mongodb.ObjectID;
var SECTIONS_COLLECTION = "sections";
//External database identifier
var db;
//Path to the database with URI
var dbpath = process.env.MONGODB_URI || 'mongodb://heroku_fmvc5nhk:5rqdhjqc2ovanbfd7knanjpfmd7#ds019986.mlab.com:19986/heroku_fmvc5nhk';
// Connect to the database before starting the application server.
mongodb.MongoClient.connect(dbpath, function (err, database) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
db = database;
console.log("Database connection ready");
// Initialize the app.
var server = app.listen(process.env.PORT || thePort, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
// Generic error handler used by all endpoints.
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
res.status(code || 500).json({"error": message});
}
//db.js
var express = require('express');
var mongodb = require("mongodb");
var MongoClient = require('mongodb').MongoClient
var ObjectID = mongodb.ObjectID;
var assert = require('assert');
//Path to the database with
var dbpath = process.env.MONGODB_URI || 'mongodb://heroku_fmvc5nhk:5rqdhjqc2ovahen7knanjpfmd7#ds019986.mlab.com:19986/heroku_fmvc5nhk';
//Get the section
var SECTIONS_COLLECTION = "sections";
// Use connect method to connect to the server
var database;
function connectMongo(cb){
MongoClient.connect(dbpath , function(err, database) {
assert.equal(null, err);
console.log("Connected successfully to server");
cb(database);
});
}
module.exports = connectMongo;
//routes/index.js
var express = require('express');
var router = express.Router();
var connectDB = require ('../db')
router.get('/', function (req, res) {
res.render(
'index',
{
title: 'Welcome to Awesome Place',
header: 'Home',
summary: 'This is my home. It can\'t be any simpler'
}
)
})
connectMongo(function(database){
//About
router.get('/about', function (req, res) {
//retrieve all home from Mongo
database.collection(SECTIONS_COLLECTION).find({"name": "about"}), function (err, about) {
if (err) {
handleError(res, err.message, "Failed to get sections.");
} else {
res.render('about', {})
console.log(result)
}
}
})
}
router.get('/work', function (req, res) {
res.render(
'work',
{
title: 'Work, Work, Work , Work...',
header: 'Work life',
summary: 'My first work for this bitch',
imgUrl: '/img/firaz.jpg'
}
)
})
router.get('/contact', function (req, res) {
res.render(
'contact',
{
title: 'Contact Me Any Time',
header: 'Contact Me Any Time',
summary: 'Fill the form below to be contacted'
}
)
})
module.exports = router;
Because db variable is not global by requiring var indexRoutes = require('./routes/index'); you are importing the objects from routes/index file to server not the other way around.
what you can do is make your db variable global global.db and access it anywhere or create a seperate file for mongo db connection and require that in routes file
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
// Connection URL
var url = 'mongodb://localhost:27017/database';
// Use connect method to connect to the server
var database;
function connectMongo(cb){
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected successfully to server");
cb(db);
});
}
module.exports = connectMongo;
This github Repo got good structure for mongoDB
https://github.com/OmarElGabry/chat.io