app router in Express - node.js

There currently is a difference between
app.use(function(req,res,next){
});
and
router.use('/some_route', function(req,res,next){
});
...The difference being that app.use runs for every request and router.use only runs for matching routes.
My question is about the router that must lie underneath app. Surely app has some default router internal to it. Is there a way to access that router...app.router? I thought that was deprecated?
Secondly, what I am really looking for is a way to access the current router being used.
For example,
app.use(function(req,res,next){
var currentRouter = req.app._router // (?)
});
or
router.use(function(req,res,next){
var currentRouter = req._router //(?)
});
where req._router would be equal to the same router for the router.use call of course.

In the latest Express code, the default app router is in app._router.
It is created lazily which means it's not created until a route is actually defined (with app.use() or app.get() or something like that).
It does not appear that this is meant to be a public property and thus is subject to change. You can, of course, just define your own router with the root path and only use your own router and then you would not have to access or use this non-public property.
You are correct that app.router is deprecated. Trying to access it purposely throws an exception in the Express code.

Related

What is the difference between "app.get/post/put/delete()" and "router.get/post/put/delete()"? [duplicate]

I'm starting with NodeJS and Express 4, and I'm a bit confused. I been reading the Express website, but can't see when to use a route handler or when to use express.Router.
As I could see, if I want to show a page or something when the user hits /show for example I should use:
var express = require('express')
var app = express()
app.get("/show", someFunction)
At the beginning, I thought this was old (for Express 3). Is that right or this is the way for Express 4 too?
If this is the way to do it in Express 4, what is express.Router used for?
I read almost the same example as above but using express.Router:
var express = require('express');
var router = express.Router();
router.get("/show", someFunction)
So, what's the difference between both examples?
Which one should I use if I just want to do a simple testing website?
app.js
var express = require('express'),
dogs = require('./routes/dogs'),
cats = require('./routes/cats'),
birds = require('./routes/birds');
var app = express();
app.use('/dogs', dogs);
app.use('/cats', cats);
app.use('/birds', birds);
app.listen(3000);
dogs.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('GET handler for /dogs route.');
});
router.post('/', function(req, res) {
res.send('POST handler for /dogs route.');
});
module.exports = router;
When var app = express() is called, an app object is returned. Think of this as the main app.
When var router = express.Router() is called, a slightly different mini app is returned. The idea behind the mini app is that each route in your app can become quite complicated, and you'd benefit from moving all that code into a separate file. Each file's router becomes a mini app, which has a very similar structure to the main app.
In the example above, the code for the /dogs route has been moved into its own file so it doesn't clutter up the main app. The code for /cats and /birds would be structured similarly in their own files. By separating this code into three mini apps, you can work on the logic for each one in isolation, and not worry about how it will affect the other two.
If you have code (middleware) that pertains to all three routes, you can put it in the main app, before the app.use(...) calls. If you have code (middleware) that pertains to just one of those routes, you can put it in the file for that route only.
Express 4.0 comes with the new Router. As mentioned on the site:
The express.Router class can be used to create modular mountable route
handlers. A Router instance is a complete middleware and routing
system; for this reason it is often referred to as a “mini-app”.
There is a good article at https://scotch.io/tutorials/learn-to-use-the-new-router-in-expressjs-4 which describes the differences and what can be done with routers.
To summarize
With routers you can modularize your code more easily. You can use routers as:
Basic Routes: Home, About
Route Middleware to log requests to the console
Route with Parameters
Route Middleware for Parameters to validate specific parameters
Validates a parameter passed to a certain route
Note:
The app.router object, which was removed in Express 4, has made a comeback in Express 5. In the new version, it is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
How they are different
Everyone, including the documentation, tends to refer back to how much they are the same, but not actually reference any differences. Well, they are, in fact, different.
var bigApp = express();
var miniApp = express.Router();
listen()
The most obviously difference is that the bigApp will give listen, which just a rather confusing way to do what would otherwise be simple and obvious the node http or https module:
var server = require('http').createServer(bigApp);
server.listen(8080, function () {
console.info(server.address());
});
I consider this an anti-pattern because it abstracts and obscures away something that wasn't complicated or difficult in the first place, and then makes it difficult for people to use websockets and other middleware that require the raw http server.
Internal State
The big difference, which is really important, is that all bigApps have separate internal state.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var bigApp2 = express();
bigApp2.enabled('trust proxy');
// false
bigApp.use('/bunnies', bigApp2);
// WRONG! '/bunnies' will NOT trust proxies
A miniApp passed to a bigApp, however, will be operated by the bigApp in such a way that its internal state and thisness will be preserved and those routes will behave accordingly.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var miniApp = express.Router();
bigApp.use('/bunnies', miniApp);
// CORRECT! All state and such are preserved
This can be a big deal because express does a lot of (sometimes trixy) things to the http.ServerRequest and httpServerResponse object - such as modifying (or hijacking) req.url and req.originalUrl and various other properties you've been using without realizing - and you probably don't want that duplicated and separated.
Smaller API
There is a smaller, more well-defined number of functions a Router can use:
.use(mount, fn)
.all(mount, fn)
.options(mount, fn)
.head(mount, fn)
.get(mount, fn)
.post(mount, fn)
.patch(mount, fn)
.put(mount, fn)
.delete(mount, fn)
.route(mount).XXXX
.param(name, cb).XXXX
There are a few other convenience methods as well, such as basic(), but you won't find set() or enable() or other methods that change the larger app state.
app.route('/book')
.get(function (req, res) {
res.send('Get a random book')
})
.post(function (req, res) {
res.send('Post a random book')
})
As in above example, we can add different HTTP request method under a route.
Let’s say your application is little complex. So what we do first is we divide the application into multiple modules so that changes in one module doesn't clutter the others and you can keep working on individual modules, but at the end of the day you need to integrate everything into one since you are building a single application. It is like we have one main application and few child applications whose parent is the main application.
So when we create the parent application we create one using
const express = require("express");
const parent = express();
And to this parent application we need to bring in the child applications. But since the child applications are not totally different applications (since they run in the same context - java term), express provides the way to do it by means on the Express's Router function and this is what we do in the each child module file and lets call one such child module as aboutme.
const express = require("express");
export const router = express.Router();
By export we are making this module available for other to consume and since we have modularized things we need to make the module files available to the parent application by means of node's require function just like any other third party modules and the parent file looks something like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
After we make this child module available to the parent, we need to tell the parent application when to use this child application. Lets say when a user hits the path aboutme we need the child application about me to handle the request and we do it by using the Express's use method:
parent.use("/aboutme", child);
and in one shot the parent file looks like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
parent.use("/aboutme", child);
Above all what the parent can do is it can start a server where as the child cannot. Hope this clarifies. For more information you can always look at the source code which takes some time but it gives you a lot of information.
using app.js to write routes means that they are accessible to all the users as app.js is loaded on application start. However, putting routes in express.router() mini apps protect and restrict their accessibility.
In a word , express.Routercan do more things when compares to app.get(),such as middleware, moreover, you can define one more router object with express.Router()
express.Router has many options:
enable case sensitivity: /show route to not be the same as /Show, this behavior is disabled by default
strict routing mode: /show/ route to not the same as /show, this behavior is also disabled by default
we can add specific middleware/s to specific routes
In one of the questions in the quiz this was asked: "express.Router() creates an object that behaves similar to the app object."
The correct answer is 'True'. I know that we can both create routers by using either of the two but is it safe to say that they are not the same in all cases? If my understanding is correct, the express() variable can do more things like start a server while the other one cannot.
In a complicated application, app is module, for example article and user. router is controller or action in module, for example article create and list.
E.g the url https://example.com/article/create parse article module and create router.
also app and router can be level-in-level.

