const express = require('express')
const app = express()
app.get('/user/:uid', (req, res, next) => {
if (req.params.uid === 'lai9fox') next('route')
else next()
}, (req, res, next) => {
res.send(`<h1>hello, ${req.params.uid}</h1>`)
})
app.get('/user/:id', (req, res, next) => {
res.send(`<h1>Welcome you, ${req.params.uid} !</h1>`)
})
app.listen(3000, () => console.log('server is running at port 3000...'))
When I visit http://localhost:3000/user/lai, it correctly shows:
hello, lai
But when I visit http://localhost:3000/user/lai9fox, it shows:
Welcome you, undefined!
What's go wrong?
you need to change the req.params.uid for id
app.get('/user/:id', (req, res, next) => {
res.send(`<h1>Welcome you, ${req.params.id} !</h1>`)
})
Related
In my Express application I implement routes in routes.ts:
var Router = express.Router();
Router.route('/models/:modelId')
.get(function (req, res) {
service.setParameter(req)
service.get(req,res)
});
Router.route('/models/:modelId')
.post(function (req, res) {
service.setParameter(req)
service.post(req,res)
});
And express.ts:
export const App = express()
App.use(express.json())
App.use(express.urlencoded({ extended: true }))
App.use(helmet())
App.use('/', Router)
At each router call I'd like to execute a piece of code service.setParameter(req) that gets particular parameter from 'params', but I don't want to add to each router method explicitly.
I tried adding it at as middleware before and after Router
App.use('/', Router)
App.use(function(req, res, next){
service.setParameter(req)
next()
})
But if I define it before Router then route hasn't been set yet, and I don't get the parameter I want, and if I define it after, then middleware is not executed.
How can execute service.setParameter(req) in a generic way so that it applies to all the routes?
In express.ts file, you can add a middleware that would do it before mounding the Router, and then just procced forward with next(). You can do it like this:
App.use('/*', (req, res, next) => {
service.setParameter(req);
next();
});
App.use('/', Router)
You need to place your custom middleware between the context path and your router inside app.use(..):
const router = express.Router();
router.post('/', (req, res) => {
service.post(req,res);
});
router.get('/', (req, res) => {
service.get(req,res)
});
app.use('/models', (req, res, next) => {
service.setParameter(req);
next();
}, router);
With above code the middleware will be excecuted for all requests to '/models'.
You can use app.use(async (req,res,next) => {...}) in order to declare a middleware that executes in all the requests, if you want this middleware to be called first, it must be declare before than your routes, the middleware have to call next() in order to continue with the execution flow, if you want to be called at the end of you request, you have to put at the end of your declarations but before of the error middleware, in that approach each route have to call next() at the end of your function.
First approach
const express = require('express');
const app = express();
const router = express.Router();
router.post('/', async (req, res) => {
await service.post(req,res);
});
router.get('/', async (req, res) => {
await service.get(req,res)
});
app.use((req,res,next) => {
console.log("always called");
next();
});
app.use('/',router);
Second approach
const express = require('express');
const app = express();
const router = express.Router();
router.post('/', async (req, res, next) => {
await service.post(req,res);
next();
});
router.get('/', async (req, res, next) => {
await service.get(req,res);
next();
});
app.use('/',router);
app.use((req,res) => {
console.log("always called");
});
Thanks for all the answers, they helped me better understand how routing works on Express.
I found another solution, which I think works best in my case - using Router.all() method:
const setRequest = function(req, res, next){
logger.setRequest(request)
next()
}
Router.route('/models/:model_id')
.all(setRequest)
.get(function (req, res) {service.execute()})
.put(function (req, res) {service.execute()})
How can I insert isLoggedIn as a condition to the get request using router.route?
const controller = require('./controller');
const Router = require('express').Router;
const router = new Router();
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
router.route('/')
.get((...args) => controller.find(...args))
I assume that the ...args are (req, res, next)
I tried
router.route('/')
.get(isLoggedIn(...args) => controller.find(...args))
But I get
.get((isLoggedIn(...args)) => controller.find(...args))
^
SyntaxError: Unexpected token (
The docs say, that you can assign multiple handlers to one route. Like this:
app.use('/user/:id', function (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
console.log('Request Type:', req.method)
next()
})
Source
In your case the coding looks like the following
router.get('/', isLoggedIn, controller.find);
I want to create a simple application with auth system. When someone visits my page server must return authorization html page, than visitor can fill the inputs and send login and password through socket.io to server. And if the values are correct, server sends second html page to client. I know that I can use this code and redirect on client side:
app.get('/page1', function(req, res){
res.sendFile(__dirname + '/page1.html');
});
app.get('/page2', function(req, res){
res.sendFile(__dirname + '/page2.html');
});
But I want users to always stay on the same address, it must always be example.com/
You can use express middleware for authentication.
function authCheck(req,res,next){
//Your auth check will be here
if(isValidUser){
next();
}
else{
res.sendFile(__dirname + '/login.html');
}
}
app.get('/afterlogin', authCheck, function(req, res){
res.sendFile(__dirname + '/afterlogin.html');
});
You can use Passport for authentication provider.
Then you can register some authentication middleware like so:
// auth.js
module.exports = {
isGuest: (req, res, next) => {
if (req.isAuthenticated()) {
res.redirect('/');
} else {
next();
}
},
isAuthenticated: (req, res, next) => {
if (req.isAuthenticated()) {
next()
} else {
res.redirect('/users/login')
}
},
};
Then you can apply the middleware on your routes like so:
// users.js
let express = require('express'),
router = express.Router(),
usersController = require('../controllers/usersController'),
auth = require('../middlewares/auth');
router.get('/register', auth.isGuest, (req, res) => {
usersController.showRegisterPage(req, res);
});
router.post('/register', auth.isGuest, (req, res) => {
usersController.register(req, res);
});
router.get('/login', auth.isGuest, (req, res) => {
usersController.showLoginPage(req, res);
});
router.post('/login', auth.isGuest, (req, res) => {
usersController.login(req, res);
});
router.post('/logout', (req, res) => {
usersController.logout(req, res);
});
router.get('/profile/:username', auth.isAuthenticated, (req, res) => {
usersController.showProfilePage(req, res);
});
Hope this helps.
The below code not functioning as expected
var express = require('express');
var app = express();
app.use(function(req, res, next) {
console.log('first text');
next();
}, function (req, res, next) {
console.log('secondText');
res.end()
}).listen(3000)
app.use([path,] function [, function...])
Mounts the specified middleware function or functions at the specified path. If path is not specified, it defaults to '/' in express documentation but I can't run the second function, not sure why. When I try localhost:3000 in Firefox I receive Cannot GET /
This code is working, but previously it wasn't working:
var express = require('express');
var app = express();
app.use(function(req, res, next) {
console.log("one");
next();
})
.use(function(req,res,next){
console.log("second");
res.end()
})
.listen(3000)
Could it be because of the missing .?
var express = require('express');
var app = express();
app.use(function(req, res, next) {
console.log('first text');
next();
}, function (req, res, next) {
console.log('secondText');
}).listen(3000) //Was missing a period
Am I doing something wrong here, or does express just not support next('route') with .use()?
var express = require('express')
var app = express()
app.use([
function (req, res, next) {
return next('route')
},
function (req, res, next) {
return res.send('sigma')
},
])
app.use(function (req, res, next) {
return res.send('alpha')
})
module.exports = app
This serves the string sigma and should server the string alpha.
Update: just tried this and it didn't work as well.
var express = require('express')
var app = express()
app.use('/', [
function (req, res, next) {
return next('route')
},
function (req, res, next) {
return res.send('sigma')
},
])
app.use('/', function (req, res, next) {
return res.send('alpha')
})
module.exports = app
Update, this too:
var express = require('express')
var app = express()
app.use(function (req, res, next) {
return next('route')
},
function (req, res, next) {
return res.send('sigma')
})
app.use(function (req, res, next) {
return res.send('alpha')
})
module.exports = app
According to the discussion in node issue #2591: since app.use() defines middleware, and not a "route", next('route') is meaningless when used with app.use().
The only difference I can tell between .all and .use is that .use defaults the path to /.
So this works:
var express = require('express')
var app = express()
app.all('/', [
function (req, res, next) {
return next('route')
},
function (req, res, next) {
return res.send('sigma')
},
])
app.all('/', function (req, res, next) {
return res.send('alpha')
})
module.exports = app