Overwrite the Express router - node.js

I wanted to create MVC based architecture on the express for that I want to overwrite the Express Router.
Consider following as an example:
// usual express router
var userRouter = require('express').Router();
userRouter.get("/",function(req, res, next){
//.....
});
userRouter.post("/",function(req, res, next){
//.....
});
app.use('/users', userRouter);
//routes.js
module.exports = function(app){
var userRouter = app.Router();
userRouter.get('/', {controller: 'User', action: 'show'});
userRouter.post('/', {controller: 'User', action: 'new'});
app.use('/users', userRouter);
};
So, do I have to implement router again like the express with my controller parsing functionality?

Rewriting already existing functionality is commonly accepted as bad practice. Express has the option to modify data via middleware services.
If neither the native router, nor the middleware functionality works for you, then maybe you should go and change the framework to Hapi.
I judge my own short experience, Hapi provides better accommodation for routing and server magic.

Related

Confusion with app.use with Router() in express

I was learning Express in Node.js and came across Router() allowing us to modularize our routes. But than I found this code:
// we'll create our routes here
// get an instance of router
var router = express.Router();
...
// route with parameters (http://localhost:8080/hello/:name)
router.get('/hello/:name', function(req, res) {
res.send('hello ' + req.params.name + '!');
});
// apply the routes to our application
app.use('/', router);
What confused me is that why we need to use app.use('/', router); to apply the routes. That is, what if we use app.get('/', router);
I am giving you a simple code example to make you understand the use of express.Router(). Yes you are right that it helps in modularization. Actually it makes our main app.js file clean from all the routes. We just put all those routes based on their purposes in different files and require them when needed.
so suppose I have two files app.js and register.js
// app.js file's code goes here
let express = require("express")
let app = express()
let register = require("./routes/register")
app.use(register) // This will tell your app to import all those routes which are in register
// register.js file's code goes here
let express = require("express")
let router = express.Router()
router.get("/register", callback_function);
router.post("/register", callback_function);
module.exports = router;
So basically what I am trying to show is your register.js can contain all types of HTTP requests(GET, POST, PUT,...) and when we use app.use(register) this will handle all those routes. app.get("route_path", callback_function) is only for handling get requests to that path.
Router is just a middleware of it's own. If you use app.get('/', router) you will use the router just for GET requests. Using use channels all requests there.
When app.use is used then it handled all the HTTP methods, but when app.get is used it takes just GET method.
Added advantage to app.use is that route will match any path that follows its path immediately with a /.
For example:
app.use('/v1', ...)
will match /users, /users/accounts, /users/accounts/account-id, and so on.

Difference between app.get() or router.get() - ExpressJs

What is the difference between:
var express = new express();
var app = new express();
app.get("/", function() {
.....
})
And:
var express = new express();
var router= express.Router();
router.get("/", function() {
.....
})
app.get can be used to create routes for your application at the top level.
From the documentation about 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 needs to be mounted to an app:
const router = express.Router();
router.get("/", (res, req) => res.end());
router.post("/", (res, req) => res.end());
app.use("/empty", router);
This allows you to more easily encapsulate the functionality of several routes into an app which will be namespaced under a particular route.
When express() is called in app.js, an app object is returned. Think of an app object as an Express application.
When express.Router() is called, a slightly different "mini app" is
returned. The idea behind the "mini app" is that different routes in
your app can become quite complicated, and you'd benefit from moving
that logic into a separate file.
Check this SO Thread for details.

Express JS Router Middleware Abstraction

I have developed an API using Node.js + Express JS and i use token-based authentication.
I used two differents routers in this api, userRoute (/USER) and postRoute (/POST). The postRoute can be used within authentication but userRoute needs the token.
To solve that i use a router middleware for userRoute but it interferes with portRoute
This is the code:
...
var postRoute = express.Router();
var userRoute = express.Router();
// Route middleware to verify a token
userRoute.use(function(req, res, next) {
security.checkToken(req,res, next);
});
userRoute.route('/users')
.get(userCtrl.findAllUsers)
.post(userCtrl.addUser);
postRoute.route('/posts')
.get(userCtrl.findAllPosts)
.post(userCtrl.addPost);
app.use(userRoute);
app.use(postRoute);
...
If i try to access '/posts' the servers checks the token and does not let me in. I know if i change the order of app.use it works, but i dont understand why works in this way if i am using "Router Middleware".
Someone knows?
This happens because if the express router implementation, you will be able to understand it quite easily if you have a look at it. Here is the path: node_modules/express/lib/router/index.js. Every time that you call the Router(), like in your case
var postRoute = express.Router();
var userRoute = express.Router();
this function will be invoked:
var proto = module.exports = function(options) { ... }
and it is true that there is a different router instance that is being returned every time. The difference is in the way that the use is registering the middlewares. As you see the use it is registered against the proto.use
proto.use = function use(fn) { ... }
this means that the middleware that you register there they will be registered for every instance of the router that you define.

Nodejs have an optional extra path in URL

I'm developing part of a system where we have two applications sharing the same domain so nginx makes exampleurl.com go to one application and example.com/admin/* go to the second.
The /admin/* part is going to a NodeJs app using express.
Is there an elegant way of making sure that node can add in the /admin without having to do
app.get('/admin/endpoint', ...)
?
you can use http://expressjs.com/fr/api.html#router
var router = express.Router();
router.get('/', function(req, res) {
res.send('One page in admin website');
});
// router.get('/adminWebsite'); // idem for all routes(you always use this router)
app.use('/admin', router);
you would would to use routers (preferably) but you can also create another express app. using different Apps allow you to have more global middlewear control whereas using different routes mean that they share the same express instance.
var express = require('express');
var admin = express(); // <- this is now your admin application
var app = express(); // <- this is your main applicaiton regular users
//you will need to set up middlewear like body-parser and stuff for both of them now
//but it allows you to use different logging and authentication system or w.e you
//want
//once everything is done you can 'MOUNT' virtually the admin app to the regular app
app.use('/admin', admin); //<- this will nest apps together but allow the sub-app admin
//to be it's own instance.
//app.js
const admin = require('admin'); //you admin module (where you routes wiil be)
app.use('/admin', [functions... example authCheck], admin);
//index file of admin module
`var express = require('express');
var router = express.Router();
router.use(function authCheck(req, res, next) {
//check if user is logged
});
router.get('/main', require('./main').get);
module.exports = router;`
//main.js
`exports.get = function(req, res, next){
res.render('admin/admin', {
title: "Main panel"
});
};`
and now you can access site.com/admin/main

How can I still use a router in node express and still have a wildcard and params?

So basically I want my code being able to go mywebsite.com/username and itll take them to their profile.
My app.js has -
var user = require('./routes/user');
app.use('/*', user);
and then in my user.js I have
router.get('/:username', function(req, res) {
console.log('the user name', req.params.username);
})
If I change router.get to just router.get('/') my console.log logs out undefined and if I leave it as router.get('/:username') I get a 404.. I also tried doing app.use('/:username', user) as well but that still didn't work.
You should't need to have a wildcard like you do on app.use
Try something like this.
Also see the express router documentation http://expressjs.com/en/guide/routing.html
// Required Moduiles
var express = require('express');
var router = express.Router();
var app = express();
// Add route to get
router.get('/:username', function(req, res) {
res.status(200).send(req.params.username)
})
// Add username
app.use('/', router)
// Start express server
app.listen(3030);
Update -
Just using app.use(router) would do the same thing if all your routes are going to be contained in this new router instance / middleware you are creating in a separate file.

Resources