如何在ExpressJS服务器中判断请求路径是否真的不存在(排除业务404)
解决方案
方法一:提前检测请求是否匹配已定义路由
Express内部的路由系统自带匹配机制,你可以在Morgan中间件之前添加一个前置中间件,提前判断当前请求路径是否能匹配到已注册的路由,把结果存在req对象上,后续在Morgan的skip回调里用这个结果区分两种404。
代码示例:
// 前置中间件:检测请求是否匹配已定义路由 app.use((req, res, next) => { // 调用Express内部的路由匹配方法 const matchedRoutes = app._router.match(req, res); // 标记是否找到匹配路由 req.hasMatchingRoute = matchedRoutes.length > 0; next(); }); // 配置Morgan日志 app.use( morgan('combine', { skip(req, res) { // 只过滤「状态码404且无匹配路由」的垃圾请求 if (res.statusCode === 404 && !req.hasMatchingRoute) return true; if (res.statusCode < 400) return true; return false; } }) );
注意:app._router是Express内部属性,若担心版本兼容性,可以用Express底层依赖的path-to-regexp库自行实现路由匹配逻辑。
方法二:给业务逻辑返回的404加自定义标记
和开发团队约定:当业务接口因资源不存在主动返回404时,给响应对象添加一个自定义属性(比如res.isBusiness404 = true),以此区分路径不存在的404和业务逻辑的404。
业务代码示例:
app.get('/api/resources/:id', (req, res) => { const resource = getResourceById(req.params.id); if (!resource) { res.isBusiness404 = true; // 标记这是业务逻辑返回的404 return res.status(404).json({ error: '资源不存在' }); } res.json(resource); });
修改后的Morgan配置:
app.use( morgan('combine', { skip(req, res) { // 只过滤「状态码404且非业务逻辑返回」的垃圾请求 if (res.statusCode === 404 && !res.isBusiness404) return true; if (res.statusCode < 400) return true; return false; } }) );
这个方法实现简单,只要团队遵守约定就能稳定生效。
方法三:区分静态资源与业务接口的404
如果大部分垃圾请求是针对静态资源的随机路径,可以单独给静态资源请求打标记,再针对性过滤:
// 配置静态资源中间件,标记静态资源请求 app.use(express.static('public', { setHeaders: (res) => { res.isStaticRequest = true; } })); // 配置Morgan日志 app.use( morgan('combine', { skip(req, res) { // 只过滤静态资源的404请求 if (res.statusCode === 404 && res.isStaticRequest) return true; if (res.statusCode < 400) return true; return false; } }) );
内容的提问来源于stack exchange,提问作者DaaWaan
相关产品推荐
相关产品推荐

