Making route unique to one ejs file - javascript

i want a URL like this localhost3000/hh234due, with a unique id, to route to specific page, but with what am doing it is conflicting with other routes.
how to make /:id unique to one view
module.exports = function (app) {
app.get('/:id', function (req, res) {
res.render('page/index');
});
}

Since routes are tested in order, place it last in the sequence and anything it would conflict with will take precedence over it.

In general, this is just a questionable practice because
app.get('/:id', ...)
matches every single possible top level route and invites conflicts with other top level routes that you want/need in the workings of your site.
You can make it work by always placing it as the last possible route definition, but I would recommend changing the URL to something like
http://localhost:3000/id/hh234due
and then you can use:
app.get('/id/:id', ...)
and not have any conflicts with any of your other top level routes.
When doing it this way, the URL structure is more declarative too since the /id part clearly states what this URL is rather than before where you were more relying on the fact that it doesn't look like any of the other top level routes on your site so "I guess" it must be an id which is not as declarative or clear to the other developers that might work on this site some time in the future.

It should be enough to put the spcific page routing before the general one, like this:
module.exports = function (app) {
app.get('/hh234due', function (req, res) {
res.render('<your special page>');
});
app.get('/:id', function (req, res) {
res.render('page/index');
});
}

Related

Is there a way in Node.js to create global variables that live only for the lifetime of the request? [duplicate]

