Node.js 如何从express.static检测404错误

Node.js 如何从express.static检测404错误,node.js,express,Node.js,Express,我使用express.static提供静态文件,如下所示: ['/images','/packages','/scripts','/stylesheets'].forEach(p => { app.use(p, express.static(siteSettings.publicFolder + p)); }); 这很好,但是,当请求不存在的文件时,express会按预期引发错误,但这会影响我的自定义错误捕获所有路由: // error handler app.use(functio

我使用
express.static
提供静态文件,如下所示:

['/images','/packages','/scripts','/stylesheets'].forEach(p => {
  app.use(p, express.static(siteSettings.publicFolder + p));
});
这很好,但是,当请求不存在的文件时,express会按预期引发错误,但这会影响我的自定义错误捕获所有路由:

// 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') === 'production' ? {} : err;

  // render the error page
  res.status(err.status || 500);
  res.render('views/error');
});
这意味着文件404错误(例如,图像文件)将向客户端返回完整的错误文档(26kb),这似乎是个坏主意

有什么方法可以让我找到导致错误的express.static吗

我想做一些事情,比如:

if (req.path.indexOf("/images") === 0){
    res.send('Not found');
} else {
    res.render('views/error');
}
if (req.errorFromStatic){
    res.send('Not found');
} else {
    res.render('views/error');
}
但我在寻找类似的东西:

if (req.path.indexOf("/images") === 0){
    res.send('Not found');
} else {
    res.render('views/error');
}
if (req.errorFromStatic){
    res.send('Not found');
} else {
    res.render('views/error');
}
有什么方法可以做到这一点吗?

请参阅

有一个
fallthrough
选项,它将为不存在的文件调用
next()
,从而到达错误处理程序块

app.use("/public", express.static("/static", {fallthrough: false}));
就你而言

['/images','/packages','/scripts','/stylesheets'].forEach(p => {
  app.use(p, express.static(siteSettings.publicFolder + p, {fallthrough: false}));
});
另外编写一个自己的中间件。将其置于错误处理程序之上:

var fs = require('fs');

app.use(function (req, res, next) {
    if(['/images', '/packages', '/scripts', '/stylesheets'].includes(req.path)) {
        if (!fs.existsSync(path.join(__dirname, siteSettings.publicFolder, req.originalUrl))) {
            res.send('Not found');
        }
    }
    return next();
});

正如我在评论中所说,您可以将所有工作委托给nginx并返回自定义页面。这是一个快速而干净的解决方案,但您失去了在express中记录此尝试的选项(但您可以在nginx错误日志中看到后台发生的情况)

配置示例:

server {
   listen                          80;
   server_name                     example.local;
   charset                         utf-8;

   root /path/to/root/folder;

  location / {
           limit_req               zone=ddos burst=30 nodelay;
           proxy_set_header        Host $http_host;
           proxy_set_header        X-Forwarded-For $remote_addr;
           proxy_set_header        X-Forwarded-Protocol $scheme;
           proxy_set_header        X-NginX-Proxy true;
           proxy_pass              http://127.0.0.1:8000;
           proxy_redirect          off;
           proxy_http_version      1.1;

           proxy_intercept_errors  on;
           error_page 404 @errors;

   }

    location @errors {
            # /path/to/root/folder/404.html;
            try_files /404.html =404;
    }
}

在这个设置中,您可以捕获所有404错误并返回自定义html,因此创建两个位置块非常理想,一个用于路由到静态文件,另一个用于api(或其他任何内容),并仅在静态文件中返回自定义页面。

我尝试过这个选项,它似乎要做的就是将自定义处理程序中的错误命中从
404-notfound
更改为
500-NOENT file notfound
。这两种方法都已经遇到了自定义错误块。重新检查文件系统似乎比我原来的解决方案更糟糕,我正在寻找一个更干净的解决方案。我认为如果您想使用类似
req.errorFromStatic
的方法,唯一的方法是使用带有文件检查的自定义中间件。但也许您可以在nginx/apache中重载404,并在特定路径上返回带有错误的自定义html页面。您找到其他解决方案了吗?@l2ysho部分,一个混乱的解决方案,我启用了fallthrough,它给出了Enonet错误,我在错误捕获中检查了这些错误,并发送了一个空的404响应,但仍然不理想。