Jak przekierować błędy 404 na stronę w ExpressJS?

203

Nie znam funkcji do zrobienia tego, czy ktoś o niej wie?

heksacyjanid
źródło

Odpowiedzi:

274

Ten przykład był dla mnie bardzo pomocny:

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

Więc to właściwie ta część:

// "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
źródło
Proszę zdefiniować „obsłużony”? Co dokładnie oznacza trasę jako obsłużoną?
Timo Huovinen
1
Przypuszczałem, że do tego momentu nie znaleziono pasującej trasy.
Felix
2
FYI, użycie app.routerjest teraz przestarzałe. Zobacz github.com/strongloop/express/wiki/…
iX3
2
W przypadku odpowiedzi JSON może być lepiej użyć res.jsonzamiast res.send(). Zachowują się tak samo w twoim kodzie, ale użycie res.jsonspowoduje magię w automatycznej konwersji obiektów na ciągi, w których .send()nie będzie. Lepiej dmuchać na zimne. expressjs.com/api.html#res.json
wgp
9
Teraz to pytanie pojawia się w FAQ expressjs.com/starter/faq.html#how-do-you-handle-404s-
Ivan Fraixedes
157

Myślę, że powinieneś najpierw zdefiniować wszystkie swoje trasy i dodać ostatnią trasę

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

Przykładowa aplikacja, która działa:

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
źródło
6
Cóż ... problem polega na tym, że „*” pasuje już do plików .js i .css, a nie są one określone w aplikacji ... cóż, nie wiem, czy istnieje jakiś sposób na złapanie dokładnie to samo, co błąd 404 lub sposób na zastąpienie komunikatu „Nie można dostać ...”. W każdym razie dziękuję
1
Czy używasz statycznego oprogramowania pośredniego, ponieważ nadal możesz obsługiwać pliki statyczne?
Alfred
4
app.get('/public/*', function(req, res){ res.sendfile(__dirname + '/public/' + req.url); })możesz użyć tej trasy do wysyłania plików statycznych. działa dobrze z powyższą trasą „*”. app.use(express.static(__dirname + '/public'));nie działa dla mnie przewodowo.
Chris
25
To nie działało dla mnie, ale potem odkryłem, że moje app.use(express.static(...))przyszły app.use(app.router). Po ich zmianie wszystko wyszło dobrze.
Stephen
5
+1 za dodanie komentarza @ Stephen do swojej odpowiedzi. Nie działało to dla mnie, dopóki nie dodałem app.use (app.router) PO app.use (express.static (...))
braitsch
37

Możesz umieścić oprogramowanie pośrednie na ostatniej pozycji, która zgłasza NotFoundbłąd,
a nawet renderuje stronę 404 bezpośrednio:

app.use(function(req,res){
    res.status(404).render('404.jade');
});
Ganesh Kumar
źródło
9
Następnym razem zastanów się nad bardziej szczegółową odpowiedzią ... Przykłady są zazwyczaj w porządku - i to dobry przykład - ale niektóre wyjaśnienia mogą być również bardzo, bardzo dobre ...
Tonny Madsen
2
+1 Bardzo dobrze! Myślę, że jest lepiej niż w ostatniej trasy, ponieważ w ten sposób nie trzeba do use()TWOJEJ app.routerpo raz ostatni. (jak w moim przypadku)
Alba Mendez
Poza tym zastępuje domyślne zachowanie każdego żądania (nie tylko GET). Spróbuj POSTużyć losowego adresu URL inną metodą; zwróci wartość domyślną Cannot POST.... Osoba atakująca wiedziałaby wtedy, że korzystasz z Express.JS.
Alba Mendez
Bardzo dobrze, z wyjątkiem korzystania z ejs, które musisz tylko umieścićres.render('404')
locrizak
Powinno to prawdopodobnie mieć również status (404) res.status (404) .render ('404')
MartinWebb
32

Powyższe odpowiedzi są dobre, ale w połowie z nich nie otrzymasz 404, ponieważ kod statusu HTTP powrócił, a w drugiej połowie nie będziesz mieć możliwości renderowania niestandardowego szablonu. Najlepszym sposobem na utworzenie niestandardowej strony błędu (404) w Expressjs jest

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

Umieść ten kod na końcu wszystkich mapowań adresów URL.

Sushant Gupta
źródło
@SushantGupta - Co rozumiesz przez „prawidłowe mapowanie egzystencjalnego adresu URL?”
Jonathan Bechtel
@JathanathanBechtel Tak jak w powyższym bloku kodu po swoich błędnych trasach adresów URL.
Sushant Gupta
6

W ostatniej linii app.js po prostu wstaw tę funkcję. Spowoduje to zastąpienie domyślnej strony błędu „nie znaleziono strony”:

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

Zastąpi wszystkie żądania, które nie mają prawidłowego modułu obsługi i wyświetli własną stronę błędów.

Vivek Bajpai
źródło
2
To był twój komentarz do „ostatniej linii app.js”! Dzięki!
C0NFUS3D,
Dodano funkcję do mojej aplikacji. Dzięki :)
Pramesh Bajracharya
5

Odpowiedź na twoje pytanie brzmi:

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

A tam jest wielki artykuł o tym, dlaczego jest to najlepszy sposób tutaj .

