Come reindirizzare gli errori 404 a una pagina in ExpressJS?


Risposte:


274

Ho trovato questo esempio abbastanza utile:

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

Quindi in realtà è questa parte:

// "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');
});

Si prega di definire "gestito"? Cosa indica esattamente il percorso come gestito?
Timo Huovinen,

1
Suppongo che fino a quel momento non sia stato trovato alcun percorso corrispondente.
Felix,

2
Cordiali saluti, l'uso di app.routerè ora deprecato. Vedi github.com/strongloop/express/wiki/…
iX3

2
Per la risposta JSON potrebbe essere meglio usare res.jsoninvece di res.send(). Si comporterebbero allo stesso modo nel tuo codice ma l'utilizzo res.jsonfarà un po 'di magia nella conversione automatica degli oggetti in stringhe dove .send()non lo faranno. Meglio prevenire che curare. expressjs.com/api.html#res.json
wgp


158

Penso che dovresti prima definire tutti i tuoi percorsi e come aggiungere l'ultimo percorso

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

Un'app di esempio che funziona:

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?

6
Bene ... il problema è che "*" corrisponde già ai file .js e .css e non sono specificati nell'app ... beh, non so se ci sia un modo per catturare esattamente il stessa cosa dell'errore 404 o un modo per sovrascrivere il messaggio "Impossibile ottenere ...". Comunque, grazie

1
Stai usando middleware statico, perché allora puoi comunque servire file statici?
Alfred,

4
app.get('/public/*', function(req, res){ res.sendfile(__dirname + '/public/' + req.url); })puoi usare questa route per inviare file statici. funziona bene con il percorso "*" sopra. app.use(express.static(__dirname + '/public'));non funziona per me, cablato.
Chris,

25
Questo non funzionava per me, ma poi ho scoperto che il mio è app.use(express.static(...))venuto dopo app.use(app.router). Una volta che li ho scambiati tutto è venuto bene.
Stephen,

5
+1 per l'aggiunta del commento di @Stefano alla tua risposta. Questo non ha funzionato neanche per me fino a quando ho inserito app.use (app.router) DOPO app.use (express.static (...))
braitsch,

37

È possibile inserire un middleware nell'ultima posizione che genera un NotFounderrore
o addirittura visualizzare direttamente la pagina 404:

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

9
Ti preghiamo di considerare una risposta un po 'più dettagliata la prossima volta ... Gli esempi di solito vanno bene - e questo è un buon esempio - ma alcune spiegazioni possono essere anche molto, molto buone ...
Tonny Madsen

2
+1 Molto bene! Penso che questo sia meglio di un ultimo percorso, perché in questo modo non è necessario per il use()tuo app.routerl'ultima volta. (come nel mio caso)
Alba Mendez,

Inoltre, questo sostituisce il comportamento predefinito su qualsiasi richiesta (non solo GET). Prova a POSTun URL casuale con l'altro metodo; restituirà il valore predefinito Cannot POST.... Un utente malintenzionato potrebbe quindi sapere che stai utilizzando Express.JS.
Alba Mendez,

Molto buono, tranne usare ejs che devi solo mettereres.render('404')
locrizak il

Questo dovrebbe probabilmente avere anche uno status (404) res.status (404) .render ('404')
MartinWebb

32

Le risposte di cui sopra sono buone, ma nella metà di queste non otterrai 404 come il tuo codice di stato HTTP restituito e nella seconda metà non sarai in grado di avere un rendering del modello personalizzato. Il modo migliore per avere una pagina di errore personalizzata (404) in Expressjs è

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

Inserisci questo codice alla fine di tutti i tuoi mapping URL.


@SushantGupta - Cosa intendi con "mapping URL esistenziali validi?"
Jonathan Bechtel,

@JonathanBechtel Come in hanno il blocco di codice sopra riportato dopo i percorsi URL non errati.
Sushant Gupta,

6

All'ultima riga di app.js inserisci questa funzione. Questo sostituirà la pagina di errore predefinita non trovata:

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

Sovrascriverà tutte le richieste che non hanno un gestore valido e visualizzerà la tua pagina di errore.


2
È stato il tuo commento "ultima riga di app.js" che mi ha aiutato! Grazie!
C0NFUS3D,

Aggiunta una funzione alla mia app. Grazie :)
Pramesh Bajracharya il

5

La risposta alla tua domanda è:

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

E c'è un ottimo articolo sul perché è il modo migliore qui .


1
Qual è la differenza tra sende end?
Timo Huovinen,

