cómo obtener la ruta de solicitud con el objeto express req

158

Estoy usando express + node.js y tengo un objeto req, la solicitud en el navegador es / account pero cuando registro req.path obtengo '/' --- not '/ account'.

  //auth required or redirect
  app.use('/account', function(req, res, next) {
    console.log(req.path);
    if ( !req.session.user ) {
      res.redirect('/login?ref='+req.path);
    } else {
      next();
    }
  });

req.path es / cuando debería ser / cuenta ??

chovy
fuente
2
TypeError: Cannot read property 'path' of undefined
chovy
req.route.path es correcto y está documentado aquí . ¿Qué versión de express estás usando?
zemirco
Estoy teniendo el mismo problema req.routees indefinido. Estoy usando express 3.4.4. ¿Qué puede hacer que la ruta sea indefinida?
davidpfahler
@vinayr req.route.path todavía me da / create en lugar de / quizzes / create, que es la URL completa
Sandip Subedi
Este es el comportamiento previsto. Y deberías abrazarlo. Su controlador no debería preocuparse por la ruta completa, sino solo por la parte 'local' de la ruta. Esa es la parte después del camino en el que se montó. Esto hace que la función del controlador sea más fácil de reutilizar en otros contextos.
Stijn de Witt

Respuestas:

234

Después de jugar un poco, deberías usar:

console.log(req.originalUrl)

Menztrual
fuente
3
Creo que tiene algo que ver con el posicionamiento del middleware, pero tienes razón, no tiene sentido.
Menztrual
1
Definitivamente es el middleware. Esto sucede también con enrutadores adicionales en Express 4. Cuando cualquiera de los dos está montado fuera de una ruta determinada, dentro de sí mismo se hace pasar por fuera de la raíz. Eso es bueno para el aislamiento, pero complicado cuando no sabes cómo obtener el valor total original. ¡Gracias por publicar esto!
juanpaco
3
Cualquiera que llegue aquí en 4.0, req.url está diseñado para ser mutable por middleware con fines de reenrutamiento, y req.path podría perder puntos de montaje dependiendo de dónde se llame. expressjs.com/en/api.html#req.originalUrl
Christian Davis
3
Si no desea que se incluya la cadena de consulta:const path = req.originalUrl.replace(/\?.*$/, '');
Adam Reis
1
Advertencia: esta es una respuesta engañosa, basada en la pregunta OP. Esto también devolverá la cadena de consulta (por ejemplo,? A = b & c = 5) si estaba presente. Ver expressjs.com/en/api.html#req.originalUrl
Ciabaros
60

En algunos casos deberías usar:

req.path

Esto le proporciona la ruta, en lugar de la URL completa solicitada. Por ejemplo, si solo está interesado en qué página solicitó el usuario y no en todo tipo de parámetros, la URL:

/myurl.htm?allkinds&ofparameters=true

req.path te dará:

/myurl.html
DivZero
fuente
1
Tenga cuidado de que si realiza comprobaciones con esta URL, también incluya una comprobación de una barra diagonal final si es válida en su aplicación. (es decir, la verificación /demotambién debería potencialmente verificar /demo/).
Vinay
Si no desea que se incluya la cadena de consulta: const path = req.originalUrl.replace (/\?.*$/, '');
Adam Reis
req.pathes la abreviatura de url.parse(req.url).pathnamey esta debería ser la respuesta aceptada
sertsedat
1
@sertsedat Incorrecto. req.pathle brinda la ruta relativa a donde está montada su aplicación. Si está montado en la raíz, entonces esto es correcto, pero para una ruta /my/path, dentro de una aplicación montada en /my, req.urldará /path.
Stijn de Witt
21

Para complementar, aquí hay un ejemplo ampliado de la documentación, que envuelve muy bien todo lo que necesita saber sobre el acceso a las rutas / URL en todos los casos con express:

app.use('/admin', function (req, res, next) { // GET 'http://www.example.com/admin/new?a=b'
  console.dir(req.originalUrl) // '/admin/new?a=b' (WARNING: beware query string)
  console.dir(req.baseUrl) // '/admin'
  console.dir(req.path) // '/new'
  console.dir(req.baseUrl + req.path) // '/admin/new' (full path without query string)
  next()
})

Basado en: https://expressjs.com/en/api.html#req.originalUrl

Conclusión: como dice la respuesta de c1moore arriba, use:

var fullPath = req.baseUrl + req.path;
Ciabaros
fuente
9
//auth required or redirect
app.use('/account', function(req, res, next) {
  console.log(req.path);
  if ( !req.session.user ) {
    res.redirect('/login?ref='+req.path);
  } else {
    next();
  }
});

req.path es / cuando debería ser / cuenta ??

La razón de esto es que Express resta la ruta en la que está montada su función de controlador, que es '/account'en este caso.

¿Por qué hacen esto?

Porque facilita la reutilización de la función del controlador. Puede hacer una función de controlador que haga cosas diferentes para req.path === '/'y req.path === '/goodbye'por ejemplo:

function sendGreeting(req, res, next) {
  res.send(req.path == '/goodbye' ? 'Farewell!' : 'Hello there!')
}

Luego puede montarlo en múltiples puntos finales:

app.use('/world', sendGreeting)
app.use('/aliens', sendGreeting)

Dando:

/world           ==>  Hello there!
/world/goodbye   ==>  Farewell!
/aliens          ==>  Hello there!
/aliens/goodbye  ==>  Farewell!
Stijn de Witt
fuente
9

Si realmente desea obtener solo la "ruta" sin la cadena de consulta, puede usar la urlbiblioteca para analizar y obtener solo la parte de la ruta de la URL.

var url = require('url');

//auth required or redirect
app.use('/account', function(req, res, next) {
    var path = url.parse(req.url).pathname;
    if ( !req.session.user ) {
      res.redirect('/login?ref='+path);
    } else {
      next();
    }
});
Murat Çorlu
fuente
Esto es exactamente lo que quiero. Úselo con req.query.refsi el inicio de sesión es exitoso
Ryan Wu
Esto funciona bien con el código universal, ya que se ajusta a las especificaciones de ubicación . Menos cosas para recordar y más fácil de realizar pruebas unitarias en clientes y servidores.
cchamberlain
req.pathes solo un alias paraurl.parse(req.url).pathname
mhodges
8

Para la versión 4.x ahora puede usar req.baseUrlademás de req.pathpara obtener la ruta completa. Por ejemplo, el OP ahora haría algo como:

//auth required or redirect
app.use('/account', function(req, res, next) {
  console.log(req.baseUrl + req.path);  // => /account

  if(!req.session.user) {
    res.redirect('/login?ref=' + encodeURIComponent(req.baseUrl + req.path));  // => /login?ref=%2Faccount
  } else {
    next();
  }
});
c1moore
fuente
5

req.route.path está funcionando para mí

var pool = require('../db');

module.exports.get_plants = function(req, res) {
    // to run a query we can acquire a client from the pool,
    // run a query on the client, and then return the client to the pool
    pool.connect(function(err, client, done) {
        if (err) {
            return console.error('error fetching client from pool', err);
        }
        client.query('SELECT * FROM plants', function(err, result) {
            //call `done()` to release the client back to the pool
            done();
            if (err) {
                return console.error('error running query', err);
            }
            console.log('A call to route: %s', req.route.path + '\nRequest type: ' + req.method.toLowerCase());
            res.json(result);
        });
    });
};

después de ejecutar, veo lo siguiente en la consola y obtengo un resultado perfecto en mi navegador.

Express server listening on port 3000 in development mode
A call to route: /plants
Request type: get
Bahman.A
fuente