router vs app in express 4.0 - express

I am learning express js 4.0 and building compact CRUD REST API web application with it. In the tutorial, it shows two ways; using app and using router.
//using router
var router = express.Router();
router.get('/', function(req,res){
res.send('hello, world')
});
//using app
app.get('/', function(req,res){
res.send('hello, world')
});
To me, I feel they work same but I don't know why people use router, I think using app is more simple. Can anybody explain what is difference between them?

It allows for modularity. A lot of people have a routes folder that they keep all their route handlers in. And then in their app.js file, they just do something like app.use(<prefix>, <routes>); after they require their router. It keeps your files smaller and more organized.
Example:
app.js
var express = require('express');
var rootRoutes = require('./routes/index');
var userRoutes = require('./routes/user');
var app = express();
app.use('/', rootRoutes);
app.use('/user', userRoutes);
module.exports = app;
routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index.jade');
});
router.get('/about', function(req, res) {
res.render('about.jade');
});
module.exports = router;
routes/user.js
var express = require('express');
var router = express.Router();
router.get('/:name', function(req, res) {
var userName = req.params.name;
res.render('user.jade', {
userName: userName
});
});
module.exports = router;

Related

express routes not working - returning 404 error

I'm trying to set up a simple express project, and backend will be purely for api and frontend will be vue. I tried adding an api router, and not only does it not work, but even the root page doesn't work. I've not coded in express for a very long time, and wondering if some one could guide me on what's the problem? The error message is 404 NotFoundError: Not Found.
I'm navigating to localhost:3000, and I can see the call on the terminal, so port should be correct too?
/src/api/urls.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('Just a test');
});
module.exports = router;
I didn't change the folder structure/naming for the original routes/index.js.
/src/routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('Just a test');
});
module.exports = router;
And for the main file
/src/app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var apiRouter = require('./api/urls');
var app = express();
app.use(require('connect-history-api-fallback')());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/api', apiRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
All good except endpoint url that should be with middleware function only. Modifying these should work,
/src/api/urls.js
var express = require('express');
var router = express.Router();
router.get('/api/test', function(req, res) {
res.send('Just a test');
});
module.exports = router;
/src/routes/index.js
var express = require('express');
var router = express.Router();
router.get('/api/test2', function(req, res) {
res.send('Just a test');
});
module.exports = router;
In app.js you should register your routes as,
// Routes
app.use([
require('./src/api/urls'),
require('./src/routes/index'),
]);
Access by url ( http://<yourhost>/api/test1 )

how to properly split express routes into separate files?

I have read through posts about this issue but I just can't figure out what I am doing wrong.
What I would like is to separate each of my route (login and register for now) into their own separate file, reference those files in routes/user/index, then use that in server.js. This is what I have now:
server.js
ROUTES
USER
index.js
LOGIN
index.js
REGISTER
index.js
server.js
const express = require("express");
const app = express();
(...)
app.use("/user", require("./routes/user"));
(...)
routes/user/index.js
const express = require("express");
const router = express.Router();
router.use("/login", require("./login"));
router.use("/register", require("./register"));
module.exports = router;
routes/user/login/index.js
const express = require("express");
const router = express.Router();
router.post("/login", async (request, response) => {
(...)
});
module.exports = router;
routes/user/register/index.js
const express = require("express");
const router = express.Router();
router.post("/register", async (request, response) => {
(...)
});
module.exports = router;
All I get is a 404 error. Any help would be appreciated.
Thanks!
You can create chainable route handlers for a route path by using app.route()
const express = require("express");
const router = express.Router();
router.route("/login").post((request, response) => {
//Your code goes here
});
module.exports = router;
OK, after a few more hours of googling & trial/error I finally figured it out. For some reason I didn't find earlier this setup guide but it was pretty much what I wanted.

expressjs req.body is empty

Banging my head on this. in Express app, my get request works fine. However attempting to POST results passes an empty req.body.
here is my file tree:
index.js:
const express = require('express');
const apiRoute = require('./routes/api/index.js');
const bodyParser = require('body-parser');
// const morgan = require('morgan');
const app = express();
app.use(function(req, res, next) {
if (req.headers['content-type'] === 'application/json;') {
req.headers['content-type'] = 'application/json';
}
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use('/api', apiRoute);
app.listen(3000);
routes/api/index.js
const express = require('express');
const router = express.Router();
const entityRoute = require('./entity');
router.use('/entity', entityRoute);
module.exports = router;
routes/api/entity.js:
const express = require('express');
const router = express.Router();
const db = require('../../database');
router.get('/', function(req, res) {
db.select().from('entity').then(function(data) {
res.send(data);
});
});
router.post('/', function(req, res) {
console.log(req.body);
res.send(req.body);
});
module.exports = router;
Adding my Postman request in response to comment:
I have been over this numerous times, checked body-parser docs and other SO answers and can't figure this out.
following the comments, submitting json body works. screenshot below:
Not sure why this doesnt work the other way...

Mean Stack Root Routing is not working

Can someone help me why default route is not working in my Mean App, But the next routing works
Here when I open http://localhost:3000 I am not able to see any output, But I have defined route in route.js which is working
var express = require('express');
var cors = require('cors');
var bodyparser = require('body-parser');
var mongoose = require('mongoose');
var path = require('path');
const port = 3000;
app.get('/', function (req, res) {
res.send('Test');
console.log('Opened the root path');
});
When I open the page with http://localhost:3000/main I am able to see the Output and also log written in the console
const express = require('express');
const router = express.Router();
router.get('/main', function (req, res, next) {
res.send('This is the Admin Landing Page');
});
router.get('/install', function (req, res, next) {
res.send('This is the Install Landing Page');
console.log('Opened the Install path');
});
module.exports = router;
It looks like you the code you pasted is the full version, and it's not runnable because:
You did not declare app variable.
You did not start the http server.
It's really hard to tell the root cause what's wrong of your code. Following codes works for me:
const express = require('express');
const port = 3000;
let app = express();
app.get('/', function (req, res) {
res.send('Test');
console.log('Opened the root path');
});
let server = require('http').createServer(app);
server.listen(port, function() {
console.log('Server started');
});

express.js 4 and sockets with express router

I'm trying to create a really simple node API using express.js 4 but I need a few 'realtime' events for which I added socket.io. I'm fairly new to both so I'm likely missing something basic but I can't find good docs/tuts on this.
In the express app (created with the express generator) I have something like this based on simple examples and project docs that I read. This works OK and from client apps, I can send/receive the socket events:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// error handlers omitted
module.exports = app;
but I want to use the sockets from my API routes (in the ./routes/api.js file that I 'require' above). For example, someone might use the API to PUT/POST a resource and I want that broadcast to connected socket.io clients.
I cannot see how to use the 'io' variable or organise the code currently in the io.sockets.on('connection' ... function inside express routes. Here's the ./routes/api.js file:
var express = require('express');
var router = express.Router();
var io = ???;
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
io.sockets.emit('update', foo); // how?
});
module.exports = router;
One option is to pass it in to req object.
app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// Make io accessible to our router
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/api', api);
// error handlers omitted
module.exports = app;
./routes/api.js:
var express = require('express');
var router = express.Router();
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
req.io.sockets.emit('update', foo);
});
module.exports = router;
I've modified your files a little bit, may you check if it works?
You can pass the io you've defined to your routes like below;
require('./routes/api')(app,io);
I didn't test the Socket.IO parts but there is no syntax error and routes also working.
server.js file:
var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
require('./routes/api')(app,io);
console.log("Server listening at port 3000");
api.js:
module.exports = function(app,io) {
app.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
console.log("PUT OK!");
io.sockets.emit('update'); // how?
res.json({result: "update sent over IO"});
});
}
Supposing you want to access the SocketIO from anywhere in your application, not just in the router, you could create a singleton for it. This is what works for me:
//socket-singletion.js
var socket = require('socket.io');
var SocketSingleton = (function() {
this.io = null;
this.configure = function(server) {
this.io = socket(server);
}
return this;
})();
module.exports = SocketSingleton;
Then, you need to configure it using your server:
//server config file
var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');
Finally, use it wherever you want:
//router/index.js
var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');
/* GET home page. */
router.get('/', function(req, res, next) {
setTimeout(function(){
SocketSingleton.io.emit('news', {msg: 'success!'});
}, 3000);
res.render('index', { title: 'Express' });
});
module.exports = router;
One more option is to use req.app.
app.js
const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');
const app = express();
const io = require('socket.io').listen(app.listen(3000));
// Keep the io instance
app.io = io;
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
// ...
app.use('/api', api);
module.exports = app;
routes/api.js
const express = require('express');
const router = express.Router();
router.put('/foo', function(req, res) {
/*
* API
*/
// Broadcast the updated foo..
req.app.io.sockets.emit('update', foo);
});
module.exports = router;
Refactored Edudjr's answer.
Change the singleton to create a new instance of socket.io server
const { Server } = require('socket.io');
const singleton = (() => {
this.configure = (server) => this.io = new Server(server)
return this
})();
module.exports = singleton
Initialise your express app, the server and the singleton.
// initialise app
const app = express();
const server = require('http').createServer(app);
// configure socket.io
socket.configure(server)
Then in your router
const socket = require('/utils/socket-singleton');
socket.io.emit('event', {message: 'your message here'})
I think best way is to set io as a property of req, like below:
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/your-sub-link', your-router);