Як перенаправити 404 помилки на сторінку в ExpressJS?


Відповіді:


274

Я вважаю цей приклад досить корисним:

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

Так це насправді ця частина:

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

Будь ласка, визначте "обробляється"? Що саме позначає маршрут як оброблений?
Тімо Хуовінен

1
Я припускав, що до цього моменту не знайдено відповідного маршруту.
Фелікс

2
БЮР, використання цього терміну app.routerприпинено. Дивіться github.com/strongloop/express/wiki/…
iX3

2
Для відповіді JSON, можливо, краще використовувати res.jsonзамість res.send(). Вони будуть поводитись так само у вашому коді, але використання res.jsonбуде робити певну магію в автоматичному перетворенні об'єктів у рядки, де .send()не буде. Краще перестрахуватися, ніж потім шкодувати. expressjs.com/api.html#res.json
wgp

9
Тепер це запитання з'являється у FAQ FAQ expressjs.com/starter/faq.html#how-do-you-handle-404s-
Іван Fraixedes

157

Я думаю, ви повинні спочатку визначити всі свої маршрути і як останній додавати маршрут

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

Приклад програми, яка працює:

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
Ну ... проблема полягає в тому, що "*" відповідає файлам .js та .css, і вони не вказані в додатку ... ну, я не знаю, чи є спосіб, як точно впіймати те саме, що помилка 404 або спосіб перезаписати повідомлення "Не вдається отримати ...". У будь-якому випадку, дякую

1
Ви використовуєте статичне проміжне програмне забезпечення, адже тоді ви все ще можете подавати статичні файли?
Альфред

4
app.get('/public/*', function(req, res){ res.sendfile(__dirname + '/public/' + req.url); })Ви можете використовувати цей маршрут для надсилання статичних файлів. це добре працює з вище "*" маршрутом. app.use(express.static(__dirname + '/public'));не працює для мене, провідний.
Кріс

25
Це не працювало для мене, але потім я виявив, що моє app.use(express.static(...))прийшло після app.use(app.router). Як тільки я переключив їх, все вийшло чудово.
Стефан

5
+1 для додавання коментаря @ Стівена до вашої відповіді. Це не спрацювало для мене, поки я не поставив app.use (app.router) ПІСЛЯ app.use (express.static (...))
braitsch

37

Можна поставити проміжне програмне забезпечення на останню позицію, яка видає NotFoundпомилку,
або навіть відобразить сторінку 404 безпосередньо:

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

9
Будь ласка, розгляньте трохи докладнішу відповідь наступного разу ... Приклади, як правило, добре - і це хороший приклад, - але деякі пояснення можуть бути і дуже, і дуже хорошими ...
Тонні Мадсен

2
+1 Дуже добре! Я думаю, що це краще, ніж останній маршрут, тому що таким чином вам не доведеться до use()свого app.routerостаннього часу. (як у моєму випадку)
Альба Мендес

Крім того, це замінює поведінку за замовчуванням на будь-який запит (не тільки GET). Спробуйте POSTдовільну URL-адресу за допомогою іншого методу; він поверне за замовчуванням Cannot POST.... Тоді зловмисник знає, що ви використовуєте Express.JS.
Альба Мендес

Дуже добре, окрім використання ejs, який ви просто повинні поставитиres.render('404')
locrizak

Це, мабуть, має також мати статус (404) res.status (404) .render ('404')
MartinWebb

32

Наведені вище відповіді хороші, але в половині з них ви не отримаєте 404, коли ваш код статусу HTTP повернувся, а в іншій половині ви не зможете мати користувальницький шаблон відображення. Найкращий спосіб мати користувальницьку сторінку помилок (404-х) у Expressjs - це

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

Розмістіть цей код в кінці всіх ваших відображень URL-адрес.


@SushantGupta - Що ви маєте на увазі під "дійсними екзистенційними відображеннями URL-адрес?"
Джонатан Бехтел

@JonathanBechtel Як і в наведеному вище блоці коду після ваших невірних маршрутів URL.
Сушант Гупта

6

В останньому рядку app.js просто поставили цю функцію. Це змінить сторінку помилки, яку не знайдено за замовчуванням:

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

Він скасує всі запити, які не мають дійсного обробника, і видасть вашу власну сторінку помилок.


