Lets say I want to have 2 different instances in "subfolders" in the url. In app js I have it defined like this:
var routes = require('./routes/index');
app.use('/myapp1', routes);
app.use('/myapp2', routes);
The inner routing would be the same.
But still in the router I want to "get" the path defined in the app.use - eg.: myapp1, myapp2
How do I get this in the router?
From routes/index.js:
router.use(/\/.*/, function (req, res, next) {
// want to see "myapp1/myapp2" without the *sub* path defined in this particular router eg.: /products /user etc.
next();
});
You might want to use the req.baseUrl property.
Example:
routes.get('/1', function(req, res) {
res.send([
req.baseUrl,
req.path,
req.baseUrl + req.path,
].join('\n'));
});
app.use('/api', routes);
Making an HTTP request to /api/1 would print:
/api
/1
/api/1
var express = require('express');
var app = express();
var router = express.Router();
app.use(function(req, res, next) {
req.appInstance = (req.url.indexOf('/app2/') == 0) ? 2 : 1;
next();
});
app.get('/', function(req, res, next) {
res.redirect('/app1/user');
});
router.get('/user', function(req, res, next) {
res.send(req.url +' on app' + req.appInstance);
});
app.use('/app1', router);
app.use('/app2', router);
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Related
I would like to understand the order precedence in express.js. For example, as bellow code
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/api', api);
app.use('/users', users);
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
If a request come from client localhost:3000/api/abc and localhost:3000/user/abc, the response from api and user module. But if I make a request like localhost:3000/myName/xyz, the app module return a response. This behavior let me concern about what is precedence of expressjs and what is correct order for router modules. Why routers do not confuse between actions "api", "users" and parameter ":name". Please let me understand clearly how express does and what is precedence.
The order is first come first serve.
In your case, if user hits /api, he will get response from api, but if you write /:name route before /api, /:name will serve for /api requests also.
Case1: /api will serve requests for /api.
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/api', api);
app.use('/users', users);
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
Case2: /:name serves requests for /api and /users
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/api', api);
app.use('/users', users);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
The example given in the ExpressJS documentation is pretty simple and was unfortunately difficult to find. I only found it through another SO question.
Middleware functions are executed sequentially, therefore the order of middleware inclusion is important
app.use(function(req, res, next) {
res.send('This is the only thing that ever happens')
}
app.use(...) // never used
app.get(...) // never used
app.put(...) // never used
app.post(...) // never used
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.
Is it possible to apply different ip filters to different routes?
For example, I want only people from 123.123.123.123 can access my server's /test route, and only people from 124.124.124.124 can access my server's / route.
I know that express-ipfilter can restrict site access by IP Address. But it cannot apply the filter to specific routes.
I also know that adding app.use(ipfilter(ips, {})); in the middle of the routes can apply filter only to the routes below:
var express = require('express'),
ipfilter = require('express-ipfilter').IpFilter;
var ips = ['::ffff:127.0.0.1'];
var app = express();
app.get('/test', function(req, res) {
res.send('test');
});
app.use(ipfilter(ips, {})); // the ipfilter only applies to the routes below
app.get('/', function(req, res) {
res.send('Hello World');
});
app.listen(3000);
But I want different filters for different routes.
Is it possible to do this?
Yeah, it's possible. You could do something like:
app.get('/test', function(req, res){
var trustedIps = ['123.123.123.123'];
var requestIP = req.connection.remoteAddress;
if(trustedIps.indexOf(requestIP) >= 0) {
// do stuff
} else {
// handle unallowed ip
}
})
You may need to make sure that requestIP is correctly formatted though.
Warning: package express-ipfilter is now deprecated.
You can chain middlewares (and ipFilter is a middleware). There are 2 ways to do this:
var express = require('express'),
ipfilter = require('express-ipfilter').IpFilter;
var ips = ['::ffff:127.0.0.1'];
var testers = ['1.2.3.4'];
var app = express();
app.get('/test', ipfilter(testers, {mode: 'allow'}), function(req, res) {
res.send('test');
});
// the ipfilter only applies to the routes below
app.get('/', ipfilter(ips, {mode: 'allow'}), function(req, res) {
res.send('Hello World');
});
app.listen(3000);
Or qualify the use of the middleware:
var express = require('express'),
ipfilter = require('express-ipfilter').IpFilter;
var ips = ['::ffff:127.0.0.1'];
var testers = ['1.2.3.4'];
var app = express();
app.use('/test', ipfilter(testers, {})); // the ipfilter only applies to the routes below
app.get('/test', function(req, res) {
res.send('test');
});
app.use('/', ipfilter(ips, {})); // the ipfilter only applies to the routes below
app.get('/', function(req, res) {
res.send('Hello World');
});
app.listen(3000);
In your main file where u defined app,
app.use('/test',require('./whereever-my-route-is-located-where /test routes '));
app.use('/',require('./wherever-my-this-routes-are-located'))
in your route file .
var express = require('express'),
router = express.Router();
//Ip verification for all requests : for whereever-my-route-is-located-where /test routes
router.use(function(req, res, next) {
//verify Ip Logic
});
//this will be called for every route u define in that file, if it fails.
This is my code:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/test-angular.html');
})
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.sendFile(__dirname + '/public/error.html');
});
var server = app.listen(3000, function () {
console.log("Example app listening on port 3000");
});
When I access the url http://localhost:3000/xyz, which does not exist, I get the standard page saying Cannot GET /xyz, instead of my custom error page. Why?
The function signature you're using (err, req, res, next) is for errors. E.g. a middleware calls next(new Error('failed')). What you need is a regular middleware which simply happens to be the last one that is executed, which means you interpret it as 404 (see answer below).
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/test-angular.html');
})
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.sendFile(__dirname + '/public/error.html');
});
//------------------
app.use(function(req, res, next) {
res.status(404);
res.sendFile(__dirname + '/public/error.html');
});
//------------------
var server = app.listen(3000, function () {
console.log("Example app listening on port 3000");
});
Node usually starts matching endpoints from top to bottom.
So first write down all the endpoints of your app, then write an endpoint like below at the end which will be executed when none of your defined endpoints match.
app.get('/path1', handler1);
app.get('/path2', handler2);
app.get('/path3', handler3);
app.get('/*',function (req, res) {
//This block will executed when user tries to access endpoint other than /path1,/path2,/path3
// Handle error here
})
Your code should look like this :
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/test-angular.html');
})
app.get('/*',function (req, res) { //If any of your defined endpoints doesn't match, this block will be executed.
res.status(404);
res.sendFile(__dirname + '/public/error.html');
});
var server = app.listen(3000, function () {
console.log("Example app listening on port 3000");
});
I would like to understand the order precedence in express.js. For example, as bellow code
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/api', api);
app.use('/users', users);
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
If a request come from client localhost:3000/api/abc and localhost:3000/user/abc, the response from api and user module. But if I make a request like localhost:3000/myName/xyz, the app module return a response. This behavior let me concern about what is precedence of expressjs and what is correct order for router modules. Why routers do not confuse between actions "api", "users" and parameter ":name". Please let me understand clearly how express does and what is precedence.
The order is first come first serve.
In your case, if user hits /api, he will get response from api, but if you write /:name route before /api, /:name will serve for /api requests also.
Case1: /api will serve requests for /api.
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/api', api);
app.use('/users', users);
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
Case2: /:name serves requests for /api and /users
var routes = require('./routes/index');
var users = require('./routes/users');
var api = require('./routes/api');
app.use('/:name', function(req, res, next) {
console.log('from app.js name:', req.params.name);
res.render('index', {
title: req.params.name
});
}, routes);
app.use('/api', api);
app.use('/users', users);
app.use('/', function(req, res, next) {
res.render('index', {
title: 'MainPage'
});
});
The example given in the ExpressJS documentation is pretty simple and was unfortunately difficult to find. I only found it through another SO question.
Middleware functions are executed sequentially, therefore the order of middleware inclusion is important
app.use(function(req, res, next) {
res.send('This is the only thing that ever happens')
}
app.use(...) // never used
app.get(...) // never used
app.put(...) // never used
app.post(...) // never used