如何使用node-soap在服务端映射SOAP请求与响应
关联node-soap请求与响应日志的解决方案
我之前在用node-soap搭建服务端的时候,也遇到过要把请求和响应日志一一对应的需求,折腾了一阵后找到了几个靠谱的实现方式,分享给你:
核心思路其实很简单:在收到请求的瞬间生成唯一的logId,把这个ID跟当前请求的上下文绑定,等返回响应的时候再用同一个ID记录日志,这样就能精准对应上哪条响应属于哪条请求了。
下面是具体的实现步骤,你可以根据自己的node-soap版本来选:
1. 先整个生成唯一logId的工具函数
我习惯用uuid来生成唯一ID,随机性够强,不会重复。先装个依赖:npm install uuid,然后写个生成函数:
const { v4: uuidv4 } = require('uuid'); function generateLogId() { return uuidv4(); // 生成标准UUID作为logId,当然你也可以用时间戳加随机数的方式 }
2. 把logId绑定到请求上下文里
这里有两种方式,一种是包装服务方法(兼容性最好,不管node-soap版本都能用),另一种是利用node-soap的事件(如果你的版本支持的话)。
方式一:包装服务方法(推荐)
不管你用的是哪个版本的node-soap,这种方法都能稳拿logId。假设你原本的服务方法是这样的:
const myService = { CalculatorPort: { CalculatorService: { AddNumbers(args, callback) { const sum = args.num1 + args.num2; callback(null, { sumResult: sum }); } } } };
我们写个包装函数,把原方法包一层,在调用原方法前生成logId,记录请求日志,然后重写回调函数,在响应的时候用同一个logId记录:
// 包装服务方法的工具函数 function wrapServiceMethod(originalMethod) { return function(args, callback) { // 第一步:收到请求,生成logId并打请求日志 const logId = generateLogId(); server.log('received', logId, args); // 第二步:重写回调,在响应时打关联日志 const originalCallback = callback; callback = function(err, responseData) { // 用同一个logId记录响应,不管成功失败都打 server.log('replied', logId, err ? { error: err.message } : responseData); originalCallback(err, responseData); }; // 第三步:调用原来的服务方法 return originalMethod.call(this, args, callback); }; } // 把所有服务方法都包一层 const wrappedService = { CalculatorPort: { CalculatorService: { AddNumbers: wrapServiceMethod(myService.CalculatorPort.CalculatorService.AddNumbers) } } }; // 最后注册包装后的服务到node-soap soap.listen(server, '/soap-endpoint', wrappedService, wsdlXml, () => { console.log('SOAP server up and running'); });
方式二:利用node-soap的request事件(版本兼容注意)
如果你的node-soap版本比较新,支持request事件的话,可以在事件里给请求对象加个logId属性,然后在服务方法里直接拿:
// 监听request事件,生成logId并挂载到请求上 soapServer.on('request', (request, methodName) => { const logId = generateLogId(); request.logId = logId; // 先打请求日志 server.log('received', logId, request.body); }); // 服务方法里直接取logId const myService = { CalculatorPort: { CalculatorService: { AddNumbers(args, callback) { // 这里的this.request就是当前请求对象,视node-soap版本可能略有不同 const logId = this.request.logId; const sum = args.num1 + args.num2; // 打响应日志 server.log('replied', logId, { sumResult: sum }); callback(null, { sumResult: sum }); } } } };
3. 调整你的server.log函数
最后把原来的log函数改一下,接收logId参数,这样日志输出就能清晰看到关联关系了:
function log(type, logId, data) { const time = new Date().toISOString(); console.log(`[${time}] [${type}] [LOG-ID: ${logId}]`, JSON.stringify(data, null, 2)); }
这样打出来的日志就是下面这样的,一眼就能通过LOG-ID找到对应的请求和响应:
[2024-05-20T14:20:00.123Z] [received] [LOG-ID: 550e8400-e29b-41d4-a716-446655440000] {"num1":10,"num2":20} [2024-05-20T14:20:00.125Z] [replied] [LOG-ID: 550e8400-e29b-41d4-a716-446655440000] {"sumResult":30}
如果遇到node-soap版本差异导致上下文拿不到的情况,优先用包装方法的方式,兼容性拉满。
内容的提问来源于stack exchange,提问作者Tommz
相关产品推荐
相关产品推荐

