P
P
Pavel Tkachenko2018-05-10 21:57:40
Node.js
Pavel Tkachenko, 2018-05-10 21:57:40

How to get the name of an Express route parameter?

How can I get the parameter name in an Express route?
For example, I have a route
'/user/:userId'
When I go, I get a dynamic address /user/5af2fe6cc7a7631ae040db43
. I want to make an intermediate handler that will select information about the route from the database.
Finding a dynamic address in the database will not work without converting 5af2fe6cc7a7631ae040db43to /:and searching for a match /user/:
. I made such a script, but I wonder if there is an easier way, especially that the script works with only 1 parameter, that is, for example /user/:username/:userId, it will not be able to process it yet (it needs to be finished).
Sample code for clarity:

// Moongose
var Routes = mongoose.model('Routes', RoutesSchema);

app.use((req, res, next) => {
    //Получаем информацию о маршруте из бд
    Routes.find({'path' : req.originalUrl}, (err, pageInfo) => {
        // Если документ не найден
        if(pageInfo == null) {
            var search = req.originalUrl.split('/');
            search.splice(-1,1,':');
            search = search.join('/');
            // serach =  /user/:
            Routes.findOne({'path' : {$regex: search}}, function(err, pageInfo) {
                // Устанавливаем локальные переменные ответа
                res.locals.title = pageInfo.title;
                res.locals.description = pageInfo.description;
                next()
            })
        }
        // Если все ок
        else {
            // Устанавливаем локальные переменные ответа
            res.locals.title = pageInfo.title
            res.locals.description= pageInfo.description
            next()
       }
    })
})

Thanks in advance

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
rustler2000, 2018-05-11
@rustler2000

In short, the question is simple without a bullshit.
Here is a piece of code taken from a case in expressjs and their docks.
The bottom line is that before starting the server, it passes through the handlers and inserts the front springboard.

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

app.get('/path/:id', function(req, res, next) {
    res.send(`${this.method} ${this.path}`)
})

function print (path, layer) {
  if (layer.route) {
    layer.route.stack.forEach(print.bind(null, path.concat(split(layer.route.path))))
  } else if (layer.name === 'router' && layer.handle.stack) {
    layer.handle.stack.forEach(print.bind(null, path.concat(split(layer.regexp))))
  } else if (layer.method) {
    console.log('%s /%s',
      layer.method.toUpperCase(),
      path.concat(split(layer.regexp)).filter(Boolean).join('/'))
      
    // 
    // Аттачим хэндлеру this :D
    // 
    const m = layer.method.toUpperCase()
    const p = path.concat(split(layer.regexp)).filter(Boolean).join('/')
    const fn = layer.handle
    layer.handle = function trampoline() {
        const self = {
            method: m,
            path: p
        }
        
        fn.apply(self, arguments)
    }
  }
}

function split (thing) {
  if (typeof thing === 'string') {
    return thing.split('/')
  } else if (thing.fast_slash) {
    return ''
  } else {
    var match = thing.toString()
      .replace('\\/?', '')
      .replace('(?=\\/|$)', '$')
      .match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//)
    return match
      ? match[1].replace(/\\(.)/g, '$1').split('/')
      : '<complex:' + thing.toString() + '>'
  }
}
app._router.stack.forEach(print.bind(null, []))

app.listen(3000, () => console.log('Example app listening on port 3000!'))

P
Pavel Tkachenko, 2018-05-11
@Pavel_Tkachenko

It will not work to get the name of the request parameter, since the intermediate handler is executed before processing the route itself and is not aware that 5af2fe6cc7a7631ae040db43this is a request parameter.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question