Problem using Nodejs / Express routing paths

I am a long time programmer but I'm new to Node and have a simple question about routing paths in Express which I cannot get to the bottom of.
I've developed a very simple app using node/express and MySql. I have then split up my GET and POST routes in the app just for convenience. I am using the route '/posts' at the app level and the sub route '/submit-form' in my router() which is the URL my form submits to.
I'm obviously doing something stupid because it doesn't work, I get the cannot POST message. If I use the full URL in the app and in the router then it works fine so there's nothing wrong with the code I think, only with my understanding of how express does routing.
Any advice appreciated.
A router should be used with the .use() method. Therefore, you should use the following in your app.js file
app.use('/posts', PostRoute)
When the nested router (on /posts) will handle the request, it will now based on the nested route declaration which HTTP method should match
app.js
const app = express();
app.use('/user', require('./routes/user'))
then inside the user;
const router = express.Router({});
router.post('/login', (req,res,next) => {
});
module.exports = router;

How to serve user specific static content in Express.js

I want to serve user-specific static content in Express. That means, if a user is logged in, his private static folder is served by express. Other users shall not have access.
I tried the following (see below), but the static content is not being served. In fact, the route seems to be completely ignored and I get a 404.
I am not sure if the way I do it is the right way to go and if express is capable of dynamically serving different static folders. Thanks in advance for your thoughts on this.
Here's the code (simplified):
routes.js:
express = require 'express'
router = express.Router()
router.use '/user/assets', (req, res, next) ->
if req.user
userpath = 'uploads/' + md5(req.user._id)
if not fs.existsSync userpath
fs.mkdirSync userpath
console.log "Created user directory at " + userpath
express.static(userpath)
next()
module.exports = router
index.js:
express = require 'express'
app = express()
app.use '/', require './routes'
Sidenotes:
The md5 is just a way of escaping weird characters in the user id, which is a string. I know there is a possibility for a mismatch, which is tiny, and about which I don't wanna care for now. Concerns about general security of the fashion of the solving attempt are appreciated.
The code is written in CoffeeScript.
req.user contains a valid user element.
Just calling express.static is not enough, you need to use() it with the router. Unfortunately you can't directly do that, since you require a different set of routes for each user.
Calling express.static will return a middleware function. You could call it directly, i.e. something like this:
var files = express.static(userpath);
return files(req, res, next);
However that's still not enough, as the middleware uses req.url to build the file path. The express router adjusts this property and removes the mount point (see req.originalUrl in the docs). So you need to strip /user/assets from it, before calling the middleware.
By the way, you should set the DEBUG environment variable for node. It allows you to see what routes are created by express, which is very handy in debugging express.static 404 problems. E.g. you'd do $ DEBUG=* node index.js on Linux.
As you can see the approach starts to be a bit hacky and creating a new express.static middleware on each request is not very performance friendly too. So depending on what your user directories contain, using res.sendFile might actually be better.
As a sidenote, I assume you've checked that req.user actually contains something if the user is logged in.

