如何将404错误重定向到ExpressJS中的页面?


Answers:


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
我以为直到那个时候都找不到匹配的路由。
Felix

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 2014年


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,用于将@Stephen的评论添加到您的答案中。直到我将app.use(app.router)之后放到app.use(express.static(...))上,这对我都没有作用
braitsch 2012年

37

您可以将中间件放在抛出NotFound错误的最后位置,
甚至直接呈现404页面:

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

9
下次请考虑更冗长的答案...例子通常很好-这是一个很好的例子-但一些解释也可能非常非常好...
Tonny Madsen

2
+1 很好!我认为这是比最后的路线比较好,因为这样你就不必use()app.router在最后的时间。(以我的情况
阿尔巴·门德斯

此外,这将替换任何请求(不仅GET是s)上的默认行为。尝试POST使用其他方法随机输入URL;它将返回默认值Cannot POST...。然后,攻击者会知道您正在使用Express.JS。
阿尔巴·门德斯

很好,除了您只需要使用ejs即可res.render('404')
locrizak

这可能也应该具有status(404)res.status(404).render('404')
MartinWebb

32

上面的答案很好,但是其中一半不会因为返回HTTP状态代码而得到404,而另一半则无法呈现自定义模板。在Expressjs中拥有自定义错误页面(404)的最好方法是

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

将此代码放在所有URL映射的末尾。


@SushantGupta-“有效的存在性URL映射”是什么意思?
乔纳森·贝希特

@JonathanBechtel在您的非错误URL路由之后,具有上面的代码块。
Sushant Gupta

6

在app.js的最后一行中,只需放置此函数即可。这将覆盖默认的页面未找到错误页面:

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

它将覆盖所有没有有效处理程序的请求,并呈现您自己的错误页面。


2
正是您的“ app.js的最后一行”评论对您有所帮助!谢谢!
C0NFUS3D

向我的应用添加了功能。谢谢:)
Pramesh Bajracharya


4

express-error-handler允许您为错误指定自定义模板,静态页面或错误处理程序。它还执行了每个应用程序都应该实现的其他有用的错误处理功能,例如防止4xx错误的DOS攻击以及对不可恢复的错误的正常关闭。这是您要执行的操作:

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
太好了,谢谢!唯一不依赖于express的线性处理的答案(?)(即“仅将错误处理程序放在最后”)。
尼克·格莱利


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

要发送到自定义页面:

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

0

我使用下面的处理程序来处理带有静态.ejs文件的404错误。

将这个代码的路线脚本,然后需要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

应该在对app.listen.Express的调用在路由路径中支持*之前设置404页面。这是一个匹配任何内容的特殊字符。这可用于创建匹配所有请求的路由处理程序。

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

希望这对您有所帮助!


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.