Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to throw a 404 error in express.js?

In app.js, I have

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

so if I request some not exist url like http://localhost/notfound, above code will execute.

In exist url like http://localhost/posts/:postId, I would like to throw 404 error when access some not exist postId or deleted postId.

Posts.findOne({_id: req.params.id, deleted: false}).exec()
  .then(function(post) {
    if(!post) {
      // How to throw a 404 error, so code can jump to above 404 catch?
    }
like image 552
Sato Avatar asked Apr 25 '16 10:04

Sato


3 Answers

In Express, a 404 isn't classed as an 'error', so to speak - the reasoning behind this is that a 404 isn't usually a sign that's something's gone wrong, it's just that the server couldn't find anything. Your best bet is to explicitly send a 404 in your route handler:

Posts.findOne({_id: req.params.id, deleted: false}).exec()
  .then(function(post) {
    if(!post) {
      res.status(404).send("Not found.");
    }

Or alternatively, if this feels like too much repeated code, you could always pull that code out into a function:

function notFound(res) {
    res.status(404).send("Not found.");
}

Posts.findOne({_id: req.params.id, deleted: false}).exec()
      .then(function(post) {
        if(!post) {
          notFound(res);
        }

I wouldn't recommend using a middleware in this situation solely because I feel like it makes the code less clear - the 404 is the direct result of the database code not finding anything, so it makes sense to have the response in the route handler.

like image 97
Joe Clay Avatar answered Nov 19 '22 20:11

Joe Clay


I have the same app.js structure, and I solved this problem in this way in the route handler:

router.get('/something/:postId', function(req, res, next){
    // ...
    if (!post){
        next();
        return;
    }
    res.send('Post exists!');  // display post somehow
});

The next() function will call the next middleware which is the error404 handler if it is right after your routes in the app.js.

like image 4
Herbertusz Avatar answered Nov 19 '22 20:11

Herbertusz


You can use this and the end of your routers.

app.use('/', my_router);
....
app.use('/', my_router);

app.use(function(req, res, next) {
        res.status(404).render('error/404.html');
    });
like image 1
DJeanCar Avatar answered Nov 19 '22 21:11

DJeanCar