Differences between express.Router and app.get?

I'm starting with NodeJS and Express 4, and I'm a bit confused. I been reading the Express website, but can't see when to use a route handler or when to use express.Router.
As I could see, if I want to show a page or something when the user hits /show for example I should use:
var express = require('express')
var app = express()
app.get("/show", someFunction)
At the beginning, I thought this was old (for Express 3). Is that right or this is the way for Express 4 too?
If this is the way to do it in Express 4, what is express.Router used for?
I read almost the same example as above but using express.Router:
var express = require('express');
var router = express.Router();
router.get("/show", someFunction)
So, what's the difference between both examples?
Which one should I use if I just want to do a simple testing website?
app.js
var express = require('express'),
dogs = require('./routes/dogs'),
cats = require('./routes/cats'),
birds = require('./routes/birds');
var app = express();
app.use('/dogs', dogs);
app.use('/cats', cats);
app.use('/birds', birds);
app.listen(3000);
dogs.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('GET handler for /dogs route.');
});
router.post('/', function(req, res) {
res.send('POST handler for /dogs route.');
});
module.exports = router;
When var app = express() is called, an app object is returned. Think of this as the main app.
When var router = express.Router() is called, a slightly different mini app is returned. The idea behind the mini app is that each route in your app can become quite complicated, and you'd benefit from moving all that code into a separate file. Each file's router becomes a mini app, which has a very similar structure to the main app.
In the example above, the code for the /dogs route has been moved into its own file so it doesn't clutter up the main app. The code for /cats and /birds would be structured similarly in their own files. By separating this code into three mini apps, you can work on the logic for each one in isolation, and not worry about how it will affect the other two.
If you have code (middleware) that pertains to all three routes, you can put it in the main app, before the app.use(...) calls. If you have code (middleware) that pertains to just one of those routes, you can put it in the file for that route only.
Express 4.0 comes with the new Router. As mentioned on the site:
The express.Router class can be used to create modular mountable route
handlers. A Router instance is a complete middleware and routing
system; for this reason it is often referred to as a “mini-app”.
There is a good article at https://scotch.io/tutorials/learn-to-use-the-new-router-in-expressjs-4 which describes the differences and what can be done with routers.
To summarize
With routers you can modularize your code more easily. You can use routers as:
Basic Routes: Home, About
Route Middleware to log requests to the console
Route with Parameters
Route Middleware for Parameters to validate specific parameters
Validates a parameter passed to a certain route
Note:
The app.router object, which was removed in Express 4, has made a comeback in Express 5. In the new version, it is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
How they are different
Everyone, including the documentation, tends to refer back to how much they are the same, but not actually reference any differences. Well, they are, in fact, different.
var bigApp = express();
var miniApp = express.Router();
listen()
The most obviously difference is that the bigApp will give listen, which just a rather confusing way to do what would otherwise be simple and obvious the node http or https module:
var server = require('http').createServer(bigApp);
server.listen(8080, function () {
console.info(server.address());
});
I consider this an anti-pattern because it abstracts and obscures away something that wasn't complicated or difficult in the first place, and then makes it difficult for people to use websockets and other middleware that require the raw http server.
Internal State
The big difference, which is really important, is that all bigApps have separate internal state.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var bigApp2 = express();
bigApp2.enabled('trust proxy');
// false
bigApp.use('/bunnies', bigApp2);
// WRONG! '/bunnies' will NOT trust proxies
A miniApp passed to a bigApp, however, will be operated by the bigApp in such a way that its internal state and thisness will be preserved and those routes will behave accordingly.
bigApp.enable('trust proxy');
bigApp.enabled('trust proxy');
// true
var miniApp = express.Router();
bigApp.use('/bunnies', miniApp);
// CORRECT! All state and such are preserved
This can be a big deal because express does a lot of (sometimes trixy) things to the http.ServerRequest and httpServerResponse object - such as modifying (or hijacking) req.url and req.originalUrl and various other properties you've been using without realizing - and you probably don't want that duplicated and separated.
Smaller API
There is a smaller, more well-defined number of functions a Router can use:
.use(mount, fn)
.all(mount, fn)
.options(mount, fn)
.head(mount, fn)
.get(mount, fn)
.post(mount, fn)
.patch(mount, fn)
.put(mount, fn)
.delete(mount, fn)
.route(mount).XXXX
.param(name, cb).XXXX
There are a few other convenience methods as well, such as basic(), but you won't find set() or enable() or other methods that change the larger app state.
app.route('/book')
.get(function (req, res) {
res.send('Get a random book')
})
.post(function (req, res) {
res.send('Post a random book')
})
As in above example, we can add different HTTP request method under a route.
Let’s say your application is little complex. So what we do first is we divide the application into multiple modules so that changes in one module doesn't clutter the others and you can keep working on individual modules, but at the end of the day you need to integrate everything into one since you are building a single application. It is like we have one main application and few child applications whose parent is the main application.
So when we create the parent application we create one using
const express = require("express");
const parent = express();
And to this parent application we need to bring in the child applications. But since the child applications are not totally different applications (since they run in the same context - java term), express provides the way to do it by means on the Express's Router function and this is what we do in the each child module file and lets call one such child module as aboutme.
const express = require("express");
export const router = express.Router();
By export we are making this module available for other to consume and since we have modularized things we need to make the module files available to the parent application by means of node's require function just like any other third party modules and the parent file looks something like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
After we make this child module available to the parent, we need to tell the parent application when to use this child application. Lets say when a user hits the path aboutme we need the child application about me to handle the request and we do it by using the Express's use method:
parent.use("/aboutme", child);
and in one shot the parent file looks like this:
const express = require("express");
const parent = express();
const child = require("./aboutme");
parent.use("/aboutme", child);
Above all what the parent can do is it can start a server where as the child cannot. Hope this clarifies. For more information you can always look at the source code which takes some time but it gives you a lot of information.
using app.js to write routes means that they are accessible to all the users as app.js is loaded on application start. However, putting routes in express.router() mini apps protect and restrict their accessibility.
In a word , express.Routercan do more things when compares to app.get(),such as middleware, moreover, you can define one more router object with express.Router()
express.Router has many options:
enable case sensitivity: /show route to not be the same as /Show, this behavior is disabled by default
strict routing mode: /show/ route to not the same as /show, this behavior is also disabled by default
we can add specific middleware/s to specific routes
In one of the questions in the quiz this was asked: "express.Router() creates an object that behaves similar to the app object."
The correct answer is 'True'. I know that we can both create routers by using either of the two but is it safe to say that they are not the same in all cases? If my understanding is correct, the express() variable can do more things like start a server while the other one cannot.
In a complicated application, app is module, for example article and user. router is controller or action in module, for example article create and list.
E.g the url https://example.com/article/create parse article module and create router.
also app and router can be level-in-level.

