gpeters gpeters - 2 months ago 13
Node.js Question

Express Variable Base Routes (REST)

I'd like to extend "base" REST calls using express but I think I'm running into a limitation (or my lack of understanding). I want all REST endpoints share the same basic REST routes. I don't want to write these for every endpoint service (i.e. planets, stars, etc...)

app.get('/api/planet/type',function(req,res) {
...
});

app.get('/api/planet/type/:_id',function(req,res) {
...
});

app.post('/api/planet/type',function(req,res) {
...
});

app.patch('/api/planet/type/:_id',function(req,res){
...
});

app.delete('/api/planet/type/:_id',function(req,res) {
...
});


What I'd prefer to do is use a variable in my implementing module

require('base-rest')('/api/planet/type',planet-model);
require('base-rest')('/api/star/type',star-model);


Then use a variable for the base endpoint, but it appears express can handle dynamic routes at runtime.

app.get(baseURL,function(req,res) {
...
});

app.get(baseURL+'/:_id',function(req,res) {
...
});


Is this possible? If so, how can I achieve this?

Please note, I'm using Express v4

Answer

This can in fact be done (with caveats). This is somewhat outlined by Hage's post.

//base.js

var express = require('express');
var router = express.Router();
....
router.get('/:id', function(req, res) {
    ....
});
//Additional routes here

module.exports = router

The implementation file

//planets.js
var base = require('./base');
app.use('/api/planets',base);

Full details found here: https://expressjs.com/en/guide/routing.html

There is a caveat to this however. I cannot reuse base.js for multiple implementations since node.js by default uses singletons for require('./base'). This means you will get the same instance when I really want a new instance. Why? Because I want to inject my model for each base route.

For Example:

var model = null;
module.exports.map = function(entity) {
    model = entity;
}

router.get('/:id', function(req, res) {
    model.findOne(...) //using mongoose here
});

The same model will be used for all routes across multiple modules since the require('./base') is a singleton import.

If anyone knows a solution of this additional problem, let me know!!!