0

I have the following scenario:

users.js

const express        = require('express');
const bodyParser     = require('body-parser');
const app            = express(); 
const apiRoot        = '/api/v1/users';

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {    
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200'); 
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); 
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', false);
    next();
});

app.get(apiRoot, async function(req, res) {
    [... do stuff ...]
});
app.get(apiRoot + '/:id', async function(req, res){
    [... do stuff ...]
});
app.listen(process.env.PORT);

bookings.js

const express        = require('express');
const bodyParser     = require('body-parser');
const app            = express(); 
const apiRoot        = '/api/v1/bookings';

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {    
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200'); 
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); 
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', false);
    next();
});

app.get(apiRoot, async function(req, res) {
    [... do stuff ...]
});
app.get(apiRoot + '/:id', async function(req, res){
    [... do stuff ...]
});
app.listen(process.env.PORT);

This is working fine and without errors. Problem is that I have to maintain all my app settings in more that one single file (I have others beyond users.js and bookings.js...). Is there a way I can concentrate the app creation in one file and import it to users.js, bookings.js and so on?

Danilo Körber
  • 858
  • 1
  • 7
  • 27

3 Answers3

1

Each set of routes could simply be in a file that exports a function that takes app e.g.

// bookings.js
module.exports = function(app) {
  app.get(...)
};

then in your main

const bookingsRoutes = require('./bookings');
bookingsRoutes(app);
Joe
  • 41,484
  • 20
  • 104
  • 125
  • The solution didn't work in my environment, because I am using nodejs on an IIS server. But you put me into the right direction, thanks! – Danilo Körber Mar 07 '20 at 17:38
1

The more common design and really how Express was architected is that each of your files should create a router and export the router. Then, you'd have one main file that creates the app object, imports each of your modules and hooks in their router. In this case, you could also export the root that they want to be installed on.

// m1 module

const express        = require('express');
const router         = express.Router();
const apiRoot        = '/api/v1/users';

// set up router-specific middleware
// if this is the same for all routers, then move this to app.js and just
//    do it once there
router.use(express.urlencoded({ extended: false }));
router.use(express.json());
router.use(function (req, res, next) {    
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200'); 
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); 
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.setHeader('Access-Control-Allow-Credentials', false);
    next();
});

// Configure routes for this router
// The router is installed already on apiRoot so we don't need that in the paths here
router.get('/', async function(req, res) {
    [... do stuff ...]
});
router.get('/:id', async function(req, res){
    [... do stuff ...]
});

module.exports = {apiRoot, router};

Then, you'd have a main app.js:

const express = require('express');
const app = express();

// load and hook in the other routers
const m1 = require('./m1");
app.use(m1.apiRoot, m1.router);

const m2 = require('./m2");
app.use(m2.apiRoot, m2.router);

app.listen(process.env.PORT);

If you really want the body-parser middleware and the CORS stuff to be common to all your routers, then move it into app.js so your router files are only about serving routes.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • The solution didn't work in my environment, because I am using nodejs on an IIS server. But you put me into the right direction, thanks! – Danilo Körber Mar 07 '20 at 17:38
  • @DaniloKörber - I'm curious what nodejs on IIS has anything to do with this question or answer? – jfriend00 Mar 07 '20 at 23:41
  • the way my IIS is configured, the routes do not work unless the file of the js name is the same as the last element of the path. Maybe it's not the best way, but I cannot change this. – Danilo Körber Mar 08 '20 at 19:14
  • @DaniloKörber - Wow, that's really, really limiting. Very odd. – jfriend00 Mar 08 '20 at 19:18
0

Both answers didn't work in my environment, because I am using nodejs on an IIS server. Here is the solution I used:

app.js

const express       = require('express');
const bodyParser    = require('body-parser');
const app           = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function (req, res, next) {    
   res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
   res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
   res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
   res.setHeader('Access-Control-Allow-Credentials', false);
   next();
});
app.listen(process.env.PORT);

module.exports = function() { return app; }    

users.js

const app           = require('./app')();
const list          = require('./list'); 
const apiRoot       = '/api/v1/users'; 

app.get(apiRoot, async function(req, res) {
    // [... do stuff ...]
});

Thanks for the provided answers. They put me in the right direction.

Danilo Körber
  • 858
  • 1
  • 7
  • 27
  • 1
    FYI, you can just directly export the `app` object as `module.exports = app` and then just directly use it when importing. There is no need for the function you exported. – jfriend00 Mar 07 '20 at 23:41