Let's say you always wanted to do certain prefixes on routes, such as /before and to pop that off after a certain line in your server.js file.
Here's an example
const express = require('express');
const App = express();
App.get('/before') //so here the route is '/before'
App.push('/after') //This is a made up method, but something like this has to exist...
App.get('/before') //And this route would be '/after/before'
App.pop(); //Another made up method
App.get('/before') //and this would be just "/before"
This isn't exactly the .push() and .pop() design, but it lets you accomplish the same goal of grouping routes under a common parent path without having to specific the common parent path on each route definition.
Express has the concept of a separate router. You define a bunch of routes that want to share a common parent path on a router. You then register each leaf path on the router and then register the whole router on the parent path.
Here's an example:
const express = require('express');
const app = express();
const routerA = express.Router();
// define routes on the router
routerA.get("/somePath1", ...);
routerA.get("/somePath2", ...);
routerA.get("/somePath3", ...);
// hook the router into the server at a particular path
app.use("/parentPath", routerA);
app.listen(80);
This registers three routes:
/parentPath/somePath1
/parentPath/somePath2
/parentPath/somePath3
Related
I have 2 require('express) calls.
First:
const express = require('express');
const app = express();
Second:
const Router = require('express');
const router = new Router();
What is the difference, why in the first we call a function, and in the second we create an object, if the methods are the same in both (use, get, post, etc)?
I think your question missed something. Your second example shows this:
const Router = require('express');
... but I think you meant to do this:
const Router = require('express').Router;
... regardless, the following should help you better understand.
In express, you can think of Routers as little mini applications... lightweight express apps... which have their own routing. In fact, the main "express" object is itself a Router. For example, you might have a bunch of endpoints for managing users:
// ./routes/user-routes.js
const userRoutes = new express.Router();
userRoutes.get('/', getAllUsers);
userRoutes.get('/:userId', getUserById);
userRoutes.post('/', createUser);
userRoutes.put('/:id', updateUser);
userRoutes.delete('/:id', removeUser);
Notice how none of the urls have anything like /users/ inside them. This is important because this little mini app can now be "mounted" (for lack of better terms) in a larger express app like follows:
const express = require('espress');
const userRoutes = require('./routes/user-routes');
const app = express();
app.use('/path/to/users', userRoutes);
Notice how the userRoutes were "mounted" on the /path/to/users such that all user requests will happen to the following URLs:
GET /path/to/users - get all users
GET /path/to/users/1234 - get user with id "1234"
... you get the point
This is mostly a convenient way to think about your app as a bunch of smaller mini apps which are orchestrated together.
Your second call is incorrect, you are just calling (requiring) express which is similar to your first call.
I never did const router = new Router();, so I'm not sure what that accomplish.
I generally do-
const router = require('express').Router();
router.get();
Even though with your first call you can do
app.get() and app.post()
According to express explanation
express.Router class is used to create modular, mountable route handlers. A Router instance is a complete middleware and routing system
Read more about it here
GeekforGeeks explains express.Router() very well
I have a system where, before specifying the data you want to access, you need to provide the company you are accessing from, to check for authorization.
For example, to get products, materials and users:
GET company/123123/product
GET company/123123/material
GET company/123123/user
When creating the express routes in node JS, I'm using the prefix "company/:id" in all my routes declarations:
app.get("/company/:id/product", callbackProduct);
app.get("/company/:id/material", callbackMaterial);
app.get("/company/:id/user", callbackUser);
The question is, is there any way to generalize this 'company' part of the route, in a way that I don't need to re-write it in all routes?
For example:
app.something("/company/id:/*", genericCallback);
app.get("/product", callbackProduct);
app.get("/material", callbackMaterial);
app.get("/user", callbackUser);
What you could do is to use express.Router.
In an company.routes.js you would write something like that.
const express = require("express");
const CompanyRouter = express.Router();
CompanyRouter.get("/:id/product", callbackProduct);
CompanyRouter.get("/:id/material", callbackMaterial);
CompanyRouter.get("/:id/user", callbackUser);
module.exports = CompanyRouter;
And in your server.js file you would do the following.
const express = require("express");
const CompanyRouter = require("./path/to/CompanyRouter.js")
const app = express();
app.use("/company", CompanyRouter);
app.listen(3000);
I am planning to develop only rest api using express js, I looked into lot of boilerplate projects. None of them provide modularity. Modularity I mean all code related to articles module need to be in article folder then I can drag and drop that.
I saw MEAN somewhat close to that but it has client side (angular related) code in that. I need pure rest api framework.
To me it doesn't sound like you want to use a MEN stack, I do not see a reason to use MongoDB in your question. You can write modular express apps e.g. like this:
Assuming you have three modules in three different folders moduleA, moduleB and moduleC. Each folder contains its respective logic and provides some RESTful routes to the outside world. In express you would create one separate Router for each module like this:
ModuleA:
/* moduleA/routes.js */
var express = require('express');
var router = express.Router();
... // add all routes of moduleA
module.exports = router;
ModuleB:
/* moduleB/routes.js */
var express = require('express');
var router = express.Router();
... // add all routes of moduleB
module.exports = router;
ModuleC:
/* moduleC/routes.js */
var express = require('express');
var router = express.Router();
... // add all routes of moduleC
module.exports = router;
And then you would have one main app.js file in your root folder where you enable and disble the single modules by mounting them into the main express app:
/* app.js */
var express = require('express');
var moduleA = require('./moduleA/routes');
var moduleB = require('./moduleB/routes');
var moduleC = require('./moduleC/routes');
var app = express();
... // add your main app's middlewares
app.use('/moduleA', moduleA);
app.use('/moduleB', moduleB);
// app.use('/moduleC', moduleC);
app.listen(3000);
In this example the modules moduleA and moduleB are enabled and are reached by the routes /moduleA/* and /moduleB/* respectively. The module moduleC is disabled as we commented it out.
If you have questions please leave a comment.
It sounds like you want to use a "MEN" stack, which is MongoDB (for backend), Express, and Node.JS.
Here's a tutorial on how to build a project with a "MEN" stack: https://github.com/maslennikov/node-tutorial-men or this one: https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
I have a node express 4 app and I want to mount a route (contacts) on a parent route. i.e
/:fundid/contacts
In my fund route I declare
var router = require('express').Router({ mergeParams: true });
var contactRoutes = require('./contacts');
router.use('/:fundid/contacts', contactRoutes);
In my contact route
var router = require('express').Router({ mergeParams: true });
router.param('fundid', function(res, req, next, id){});
The problem is that this param call does not fire. From what I can garner from the documentation these param calls are relative to the router they are declared on, but i would have thought mergeParams:true would affect this, but it doesn't. The route is otherwise working, and both routes are called. Am I missing something?
The reason I want to do this is because I want to mount the contacts route on multiple parent routes, and build a filter based on those parent parameters
This comment suggests that parameters are tied to the router they are declared with; so in your case, fundid can only be handled by the "fund" router. mergeParams serves a different purpose, namely to provide access to req.params.fundid from child routers.
You can always use a request middleware in your contact router to perform special operations based on the fundid, though:
router.use(function(req, res, next) {
var id = req.params.fundid;
...
});
I’m implementing a RESTful API using Node and Express. When it comes to routing, currently it looks like this:
var cat = new CatModel();
var dog = new DogModel();
app.route('/cats').get(cat.index);
app.route('/cats/:id').get(cat.show).post(cat.new).put(cat.update);
app.route('/dogs').get(dog.index);
app.route('/dogs/:id').get(dog.show).post(dog.new).put(dog.update);
I don’t like this for two reasons:
Both cat and dog models are instantiated whether I need them or not.
I have to repeat /cats and /dogs for every path schema
I’d love to have something like this (not working, of course):
app.route('/cats', function(req, res)
{
var cat = new CatModel();
this.route('/').get(cat.index);
this.route('/:id').get(cat.show).post(cat.new).put(cat.update);
});
app.route('/dogs', function(req, res)
{
var dog = new DogModel();
this.route('/').get(dog.index);
this.route('/:id').get(dog.show).post(dog.new).put(dog.update);
});
Is there a clean way in modern Express without any further modules (like express-namespace)? I could go for separate routers for each model and assigning them with app.use('/cats', catRouter). However, what if I have more than one hierarchy level like '/tools/hammers/:id'? I would then have routers within routers within routers, which seems like overkill to me.
I would then have routers within routers within routers, which seems like overkill to me.
Perhaps, but that is the built-in method of prefixing -- to app.use() a Router().
var cats = express.Router();
app.use('/cats', cats);
cats.route('/').get(cat.index);
cats.route('/:id').get(cat.show).post(cat.new).put(cat.update);
// ...
And, to have one Router .use() another to define multiple depths:
var tools = express.Router();
app.use('/tools', tools);
var hammers = express.Router();
tools.use('/hammers', hammers);
// effectively: '/tools/hammers/:id'
hammers.route('/:id').get(...);
Though, to be closer to your 2nd snippet, you can define a custom method:
var express = require('express');
express.application.prefix = express.Router.prefix = function (path, configure) {
var router = express.Router();
this.use(path, router);
configure(router);
return router;
};
var app = express();
app.prefix('/cats', function (cats) {
cats.route('/').get(cat.index);
cats.route('/:id').get(cat.show).post(cat.new).put(cat.update);
});
app.prefix('/dogs', ...);
app.prefix('/tools', function (tools) {
tools.prefix('/hammers', function (hammers) {
hammers.route('/:id').get(...);
});
});
Check out the new Router in Express 4. It sounds exactly what you're looking for.