Comment rediriger les erreurs 404 vers une page dans ExpressJS?

203

Je ne connais pas de fonction pour ce faire, quelqu'un en connaît-il une?

hexacyanide
la source

Réponses:

274

J'ai trouvé cet exemple très utile:

https://github.com/visionmedia/express/blob/master/examples/error-pages/index.js

C'est donc en fait cette partie:

// "app.router" positions our routes
// above the middleware defined below,
// this means that Express will attempt
// to match & call routes _before_ continuing
// on, at which point we assume it's a 404 because
// no route has handled the request.

app.use(app.router);

// Since this is the last non-error-handling
// middleware use()d, we assume 404, as nothing else
// responded.

// $ curl http://localhost:3000/notfound
// $ curl http://localhost:3000/notfound -H "Accept: application/json"
// $ curl http://localhost:3000/notfound -H "Accept: text/plain"

app.use(function(req, res, next){
  res.status(404);

  // respond with html page
  if (req.accepts('html')) {
    res.render('404', { url: req.url });
    return;
  }

  // respond with json
  if (req.accepts('json')) {
    res.send({ error: 'Not found' });
    return;
  }

  // default to plain-text. send()
  res.type('txt').send('Not found');
});
Felix
la source
Veuillez définir "géré"? Qu'est-ce qui marque exactement l'itinéraire comme géré?
Timo Huovinen
1
Je suppose qu'aucun itinéraire correspondant n'a été trouvé jusqu'à ce point.
Felix
2
Pour info, l'utilisation de app.routerest désormais obsolète. Voir github.com/strongloop/express/wiki/…
iX3
2
Pour la réponse JSON, il peut être préférable d'utiliser à la res.jsonplace de res.send(). Ils se comporteraient de la même manière dans votre code, mais l'utilisation res.jsonfera de la magie dans la conversion automatique des objets en chaînes où .send()ils ne le seront pas. Mieux vaut prévenir que guérir. expressjs.com/api.html#res.json
wgp
9
Maintenant, cette question apparaît dans la FAQ expressjs.com/starter/faq.html#how-do-you-handle-404s-
Ivan Fraixedes
158

Je pense que vous devez d'abord définir tous vos itinéraires et comme dernier itinéraire ajouter

//The 404 Route (ALWAYS Keep this as the last route)
app.get('*', function(req, res){
  res.status(404).send('what???');
});

Un exemple d'application qui fonctionne:

app.js:

var express = require('express'),
    app = express.createServer();

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res){
  res.send('hello world');
});

//The 404 Route (ALWAYS Keep this as the last route)
app.get('*', function(req, res){
  res.send('what???', 404);
});

app.listen(3000, '127.0.0.1');

alfred@alfred-laptop:~/node/stackoverflow/6528876$ mkdir public
alfred@alfred-laptop:~/node/stackoverflow/6528876$ find .
alfred@alfred-laptop:~/node/stackoverflow/6528876$ echo "I don't find a function for that... Anyone knows?" > public/README.txt
alfred@alfred-laptop:~/node/stackoverflow/6528876$ cat public/README.txt 

.
./app.js
./public
./public/README.txt

alfred@alfred-laptop:~/node/stackoverflow/6528876$ curl http://localhost:3000/
hello world
alfred@alfred-laptop:~/node/stackoverflow/6528876$ curl http://localhost:3000/README.txt
I don't find a function for that... Anyone knows?
Alfred
la source
6
Eh bien ... le problème est que le "*" correspond déjà aux fichiers .js et .css, et ils ne sont pas spécifiés dans l'application ... eh bien, je ne sais pas s'il existe un moyen d'attraper exactement le même chose que l'erreur 404, ou un moyen d'écraser le message "Impossible d'obtenir ...". Quoi qu'il en soit, merci
1
Utilisez-vous un middleware statique, car alors vous pouvez toujours servir des fichiers statiques?
Alfred
4
app.get('/public/*', function(req, res){ res.sendfile(__dirname + '/public/' + req.url); })vous pouvez utiliser cette route pour envoyer des fichiers statiques. cela fonctionne très bien avec l'itinéraire "*" ci-dessus. app.use(express.static(__dirname + '/public'));ne fonctionne pas pour moi, filaire.
Chris
25
Cela ne fonctionnait pas pour moi, mais j'ai découvert que je suis app.use(express.static(...))venu après app.use(app.router). Une fois que je les ai échangés, tout s'est bien passé.
Stephen
5
+1 pour avoir ajouté le commentaire de @ Stephen à votre réponse. Cela n'a pas fonctionné pour moi non plus jusqu'à ce que je mette app.use (app.router) APRÈS app.use (express.static (...))
braitsch
37

