I have a simple scenario. I am following Max tutorial.
My http://localhost:3000/message always returns index page. That is only the first route is working. The new route is not working. I am simply trying to put node.hbs on /message
/routes/app.js
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
res.render('index');
});
router.get('/messsage', function (req, res, next) {
res.render('node', { message: 'hello' });
});
module.exports = router;
app.js
var appRoutes = require('./routes/app');
app.use('/', appRoutes);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
return res.render('index');
});
Your code is working. The requested URL http://localhost:3000/message is not matching any of your declared paths so it is defaulting to your custom 404 page which is the same as your index page. Without changing your code and simply requesting http://localhost:3000/messsage will match the path of /messsage on your router. It's a typo. 😉
Related
I wanted to automate the model and route parts in node.js express.
For example, the index.js of routes originally looked like this.
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', {title:'Express' });
});
router.get('/a1', function(req, res, next) {
res.render('a1', {title:'Repetitive router.get' });
});
router.get('/a2', function(req, res, next) {
res.render('a2', {title:'Repetitive router.get' });
});
router.get('/a3', function(req, res, next) {
res.render('a3', {title:'Repetitive router.get' });
});
module.exports = router;
I don’t want to hard-code this every time
router.get function part
var express = require('express');
var router = express.Router();
var AAA = require('myGetAll');
AAA.add('/a1', a1, {title:'Repetitive router.get' });
AAA.add('/a2', a2, {title:'Repetitive router.get' });
AAA.add('/a3', a3, {title:'Repetitive router.get' });
/* GET home page. */
for(let i = 0; i <AAA.count(); i++){
router.get(AAA.itemPath[i], function(req, res, next) {
res.render(AAA.itemFile[i], AAA.itemParameter[i]);
});
}
module.exports = router;
I would like to do it this way.
Would it be okay to do this?
if not
MVC like express, but
Recommend a framework with better code automation.
Thank you.
There is a good way you could achieve this using route params.
router.get('/:param(a+[1-3])', function(req, res, next) {
const parameter = req.params.param;
res.render(parameter, {title:`Repetitive router.get this ${parameter}` });
});
You can pass an optional regular expression to the route to match the desired param, or just handle the input inside your code logic (in this case i´ve added a regex to match a1-a3)
https://expressjs.com/en/guide/routing.html
I am trying to learn Express for NodeJS but I came across this:
I am trying to add 2 middlewares depeding on url, so on the /user to do something and on root to do something different. However the root middleware is always called even if i dont use next() and if i access the "/" url, the root middleware is called twice.
const express = require('express');
const app = express();
app.use('/user', (req, res, next) => {
console.log('In user middleware ');
res.send('<h1>Hello from User page</h1>');
});
app.use('/', (req, res, next) => {
console.log('In slash middleware !');
res.send('<h1>Hello from Express !</h1>');
});
app.disable('etag');
app.listen(3000);
it should be get or post not use
-get or post are routes
-use is middleware function
check this
const express = require('express');
const app = express();
app.get('/user', (req, res, next) => {
console.log('In user middleware ');
res.send('<h1>Hello from User page</h1>');
});
app.get('/', (req, res, next) => {
console.log('In slash middleware !');
res.send('<h1>Hello from Express !</h1>');
});
app.disable('etag');
app.listen(3000);
From an issue at GitHub.com
https://github.com/expressjs/express/issues/3260
Hi #davidgatti my "root path middlware" I assume you are talking about
nr_one. If so, yes, of course it is executed on every request; app.use
is a prefix-match system. Every URL starts with /, so anything mounted
at / will of course get executed :)
Okay, I can't confirm this but I suspect from the tutorial you are following you might be missing a line.
As you said, app.use is a middleware which will be added to all the route
So when you load say some url where you expect the middleware then it won't know about the request type (post, put, delete or get request).
Any alternate for this could be to try something like this
app.use('/user', (req, res, next) => {
if (req.method === 'GET') {
console.log('In user middleware ');
res.send('<h1>Hello from User page</h1>');
}
});
Again, Just check and compare his code thoroughly
Adding this link from Justin's answer for reference
In order to avoid such a problem, you have to use the return keyword.
When you send a file to the server, use return.
Try the following code,
const express = require('express');
const app = express();
app.use('/user', (req, res, next) => {
console.log('In user middleware ');
return res.send('<h1>Hello from User page</h1>');
});
app.use('/', (req, res, next) => {
console.log('In slash middleware !');
return res.send('<h1>Hello from Express !</h1>');
});
app.disable('etag');
app.listen(3000);
At line 13 and 8, I used the return keyword.
So when you make http://localhost:3000/ request, you will receive
Hello from Express !
And whenever you make http://localhost:3000/user request, you will receive
Hello from User page
Need some help or any clue including/requiring dynamic routes at runtime in express, its confusing but i try my best.
This is just an example of app routes configuration right now
app.use('/', require('./routes/public'));
app.use('/u', require('./routes/user'));
app.use('/a', require('./routes/admin'));
for example require('./routes/public') will include something like this
router.get('/', home.index);
router.get('/faq', faq.index)
also require('./routes/user') will include this
router.get('/dashboard', user_home.index);
router.get('/accounts', user_acc.index)
also require('./routes/admin')
router.get('/dashboard', adm_home.index);
router.get('/accounts', adm_acc.index)
i have installed passportjs so its easy to check if the user is authenticated, also if it is, user contains 1 property type, eg: 1 = user, 2 = admin.
req.user.type = 1 or 2, req.isAuthenticated()...
what i need is inject depending user type 1 or 2, require('./routes/user') or require('./routes/admin') at runetime, cos i dont want to declare invalid routes for an user type user example including admin, or backwards.
Right now, all routes are visible or valid but i need to check every controller for user type, also i dont want the '/a' OR '/u' routes prefix.
All routes must be under '/'.
Request runs to first matched path. You can render page, throw error or call next to get next middleware. Below some router examples.
'use strict'
var express = require ('express');
var app = express();
var publicRouter = express.Router();
publicRouter.get('/', (req, res) => res.send('ROOT'));
publicRouter.get('/account', function (req, res, next) {
if (!is-user)
res.send('Hello guest')
else
next();
});
var userRouter = express.Router();
function isUser (req, res, next) {
// return next() on user logon, and error otherwise
return next();
}
userRouter.use(isUser);
userRouter.get('/dashboard', (req, res) => res.send('/dashboard'));
userRouter.get('/account', (req, res) => res.send('Hello user'));
var adminRouter = express.Router();
function isAdmin (req, res, next) {
// return next() on admin logon, and error otherwise
return next(new Error('Access denied'));
}
adminRouter.get('/manage', (req, res) => res.send('/manage'));
app.use(publicRouter);
app.use(userRouter);
app.use('/admin', isAdmin, adminRouter); // "/admin/manage", not "/manage"
// error handler
app.use(function (err, req, res, next) {
res.send(err.message);
});
app.listen(2000, () => console.log('Listening on port 2000'));
Another way is
app.get('/', do-smth);
app.get('/dashboard', isUser, do-smth);
app.get('/manage', isAdmin, do-smth);
Can we define multiple routes in single router file.
e.g : Consider we have company and user tab and I want to define 1 routers file for each tab. All Company related calls should be handled by Company router and User related calls should be handled by User router.
//app.js
app.use('/', require('./routes/user'));
app.use('/api/user/load_user_list', require('./routes/user'));
app.use('/api/user/get_user_detail', require('./routes/user'));
//User.js router
var express = require('express');
var router = express.Router();
//router 1
router.get('/', function (req, res, next) {
//do something here -
});
//router 2
router.get('/api/user/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/api/user/get_user_detail', function (req, res, next) {
//do something here
});
module.exports = router;
Currently, when app receives call for '/api/user/load_user_list' my "router 1" gets called.
Am I missing out something. To deal with this, I guess I can have single router call and delegate to different function based on request baseUrl.
Any help / suggestion will be appreciated.. Thanks
Instead of :
app.use('/', require('./routes/user'));
app.use('/api/user/load_user_list', require('./routes/user'));
app.use('/api/user/get_user_detail', require('./routes/user'));
Just use :
app.use('/', require('./routes/user'))
app.use('/api/user', require('./routes/user'));
And in your router file rename the routes like so :
//router 2
router.get('/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/get_user_detail', function (req, res, next) {
//do something here
});
Reason :
When app.use('/api/user/xyz', require('./xyz')) is called, the uri path after api/user/xyz is sent to the router to be matched
What is happening here is, since you have given /api/user/load_user_list in app.use('/api/user/load_user_list', require('./routes/user'));, express will prefix all the routes inside your ./routes/user with /api/user/load_user_list.
The / router 1 in your user.js becomes /api/user/load_user_list + / and /api/user/load_user_list in your user.js becomes /api/user/load_user_list(from app.js) + /api/user/load_user_list.
So only when you hit /api/user/load_user_list/api/user/load_user_list, your router 2 will be called.
You can change your app.js code to
app.use('/api/user', require('./routes/user'));
and your routes/user.js to
//router 1
router.get('/', function (req, res, next) {
//do something here -
});
//router 2
router.get('/load_user_list', function (req, res, next) {
//do something here
});
//router 3
router.get('/get_user_detail', function (req, res, next) {
//do something here
});
Now, when you hit /api/user/load_user_list, it will match /api/user(app.js) + /load_user_list(routes/user.js) and the route which you wanted will be called.
In my very simple app I have a users route which is hit when I browse to http://localhost/api/users
Is it possible for me to handle a post or get request to that url without appending anything extra to the route? Using the code below the route handler fires when I post to http://localhost/api/users/new but not to http://localhost/api/users and when I try get http://localhost/api/users/13 but not http://localhost/api/users
I know I could use router.post('/', function(req, res) {}); to post to http://localhost/api/users/ but that extra slash seems inelegant
app.js
var express = require('express');
var users = require('./routes/user');
var app = express();
app.use('/api/users', users);
module.exports = app;
routes\user.js
var express = require('express');
var User = require('../models/user');
var router = express.Router();
router.post(function(req, res) {
// post to root
});
router.post('/new', function(req, res) {
// post to /new
});
router.get(function (req, res, next) {
// get root
});
router.get('/:id', function (req, res, next) {
// get /id
});
module.exports = router;
in routes/user.js, you can simply write:
router.post('/', function (req, res, next) {
// post to /api/user or /api/user/
});
router.get('/', function (req, res, next) {
// get /api/user or /api/user/
});
This would work for both: http://localhost/api/users as well as http://localhost/api/users/
Also, there's nothing inelegant about having a / at the end of the url!
You can use an empty route like this :
router.get("", function (req, res, next) {
// get root
});
You will be able to access to /api/user as well as /api/user/
Also you can handle the route with the route method of router to simplify the code and make it more "elegant" :
router.route('/')
.get(function(req, res){}) // GET method of /api/users
.post(function(req, res){}) // POST method of /api/users
.put(function(req, res){}) // PUT method of /api/users
.delete(function(req, res){}) // DELETE method of /api/users
http://expressjs.com/es/api.html#router.route