Як перенаправити 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.