Marius Cotofana
źródło
1
Jaka jest różnica między sendi end?
Timo Huovinen
myślę, że nie napisał tak powiniensend
Zaid abu khalaf
4

express-error-handler umożliwia określenie własnych błędów, szablonów, stron statycznych lub programów obsługi błędów. Wykonuje także inne przydatne czynności związane z obsługą błędów, które każda aplikacja powinna wdrożyć, takie jak ochrona przed atakami DOS z błędem 4xx i płynne zamykanie w przypadku nieodwracalnych błędów. Oto jak robisz to, o co prosisz:

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

Lub dla niestandardowego modułu obsługi:

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

Lub dla niestandardowego widoku:

handler = errorHandler({
  views: {
    '404': '404.jade'
  }
});
Eric Elliott
źródło
4

W niektórych przypadkach strona 404 nie może zostać zapisana jako ostatnia trasa, szczególnie jeśli masz asynchroniczną funkcję routingu, która sprowadza trasę / późno na imprezę. W takich przypadkach można zastosować poniższy wzór.

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
źródło
2
Świetnie, dziękuję! Jedyna odpowiedź (?), Która nie opiera się na liniowym przetwarzaniu wyrażeń ekspresowych (tzn. „Po prostu umieść moduł obsługi błędów na końcu”).
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
źródło
2

Najprostszym sposobem na to jest złapanie wszystkich na stronę błędu

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

Następnie

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

Teraz możesz przechowywać wszystkie strony „html” (w tym stronę błędu „html”) w zmiennej

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

Teraz po prostu wywołujesz strony za pomocą metody Get i łapiesz wszystkie dla wszystkich niedostępnych tras, aby przekierować na stronę błędu za pomocą 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);
});

Nie zapomnij skonfigurować portu i nasłuchuj na serwerze:

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

Powinno to teraz wyświetlać stronę błędów dla wszystkich nierozpoznanych punktów końcowych!

Kean Amaral
źródło
1

Chociaż powyższe odpowiedzi są poprawne, dla tych, którzy chcą, aby to działało w IISNODE, musisz również określić

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

w pliku web.config (w przeciwnym razie IIS zje dane wyjściowe).

laktak
źródło
2
Dziękuję Ci!!! Jesteś jedyną osobą w Internecie, która zdaje się to wiedzieć (a przynajmniej to udostępniać)! na zdrowie
André Lucas
1

możesz obsługiwać błędy w zależności od typu zawartości

Dodatkowo obsługa zgodnie z kodem statusu.

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

Jeśli możesz użyć res.format, możesz napisać prosty kod obsługi błędów.

Zalecenie res.format()zamiast res.accepts().

Jeśli błąd 500 występuje w poprzednim kodzie, if(500 == err.status){. . . }wywoływany jest

멍개 -mung
źródło
1

Cześć, proszę znaleźć odpowiedź

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
źródło
0

Jeśli używasz pakietu ekspresowego:

next (err);

Ten kod przesyła cię do oprogramowania pośredniego 404.

Josué Díaz
źródło
0

Aby wysłać na niestandardową stronę:

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

Użyłem poniższego programu obsługi do obsługi błędu 404 za pomocą .ejspliku statycznego .

Umieść ten kod w skrypcie trasy i następnie wymagają file.jspośrednictwem app.use()w twoim app.js/ server.js/ www.js(w przypadku korzystania IntelliJ dla NodeJS)

Możesz także użyć .htmlpliku statycznego .

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

W ten sposób działający serwer ekspresowy zareaguje poprawnie, 404 errora twoja strona internetowa może również zawierać stronę, która poprawnie wyświetla odpowiedź 404 serwera poprawnie. Można również zawierać navbarw to 404 error template, że linki do innych ważnych treści witryny.

mudrak patel
źródło
0

Jeśli chcesz przekierowywać na strony błędów ze swoich funkcji (tras), wykonaj następujące czynności -

  1. Dodaj kod ogólnych komunikatów o błędach w pliku 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. W swojej funkcji zamiast przekierowania na stronę błędów możesz najpierw ustawić status błędu, a następnie użyć next (), aby przepływ kodu przebiegał powyżej kodu -

    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
źródło
0

Strona 404 powinna zostać skonfigurowana tuż przed wywołaniem app.listen.Express obsługuje * w ścieżkach tras. To specjalna postać, która pasuje do wszystkiego. Można tego użyć do utworzenia procedury obsługi trasy, która pasuje do wszystkich żądań.

app.get('*', (req, res) => {
  res.render('404', {
    title: '404',
    name: 'test',
    errorMessage: 'Page not found.'
  })
})
Rajat
źródło
0

Obejmujące wszystkie czasowniki HTTP w express

Aby objąć wszystkie czasowniki HTTP i wszystkie pozostałe ścieżki, których możesz użyć:

app.all('*', cb)

Ostateczne rozwiązanie wyglądałoby tak:

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

Nie należy zapominać o umieszczeniu routera na końcu. Ponieważ kolejność routerów ma znaczenie.

NGS
źródło
0

Powyższy kod nie działał dla mnie.

Więc znalazłem nowe rozwiązanie, które faktycznie działa!

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

Lub możesz nawet wyrenderować go na stronie 404.

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

Mam nadzieję, że to ci pomogło!

John Tasci
źródło
-3
app.get('*',function(req,res){
 res.redirect('/login');
});
srinivas
źródło