How can I get Express.js to 404 only on missing routes? - node.js

At the moment I have the following which sits below all my other routes:
app.get('*', function(req, res){
console.log('404ing');
res.render('404');
});
And according to the logs, it is being fired even when the route is being matched above. How can I get it to only fire when nothing is matched?

You just need to put it at the end of all route.
Take a look at the second example of Passing Route Control:
var express = require('express')
, app = express.createServer();
var users = [{ name: 'tj' }];
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('cannot find user ' + req.params.id));
}
});
app.get('/user/:id', function(req, res){
res.send('viewing ' + req.user.name);
});
app.get('/user/:id/edit', function(req, res){
res.send('editing ' + req.user.name);
});
app.put('/user/:id', function(req, res){
res.send('updating ' + req.user.name);
});
app.get('*', function(req, res){
res.send('what???', 404);
});
app.listen(3000);
Alternatively you can do nothing because all route which does not match will produce a 404. Then you can use this code to display the right template:
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
});
It's documented in Error Handling.

I bet your browser is following up with a request for the favicon. That is why you are seeing the 404 in your logs after the 200 success for the requested page.
Setup a favicon route.

You can this at the end of all routes,
const express = require('express');
const app = express();
const port = 8080;
// All your routes and middleware here.....
app.use((req, res, next) => {
res.status(404).json({
message: 'Ohh you are lost, read the API documentation to find your way back home :)'
})
})
// Init the server here,
app.listen( port, () => {
console.log('Sever is up')
})

Hope it helpful, I used this code in bottom of routes
router.use((req, res, next) => {
next({
status: 404,
message: 'Not Found',
});
});
router.use((err, req, res, next) => {
if (err.status === 404) {
return res.status(400).render('404');
}
if (err.status === 500) {
return res.status(500).render('500');
}
next();
});

You can use this
const express = require('express');
const app=express();
app.set('view engine', 'pug');
app.get('/', (req,res,next)=>{
res.render('home');
});
app.use( (req,res,next)=>{
res.render('404');
})
app.listen(3000);

I wanted a catch all that would render my 404 page only on missing routes and found it here in the error handling docs https://expressjs.com/en/guide/error-handling.html
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(404).render('404.ejs')
})
This worked for me.

Very simple you can add this middleware.
app.use(function (req, res, next) {
//Capture All 404 errors
res.status(404).render("404.ejs")
})
404 error in a service is typically used to denote that the requested resource is not available. In this article we will see how to handle 404 error in express.

We need to handle the Error and Not-Found collectively as
Write two separate middleware for each,
// Import necessary modules
const express = require('express');
// Create a new Express app
const app = express();
// Define routes and middleware functions
app.get('/', (req, res) => {
res.send('Hello World!');
});
// Catch 404 Not Found errors and forward to error handler
app.use((req, res, next) => {
const error = new Error('Not Found');
error.status = 404;
next(error);
});
// Error handler middleware function
app.use((err, req, res, next) => {
// Set status code and error message based on error object
res.status(err.status || 500);
res.send({
error: {
message: err.message
}
});
});
// Start the server
app.listen(3000, () => {
console.log('Server started on port 3000');
});

Related

Error handling problem with Nodejs and Express