2
Саме ваш останній рядок коментаря app.js допоміг! Дякую!
C0NFUS3D

Додано функцію до мого додатку. Дякую :)
Прамеш Байрачаря


4

express-error-обработчик дозволяє вказувати власні шаблони, статичні сторінки або обробники помилок для своїх помилок. Він також виконує інші корисні функції з помилками, які має застосовувати кожен додаток, як захист від атак DOS 4xx з помилками та витончене вимкнення непоправних помилок. Ось як ви робите те, що просите:

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

Або для користувацького обробника:

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

Або для користувацького перегляду:

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

4

Бувають випадки, коли сторінка 404 не може бути записана для виконання як останнього маршруту, особливо якщо у вас є функція асинхронного маршрутизації, яка запускає / з маршрутом пізно до партії. У цих випадках може бути прийнята схема нижче.

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
Блискуче, дякую! Єдина відповідь (?), Яка не покладається на лінійну обробку експресу (тобто "просто поставте обробник помилок у кінець").
Нік Грілі


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

Найпростіший спосіб зробити це - виловити все для сторінки помилок

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

Тоді

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

Тепер ви можете зберігати всі ваші "html" сторінки (включаючи сторінку "html" з помилкою) у змінній

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

Тепер ви просто зателефонуйте на сторінки за допомогою методу Get і отримаєте спір для всіх маршрутів, недоступних для переходу на вашу сторінку помилок за допомогою 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);
});

Не забудьте налаштувати порт і слухати сервер:

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

Тепер це має відображати вашу сторінку помилок для всіх нерозпізнаних кінцевих точок!


1

Хоча відповіді вище правильні, для тих, хто хоче це зробити в IISNODE, вам також потрібно вказати

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

у вашому web.config (інакше IIS з'їсть ваш результат).


2
Дякую!!! Ви єдиний в Інтернеті, хто, здається, знає це (або принаймні поділяється цим)! ура
Андре Лукас

1

ви можете помилитися з обробкою відповідно до типу вмісту

Крім того, обробка відповідно до коду статусу.

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

Якщо ви можете використовувати res.format, ви можете написати простий код обробки помилок.

Рекомендація res.format()замістьres.accepts() .

Якщо помилка 500 трапляється в попередньому коді, if(500 == err.status){. . . }викликається


1

Привіт, будь ласка, знайдіть відповідь

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

Якщо ви використовуєте пакет експрес-генераторів:

наступний (помилка);

Цей код надсилає вас до програмного забезпечення 404.


0

Щоб надіслати на власну сторінку:

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

0

Я використовував обробник нижче, щоб обробляти помилку 404 зі статичним .ejsфайлом.

Помістіть цей код в сценарії маршруту , а потім вимагають , щоб file.jsчерез app.use()у вашому app.js/ server.js/ www.js(при використанні IntelliJ для NodeJS)

Ви також можете використовувати статичний .htmlфайл.

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

Таким чином, запущений експрес-сервер відповість належним чином, 404 errorі ваш веб-сайт також може включати сторінку, яка належним чином відображає відповідь 404 сервера. Ви також можете включити navbarте, 404 error templateщо посилається на інший важливий вміст вашого веб-сайту.


0

Якщо ви хочете переспрямувати на сторінки помилок зі своїх функцій (маршрутів), виконайте наступні дії -

  1. Додайте загальний код повідомлень про помилки у свій 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. У своїй функції замість переспрямування сторінки помилок ви можете спочатку встановити статус помилки, а потім використовувати next () для потоку коду, щоб пройти вищевказаний код -

    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

Сторінка 404 повинна бути налаштована безпосередньо перед викликом до app.listen.Express має підтримку * у маршрутних маршрутах. Це особливий персонаж, який відповідає будь-якому. Це можна використовувати для створення обробника маршруту, який відповідає всім запитам.

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

0

Покриття всіх дієслів HTTP в express

Щоб охопити всі HTTP дієслова та всі інші шляхи, які ви можете використати:

app.all('*', cb)

Остаточне рішення виглядатиме так:

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

Ви не повинні забувати поставити маршрутизатор в кінці. Тому що порядок маршрутизаторів має значення.


0

Наведений вище код не працював для мене.

Тож я знайшов нове рішення, яке насправді працює!

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

Або ви навіть можете перенести його на сторінку 404.

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

Сподіваюся, це вам допомогло!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.