จะเปลี่ยนเส้นทางข้อผิดพลาด 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');
});

โปรดระบุ "จัดการ" หรือไม่ เส้นทางใดที่ทำเครื่องหมายว่าจัดการแล้ว
Timo Huovinen

1
ฉันคิดว่าไม่พบเส้นทางที่ตรงกันจนกว่าจะถึงจุดนั้น
เฟลิกซ์

2
FYI, 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
ตอนนี้คำถามนี้ปรากฏในคำถามที่พบบ่อยexpressjs.com/starter/faq.html#how-do-you-handle-404s-
Ivan 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)นั้น เมื่อฉันเปลี่ยนพวกเขาทุกอย่างก็ออกมาดี
Stephen

5
+1 สำหรับการเพิ่มความคิดเห็นของ @ Stephen ในคำตอบของคุณ สิ่งนี้ไม่ได้ผลสำหรับฉันจนกว่าฉันจะวาง app.use (app.router) หลังจาก app.use (express.static (... ))
braitsch

37

คุณสามารถวางมิดเดิลแวร์ไว้ที่ตำแหน่งสุดท้ายที่ทำให้เกิดNotFoundข้อผิดพลาด
หรือแม้แต่แสดงหน้า 404 โดยตรง:

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

9
โปรดพิจารณาคำตอบที่ละเอียดมากขึ้นในครั้งต่อไป ... ตัวอย่างมักจะดี - และนี่เป็นตัวอย่างที่ดี - แต่คำอธิบายบางอย่างอาจดีมากเช่นกัน ...
Tonny Madsen

2
+1 ดีมาก! ผมคิดว่านี้จะดีกว่าเส้นทางที่ผ่านมาเพราะวิธีการที่คุณไม่จำเป็นต้องuse()ของคุณapp.routerในช่วงเวลาที่ผ่านมา (ดังในกรณีของฉัน)
Alba Mendez

นอกจากนี้จะแทนที่พฤติกรรมเริ่มต้นในคำขอใด ๆ (ไม่เพียงGETs) ลองใช้POSTURL สุ่มด้วยวิธีอื่น Cannot POST...มันจะกลับมาเริ่มต้น ผู้โจมตีจะรู้ว่าคุณกำลังใช้ Express.JS
Alba Mendez

ดีมากยกเว้นใช้ 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 ที่มีอยู่ที่ถูกต้องหรือไม่'
Jonathan Bechtel

@JonathanBechtel ในขณะที่มีบล็อกรหัสข้างต้นหลังจากเส้นทาง URL ที่ไม่ผิดพลาดของคุณ
Sushant Gupta

6

ที่บรรทัดสุดท้ายของ app.js เพียงแค่ใส่ฟังก์ชั่นนี้ สิ่งนี้จะแทนที่หน้าข้อผิดพลาดที่ไม่พบหน้าเริ่มต้น:

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

มันจะแทนที่คำขอทั้งหมดที่ไม่มีตัวจัดการที่ถูกต้องและแสดงหน้าข้อผิดพลาดของคุณเอง


2
มันเป็นความคิดเห็น "บรรทัดสุดท้ายของ app.js" ของคุณที่ช่วยได้! ขอบคุณ!
C0NFUS3D

เพิ่มคุณสมบัติให้กับแอพของฉัน ขอบคุณ :)
Pramesh Bajracharya

5

คำตอบสำหรับคำถามของคุณคือ:

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

และมีบทความดี ๆ เกี่ยวกับเหตุผลที่มันเป็นวิธีที่ดีที่สุดที่นี่


1
ความแตกต่างระหว่างsendและendคืออะไร?
Timo Huovinen

ฉันคิดว่าเขาควรจะเขียนพลาดsend
Zaid abu khalaf

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 เพื่อดำเนินการเป็นเส้นทางสุดท้ายโดยเฉพาะอย่างยิ่งหากคุณมีฟังก์ชั่นการกำหนดเส้นทางแบบอะซิงโครนัสที่นำ a / เส้นทางไปยังปาร์ตี้ รูปแบบด้านล่างอาจนำมาใช้ในกรณีเหล่านั้น

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
ยอดเยี่ยมขอบคุณ! คำตอบเดียว (?) ที่ไม่ขึ้นอยู่กับการประมวลผลเชิงเส้นของ express (เช่น "เพียงแค่ใส่ตัวจัดการข้อผิดพลาดในตอนท้าย")
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');
  });

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

ตอนนี้คุณเพียงแค่เรียกหน้าโดยใช้วิธีการรับและจับทั้งหมดสำหรับเส้นทางใด ๆ ที่ไม่สามารถนำไปยังหน้าข้อผิดพลาดของคุณโดยใช้ 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();
 });

ด้วยวิธีนี้เซิร์ฟเวอร์ Express ที่ทำงานอยู่จะตอบสนองด้วยความเหมาะสม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");
});

หวังว่านี่จะช่วยคุณได้!


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.