I'm trying to handle errors produced in a Nodejs with Express app. I'm following Express error-handling guide but the errors didn't catched, and nothing appears on console and browser simply show Cannot GET /abc when request the incorrect url http://localhost:3000/abc
const express = require("express")
const app = express()
const port = 3000
const config = require("./config.js");
function logErrors (err, req, res, next) {
console.error(err.stack)
next(err)
}
function errorHandler (err, req, res, next) {
res.status(500)
res.render("error", { error: err })
}
app.all("/", function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
app.get("/favicon.ico", (req, res) => res.status(204));
app.use(express.static("public"))
app.use("/zips/:idReq", express.static("zips"))
const generateZip = require("./generateZip")
const fmeForm = require("./fmeForm")
app.get("/", function (req, res) {
res.send("Hello World !")
})
app.use("/generateZip", generateZip)
app.use("/downloadForm", fmeForm)
app.use(logErrors)
app.use(errorHandler)
app.listen(port, () => console.log(`${config.nameServer} App listening on port ${port}`))
Any idea?
You need to include a common route handler to invoke error handling method at last
app.all('*', function (req, res, next) {
// Either invoke error handler method by raising new error
next(new Error('page not found'));
// Or simply return the response
res.status(404).send('page not found')
})

What are different between next(error) and throw new Error in Express framework?

Can someone explain to me about the different between two ways exception error handling in code Express JS below:
const express = require('express');
const app = express();
app.get('/test', (req, res, next) => {
// the first way:
throw new Error('my error message');
// the second way:
next(new Error('my error message'));
});
app.use((err, req, res, next) => {
res.status(err.status || 500).send(err.message || 'Internal Server Error');
});
app.listen(3000, () => console.log('Welcome to ExpressJS'));
It returns the same result handled by error middleware but what is the difference here?
Nothing, based on the source code.
try {
fn(req, res, next);
} catch (err) {
next(err);
}

Node Express custom 404 page

I have a pretty standard Node Express app with a global 404 handler like.
app.get('*', function(req, res){
res.status(404);
res.render('404page');
});
Now in some routes I have code like
app.get('/store/:product', function (req, res) {
if (productNotFound) return res.sendStatus(404);
});
What I would like is the res.sendStatus(404) to redirect to the error page WITHOUT having to change it to res.sendStatus(404).render('404page').
Is that possible?
Just override .sendStatus of res object.
Register this middleware right after creating the express app:
app.use((req, res, next) => {
const sendStatus = res.sendStatus.bind(res);
res.sendStatus = (status) => {
if (status === 404) {
return res.status(404).render('404page');
}
return sendStatus(status);
}
next()
});

Express.js ignore SyntaxError in case of unknown route

In the express app below:
Executing a POST for /push with invalid json data will cause an HTTP 400 error to be sent back to the client
Executing a POST with valid json data, but for an unknown route will cause an HTTP 404 error to be sent back to the client
Executing a POST with invalid json data for an unknown route, will cause an HTTP 400 error to be sent back to the client
What I'd like to achieve, is that in the third scenario, also the 404 would be sent. In other words, in case the route is unknown, I want that to be catched by app.post('*',(req, res, next)), which will throw the 404, and not by the generic middleware error handler, which throws a 400 json SyntaxError
Any way to achieve this?
const express = require('express');
const { handleError, ErrorHandler } = require('./helpers/error');
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.get('/', function(req, res){
res.send('Hello World');
});
app.post('/', function(req, res){
console.log(req.body.data);
res.sendStatus(200);
});
app.post('/push', function(req, res){
console.log('push API');
res.sendStatus(200);
});
app.post('*',(req, res, next) => {
console.log('Unknown route');
throw new ErrorHandler(404, 'API endpoint does not exist.');
});
app.use((err, req, res, next) => {
console.log('Middleware error handling');
handleError(err, res);
});
app.listen(3000, function(){
console.log('Server started on port 3000')
});
error.js content:
class ErrorHandler extends Error {
constructor(statusCode, message) {
super();
this.statusCode = statusCode;
this.message = message;
}
}
const handleError = (err, res) => {
const { statusCode, message } = err;
res.status(statusCode).json({
status: "error",
statusCode,
message
});
};
module.exports = {
ErrorHandler,
handleError
}
By sending a request to a non-existing route, none of your handlers are matched. Thus, your error handling middleware
app.use((err, req, res, next) => {
console.log('Middleware error handling');
handleError(err, res);
});
is executed directly. What you can do is to try to detect a Syntax/parsing error in your handleError function. Something like:
const handleError = (err, res) => {
let {statusCode, message} = err;
if (err.status === 400 && err.message.includes("Unexpected token")) {
statusCode = 404;
}
res.status(statusCode).json({
status: "error",
statusCode,
message
});
};
EDIT:
The issue can be fixed by only using the json-parser middleware for the routes you want to parse json and removing it as a general middleware for all requests:
...
//app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.post('/', express.json(), function (req, res) {
console.log(req.body.data);
res.sendStatus(200);
});
app.post('/push', express.json(), function (req, res) {
console.log('push API');
res.sendStatus(200);
});

created a simple middleware game with Nodejs, and an http header error occurs

I am a beginner studying Nodejs.
I have recently studied node middleware and have created a simple game using middleware.
The purpose of the generated code is to respond to hello by connecting as root and then respond to the browser with 50% probability through the middleware.
However, I get the following error:
I did a search and found that res.send is not available after next ().
Is that correct?
But I could not figure out why and I did not realize why the code did not work.
code
const express = require('express');
var app = express();
app.use('/', (req, res, next) =>{
res.send('hello');
next();
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.listen(3000, () => console.log(`Example!`))
error
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const express = require('express');
var app = express();
app.use(/^\/$/, (req, res, next) =>{
res.send('hello');
return;
});
app.use((req, res, next) => {
if (+new Date() % 2 === 0) {
console.log('continue');
res.send('lucky!');
next();
} else {
console.log('failed');
res.send('end');
}
});
app.listen(3000, () => console.log(`Example!`))
you cannot use res.send() twice
res.send() = Sends the HTTP response.

Resources