Express router - :id? - node.js

Real simple question guys: I see a lot of books/code snippets use the following syntax in the router:
app.use('/todos/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
I'm not sure how to interpret the route here... will it route '/todos/anything'? and then grab the 'anything' and treat is at variable ID? how do I use that variable? I'm sure this is a quick answer, I just haven't seen this syntax before.

This is an express middleware.
In this case, yes, it will route /todos/anything, and then req.params.id will be set to 'anything'

On your code, that is for express framework middleware, if you want to get any id in the server code using that route, you will get that id by req.params.id.
app.use('/todos/:id', function (req, res, next) {
console.log('Request Id:', req.params.id);
next();
});

Route path: /student/:studentID/books/:bookId
Request URL: http://localhost:xxxx/student/34/books/2424
req.params: { "studentID": "34", "bookId": "2424" }
app.get('/student/:studentID/books/:bookId', function (req, res) {
res.send(req.params);
});
Similarly for your code:
Route path: /todos/:id
Request URL: http://localhost:xxxx/todos/36
req.params: { "id": "36" }
app.use('/todos/:id', function (req, res, next) {
console.log('Request Id:', req.params.id);
next();
});

Yes, in your example youl get req.params.id set to 'anything'

A bit late to the party but the question mark in your question made me think of something that hasn't been touched upon.
If your route had a question mark after the id like so: '/todos/:id?', id would be an optional parameter, meaning you could do a getAll() if id was omitted (and therefore undefined).

This is called Path params and it's used to identify a specific resource.
and as all answer how to get the value of the path params
app.use('/todos/:id', function (req, res) {
console.log('Request Id:', req.params.id); // 'anything'
});
read more about params type
https://swagger.io/docs/specification/describing-parameters/

Related

Node.js & Sequelize : res.json on findAll?

I have an issue with Res.json in the code below :
/* GET all users */
app.get('/users', function (res) {
db.users.findAll()
.then(users => {
res.json(users);
});
});
It worked pretty well yersteday but now, it doesn't. I have this error for all res.json only with the app.get which uses findAll...
Unhandled rejection TypeError: res.json is not a function
I don't understand why res.json is working in all my fonctions but not with findAll :/
The callback prototype / signature is wrong, it should be like that :
app.get('/users', function(req, res) { ... })
In your example, you're trying to call req.json, which doesn't exists.
Hope it helps,
Best regards
EDIT
If you don't want the req, you can't just remove it, because Express expect it to be there, so he will call your anonymous functio with the 3 usual parameters : req, res, and next.
Express cannot guess that you want res as first parameter of your function.
But if you want other people to know that you will not use this variable, you could do something like that :
app.get('/users', function(_, res) { ... })
OR
app.get('/users', function(_req, res) { ... })
It is an acceptable practice to prefix useless variables with an underscore, if the underscore has no other meaning. Don't do that if you use underscore.js or lodash

Expressjs - Get req.route in a middleware [duplicate]

Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.

Get specific parameter no matter the URL in Express.JS

I want to check for a consistent URL parameter in each request in my Express.JS app. The base of the URL is always the same:
/command/UUID
But some times it can be
/command/UUID/something/1
The following code works only in the first case. As soon as I add another slash at the end, this middleware won't be executed.
app.all('/*/:uuid', function(req, res, next) {
console.log(req.params)
next();
});
I would appreciate if someone could help me out solve this issue.
Best.
Something like this:
app.all('/:command/:uuid/(*?)', function(req, res, next) {
console.log(req.params.command, req.params.uuid);
next();
});
What actually worked is the following code
app.set('strict routing', false );
app.all('/:cmd/:uuid*', function(req, res, next) {
console.log(req.params)
next();
});
And the result is as follow with this URL: /ip/165420/3123123/adasdsad
{ '0': '/3123123/adasdsad', cmd: 'ip', uuid: '165420' }

I would like to add a query param apikey for all my external call

I have a server in express and it uses an external api. I would like for each request to that api ('/api/*'), that it appends a query param in the url without to write it for each requests.
app.use(function(req, res) {
req.query.key = process.env.APIKEY;
});
I tried something like that but it doesn't work.
I thought of doing something like :
app.get('/api/stuff', addApiKey, api.stuff);
Is there a better way?
You need to supply your middleware function with a next callback:
function addApiKey(req, res, next) {
req.query.key = process.env.APIKEY;
next();
});
app.get('/api/:endpoint', addApiKey, function(req, res) {
// do your stuff here
});

Get route definition in middleware

Does anyone know if it's possible to get the path used to trigger the route?
For example, let's say I have this:
app.get('/user/:id', function(req, res) {});
With the following simple middleware being used
function(req, res, next) {
req.?
});
I'd want to be able to get /user/:id within the middleware, this is not req.url.
What you want is req.route.path.
For example:
app.get('/user/:id?', function(req, res){
console.log(req.route);
});
// outputs something like
{ path: '/user/:id?',
method: 'get',
callbacks: [ [Function] ],
keys: [ { name: 'id', optional: true } ],
regexp: /^\/user(?:\/([^\/]+?))?\/?$/i,
params: [ id: '12' ] }
http://expressjs.com/api.html#req.route
EDIT:
As explained in the comments, getting req.route in a middleware is difficult/hacky. The router middleware is the one that populates the req.route object, and it probably is in a lower level than the middleware you're developing.
This way, getting req.route is only possible if you hook into the router middleware to parse the req for you before it's executed by Express itself.
FWIW, two other options:
// this will only be called *after* the request has been handled
app.use(function(req, res, next) {
res.on('finish', function() {
console.log('R', req.route);
});
next();
});
// use the middleware on specific requests only
var middleware = function(req, res, next) {
console.log('R', req.route);
next();
};
app.get('/user/:id?', middleware, function(req, res) { ... });
I know this is a little late, but for later Express/Node setups req.originalUrl works just fine!
Hope this helps
This nasty trick using prototype override will help
"use strict"
var Route = require("express").Route;
module.exports = function () {
let defaultImplementation = Route.prototype.dispatch;
Route.prototype.dispatch = function handle(req, res, next) {
someMethod(req, res); //req.route is available here
defaultImplementation.call(this, req, res, next);
};
};
req.route.path will work to get the path for the given route. But if you want the complete path including the path of the parent route, use something like
let full_path = req.baseUrl+req.route.path;
Hope it helps
You can take a look at Router().stack, which has all the routes defined. In your middleware you need to manually compare the available routes with the one called to define actions.

Resources