Express use function - javascript

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

Related

Execute middleware on every route call

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()})

"next('route')" doesn't work with ".use()"

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

How to handle "Cannot <METHOD> <ROUTE>" in Express?

As a minimal example, consider following code:
var express = require('express');
var bodyparser = require('body-parser');
var app = express();
app.use(bodyparser.json());
app.use(errorhandler);
function errorhandler(err, req, res, next) {
res.setHeader('Content-Length', 0);
res.status(500).end();
}
app.post('/example', function(req, res) {
res.setHeader('Content-Length', 0);
res.status(200).end();
});
var server = app.listen(3000, function() {
console.log('server listening on http://%s:%s ...', server.address().address, server.address().port);
});
When I, for example, now try a PUT on /example, I get a Cannot PUT /example message with 404 status code. The same is true for all other routes and methods I did not declare. My error handler is only getting called on actual errors within a route or the body parser itself.
Is there a way to handle them by myself? I am using Express4.
Define a general handler with no route after all other use/get/post/etc:
app.use(function(req, res, next){
res.status(404);
res.render(...);
}

express (4.0) custom middleware runs on both instances of router even though it's only declared for one

I'm using the code below to learn a bit about the new express.js (4.0). I can't seem to understand why the logging is happening regardless of which path I hit with my browser. Shouldn't it only log for website.get and not for api.get paths?
// Express 4.0 test...
var express = require('express');
var app = express();
var website = express.Router();
var api = express.Router();
var port = process.env.PORT || 3000;
website.use(function (req, res, next) {
console.log(req.method, req.url);
next();
});
website.get('/', function (req, res) {
res.send('Home page');
});
website.get('/about', function (req, res) {
res.send('About page');
});
api.get('/', function (req, res) {
res.send({'json':'response'});
});
api.get('/user', function (req, res) {
res.send({'user':'john'});
});
// app.get('/', function (request, response) {
// response.writeHead(200, {"Content-Type": "text/html"});
// response.end("<h1>Hello, World!</h1>");
// });
app.use('/', website);
app.use('/api', api);
app.listen(port);
console.log('http(s) server revved up on port ' + port);
Any help would rock!
Update: I see, because '/api' matches '/', website gets applied to all routes. Is there any way to avoid this?
probably define the /api router first and the other one - second.
app.use('/api', api);
app.use('/', website);

Using different router for different subdomains in node.js with express

I want to use different routes in my app, depending on the subdomain in req.headers.host.
So I came around with this idea (extremely simplified example):
var express = require('express');
var domain1 = require('./routes/domain1');
var domain2 = require('./routes/domain2');
var app = express();
app.use('*', domainRouting);
function domainRouting(req, res, next){
var subdomain = req.headers.host.split('.')[0];
if(subdomain === 'domain1'){
app.use(domain1);
}
else{
app.use(domain2);
}
next();
}
//404 handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
res.send('error');
});
var server = app.listen(3001, function() {
console.log('Listening on port %d', server.address().port);
});
domain1.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('DOMAIN 1: ' + req.url);
});
module.exports = router;
domain2.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('DOMAIN 2: ' + req.url);
});
module.exports = router;
But this does not work, the routes are ignored and the request jumps into the last 404-handler.
Any ideas for this?
You can't use app.use() dynamically like that within a middleware. You might call your router directly with domain1(req, res, next) instead of app.use(domain1).
Or you might look into using a module like subdomain to make it easier to handle subdomains in Express.

Categories