Difference Between app.use() and router.use() in Express

I was just reading the documentation on express and found these two terms, app.use(); and router.use();
I know app.use(); is used in node for Mounting a middleware at a path, and we often use it in most of the node apps. but what is router.use(); are they both same? if not, whats the difference ?
I read about router here. I also found similar questions on SO What is the difference between "express.Router" and routing using "app.get"?
and Difference between app.all('*') and app.use('/'), but they do not really answer my question. Thanks.
router.get is only for defining subpaths. Consider this example:
var router = express.Router();
app.use('/first', router); // Mount the router as middleware at path /first
router.get('/sud', smaller);
router.get('/user', bigger);
If you open /first/sud, then the smaller function will get called.
If you open /first/user, then the bigger function will get called.
In short, app.use('/first', router) mounts the middleware at path /first, then router.get sets the subpath accordingly.
But if we instead use the following:
app.use('/first', fun);
app.get('/sud', bigger);
app.get('/user', smaller);
If you open /first in your browser, fun will get called,
For /sud, bigger will get called
For /user, smaller will get called
But remember for /first/sud, no function will get called.
This link may also help: http://expressjs.com/api.html#router
router.use(); mounts middleware for the routes served by the specific router, app.use(); mounts middleware for all routes of the app (or those matching the routes specified if you use app.use('/ANYROUTESHERE', yourMiddleware());).
Example use case could be an app with one router with standard routes and one router that handles api routes, which need a valid user.
You would then mount the authentication middleware for the api router only with router.use(yourAuthMiddleware());.
If you would have an app though that requires a valid user for all routes, mount the middleware for the app with app.use(yourAuthMiddleware());
app.use() used to Mounts the middleware function or functions at the specified path,the middleware function is executed when the base of the requested path matches path.
router.use() is used to middleware function or functions, The defaults mount path to “/”.
But in
app.use() you will have to give a specified path like that:
var adsRouter = require('./adsRouter.js');
app.use('/ads', adsRouter);
or
app.use('/ads', function(req, res, next) {
// write your callback code here.
});
But while using router.use() you can give only middleware, like this:
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
});
or
router.use('/test', function(req, res, next) {
// write your callback code here.
next();
});
or
//in router.js
router.use('/admin', authUtil.verifySessionId, authUtil.verifyLisencee);
router.post('/admin', controllerIndex.ads.adListingAdmin);
In the above code when the end point is '/admin' then first it will call the authUtil.verifySessionId and authUtil.verifyLisencee then it will execute next line with 'admin' end point and according to controllerIndex.ads.adListingAdmin method.
app.use(middleware): application-level middleware.
router.use(middleware): router-level middleware.
("middleware" refers to methods/functions/operations that are called between processing the request and sending the response.)
See https://expressjs.com/en/guide/using-middleware.html for a comparison of different types of middleware used in an Express app.
When looking at the express js docs for Routing (https://expressjs.com/en/guide/routing.html#express-router):
Use the express.Router class to create modular, mountable route handlers. A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.
A Router created with express.Router() is no different than an app created with express() in terms of functionality; it's like a logical grouping of routes/handlers/services/databases/etc. The biggest difference is the scope that it affects. A router just affects its own scope while the app is like the master/global scope for your web/app server. You could have many routers or "apps" running on one main app/web server instance. This is why you could listen to requests on an app instance via app.listen(80) but not on a router.

Resources