I want to pass some variable from the first middleware to another middleware, and I tried doing this, but there was "req.somevariable is a given as 'undefined'".
//app.js
..
app.get('/someurl/', middleware1, middleware2)
...
////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...
////middleware2
...
some conditions
...
variable = req.somevariable;
...
v4.x API docs
This is what the res.locals object is for. Setting variables directly on the request object is not supported or documented. res.locals is guaranteed to hold state over the life of a request.
Quote from the docs:
An object that contains response local variables scoped to the
request, and therefore available only to the view(s) rendered during
that request / response cycle (if any). Otherwise, this property is
identical to app.locals.
This property is useful for exposing request-level information such as
the request path name, authenticated user, user settings, and so on.
app.use(function(req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
To retrieve the variable in the next middleware:
app.use(function(req, res, next) {
if (res.locals.authenticated) {
console.log(res.locals.user.id);
}
next();
});
Attach your variable to the res.locals object, not req.
Instead of
req.somevariable = variable1;
Have:
res.locals.somevariable = variable1;
As others have pointed out, res.locals is the recommended way of passing data through middleware.
I don't think that best practice will be passing a variable like req.YOUR_VAR. You might want to consider req.YOUR_APP_NAME.YOUR_VAR or req.mw_params.YOUR_VAR.
It will help you avoid overwriting other attributes.
The most common pattern for passing variables on to other middleware and endpoint functions is attaching values to the request object req.
In your case, that would mean having middlewares such as these:
app.use(function (req, res, next) {
req.someVariable = 123;
next();
});
app.use(function (req, res, next) {
console.log("The variable is", req.someVariable);
next();
});
There are many common use cases of this pattern, and it is the standard way of doing it in the express community. See, for example:
express.json, which ships with express, previously part of body-parser which follows the same pattern for all request parsing.
multer used for parsing multipart data
express-jwt
express-validator (see code)
express-session
express-useragent
express-pino-logger
express-bunyan-logger
It is worth noting that the currently most highly voted answer incorrectly recommends using res.locals for this purpose---which seems to stem from a misreading of the documentation. For that reason, I'll elaborate on why this is not the usual approach to the problem (although it isn't particularly harmful either).
The documentation
As supporting evidence for the res.locals approach being the appropriate one for the case, the now outdated documentation is cited:
An object that contains response local variables scoped to the request, and therefore available only to the view(s) rendered during that request / response cycle (if any). Otherwise, this property is identical to app.locals.
This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on.
Note the framing here: res.locals is for variables only available "to the view(s) rendered during that request" (emphasis added).
That is what res.locals relates to. res.render renders some template file with some given data as well as access to the locals. This was actually more clear in the v2 docs, and we've now updated the current Express documentation to be clearer:
Use this property to set variables accessible in templates rendered with res.render. The variables set on res.locals are available within a single request-response cycle, and will not be shared between requests.
In order to keep local variables for use in template rendering between requests, use app.locals instead.
This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on to templates rendered within the application.
(Emphasis added.)
The guide
Further evidence of extending req being the standard approach is found in the guide on Writing Middleware, which states:
Next, we’ll create a middleware function called “requestTime” and add a property called requestTime to the request object.
const requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
When this was mentioned in discussion in the answers on this here question, one user responded: "This was the way you'd do it before they added res.locals so might be old docs. res.locals is a namespace specifically for this."
This doesn't track with the history of the codebase, however: locals have been present since v2, which is significantly before e.g. express.json was included in the library, at which point it would have made sense to change the behvaior, if it was indeed correct to save values in res.locals.
Closing notes
Shoutout to #real_ate who wrote in the comments, but was overlooked.
That's because req and res are two different objects.
You need to look for the property on the same object you added it to.
The trick is pretty simple... The request cycle is still pretty much alive. You can just add a new variable that will create a temporary, calling
app.get('some/url/endpoint', middleware1, middleware2);
Since you can handle your request in the first middleware
(req, res, next) => {
var yourvalue = anyvalue
}
In middleware 1 you handle your logic and store your value like below:
req.anyvariable = yourvalue
In middleware 2 you can catch this value from middleware 1 doing the following:
(req, res, next) => {
var storedvalue = req.yourvalue
}
As mentioned above, res.locals is a good (recommended) way to do this. See here for a quick tutorial on how to do this in Express.

How to customize default find, findOne, create and update actions in SailsJS?

I'm using SailJS to build a REST API.
I've a lot of nested models, such as:
A building has many Floors, which have many Apartments, which have an Owner.
The Sails populate implementation doesn't work as expected, and I can populate at max a single level nested model.
In order to make things work I would like to rewrite custom controllers like this:
controllers/BuildingController.js
module.exports = {
find: function (req, res) {
// Custom code with population
}
findOne: function (req, res) {
// Custom code with population
}
create: function (req, res) {
// Custom code with nested object creation and connection to parent object
}
...
}
If I call an endpoint through the blueprint my custom controller for that model is called, but if I call it from another point in the code (e.g. Apartment.find()) Sails use its default action, not mine.
Do you have some kind of hint or solution to this problem? Is this possible to implement?
Thanks in advance

Why is Express rendering a page other than specified in res.render

I am trying to render an ejs page called compare.ejs but when I navigate to the page where i am expecting compare to be rendered, another page has been rendered. What am I missing here?
in app.js :
var compare = require('./routes/compare')(nav);
app.use('/compare', compare);
in routes/compare.js
var compare = express.Router();
var router = function (nav) {
compare.route('/')
.get(function(req,res){
res.render('compare',
{
nav: nav
})
});
return compare
};
module.exports = router;
However when I navigate to /compare another page with another name is rendered.
Probably you have another route before compare that is matching the same location. Remember that the routes are middleware so, you must be careful with the order.
Might need to be router.route() rather than compare.route()
// after edit
This sort of thing usually happens if an earlier route matches the same route. Do you have other, similar routes?

What's the purpose of using ":" before a name in the path of a URL?

This might seem a trivial problem, but I have searched for a while for a concrete authoritative answer, but nothing came out so far.
I have been using express.js, and I have been seeing URLs' handlers with paths such as
app.get("/users/:id", function(req, res) {
res.send(req.params)
})
or
app.get("/users/:name/photos", function(req, res) {
res.send(req.params)
})
But I am not completely sure of the purpose of using : before id (or name) in those cases.
I know that, if I use : before id, id will be available as parameter of req.params, i.e. req.params.id. Usually id is an integer, but this is actually not strictly necessary, it could be anything else (e.g. string).
My guess about the reason of using : before a name in the path of a URL is simply to say to express that instead of :id or :name, we can pass whatever we want of any type. :id or :name are considered variables. Is this guess correct?
What are the purposes of using : when handling routing? When should we use it?
The : just indicates a named variable as a placeholder in that part of the url. Without it, id would get matched literally in the url and would not be interpreted as a dynamic placeholder. That's all there is to it.
You are right.
: is just used to set a route. It could have been a ! or # or anything else for that matter. It declares a variable in route.
In your code:
app.get("/users/:id", function(req, res) {
res.send(req.params)
})
/users/:id becomes a route. It means anything after users/ will be caught by this handler and become available in the id variable inside it. It doesn't have to be an integer.
Here:
app.get("/users/:name/photos", function(req, res) {
res.send(req.params)
})
The route is defined something like this:
/users/john/photos/
In this case, john is a variable which matched the route set.

Passing variables to the next middleware using next() in Express.js

I want to pass some variable from the first middleware to another middleware, and I tried doing this, but there was "req.somevariable is a given as 'undefined'".
//app.js
..
app.get('/someurl/', middleware1, middleware2)
...
////middleware1
...
some conditions
...
res.somevariable = variable1;
next();
...
////middleware2
...
some conditions
...
variable = req.somevariable;
...
v4.x API docs
This is what the res.locals object is for. Setting variables directly on the request object is not supported or documented. res.locals is guaranteed to hold state over the life of a request.
Quote from the docs:
An object that contains response local variables scoped to the
request, and therefore available only to the view(s) rendered during
that request / response cycle (if any). Otherwise, this property is
identical to app.locals.
This property is useful for exposing request-level information such as
the request path name, authenticated user, user settings, and so on.
app.use(function(req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
To retrieve the variable in the next middleware:
app.use(function(req, res, next) {
if (res.locals.authenticated) {
console.log(res.locals.user.id);
}
next();
});
Attach your variable to the res.locals object, not req.
Instead of
req.somevariable = variable1;
Have:
res.locals.somevariable = variable1;
As others have pointed out, res.locals is the recommended way of passing data through middleware.
I don't think that best practice will be passing a variable like req.YOUR_VAR. You might want to consider req.YOUR_APP_NAME.YOUR_VAR or req.mw_params.YOUR_VAR.
It will help you avoid overwriting other attributes.
The most common pattern for passing variables on to other middleware and endpoint functions is attaching values to the request object req.
In your case, that would mean having middlewares such as these:
app.use(function (req, res, next) {
req.someVariable = 123;
next();
});
app.use(function (req, res, next) {
console.log("The variable is", req.someVariable);
next();
});
There are many common use cases of this pattern, and it is the standard way of doing it in the express community. See, for example:
express.json, which ships with express, previously part of body-parser which follows the same pattern for all request parsing.
multer used for parsing multipart data
express-jwt
express-validator (see code)
express-session
express-useragent
express-pino-logger
express-bunyan-logger
It is worth noting that the currently most highly voted answer incorrectly recommends using res.locals for this purpose---which seems to stem from a misreading of the documentation. For that reason, I'll elaborate on why this is not the usual approach to the problem (although it isn't particularly harmful either).
The documentation
As supporting evidence for the res.locals approach being the appropriate one for the case, the now outdated documentation is cited:
An object that contains response local variables scoped to the request, and therefore available only to the view(s) rendered during that request / response cycle (if any). Otherwise, this property is identical to app.locals.
This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on.
Note the framing here: res.locals is for variables only available "to the view(s) rendered during that request" (emphasis added).
That is what res.locals relates to. res.render renders some template file with some given data as well as access to the locals. This was actually more clear in the v2 docs, and we've now updated the current Express documentation to be clearer:
Use this property to set variables accessible in templates rendered with res.render. The variables set on res.locals are available within a single request-response cycle, and will not be shared between requests.
In order to keep local variables for use in template rendering between requests, use app.locals instead.
This property is useful for exposing request-level information such as the request path name, authenticated user, user settings, and so on to templates rendered within the application.
(Emphasis added.)
The guide
Further evidence of extending req being the standard approach is found in the guide on Writing Middleware, which states:
Next, we’ll create a middleware function called “requestTime” and add a property called requestTime to the request object.
const requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
When this was mentioned in discussion in the answers on this here question, one user responded: "This was the way you'd do it before they added res.locals so might be old docs. res.locals is a namespace specifically for this."
This doesn't track with the history of the codebase, however: locals have been present since v2, which is significantly before e.g. express.json was included in the library, at which point it would have made sense to change the behvaior, if it was indeed correct to save values in res.locals.
Closing notes
Shoutout to #real_ate who wrote in the comments, but was overlooked.
That's because req and res are two different objects.
You need to look for the property on the same object you added it to.
The trick is pretty simple... The request cycle is still pretty much alive. You can just add a new variable that will create a temporary, calling
app.get('some/url/endpoint', middleware1, middleware2);
Since you can handle your request in the first middleware
(req, res, next) => {
var yourvalue = anyvalue
}
In middleware 1 you handle your logic and store your value like below:
req.anyvariable = yourvalue
In middleware 2 you can catch this value from middleware 1 doing the following:
(req, res, next) => {
var storedvalue = req.yourvalue
}
As mentioned above, res.locals is a good (recommended) way to do this. See here for a quick tutorial on how to do this in Express.

Categories