JavaScript,如何抛出一个不带堆栈调试信息的error?
发布于 作者:苏南大叔 来源:程序如此灵动~需求是这样的,希望抛出一个自定义错误。但是,不想暴露任何的调试信息。比如:在网络接口服务中,throw
了一个new Error()
。这个时候,就是单纯的错误发生在第几行第几列,错误信息的堆栈是怎样的。因为这个属于网络接口,存在非法访问的可能性。所以,这些对于报错堆栈信息,就存在着信息安全风险。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70
,nodejs@20.18.0
。
抛出一个错误
throw new Error("这是个带stack的error");
可以看到,在没有try{}catch(){}
的情况下,会显示具体的调试信息。例如:
Error: 这是个带stack的error
at D:\test\express.js:4:9
at Layer.handle [as handle_request] (D:\test\node_modules\express\lib\router\layer.js:95:5)
at next (D:\test\node_modules\express\lib\router\route.js:149:13)
at Route.dispatch (D:\test\node_modules\express\lib\router\route.js:119:3)
at Layer.handle [as handle_request] (D:\test\node_modules\express\lib\router\layer.js:95:5)
at D:\test\node_modules\express\lib\router\index.js:284:15
at Function.process_params (D:\test\node_modules\express\lib\router\index.js:346:12)
at next (D:\test\node_modules\express\lib\router\index.js:280:10)
at expressInit (D:\test\node_modules\express\lib\middleware\init.js:40:5)
at Layer.handle [as handle_request] (D:\test\node_modules\express\lib\router\layer.js:95:5)
方案一,清空stack
错误定义好之后,清空stack
属性即可,这个是最简单的方案。
let e = new Error("这是个带stack的error");
e.stack = "";
throw e;
方案二,CustomError
继承Error
,使用CustomError
做类定义进行初始化,这样的操作很常规化。如果一个项目里面,有很多本文的需求的话,就可以选择这个方案。
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
// Error.captureStackstack(this, this.constructor); // 为了兼容性,确保stack包含message
this.stack = "";
}
}
throw new CustomError("这是个不带stack的CustomError");
方案三,改写Error
这个方案就略显极端了,使用Proxy
改写Error
这个类定义。很极端...。悄咪咪的,以后所有的Error
都不带调试信息了。
Error = new Proxy(Error, {
construct: function (target, args) {
var obj_tmp = new target(...args);
obj_tmp.stack = "";
return obj_tmp;
},
});
// console.log(e instanceof Error); // true
throw new Error("这是个不带stack的修改版Error");
参考文章:
题外话,express的代码机制
本文以express
提供的网络接口作为载体,演示本文的内容。当然,普通的node
代码或者浏览器运行环境里面,也是可以运行生效的。
测试基础代码(仅龙套,没实际意义):
const express = require("express");
const app = express();
app.get("/", function (req, res) {
// ##################################
// 测试代码放这里
// ##################################
res.send("苏南大叔的博客:newsn.net");
});
const server = app.listen(process.env.PORT || 3222, () => {
const port = server.address().port;
console.log("http://localhost:%d", port);
});
虽然这个被改写的Error
类被定义在某个路由下面,但是一旦访问了这个路由,其它的本来会被输出调试信息的路由,也会被一并改写生效,变成不输出stack
信息。
这就深深的引发思考了,php
下正常情况下来说,是肯定不会发生这样的事情的。两个不同的请求绝对不会相互干扰。而这个express
的代码,两个请求中居然会相互干涉... 这说明了什么?就本文的代码来说,先访问/4
,再访问/
,就会发现这个问题。Error
的改写被应用到全局了......................................
参考文章:
结语
本文清空Error
的堆栈信息,其核心点就一句话.stack=""
。更多苏南大叔的js
调试经验文章,请参考:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。