I separated routes for rest api like this. Is there better way to organize router ? or the way I am doing is fine?
app.js
app.use('/api/auth',auth);
app/controllers/auth/index.js
var express = require('express'),
router = express.Router(),
register = require('./register');
router.get('/',function(req,res,next){
console.log("api/auth");
res.send('api/auth');
next();
});
router.use('/register',register);
module.exports = router;
app/controllers/auth/register.js
var express = require('express'),
router = express.Router(),
rootPath = require('app-root-path'),
User = require(rootPath+'/app/models/user');
router.post('/',function(req,res,next){
console.log("api/auth/register");
next();
});
module.exports = router;
Building on swaraj'a answer, you should divide your project files into two folders lib and config. Please note that I'm giving you a generic structure this should be customised according to your project.
Config
It should contain all the configuration files for your project.
lib
It should basically have files like controller.js, routes.js, db-ops.js
controller.js contains and exports all functions required for your program logic.
routes.js contains and exports all the routes
db-ops.js intializes db connections and contains functions that define operations on database.
All these files should be required into your app.js which will reside in your projects root directory.
A typical project structure should look something like this:
lib
-routes.js
-controller.js
-db-ops.js
config
-config.json
app.js
You could create a routes.js which has all the separate routes.
Something like,
module.exports = function (app) {
app.use('/api/route1', require('path/to/route1'));
app.use('/api/route2', require('path/to/route2'));
};
Mount this routes in your main app.js.
require('path/to/routes')(app);
Shameless plug of an example, https://github.com/swarajgiri/express-bootstrap/blob/master/web/routes.js
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
I want my routes to be like the following:
/
/business
/business/stuff1
/business/stuff2
/business/admin
for /business I want to have a separate file for the routing and functions.
and also for /business/admin I want to have a separate file for the routing and functions.
so what I did is:
app.js
//Business route
const business = require("./business/business");
app.use("/business", business);
This works fine - but when I add in business.js
//admin route
const admin = require("./admin");
app.use("/admin", admin);
I get 404 for some reason.
Depends on what you are exporing from business.js. It should be an instance of express.Router and you have to mount the /admin route on this instance. Example:
// business.js
const admin = require("./admin");
const businessApp = express.Router();
businessApp.use("/admin", admin);
module.exports = businessApp;
Routing:
app.use('/cms/', require('./routes/index.js'));
app.use('/cms/schools/', require('./routes/schools.js'));
Routes:
/cms/
/cms/schools/
/cms/schools/:schoolId/classes/:classId
Goal: I'd like to split ./routes/schools.js into two files: schools.js and schools_classes.js, to keep a better overview.
Problem: I'd like to keep the prefixed path /cms/schools/, but don't know how to split it correctly.
How can I structure the files to reach the desired goal?
Thanks in advance!
Edit 1:
I tried the following, which is not working (duplicated route prefix):
app.use('/cms/', require('./routes/index.js'));
app.use('/cms/schools/', require('./routes/schools.js'));
app.use('/cms/schools/', require('./routes/schools_classes.js'));
You can do It using the express router:
Routes:
const schoolsRouter = require('./routes/schools');
app.use('/cms/schools', schoolsRouter)
./routes/schools/index.js:
const express = require('express');
const router = express.Router();
router.use('/',require('./schools _controller.js'));
router.use('/:schoolId/classes/:classId', require ('./schools_classes_controller.js'));
module.exports = router;
You can check the entire router docs here: http://expressjs.com/en/4x/api.html#router
My project directory looks something like this:
MyProject
-app.js
-routes
-routeone
-routetwo
Inside of my app.js file it looks like this:
var express = require('express');
var app = express();
var myModule= require('myModule');
app.use(myModule());
var routeone = require('./routes/routeone');
var routetwo = require('./routes/routetwo');
app.use('/routeone', routeone);
app.use('/routetwo', routetwo);
.
.
.
Each route file looks something like this:
var express = require('express');
var router = express.Router();
router.post('/', urlencodedParser, function(req, res, next) {
//Need to call myModule's createUser function. How do I call it here?
});
module.exports = router;
As you can see I have a dependency on the myModule module. I need to call a function in this module in every route.I may have many more routes in the future. I would like to avoid specifying this (calling require) in every single route file because in the future if I have hundreds of route and say the module now accepts options I would need to to every single file and since this manually. Is there a way to require it once (e.g in the app.js file) and then be able to use it everywhere?
You can write your route modules as such that during the time of creation(require call) they get their dependencies injected. I have added a sample below
route.js
module.exports = function(myModule, router, dep1, dep2){
router.post()
//use my module, dep1 and dep2
}
app.js
var mymodule = require('./myModule')
var dep1 = require('./dep1');
var dep2 = require('./dep2');
var router = express.Router();
var route = require('route')(mymodule, router, dep1, dep2);
Update - For returning router instance from route.js
route.js
module.exports = function(myModule, dep1, dep2){
router.post()
//other router invocations
return router
}
In app.js
var customRouter = require('route')(mymodule, router, dep1, dep2);
the customRouter will be an router instance since thats what is being returned by te invoked function in route.js
my routes are defined in an external folder
./routes
here's the way i define the routes in my server.js file
app.get('/', routes.index);
app.post('/validation', register.valid);
the register.valid module, which is originally written in
./routes/validation.js
is responsible for creating a new user account and register it into a database (MongoDB).
How can i access an object from server.js in validation.js ? First, i thought declaring the object before defining my routes would resolve the case, but actually it doesn't seem to be the solution.
I'm assuming your current code already does work (that is, you receive the posted data), but you need access to another object from validation.js.
If your code works, then you probably have this line in server.js:
var register = require('./routes/validation');
And you need acess to the variable obj in the validation module. You could have a function inside the validation module:
var foo;
exports.configure = function(obj) {
foo = obj;
}
The exports mean the variable configure will be accessible to modules which "require" the validation module. This way you can do, inside the server.js module:
register.configure(obj);
app.post('/validation', register.valid);
The exact configuration of this will depend on what you are actually trying to accomplish. Sometimes, for example, it's good to have a database object stored in a global variable.
Generally in this kind of structure server.js will create the app object and then pass that to individual routes modules via a function. I do it by having each router module export a single function like this:
//routes/validation.js
function setup(app) {
app.get(....blah
app.post(....blah
}
module.exports = setup;
Then I tie that together in server.js like this:
//server.js
var express = require('express');
var app = express();
require('./routes/validation')(app);
See also my express_code_structure sample project for other code organization tips.