express middleware functions invoked twice when request is made from browser - node.js

Below is my nodejs code
const express = require('express');
const app = express();
app.use('/', (req, res, next) => {
console.log("In interceptor");
next();
});
app.use('/users', (req, res, next) => {
console.log('In /users middleware');
res.send('<h1>From "/users" handler </h1>');
});
app.use('/', (req, res, next) => {
console.log("Default handler");
res.send('<h1>From default handler</h1>');
});
app.listen(3000);
Console output when a request is made from browser (both chrome and edge)
http://localhost:3000
******************
In interceptor
Default handler
In interceptor
Default handler
******************
http://localhost:3000/users
******************
In interceptor
In /users middleware
In interceptor
Default handler
******************
But when a request is made using curl, I don't see multiple invocations
curl http://localhost:3000
******************
In interceptor
Default handler
******************
curl http://localhost:3000/users
******************
In interceptor
In /users middleware
******************
Can someone explain why middleware functions are invoked multiple times when request is made from browser?

The usual reasons you see multiple requests when a page loads from a browser are one of two things:
The browser automatically requesting the favicon.ico file.
The browser attempting to load some resource from the HTML file (script file, image, CSS file, etc..)
You can see exactly what each request is for by adding:
console.log(req.url);
to your middleware.

Found that it is happening due to /favicon.ico request made by browser. Adding specific handler (shown below) prevented default handler from being called twice
app.use('/favicon.ico', (req, res, next) => {
console.log('favicon handler');
res.sendStatus(200);
});

Related

express gives error 404 on when trying to visit existing route

I have created a route to 404.html page if user enters incorrect url route
app.use(function (req, res, next) {
res.status(404).sendFile('public/404.html', {root: __dirname})
})
The problem is that when I enter existing route (in this case I use oauth google authentication) it still leads me to 404 page I created but It should redirect me to google login page.
app.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
Same with logout, it leads me to 404 page
app.get('/logout', (req, res) => {
console.log(`\n`);
console.log('\x1b[1m\x1b[31m', `*** User ${req.user.displayName} has logged out ***`);
req.session = null;
req.logout();
res.redirect('/');
});
Your 404 route needs to be the last route you declare. The declaration order matters. This way, the 404 route handler executes ONLY when no other route has already handled the request (which is what you want it to do).
In Express, routes attempt to match the incoming request in the order the route handlers are registered. Since your 404 handler matches all routes, it has to be last so that it comes into play only when no other route handler has already taken the request.
This is what I always use:
// Pages
app.get('/file', function(req, res){
res.sendFile('/path/to/file.html');
});
// 404
app.get('*', function(req, res){
res.sendFile('/path/to/404/file.html');
res.statusCode = 404;
});
Make sure the 404 handler is after all existing responses, and make sure you restart your server after updating.

Does res.send() in an Express JS handler automatically call next()?

