Search code examples
javascriptnode.jsexpresscsrf

How to use Express middleware functions correctly in router?


In this example below, you can see that the csrfProtection and parseForm functions are passed as parameters/callbacks in the GET and POST requests...

var cookieParser = require('cookie-parser')
var csrf = require('csurf')
var bodyParser = require('body-parser')
var express = require('express')

// setup route middlewares
var csrfProtection = csrf({ cookie: true })
var parseForm = bodyParser.urlencoded({ extended: false })

// create express app
var app = express()

// parse cookies
// we need this because "cookie" is true in csrfProtection
app.use(cookieParser())

app.get('/form', csrfProtection, function(req, res) { // HERE 
  // pass the csrfToken to the view
  res.render('send', { csrfToken: req.csrfToken() })
})

app.post('/process', parseForm, csrfProtection, function(req, res) { // AND HERE
  res.send('data is being processed')
})

However, if you are using a router, like I am, how can use these same functions? I am aware that by "using" them in app.js, they are made available on the req object but in the example given above, they are required as the 2nd and 2nd & 3rd arguments of the GET and POST routes, but req isn't made available until you're inside the final callback?!

So I know you can't do the below (just as an example)... so how should you use them? Would I have to re-declare them in every routes file?

Separate routes file: routes/someroute.js ...

router
    .post('/', req.body, req.csrfProtection, (req, res) => {

    })

...

Thanks in advance :)

Reference: https://www.npmjs.com/package/csurf

UPDATE

Following comments below, I have made the following changes to my app.js file.

app.js

...

global.bodyParser = require('body-parser').urlencoded({extended: false});
app.use(global.bodyParser);

global.csrfProtection = csrf({ cookie: false });

...

routes/myroute.js

router
    .post('/', global.bodyParser, global.csrfProtection, (req, res) => {})

However, when I restart the server I am seeing this error, which suggests that that the global function is not defined... what am I missing here? :-/

Error: Route.post() requires a callback function but got a [object Undefined]

Solution

  • I think you ask about sharing middlewares across all API/routes files

    You can do it like this :

    First in your main file lets call it server.js we use you're code

    var cookieParser = require('cookie-parser')
    var csrf = require('csurf')
    var bodyParser = require('body-parser')
    var express = require('express')
    
    // create express app
    var app = express()
    
    // setup route middlewares
    app.use(bodyParser.urlencoded({ extended: false }))
    
    // parse cookies
    app.use(cookieParser())
    //enable your JS API/route script.
    const awesomeAPI = require('./awesomeApi.js');
    app.use('/awesome', awesomeAPI );
    app.listen(3000);
    

    Now you have file let's calle it awesomeApi.js

    const express = require('express');
    const awesomeApi = express.Router();
    awesomeApi.route('/')
       .post(req,res => {
      //req.body present here. And body parser middle ware works.
    })
    module.exports = awesomeApi;
    

    Hope this helps.

    Some links:

    https://expressjs.com/en/guide/using-middleware.html

    https://expressjs.com/en/4x/api.html#express