I have the following app code:
(app.js)
var express = require('express')
, app = express()
, port = process.env.PORT || 8082
app.use(require('./controllers'))
app.use(function(req, res, next) {
res.send('Test')
next()
})
app.listen(port, function() {
console.log('Listening on port ' + port)
})
and two controllers:
(index.js)
var express = require('express')
, router = express.Router()
router.use('/projects', require('./projects'))
module.exports = router
(projects.js)
var express = require('express')
, router = express.Router()
router.get('/:id', function(req, res, next) {
res.json({project: req.params.id})
})
module.exports = router
This works but now I have to check my url for a valid token.
My url looks like http://server/api/projects?token=abc or http://server/api/projects/:id?token=abc
If the token is not valid no projects (or other controllers) should be load / shown.
What is the best way to handle this and where (in app.js or controllers/index.js)?
Use a middleware.
app.use(function (req, res, next) {
if (checkToken(req.query.token) {
return next();
}
res.status(403).end("invalid token");
});
app.use(require('./controllers'))
You can do this validation inside your route function or you can use a middleware that validates the param and then do some logic.
var express = require('express')
, router = express.Router()
function validate(req,res,next) {
if(req.params.id) // some logic
else other stuff
next();
}
router.get('/:id', validate, function(req, res, next) {
res.json({project: req.params.id})
})
module.exports = router
Related
app.js
const adminRoutes = require('./routes/admin');
app.use('/admin/customer/:customerId', (req, res, next) => {
console.log('middleware id=', req.params.customerId);
next();
}, adminRoutes);
and here is routes/admin.js
const express = require('express');
const router = express.Router();
router.post('/user', (req, res) => {
console.log('route id=', req.params.customerId);
res.json(req.params);
});
module.exports = router;
I am getting following output
middleware id= 1
route id= undefined
while expected output is
middleware id= 1
route id= 1
You need to use Router options property mergeParams if you want to access params from the parent router.
const express = require('express');
const router = express.Router({mergeParams:true});
router.post('/user', (req, res) => {
console.log('route id=', req.params.customerId);
res.json(req.params);
});
module.exports = router;
You can try this:
You can directly call your route without using another callback and it should work
app.js
const adminRoutes = require('./routes/admin');
app.use('/admin/customer/:customerId',adminRoutes);
If it does't work then you will have to set the params in request object before using your routes
I use a regular exp to match a path and route the request to pageRouter.
When I request the localhost:8000/new, the regular EXP looks not work, but I have test the EXP use /^\/(?!api$|api\/.*|resource$|resource\/.*)/.test('/new'), it return true.
What happened?
router.use('/api',apiRouter);
router.use('/resource',resourceRouter);
router.use(/^\/(?!api$|api\/.*|resource$|resource\/.*)/,pageRouter);
pageRouter.get("*",(req,resp,next)=>{let name = req.originalUrl...})
In this case, instead of regexp you just need to use the wildcard :
const express = require('express'); const app = express()
app.get('/api', function(req, res){ res.send('API·Router') })
app.get('/resource', function(req, res){ res.send('RESOURCE·Router') })
app.get('/*', function(req, res){ res.send('[*] PAGE.Router') })
app.listen(3000)
Its important to define all the other routes before the wildcard '/*'
WHY? : If your first route is the wildcard, it will trap all the requests
Detecting Paths using Wildcard
app.get('/*', function (req, res) {
var paths = req.path.split("/")
if(paths[1].length==0){
res.send('[/] Page.Root')
}else if(paths[1]=='portal'){
if(paths[2]){ res.send('[*] PAGE.Router : '+paths[2]) }
else{ res.send('[*] PAGE.Router : '+paths[1]) }
}else{ res.send('[404] PATH : '+paths[1]+' not found!') }
});
Using an array :
If you have a specific list of routes that you want to use for pageRouter you can always group them inside an array for the first argument of the app.get() handler :
const pageRoutes = ['en/page','es/pagina','dk/side','jp/頁']
app.get(pageRoutes, function(req, res){ res.send('[*] PAGE.Router') })
It seems OP is trying to exclude /api and /resource for pageRouter by regular expression. However, it's not needed. As long as /api and /resource router are defined before pageRouter, they will be triggered first, and won't go though pageRouter any more.
Just define /api and /resource before pageRouter, and then use router.use('/', pageRouter);, so that all URL except /api and /resource will be listened by pageRouter.
Here is the example code. I've verified and confirmed that HTTP request to /resource won't go through pageRouter.
Files:
./app.js
./routes.js
./pageRouter.js
./resourceRouter.js
For ./app.js:
const express = require('express');
const app = express();
const routes = require('./routes');
app.use('/', routes);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
For ./routes.js:
var express = require('express');
var router = express.Router();
const resourceRouter = require('./resourceRouter');
const pageRouter = require('./pageRouter');
router.use('/resource',resourceRouter);
router.use('/', pageRouter);
module.exports = router;
For ./resourceRouter.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.send('respond with resource');
});
module.exports = router;
For ./pageRouter.js:
var express = require('express');
var router = express.Router();
router.get('/resource', function(req, res, next) {
console.log('hit /resource in pageRouter');
res.send('respond with page by /resource');
});
router.get('/new-page', function(req, res, next) {
res.send('respond with page by /new-page');
});
router.get('*', function(req, res, next) {
console.log('hit * in pageRouter');
res.send('respond with page by *');
});
module.exports = router;
After running ./app.js, the HTTP GET request for /resource would never hit ./pageRouter.js.
I got an answer from the expressjs's github,the link is https://github.com/expressjs/express/issues/3404
It is not just a matter of does the regular expression match the
input, but since .use needs to strip down the matched path, it expects
your match to stop before a / character to cut on.
I have a route file in my project and it is called from my app with these lines:
var index = require('./routes/index');
app.use('/', index);
But I need to separate the route file, and I'm trying to do this:
var index = require('./routes/index');
var user = require('./routes/user');
app.use('/', index);
app.use('/user', user);
In route user.js I put the service that I need to access from the client. But it's not working. I don't know what is wrong, I am a beginner in Node.js.
The request returns:
GET /user/find 304 4.203 ms - -
And user.js file is:
var router = express.Router();
router.get('/user/find',function(req, res){
Object.find(function(err, s){
if(err) res.send(err);
res.json(s);
});
});
module.exports = router;
*This request works well on index.js
You put user router under /user route, and in your user router you defined app.get('/user/find'), so the actual path would be /user/user/find, you need to remove the user prefix in router
var router = express.Router();
router.get('/find',function(req, res){
Object.find(function(err, s){
if(err) res.send(err);
res.json(s);
});
});
module.exports = router;
A simple way to do this can be:
index.js
var express = require('express')
var app = express()
var route1 = require('./route1')
var route2 = require('./route2')
app.use('/', route1);
app.use('/hello', route2);
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
route1.js
var express = require('express')
var router = express.Router()
router.get('/', function (req, res) {
res.send('Hello route1');
})
module.exports = router
route2.js
var express = require('express')
var router = express.Router()
router.get('/', function (req, res) {
res.send('Hello route2');
})
module.exports = router
Have you made sure to include a module.exports = router at the end of each of your route files?
Your route files should be set up thusly:
var router = require('express').Router();
router.get("/example", function (req, res) {
res.send("Hello");
});
module.exports = router;
How do I use multiple router files using express framework?
In my app.js, I have the following code:
var controller = require('./controller/index');
var healthController = require('./controller/health/');
app.use('/', controller);
app.use('/health', healthController);
And controller/index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
module.exports = router;
And health.js:
var express = require('express');
var router = express.Router();
/* GET health confirmation. */
router.get('/health', function(req, res, next) {
res.send('OK');
});
module.exports = router;
When I hit the http://localhost:8000/, I get the correct page without any problem, however, http://localhost:8000/health results in 404 error.
Thanks in advance.
Assuming the "health.js" resides in "controller" directory, may it be just a typo issue? var healthController = require('./controller/health/'); has a trailing slash (/). Removing it would fly? So it becomes var healthController = require('./controller/health');
Your single node app must have single router object, a router object represents a server in express requiring unique port.
Hence you should create router object in you app.js passing it to all router files.
Code will be like -
app.js
var express = require('express');
var router = express.Router();
var controller = require('./controller/index');
var healthController = require('./controller/health/');
controller(router);
healthController(router);
index.js
module.exports = function(router) {
router.get('/', function(req, res, next) {
res.render('index');
});
}
health.js
module.exports = funtion(router) {
router.get('/health', function(req, res, next) {
res.send('OK');
});
}
See How to include route handlers in multiple files in Express?.
Export an anonymous function that can be "initiated" with a reference to the original express app.
./controller/index.js:
module.exports = function(app) {
/* GET home page. */
app.get('/', function(req, res, next) {
res.render('index');
});
};
./controller/health.js:
module.exports = function(app) {
/* GET health confirmation. */
app.get('/health', function(req, res, next) {
res.send('OK');
});
};
./app.js:
var app = require('express')();
var controller = require('./controller/index');
var healthController = require('./controller/health');
controller(app);
healthController(app);
Change in health.js:
router.get('/health', function(req, res, next) {
res.send('`OK`');
});
to
router.get('/', function(req, res, next) {
res.send('OK');
});
This will work fine check it out.
I have a middleware function to do the basic authorization which is in app.js (starter javascript). But there are a few router files in other javascript files. My question is how I can call the authorization middleware function in my router?
Here is my app.js:
var basicAuth = require('basic-auth');
var auth = function (req, res, next) {
function unauthorized(res) {
res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return res.send(401);
};
var user = basicAuth(req);
if (!user || !user.name || !user.pass) {
return unauthorized(res);
};
if (user.name === 'foo' && user.pass === 'bar') {
return next();
} else {
return unauthorized(res);
};
};
module.exports = app;
My router file index.js:
var express = require('express');
var router = express.Router();
router.get('/', auth, function(req, res) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Apparently the auth is not defined here. Can anybody tell me how can I use auth middleware function in my index.js router functions? Thanks
I'm not sure exactly what you're attempting to export with.
module.exports = app;
in app.js
Here is a simplifed solution:
index.js
var express = require('express');
var app = express();
var auth = require('./auth');
var router = express.Router();
router.use(auth); // Auth middleware is first
router.get('/', function(req, res) {
return res.send('Hello world');
}
// More routes can go here
// require('./external')(router);
// router.get('/route', function(req, res) {}
app.use(router);
app.listen(3000);
auth.js
module.exports = function(req, res, next) {
return next();
}
If you have routes in other files you can either pass app or router
external.js
module.exports = function(router) {
}
Why not put your auth middleware in a separate file that you can require() and use from both app.js and your router files?