I believe in express 4.0 this is the way for creating router-level middleware, is this a good approach creating multiple instance of express.Router?
var userRouter = express.Router();
var paymentRouter = express.Router();
userRouter.get("/login", function (req, res, next) {
res.send("okay this is route")
});
paymentRouter.get("/pay", function (req, res, next) {
res.send("okay this is route")
});
app.use("/user" ,userRouter);
app.use("/payment" ,paymentRouter);
Separate routers can be used to modularize your application.
In your case, it looks like you have (at least) two distinct parts of an API or web app, a user part and a payment part:
app.use("/user", userRouter);
app.use("/payment", paymentRouter);
It's perfectly reasonable to use two separate routers for this.
Usually, each router is modularized even further by placing them in separate modules, that contain the specifics for that router:
app.use("/user", require('./routers/user'));
app.use("/payment", require('./routers/payment'));
So you get a nice separation of concern.
The Express documentation also touches on this topic here.
Really depends on what you want to achieve.
The normal way is to have just one router that is used to define your routes.
Please explain better why you would like to have more routers.
Related
I'm trying to set up routes for my backend. I have two ways that I've tried setting these routes up, and I'm wondering which way fits best practices (or neither?). The differences are minimal, but I'd love to know if there is an objective "best" here.
Here are my attempts:
const express = require("express");
const router = express.Router();
const flashcardController = require('../controllers/flashcardController');
router.get('/', flashcardController.readFlashcard);
router.post('/', flashcardController.createFlashcard);
router.patch('/', flashcardController.updateFlashcard);
router.delete('/', flashcardController.deleteFlashcard);
module.exports = router
VS
const express = require("express");
const router = express.Router();
const flashcardController = require('../controllers/flashcardController');
module.exports = (app) => {
router.get('/api/flashcard', flashcardController.readFlashcard);
router.post('/api/flashcard', flashcardController.createFlashcard);
router.patch('/api/flashcard', flashcardController.updateFlashcard);
router.delete('/api/flashcard', flashcardController.deleteFlashcard);
app.use('/', router);
};
Of course, my app.js (entry-point for my backend) file will need to be coded slightly differently for each of these options.
If you believe that the job of a router is to just handle some requests that it receives and it is the job of the calling code to place the router at whatever path the calling code wants it to operate on, then only your first option will do that. This would allow a caller to use these routes in whatever path it wants.
If you want the module that implements the routes to be entirely self-sufficient and install the routes on the path it wants them to be on, then only the second option does that.
I would say that the "usual" and more "flexible" scheme is the first one where the caller places the routes on the path where it wants them. But, you are free to choose whichever style you want.
The second option is not implemented particularly efficiently so it could be improved. No router is needed at all as the routes can be just installed directly on the app object directly. And, repeating /api/flashcard multiple times can be avoided.
For example, the second option could be this:
const controller = require('../controllers/flashcardController');
const routePath = '/api/flashcard';
module.exports = (app) => {
app.get(routePath, controller.readFlashcard);
app.post(routePath, controller.createFlashcard);
app.patch(routePath, controller.updateFlashcard);
app.delete(routePath, controller.deleteFlashcard);
};
Or, even just this:
const controller = require('../controllers/flashcardController');
module.exports = (app) => {
app.route('/api/flashcard')
.get(controller.readFlashcard)
.post(controller.createFlashcard)
.patch(controller.updateFlashcard)
.delete(controller.deleteFlashcard);
};
And, the first one could be simplified to this:
const router = require("express").Router();
const controller = require('../controllers/flashcardController');
router.route('/')
.get(controller.readFlashcard)
.post(controller.createFlashcard)
.patch(controller.updateFlashcard)
.delete(controller.deleteFlashcard);
module.exports = router
As we know, Express is not very good in handling async functions, in particular for the error handling.
I did define an asyncMiddleware as follows:
const asyncMiddleware = fn => (req, res, next) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
And then:
router.get('/', asyncMiddleware(myRouteHandler))
Is there a way to properly rewrite the middleware in order to make it usable directly by the Express router?
router.use(asyncMiddleware)
Koa supports promises natively, it's expected that Express 5 will do this as well.
Is there a way to properly rewrite the middleware in order to make it usable directly by the Express router?
There is no way. In order to do that, Express app and router (express.Router and express.Route classes) methods that use middlewares and route handlers should be monkey-patched to do what asyncMiddleware does.
Otherwise promise-based middlewares should be manually wrapped with a helper like asyncMiddleware.
So I try to make a full stack project. It has controllers like signup, login, profile etc.
What I do is I require each controller manually, then use them according to the request. For example, I will have
app.use('/signup',signup);
app.use('/login',login);
app.use('/profile',profile);
However, when I build up the complexity of the project,more controllers will be needed, but manually typing everything is not the best practice.
I want to have a more general form, just one line does all the work:
app.use('whatever the link i got',load the corresponding controller);
Maybe the solution will be in different form. How can I achieve this? I need some suggestions.
The simplest solution would probably be to put them all in a controllers directory and then just do this:
const controllers = readdirSync(path.join(__dirname, 'controllers'))
controllers.forEach(controller => {
app.use(`/${controller}`, require(`./controllers/${controller}`))
})
This works great, as long as your routes and controllers are named the same thing. If you need to deal with converting kebab to camel case, there's always lodash.
Assuming you're using express 4, you could take this one step further, and put an index.js in the controllers directory. Inside:
const express = require('express')
const router = express.Router()
const controllers = readdirSync(__dirname))
.filter(f => f !== 'index.js'))
controllers.forEach(controller => {
router.use(`/${controller}`, require(`./${controller}`))
})
module.exports = router
Then you can just use the router like this:
app.use('/', require('./controllers'))
I am building a webapp in the form of a network of sorts with basic CRUD actions. I am in the process of splitting up my router files as they are becoming rather large.
I have an 'actions' route which does things such as selecting an in individual post to view, voting on a post, viewing a profile and commending a user. I cannot seem to find a way to allow me to split these 'action' routes into a seperate file and then use them as needed in the main route.
//index.js file in routes folder
var express = require('express');
var router = express.Router();
//main route
router.route('/feed')
.get(function(req, res, next){
//some code here
}
//actions.js file in routes folder
var express = require('express');
var router = express.Router();
//vote route
router.route('/vote/:id')
.post(function(req, res, next){
//some code here
}
//item route
router.route('/item/:id')
.get(function(req, res, next){
//some code here
}
I'd like to be able to use the action routes inside of the feed routes (and other routes) So I can do things like
POST /feed/vote/postid12356
GET /feed/item/itemid123456
or even in another route called 'private-feed' using the same actions from the actions route
POST /private-feed/vote/postid12356
GET /private-feed/item/itemid123456
Without having to have these actions repeated in many routes.
Is there any way in express that this can be done?
You can extract your route handler into a separate file, let's call them controllers and then reuse the logic in some of the routes:
//controllers/action.js
module.exports = {
get: (req, res, next) => {
//your post logic
}
}
///routes/item.js
const ActionController = require("../controllers/action");
router.route('/item/:id').get(ActionController.get);
module.exports = router;
I'm using node, express and connect for a simple app and have basic HTTP auth implemented as follows (lots of code left out for brevity):
var express = require('express'),
connect = require('connect');
app.configure = function(){
// other stuff...
app.use(connect.basicAuth('username', 'password'));
// other stuff...
};
I've tried googling and even attempted implementing my own auth, but I can't figure out how to skip this auth for just one route.
I'd really appreciate it if anyone offer any help with this?
If you don't want to use authentication for all routes, you should add the auth function as middleware to each individual route like so:
app.get('/mysecretpage', basicAuth, function (req, res) {
console.log('you have to be auth to see this page');
});
Here is a regular route without auth:
app.get('/sample', function (req, res) {
console.log('everybody see this page');
});
This link may be useful for you also: how to implement login auth in node.js