Làm cách nào để chuyển hướng lỗi 404 sang một trang trong ExpressJS?


203

Tôi không biết một chức năng để làm điều này, có ai biết một chức năng không?

Câu trả lời:


274

Tôi thấy ví dụ này khá hữu ích:

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

Vì vậy, nó thực sự là phần này:

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

Hãy xác định "xử lý"? Điều gì chính xác đánh dấu các tuyến đường như được xử lý?
Timo Huovinen

1
Tôi cho rằng không có tuyến đường phù hợp được tìm thấy cho đến thời điểm đó.
Felix

2
FYI, sử dụng app.routerbây giờ không được dùng nữa. Xem github.com/strongloop/express/wiki/
Mạnh

2
Đối với phản hồi JSON, có thể tốt hơn để sử dụng res.jsonthay vì res.send(). Họ sẽ hành xử giống nhau trong mã của bạn nhưng việc sử dụng res.jsonsẽ thực hiện một số phép thuật trong việc tự động chuyển đổi các đối tượng thành các chuỗi .send()không có. Cẩn tắc vô ưu. expressjs.com/api.html#res.json
wgp

9
Bây giờ câu hỏi này xuất hiện trong FAQ expressjs.com/starter/faq.html#how-do-you-handle-404s-
Ivan Fraixedes

157

Tôi nghĩ rằng trước tiên bạn nên xác định tất cả các tuyến đường của mình và khi tuyến cuối cùng thêm

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

Một ứng dụng ví dụ hoạt động:

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
Chà ... vấn đề là "*" khớp với các tệp .js và .css rồi, và chúng không được chỉ định trong ứng dụng ... tốt, tôi không biết có cách nào để bắt chính xác không điều tương tự là lỗi 404 hoặc cách ghi đè thông báo "Không thể nhận ...". Dù sao, cảm ơn bạn

1
Bạn đang sử dụng phần mềm trung gian tĩnh, bởi vì sau đó bạn vẫn có thể phục vụ các tệp tĩnh?
Alfred

4
app.get('/public/*', function(req, res){ res.sendfile(__dirname + '/public/' + req.url); })bạn có thể sử dụng tuyến đường này để gửi các tệp tĩnh. nó hoạt động tốt với tuyến đường "*" ở trên. app.use(express.static(__dirname + '/public'));không làm việc cho tôi, có dây.
Chris

25
Điều này không làm việc cho tôi, nhưng sau đó tôi phát hiện ra rằng tôi app.use(express.static(...))đến sau app.use(app.router). Khi tôi chuyển chúng, tất cả đều ổn.
Stephen

5
+1 để thêm nhận xét của @ Stephen vào câu trả lời của bạn. Điều này cũng không hiệu quả với tôi cho đến khi tôi đặt app.use (app.router) SAU app.use (express.static (...))
braitsch

37

Bạn có thể đặt phần mềm trung gian ở vị trí cuối cùng gây ra NotFoundlỗi
hoặc thậm chí hiển thị trực tiếp trang 404:

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

9
Vui lòng xem xét câu trả lời dài dòng hơn một chút vào lần tới ... Các ví dụ thường tốt - và đây là một ví dụ hay - nhưng một số lời giải thích có thể rất, rất tốt ...
Tonny Madsen

2
+1 Rất tốt! Tôi nghĩ rằng đây là tốt hơn so với một con đường cuối cùng, vì như vậy bạn không cần phải use()của bạn app.routertại thời gian qua. (như trong trường hợp của tôi)
Alba Mendez

Ngoài ra, điều này thay thế hành vi mặc định theo bất kỳ yêu cầu nào (không chỉ GETs). Cố gắng POSTmột URL ngẫu nhiên với phương pháp khác; nó sẽ trở lại mặc định Cannot POST.... Kẻ tấn công sẽ biết bạn đang sử dụng Express.JS.
Alba Mendez

Rất tốt, ngoại trừ việc sử dụng ejs bạn chỉ cần đặtres.render('404')
locrizak

Điều này có lẽ cũng phải có trạng thái (404) res.status (404) .render ('404')
MartinWebb

32

Các câu trả lời trên là tốt, nhưng một nửa trong số này bạn sẽ không nhận được 404 khi mã trạng thái HTTP của bạn được trả về và trong nửa còn lại, bạn sẽ không thể có mẫu kết xuất tùy chỉnh. Cách tốt nhất để có trang lỗi tùy chỉnh (404) trong Expressjs là

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

Đặt mã này vào cuối tất cả các ánh xạ URL của bạn.


@SushantGupta - Ý bạn là gì khi 'ánh xạ URL tồn tại hợp lệ?'
Jonathan Bechtel

@JonathanBechtel Như có khối mã ở trên sau các tuyến URL không sai.
Sushant Gupta

6

Ở dòng cuối cùng của app.js chỉ cần đặt chức năng này. Điều này sẽ ghi đè trang lỗi không tìm thấy trang mặc định:

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

Nó sẽ ghi đè tất cả các yêu cầu không có trình xử lý hợp lệ và hiển thị trang lỗi của riêng bạn.


2
Đó là nhận xét "dòng cuối cùng của app.js" của bạn đã giúp! Cảm ơn!
C0NFUS3D

Đã thêm một tính năng cho ứng dụng của tôi. Cảm ơn :)
Pramesh Bajracharya

5

Câu trả lời cho câu hỏi của bạn là:

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

Và có một bài viết tuyệt vời về lý do tại sao nó là cách tốt nhất ở đây .


