You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:22:00