Vous pouvez placer un middleware à la dernière position qui génère une NotFounderreur,
ou même afficher directement la page 404:

app.use(function(req,res){
    res.status(404).render('404.jade');
});
Ganesh Kumar
la source
9
Veuillez envisager une réponse un peu plus détaillée la prochaine fois ... Les exemples sont généralement bien - et c'est un bon exemple - mais certaines explications peuvent également être très, très bonnes ...
Tonny Madsen
2
+1 Très bien! Je pense que c'est mieux qu'un dernier itinéraire, car de cette façon, vous n'avez pas à use()vous rendre app.routerà la dernière fois. (comme dans mon cas)
Alba Mendez
En outre, cela remplace le comportement par défaut sur toute demande (pas seulement GETs). Essayez POSTune URL aléatoire avec l'autre méthode; il renverra la valeur par défaut Cannot POST.... Un attaquant saurait alors que vous utilisez Express.JS.
Alba Mendez
Très bien, sauf en utilisant des ejs que vous n'avez qu'à mettreres.render('404')
locrizak
Cela devrait probablement aussi avoir un statut (404) statut res. (404) .render ('404')
MartinWebb
32

Les réponses ci-dessus sont bonnes, mais dans la moitié d'entre elles, vous n'obtiendrez pas 404 comme votre code d'état HTTP est retourné et dans l'autre moitié, vous ne pourrez pas avoir un rendu de modèle personnalisé. La meilleure façon d'avoir une page d'erreur personnalisée (404) dans Expressjs est

app.use(function(req, res, next){
    res.status(404).render('404_error_template', {title: "Sorry, page not found"});
});

Placez ce code à la fin de tous vos mappages d'URL.

Sushant Gupta
la source
@SushantGupta - Qu'entendez-vous par «mappages d'URL existentiels valides»?
Jonathan Bechtel
@JonathanBechtel Comme dans avoir le bloc de code ci-dessus après vos routes URL non erronées.
Sushant Gupta
6

À la dernière ligne de app.js, mettez simplement cette fonction. Cela remplacera la page d'erreur par défaut de page introuvable:

app.use(function (req, res) {
    res.status(404).render('error');
});

Il remplacera toutes les demandes qui n'ont pas de gestionnaire valide et affichera votre propre page d'erreur.

Vivek Bajpai
la source
2
C'est votre "dernière ligne de app.js" qui a aidé! Merci!
C0NFUS3D
Ajout d'une fonctionnalité à mon application. Merci :)
Pramesh Bajracharya
5

La réponse à votre question est:

app.use(function(req, res) {
    res.status(404).end('error');
});

Et il y a un excellent article sur pourquoi c'est le meilleur moyen ici .

Marius Cotofana
la source
1
Quelle est la difference entre sendet end?
Timo Huovinen
je pense qu'il a raté ça devrait êtresend
Zaid abu khalaf
4

express-error-handler vous permet de spécifier des modèles personnalisés, des pages statiques ou des gestionnaires d'erreurs pour vos erreurs. Il fait également d'autres choses utiles pour la gestion des erreurs que chaque application devrait implémenter, comme se protéger contre les attaques DOS d'erreur 4xx, et l'arrêt gracieux des erreurs irrécupérables. Voici comment vous faites ce que vous demandez:

var errorHandler = require('express-error-handler'),
  handler = errorHandler({
    static: {
      '404': 'path/to/static/404.html'
    }
  });

// After all your routes...
// Pass a 404 into next(err)
app.use( errorHandler.httpError(404) );

// Handle all unhandled errors:
app.use( handler );

Ou pour un gestionnaire personnalisé:

handler = errorHandler({
  handlers: {
    '404': function err404() {
      // do some custom thing here...
    }
  }
}); 

Ou pour une vue personnalisée:

handler = errorHandler({
  views: {
    '404': '404.jade'
  }
});
Eric Elliott
la source
4

Dans certains cas, la page 404 ne peut pas être écrite pour être exécutée en tant que dernier itinéraire, en particulier si vous disposez d'une fonction de routage asynchrone qui introduit un / route en retard pour le correspondant. Le schéma ci-dessous pourrait être adopté dans ces cas.