1
Sự khác biệt giữa sendvà là endgì?
Timo Huovinen

tôi nghĩ anh ấy đã viết sai rồisend
Zaid abu khalaf

4

express-error-handler cho phép bạn chỉ định các mẫu tùy chỉnh, các trang tĩnh hoặc các trình xử lý lỗi cho các lỗi của bạn. Nó cũng thực hiện các công việc xử lý lỗi hữu ích khác mà mọi ứng dụng nên thực hiện, như bảo vệ chống lại các cuộc tấn công lỗi 4xx của DOS và tắt máy một cách duyên dáng đối với các lỗi không thể phục hồi. Đây là cách bạn làm những gì bạn yêu cầu:

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

Hoặc cho một trình xử lý tùy chỉnh:

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

Hoặc để xem tùy chỉnh:

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

4

Có một số trường hợp trang 404 không thể được viết để được thực thi như là tuyến cuối cùng, đặc biệt nếu bạn có chức năng định tuyến không đồng bộ mang đến một / tuyến muộn cho bên. Các mẫu dưới đây có thể được thông qua trong những trường hợp.

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
Rực rỡ, cảm ơn bạn! Câu trả lời duy nhất (?) Không dựa vào xử lý tuyến tính của express (nghĩa là "chỉ cần đặt trình xử lý lỗi ở cuối").
Nick Grealy 27/03/18


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

Cách dễ nhất để làm là bắt tất cả cho Trang Lỗi

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

Sau đó

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

Bây giờ bạn có thể lưu trữ tất cả các trang "html" của mình (bao gồm cả trang "html" bị lỗi) trong một biến

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

Bây giờ bạn chỉ cần gọi các trang bằng Phương thức Nhận và nắm bắt tất cả các tuyến không có sẵn để chuyển đến trang lỗi của bạn bằng 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);
});

Đừng quên thiết lập Cổng và Nghe cho máy chủ:

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

Điều này bây giờ sẽ hiển thị trang lỗi của bạn cho tất cả các điểm cuối không được nhận dạng!


1

Mặc dù các câu trả lời ở trên là chính xác, nhưng đối với những người muốn làm việc này trong IISNODE, bạn cũng cần chỉ định

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

trong web.config của bạn (nếu không IIS sẽ ăn đầu ra của bạn).


2
Cảm ơn bạn!!! Bạn là người duy nhất trên internet dường như biết điều đó (hoặc ít nhất là chia sẻ điều đó)! chúc mừng
André Lucas

1

bạn có thể xử lý lỗi theo loại nội dung

Ngoài ra, xử lý theo mã trạng thái.

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

Nếu bạn có thể sử dụng res.format, Bạn có thể viết mã xử lý lỗi đơn giản.

Khuyến nghị res.format()thay vì res.accepts().

Nếu lỗi 500 xảy ra trong mã trước đó, if(500 == err.status){. . . }được gọi là


1

Xin chào tìm câu trả lời

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

Nếu bạn sử dụng gói máy phát nhanh:

tiếp theo (lỗi);

Mã này gửi bạn đến phần mềm trung gian 404.


0

Để gửi đến một trang tùy chỉnh:

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

0

Tôi đã sử dụng trình xử lý bên dưới để xử lý lỗi 404 với một .ejstệp tĩnh .

Đặt mã này vào tập lệnh lộ trình và sau đó yêu cầu file.jsthông qua app.use()trong app.js/ server.js/ www.js(nếu sử dụng IntelliJ cho NodeJS)

Bạn cũng có thể sử dụng một .htmltệp tĩnh .

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

Bằng cách này, máy chủ thể hiện đang chạy sẽ phản hồi đúng 404 errorvà trang web của bạn cũng có thể bao gồm một trang hiển thị đúng phản hồi 404 của máy chủ. Bạn cũng có thể bao gồm một navbartrong 404 error templateđó liên kết đến nội dung quan trọng khác của trang web của bạn.


0

Nếu bạn muốn chuyển hướng đến các trang lỗi từ các chức năng (tuyến đường) của mình thì hãy làm những việc sau -

  1. Thêm mã thông báo lỗi chung trong app.js của bạn -

    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. Trong chức năng của bạn, thay vì sử dụng chuyển hướng trang lỗi, bạn có thể sử dụng đặt trạng thái lỗi trước rồi sử dụng next () cho luồng mã đi qua mã trên -

    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

Trang 404 phải được thiết lập ngay trước cuộc gọi đến app.listen.Express có hỗ trợ * trong đường dẫn tuyến. Đây là một nhân vật đặc biệt phù hợp với bất cứ điều gì. Điều này có thể được sử dụng để tạo một trình xử lý tuyến đường phù hợp với tất cả các yêu cầu.

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

0

Bao gồm tất cả các động từ HTTP trong express

Để bao quát tất cả các động từ HTTP và tất cả các đường dẫn còn lại bạn có thể sử dụng:

app.all('*', cb)

Giải pháp cuối cùng sẽ giống như vậy:

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

Bạn không nên quên đặt bộ định tuyến vào cuối. Bởi vì thứ tự của các bộ định tuyến quan trọng.


0

Các mã trên không làm việc cho tôi.

Vì vậy, tôi tìm thấy một giải pháp mới thực sự hoạt động!

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

Hoặc thậm chí bạn có thể kết xuất nó thành một trang 404.

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

Hy vọng điều này đã giúp bạn!


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.