penso che abbia sbagliato a scrivere che dovrebbe esseresend
Zaid abu khalaf

4

express-error-handler ti consente di specificare modelli personalizzati, pagine statiche o gestori di errori per i tuoi errori. Fa anche altre cose utili per la gestione degli errori che ogni app dovrebbe implementare, come la protezione dagli attacchi DOS con errore 4xx e l'arresto gradevole degli errori irrecuperabili. Ecco come fai quello che stai chiedendo:

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 );

O per un gestore personalizzato:

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

O per una vista personalizzata:

handler = errorHandler({
  views: {
    '404': '404.jade'
  }
});

4

Ci sono alcuni casi in cui la pagina 404 non può essere scritta per essere eseguita come ultima route, specialmente se si dispone di una funzione di routing asincrona che porta in / route in ritardo alla parte. Il modello seguente potrebbe essere adottato in questi casi.

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");
});

2
Fantastico, grazie! L'unica risposta (?) Che non si basa sull'elaborazione lineare di express (ovvero "basta mettere il gestore degli errori alla fine").
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');
  });

2

Il modo più semplice per farlo è di catturare tutto per la pagina di errore

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

Poi

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

Ora puoi memorizzare tutte le tue pagine "html" (inclusa una pagina "html" di errore) in una variabile

// 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

Ora chiami semplicemente le pagine usando il metodo Get e hai un fermo tutto per tutti i percorsi non disponibili per indirizzare alla tua pagina di errore utilizzando 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);
});

Non dimenticare di impostare una porta e ascoltare il server:

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

Questo dovrebbe ora mostrare la tua pagina di errore per tutti gli endpoint non riconosciuti!


1

Mentre le risposte sopra sono corrette, per coloro che vogliono farlo funzionare in IISNODE devi anche specificare

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

nel tuo web.config (altrimenti IIS mangerà il tuo output).


2
Grazie!!! Sei l'unico su Internet che sembra saperlo (o almeno condividerlo)! salute
André Lucas

1

puoi gestire gli errori in base al tipo di contenuto

Inoltre, la gestione in base al codice di stato.

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

Se è possibile utilizzare res.format, è possibile scrivere un semplice codice di gestione degli errori.

Raccomandazione res.format()anzichéres.accepts() .

Se l'errore 500 si verifica nel codice precedente, if(500 == err.status){. . . }viene chiamato


1

Ciao, per favore, trova la risposta

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}!`));

0

Se si utilizza il pacchetto express-generator:

successivo (err);

Questo codice ti invia al middleware 404.


0

Per inviare a una pagina personalizzata:

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

0

Ho usato il gestore di seguito per gestire l'errore 404 con un .ejsfile statico .

Inserire questo codice in uno script di route e quindi richiederlo file.jstramite app.use()in app.js/ server.js/ www.js(se si utilizza IntelliJ per NodeJS)

Puoi anche usare un .htmlfile statico .

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

In questo modo, il server espresso in esecuzione risponderà con una corretta 404 errore il tuo sito Web può anche includere una pagina che visualizza correttamente la risposta 404 del server. Puoi anche includere un navbarin che 404 error templaterimanda ad altri contenuti importanti del tuo sito web.


0

Se desideri reindirizzare a pagine di errore dalle tue funzioni (rotte), procedi come segue:

  1. Aggiungi il codice dei messaggi di errore generali nel tuo 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. Nella tua funzione, invece di utilizzare un reindirizzamento della pagina di errore, puoi utilizzare prima impostare lo stato dell'errore e quindi utilizzare next () affinché il flusso di codice passi attraverso il codice sopra -

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

0

La pagina 404 deve essere configurata poco prima della chiamata a app.listen.Express ha il supporto per * nei percorsi di instradamento. Questo è un personaggio speciale che si adatta a qualsiasi cosa. Questo può essere usato per creare un gestore di route che corrisponda a tutte le richieste.

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

0

Copertura di tutti i verbi HTTP in express

Per coprire tutti i verbi HTTP e tutti i percorsi rimanenti è possibile utilizzare:

app.all('*', cb)

La soluzione finale sembrerebbe così:

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

Non dovresti dimenticare di mettere il router alla fine. Perché l'ordine dei router è importante.


0

Il codice sopra non ha funzionato per me.

Quindi ho trovato una nuova soluzione che funziona davvero!

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

Oppure puoi persino renderlo in una pagina 404.

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

Spero che questo ti abbia aiutato!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.