I understand that one can call next after res.send in an ExpressJS handler, but does res.send 'automagically' call next in any case?
I have the following code
const express = require('express');
var app = express();
app.get('/', (req, res, next) => {
console.log('in route handler')
res.send('Hello World')
});
app.use((req,res, next) => {
console.log('in middleware')
console.log('...........')
})
app.listen(process.env.PORT || 8080)
My console log is
in route handler
in middleware
...........
If I do indeed call next explicitly after res.send I get
in route handler
in middleware
...........
in middleware
...........
and thus it would seem the middleware is being called twice.
Why is this? Is it because the middleware is also called 'directly' in some fashion, regardless of the route? That is, it is simply always called, even when it is after the route handlers? But I thought if it was after the route handlers, to reach the middleware the route handler preceding it has to call next, as here https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/, where it says "It turns out the order in which you add the middleware is important. And since the 2nd 'use' method is added after the 'get' handler, it is never called. The 'get' handler short-circuits the middleware when it renders the page, preventing any further middleware from being processed."
Express version 4.16.0, Node version 11.2.0
Thanks for any clarification!
Why is this?
It's because browsers send an additional request to get favicon; When you go to localhost:8080 chrome ( or firefox ) sends a get request to / hence your server matches this route and logs:
in route handler
Immediately after that it sends a second get request to /favicon.ico but your server does not match any route. it continues its way to middlewares mounted after routing and so logs:
in middleware
...........
Of course by calling next() you've called your middleware explicitly after two above request and so:
in route handler
in middleware
...........
in middleware
...........
But I thought if it was after the route handlers, to reach the
middleware the route handler preceding it has to call next
Of course you are right. Add serve-favicon middleware to your app and your custom middleware never get called without calling next() explicitly unless none of the routes does not get matched:
const express = require('express');
var favicon = require('serve-favicon')
var path = require('path')
var app = express()
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
app.get('/', (req, res, next) => {
console.log('in route handler')
res.send('Hello World')
});
app.use((req,res, next) => {
console.log('in middleware')
console.log('...........')
})
app.listen(process.env.PORT || 8080)
By the way this middleware mounted after all routes is proper place for handling 404's because if we get to this point, none of our apps routes got matched.
app.use()
Middleware allows you to have set of actions which your routes should follow. Consider as if all your routes will do some processing before actually performing designated action for that route.
When I ran your code it printed below and Hello World was rendered in both Mozilla(Version 63.0.3 (64-bit)) and Chrome(Version 71.0.3578.80)
in route handler in middleware ...........
res.send()
Now coming to your question, no there is no need to call next() after res.send() is called. Because as soon as it is encountered, it'll send the response immediately. And yes you are correct the order of middleware does matter. So when you added next() after res.send() following actions were performed:
First the '/' route will return Hello World on the browser stop loading
Your middleware will be called twice, once due to next() and 2nd time due to middleware itself.

When to use express.use, express.get, and express.post

What is the differences betwenn the 3 functions use/get/post with express?
In which case is better to use express.use instead of express.get/post?
app.use is used to load the middleware functions.
app.use example:
var myUseFunction = function (req, res, next) {
console.log('Hello World!');
next();
}
app.use(myUseFunction);
It does not have limitations for any restful api http verbs like POST, GET, PUT, PATCH, and DELETE.
app.get is route method is derived from one of the HTTP methods, and is attached to an instance of the express class.It serves the pupose of get request of apis.
GET method route
app.get('/', function (req, res) {
res.send('GET request to the page');
});
app.post is route method is derived from of the HTTP methods, and is attached to an instance of the express class. It serves the pupose of post request of apis.
POST method route
app.post('/', function (req, res) {
res.send('POST request to the page');
});
use is for middleware, e.g., all requests. It says it right in the docs:
Mounts the specified middleware function or functions at the specified path.
get is... for GET requests. post is for POST requests.

NodeJS response not sending index.html

app.get(`/`, (req, res, next) => {
console.log(`in / get`);
const indexHtml = path.resolve( __dirname + '/../public/index.html' );
res.sendFile(indexHtml);
next();
});
I'm trying to make this index.html show up on my home route using express but it's not loading. I get the console log, and I've console logged indexHTML to ensure the path is correct, but all I get is an error of cannot get.
All my other routes that are brought it are working a-ok. Just not this guy.
Remove the call to next() after res.sendFile(). You want the res.sendFile() to handle the response entirely, but calling next() passes on control to other handlers, probably ending up in the 404 handler and because that doesn't have to read the disk, it gets processed before res.sendFile() does it's job.
When you send the response, you do not want to call next() because you don't want any more request handlers in the chain to run.

How do I remove a GET/POST router endpoint from express?

So I have defined an express endpoint like:
router.get('/hello', function(req, res) {
res.send('hello');
});
Later on in the code, I have something like:
router.get('/gosilent', function(req, res) {
// When this is called, it removes /hello endpoint
// such that any subsequent calls to /hello will return standard 404.
});
How do I make it work? I know how to bind endpoints but how do I unbind then?
I'm using Express 4.0.
Thanks!

Resources