var express = require("express.io"),
    app = express(),
    router = express.Router();

router.get("/hello", function (req, res) {
    res.send("Hello World");
});

// Router is up here.
app.use(router);

app.use(function(req, res) {
    res.send("Crime Scene 404. Do not repeat");
});

router.get("/late", function (req, res) {
    res.send("Its OK to come late");
});

app.listen(8080, function (){
    console.log("Ready");
});
Dennis Mathew Philip
la source
2
Génial, merci! La seule réponse (?) Qui ne repose pas sur le traitement linéaire d'express (c'est-à-dire "il suffit de mettre le gestionnaire d'erreurs à la fin").
Nick Grealy
2
// Add this middleware
// error handler
app.use(function(err, req, res, next) {
 // set locals, only providing error in development
   res.locals.message = err.message;
   res.locals.error = req.app.get('env') === 'development' ? err : {};

 // render the error page
   res.status(err.status || 500);
   res.render('error');
  });
ASHISH RANJAN
la source
2

La façon la plus simple de le faire est d'avoir un catch all pour la page d'erreur

// Step 1: calling express
const express = require("express");
const app = express();

ensuite

// require Path to get file locations
const path = require("path");

Vous pouvez maintenant stocker toutes vos pages "html" (y compris une page d'erreur "html") dans une variable

// Storing file locations in a variable
var indexPg = path.join(__dirname, "./htmlPages/index.html");
var aboutPg = path.join(__dirname, "./htmlPages/about.html");
var contactPg = path.join(__dirname, "./htmlPages/contact.html");
var errorPg = path.join(__dirname, "./htmlPages/404.html"); //this is your error page

Maintenant, vous appelez simplement les pages à l'aide de la méthode Get et vous avez tout pour tous les itinéraires non disponibles pour les diriger vers votre page d'erreur en utilisant app.get ("*")

//Step 2: Defining Routes
//default page will be your index.html
app.get("/", function(req,res){
  res.sendFile(indexPg);
});
//about page
app.get("/about", function(req,res){
  res.sendFile(aboutPg);
});
//contact page
app.get("/contact", function(req,res){
  res.sendFile(contactPg);
});
//catch all endpoint will be Error Page
app.get("*", function(req,res){
  res.sendFile(errorPg);
});

N'oubliez pas de configurer un port et d'écouter le serveur:

// Setting port to listen on
const port = process.env.PORT || 8000;
// Listening on port
app.listen(port, function(){
  console.log(`http://localhost:${port}`);
})

Cela devrait maintenant afficher votre page d'erreur pour tous les points de terminaison non reconnus!

Kean Amaral
la source
1

Bien que les réponses ci-dessus soient correctes, pour ceux qui souhaitent que cela fonctionne dans IISNODE, vous devez également spécifier

<configuration>
    <system.webServer>
        <httpErrors existingResponse="PassThrough"/>
    </system.webServer>
<configuration>

dans votre web.config (sinon IIS mangera votre sortie).

laktak
la source
2
Je vous remercie!!! Vous êtes le seul sur Internet à avoir l'air de le savoir (ou du moins de le partager)! cheers
André Lucas
1

vous pouvez gérer les erreurs en fonction du type de contenu

En outre, la gestion selon le code d'état.

app.js

import express from 'express';

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

// when status is 404, error handler
app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    if( 404 === err.status  ){
        res.format({
            'text/plain': () => {
                res.send({message: 'not found Data'});
            },
            'text/html': () => {
                res.render('404.jade');
            },
            'application/json': () => {
                res.send({message: 'not found Data'});
            },
            'default': () => {
                res.status(406).send('Not Acceptable');
            }
        })
    }

    // when status is 500, error handler
    if(500 === err.status) {
        return res.send({message: 'error occur'});
    }
});

404.jade

doctype html

html
  head
    title 404 Not Found

    meta(http-equiv="Content-Type" content="text/html; charset=utf-8")
    meta(name = "viewport" content="width=device-width, initial-scale=1.0 user-scalable=no")

  body
      h2 Not Found Page
      h2 404 Error Code

Si vous pouvez utiliser res.format, vous pouvez écrire un code de gestion d'erreur simple.

Recommandation res.format()au lieu de res.accepts().

Si l'erreur 500 se produit dans le code précédent, if(500 == err.status){. . . }est appelée

멍개 -mung
la source
1

