Как перенаправить 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. Expressjs.com/starter/faq.html#how-do-you-handle-404s-
Иван Фрайкседес,
158

Я думаю, что вы должны сначала определить все свои маршруты и как последний маршрут добавить

//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в последний раз. (как в моем случае)
Альба Мендес
Кроме того, это заменяет поведение по умолчанию для любого запроса (не только GETs). Попробуйте 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
Добавил функцию в мое приложение. Спасибо :)
Прамеш Байрачарья
5

Ответ на ваш вопрос:

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

И есть отличная статья о том, почему это лучший способ здесь .

Мариус Котофана
источник
1
В чем разница между sendи end?
Тимо Хуовинен
я думаю, что он пропустил - это должно бытьsend
Зайд Абу Халаф
4

express-error-handler позволяет вам указать собственные шаблоны, статические страницы или обработчики ошибок для ваших ошибок. Он также выполняет другие полезные функции обработки ошибок, которые должно реализовывать каждое приложение, такие как защита от атак 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 для выполнения в качестве последнего маршрута, особенно если у вас есть функция асинхронной маршрутизации, которая вводит / route поздно для участника. Шаблон ниже может быть принят в этих случаях.

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');
  });
ASHISH RANJAN
источник
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 будет есть ваш вывод).

laktak
источник
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){. . . }вызывается

멍개 -mung
источник
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

Если вы используете пакет express-generator:

Следующий (ERR);

Этот код отправляет вас в промежуточное ПО 404.

Хосе Диас
источник
0

Чтобы отправить на пользовательскую страницу:

app.get('*', function(req, res){
  if (req.accepts('html')) {
     res.send('404', '<script>location.href = "/the-404-page.html";</script>');
     return;
  }
});
Kristian
источник
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'
    })
})

Вы не должны забыть поставить маршрутизатор в конце. Потому что порядок роутеров имеет значение.

NGS
источник
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");
});

Надеюсь, это помогло вам!

Джон Таски
источник
-3
app.get('*',function(req,res){
 res.redirect('/login');
});
сринивас
источник