Reputation: 75666
I'm using express + node.js and I have a req object, the request in the browser is /account but when I log req.path I get '/' --- 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 is / when it should be /account ??
Upvotes: 255
Views: 296764
Reputation: 2514
This can produce different results when calling directly in base module i.e. main file (e.g. index.js
or app.js
) vs calling from inside module via app.use()
middleware i.e. route file (e.g. routes/users.js
).
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en
We'll be comparing our outputs against above API call
We'll be placing our user module inside routes directory, with one route i.e. /profile/:id/:details
routes/users.js file
const router = (require('express')).Router();
router.get('/profile/:id/:details', (req, res) => {
console.log(req.protocol); // http or https
console.log(req.hostname); // only hostname without port
console.log(req.headers.host); // hostname with port number (if any); same result with req.header('host')
console.log(req.route.path); // exact defined route
console.log(req.baseUrl); // base path or group prefix
console.log(req.path); // relative path except query params
console.log(req.url); // relative path with query|search params
console.log(req.originalUrl); // baseURL + url
// Full URL
console.log(`${req.protocol}://${req.header('host')}${req.originalUrl}`);
res.sendStatus(200);
});
module.exports = router;
Now we'll import this user module in main module of the application and add /api/users
as base path for user module using app.use()
middleware
index.js file
const app = (require('express'))();
const users = require('./routes/users');
app.use('/api/users', users);
const server = require('http').createServer(app);
server.listen(8000, () => console.log('server listening'));
[req.protocol] .............
http
[req.hostname] ..........localhost
[req.headers.host] .....localhost:8000
[req.route.path] ........../profile/:id/:details
[req.baseUrl] ............../api/users
[req.path] .................../profile/123/summary
[req.url] ....................../profile/123/summary?view=grid&leng=en
[req.originalUrl] ........../api/users/profile/123/summary?view=grid&leng=en
Full URL:
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en
We'll define our route right in the main module (i.e. app.js or index.js) and concatenate base path /app/users
with route path instead of using middleware. So route will become /api/users/profile/:id/:details
index.js file
const app = (require('express'))();
app.get('/api/users/profile/:id/:details', (req, res) => {
console.log(req.protocol); // http or https
console.log(req.hostname); // only hostname without port
console.log(req.headers.host); // hostname with port number (if any); same result with req.header('host')
console.log(req.route.path); // exact defined route
console.log(req.baseUrl); // base path or group prefix
console.log(req.path); // relative path except query params
console.log(req.url); // relative path with query|search params
console.log(req.originalUrl); // baseURL + url
// Full URL
console.log(`${req.protocol}://${req.header('host')}${req.originalUrl}`);
res.sendStatus(200);
});
const server = require('http').createServer(app);
server.listen(8000, () => console.log('server listening'));
[req.protocol] .............
http
[req.hostname] ..........localhost
[req.headers.host] .....localhost:8000
[req.route.path] ........../api/users/profile/:id/:details
[req.baseUrl] ..............
[req.path] .................../api/users/profile/123/summary
[req.url] ....................../api/users/profile/123/summary?view=grid&leng=en
[req.originalUrl] ........../api/users/profile/123/summary?view=grid&leng=en
Full URL:
http://localhost:8000/api/users/profile/123/summary?view=grid&leng=en
We can clearly see in above output that the only difference is of baseUrl
which is empty string here. So, the originalUrl
also changes & looks same as the url
Upvotes: 22
Reputation: 11
When using a middleware in express, your request object has several properties you can use to get the correct path:
/api/account
/api/account
/account
/account
/account
/account
PLEASE NOTE: This applies to middlewares
Upvotes: 1
Reputation: 2159
Here is an example expanded from the documentation, which nicely wraps all you need to know about accessing the paths/URLs in all cases with 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()
})
Based on: https://expressjs.com/en/api.html#req.originalUrl
Conclusion: As c1moore's answer states, use:
var fullPath = req.baseUrl + req.path;
Upvotes: 109
Reputation: 1189
For those getting undefined
from req.route.path
that is correct.
Inside route handler, there's a route. Inside middleware handlers, there's no route.
Upvotes: 0
Reputation: 8545
UPDATE 8 YEARS LATER:
req.path
was already doing exactly same thing that I mentioned here. I don't remember how this answer solved issue and accepted as a correct answer but currently it's not a valid answer. Please ignore this answer. Thanks @mhodges for mentioning this.
Original answer:
If you want to really get only "path" without querystring, you can use url
library to parse and get only path part of 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();
}
});
Upvotes: 16
Reputation: 1867
For version 4.x you can now use the req.baseUrl
in addition to req.path
to get the full path. For example, the OP would now do something like:
//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();
}
});
Upvotes: 11
Reputation: 42075
//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 is / when it should be /account ??
The reason for this is that Express subtracts the path your handler function is mounted on, which is '/account'
in this case.
Why do they do this?
Because it makes it easier to reuse the handler function. You can make a handler function that does different things for req.path === '/'
and req.path === '/goodbye'
for example:
function sendGreeting(req, res, next) {
res.send(req.path == '/goodbye' ? 'Farewell!' : 'Hello there!')
}
Then you can mount it to multiple endpoints:
app.use('/world', sendGreeting)
app.use('/aliens', sendGreeting)
Giving:
/world ==> Hello there!
/world/goodbye ==> Farewell!
/aliens ==> Hello there!
/aliens/goodbye ==> Farewell!
Upvotes: 13
Reputation: 1296
req.route.path is working for me
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);
});
});
};
after executing I see the following in the console and I get perfect result in my browser.
Express server listening on port 3000 in development mode
A call to route: /plants
Request type: get
Upvotes: 6
Reputation: 41597
After having a bit of a play myself, you should use:
console.log(req.originalUrl)
Upvotes: 343
Reputation: 2438
In some cases you should use:
req.path
This gives you the path, instead of the complete requested URL. For example, if you are only interested in which page the user requested and not all kinds of parameters the url:
/myurl.htm?allkinds&ofparameters=true
req.path will give you:
/myurl.html
Upvotes: 83