Salut s'il te plait trouve la réponse

const express = require('express');
const app = express();
const port = 8080;

app.get('/', (req, res) => res.send('Hello home!'));
app.get('/about-us', (req, res) => res.send('Hello about us!'));
app.post('/user/set-profile', (req, res) => res.send('Hello profile!'));
//last 404 page 
app.get('*', (req, res) => res.send('Page Not found 404'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
Krishnamoorthy Acharya
la source
0

Si vous utilisez un package de générateur express:

suivant (err);

Ce code vous envoie au middleware 404.

Josué Díaz
la source
0

Pour envoyer vers une page personnalisée:

app.get('*', function(req, res){
  if (req.accepts('html')) {
     res.send('404', '<script>location.href = "/the-404-page.html";</script>');
     return;
  }
});
Kristian
la source
0

J'ai utilisé le gestionnaire ci-dessous pour gérer l'erreur 404 avec un .ejsfichier statique .

Mettez ce code dans un script de route, puis exigez- file.jsle app.use()dans votre app.js/ server.js/ www.js(si vous utilisez IntelliJ pour NodeJS)

Vous pouvez également utiliser un .htmlfichier statique .

//Unknown route handler
 router.get("[otherRoute]", function(request, response) {
     response.status(404);
     response.render("error404.[ejs]/[html]");
     response.end();
 });

De cette façon, le serveur express en cours d'exécution répondra correctement 404 erroret votre site Web peut également inclure une page qui affiche correctement la réponse 404 du serveur. Vous pouvez également inclure un navbaren ce 404 error templatequi renvoie à d'autres contenus importants de votre site Web.

mudrak patel
la source
0

Si vous souhaitez rediriger vers des pages d'erreur à partir de vos fonctions (itinéraires), procédez comme suit -

  1. Ajoutez le code général des messages d'erreur dans votre app.js -

    app.use(function(err, req, res, next) {
        // set locals, only providing error in development
        res.locals.message = err.message
        res.locals.error = req.app.get('env') === 'development' ? err : {}
    
        // render the error page
        // you can also serve different error pages
        // for example sake, I am just responding with simple error messages 
        res.status(err.status || 500)
       if(err.status === 403){
           return res.send('Action forbidden!');
       }
    
       if(err.status === 404){
           return res.send('Page not found!');
       }
    
       // when status is 500, error handler
       if(err.status === 500) {
           return res.send('Server error occured!');
       }
       res.render('error')
    })
  2. Dans votre fonction, au lieu d'utiliser une redirection de page d'erreur, vous pouvez d'abord définir le statut d'erreur, puis utiliser next () pour que le flux de code passe par le code ci-dessus -

    if(FOUND){
        ...
    }else{
        // redirecting to general error page
        // any error code can be used (provided you have handled its error response)
        res.status(404)
        // calling next() will make the control to go call the step 1. error code
        // it will return the error response according to the error code given (provided you have handled its error response)
        next()
    }
Anshul Bisht
la source
0

La page 404 doit être configurée juste avant l'appel à app.listen.Express prend en charge * dans les chemins d'itinéraire. Il s'agit d'un caractère spécial qui correspond à tout. Cela peut être utilisé pour créer un gestionnaire d'itinéraire qui correspond à toutes les demandes.

app.get('*', (req, res) => {
  res.render('404', {
    title: '404',
    name: 'test',
    errorMessage: 'Page not found.'
  })
})
Rajat
la source
0

Couverture de tous les verbes HTTP dans express

Afin de couvrir tous les verbes HTTP et tous les chemins restants, vous pouvez utiliser:

app.all('*', cb)

La solution finale ressemblerait à ceci:

app.all('*', (req, res) =>{
    res.status(404).json({
        success: false,
        data: '404'
    })
})

N'oubliez pas de mettre le routeur à la fin. Parce que l'ordre des routeurs est important.

NGS
la source
0

Le code ci-dessus n'a pas fonctionné pour moi.

J'ai donc trouvé une nouvelle solution qui fonctionne réellement!

app.use(function(req, res, next) {
    res.status(404).send('Unable to find the requested resource!');
});

Ou vous pouvez même le rendre sur une page 404.

app.use(function(req, res, next) {
    res.status(404).render("404page");
});

J'espère que cela vous a aidé!

John Tasci
la source
-3
app.get('*',function(req,res){
 res.redirect('/login');
});
s srinivas
la source