Generic route prefix + specific route in Node Express - node.js

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);

Related

What is the difference between the two calls to express()

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

Nodjs swagger auto gen integration

I need to develop an API using NodeJS and also need to develop documentation for API also. I integrated with swagger auto-gen for swagger.json creation. But the swagger.json not generating properly if I used routes.js as below
var express = require('express');
module.exports = function(app) {
var userController = require('../controller/userController');
var apiRouter = express.Router();
var routerV1 = express.Router();
var routerV2 = express.Router();
app.use('/admin', apiRouter);
apiRouter.use("/v1", routerV1);
apiRouter.use("/v2", routerV2);
routerV1.route('/users').get(userController.getUsersV1);
routerV2.route('/users').get(userController.getUsersV2);
}
and also mapped these routes.js in swagger.js
Please suggest the best way to generate swagger.js
Do we need to create routes file for all controller?
Version 2 of swagger-autogen added this feature. Previous versions don't recognize routes. In your case, the best way to generate the file swagger.js is:
file: swagger.js
const swaggerAutogen = require('swagger-autogen')();
const outputFile = './swagger_output.json';
const endpointsFiles = ['./routes.js']; // root file where the route starts.
swaggerAutogen(outputFile, endpointsFiles).then(() => {
require('./index.js'); // Your project's root file
})
Update your module to the latest version.
And run your project with: node swagger.js
And about the routes file for all controller, you don't need to implement it for each one, but it also depends on the structure of your code. If you have a root route file like the example, this is enough for all sub-routes to be scanned. I hope it helps you. Take a look at this example if you need to:
swagger-autogen using router

How to automatically include routes in ExpressJS

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

How to set custom Cloud Functions Path

Let's say I want a cloud function to have a path such as:
https://[MY_DOMAIN]/login/change_password
How do I achieve the "login/" part in Node?
Or even something more complicated such as
login/admin/get_data
?
I tried using
module.exports = {
"login/change_password" = [function]
}
But I got an error when deploying and "change_password" was omitted, so it only tried to deploy a "login" function.
Another thing I tried was using express routers but that resulted in only deploying a single function, which routed to the right path (e.g. myfunction/login/change_password) which is problematic as I have to deploy in bulk every time and can't deploy a function individually.
If you want the flexibility to define routes (paths) that are more complex than just the name of the function, you should provide an Express app to Cloud Functions. The express app can define routes that add path components to the base name of the function you export from index.js. This is discussed in the documentation for HTTP functions. For example:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/some/other/path', (req, res) => { ... });
exports.foo = functions.https.onRequest(app);
In that case, all your paths will hang off of the path prefix "foo".
There is also an official samples illustrating use of Express apps: https://github.com/firebase/functions-samples/tree/master/authorized-https-endpoint
Thanks to the discussion with Doug Stevenson I was able to better phrase my question and find that it was already answered in this question.
So this would be an example of my implementation:
const functions = require('firebase-functions');
const express = require('express');
const login = require('./login.js');
const edit_data = require('./edit-data.js');
const login_app = express();
login_app.use('/get_uuid', login.getUUID);
login_app.use('/get_credentials', login.getCredentials);
login_app.use('/authorize', login.authorize);
const edit_data_app = express();
edit_data_app.use('/set_data', edit_data.setData);
edit_data_app.use('/get_data', edit_data.getData);
edit_data_app.use('/update_data', edit_data.updateData);
edit_data_app.use('/remove_data', edit_data.removeData);
exports.login = functions.https.onRequest(login_app);
exports.edit_data = functions.https.onRequest(edit_data_app);
My takeaway from this is that there is a one-to-one Express app to HTTP function correspondence, so if I wanted to have 3 different functions I would need 3 Express apps.
A good balance is to have one app and one function per module (as shown above), which also means you can separate out your functions across several modules/javascript files for ease of maintenance.
In the above example, we can then trigger those HTTP functions using
https://[DOMAIN]/login/get_uuid/
or, from the firebase functions shell
login.get("/get_uuid")

Express js modular REST framework

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

Resources