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

如何将自定义事务ID传递给SOAP::Lite的日志传输函数?

解决SOAP::Lite传递事务ID到日志回调的问题

下面提供两种无需使用outputxml的方案,实现将getWords中的txn_id传递给log_transport日志函数:

方案一:利用闭包绑定事务ID

通过在getWords中创建绑定当前txn_id的闭包,动态替换SOAP对象的日志回调,实现上下文传递:

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

use SOAP::Lite +trace => [ transport => \&log_transport, ];

sub log_transport {
    my ($in) = @_;
    # 原全局日志逻辑(可选保留,若不需要可注释)
    if (ref($in) eq "HTTP::Request") {
        say STDERR Dumper(ref($in), $in->content);
    }
    elsif (ref($in) eq "HTTP::Response") {
        say STDERR Dumper(ref($in), $in->content);  
    }
}

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
my $soap = SOAP::Lite->proxy('https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords');
$soap->serializer()->register_ns('http://www.dataaccess.com/webservicesserver/' ,"ns");

sub getWords
{
    my ($number, $txn_id) = @_ ;

    # 保存原日志回调(若不需要保留原逻辑可省略此步骤)
    my $original_logger = $soap->transport->{'_hooks'}->{'trace'}->[0];
    
    # 创建绑定txn_id的闭包作为临时日志回调
    my $txn_logger = sub {
        my ($in) = @_;
        if (ref($in) eq "HTTP::Request") {
            # 插入日志逻辑,使用当前txn_id
            # INSERT INTO logs ( txn_id, request ) VALUES ( ?, ? )
            say STDERR "txn_id: $txn_id, Request content: ", $in->content;
        }
        elsif (ref($in) eq "HTTP::Response") {
            # 更新日志逻辑,使用当前txn_id
            # UPDATE logs SET response = ? WHERE txn_id = ?
            say STDERR "txn_id: $txn_id, Response content: ", $in->content;
        }
        # 调用原日志回调(若保留原逻辑则执行)
        $original_logger->($in) if $original_logger;
    };

    # 设置临时日志回调
    $soap->transport->add_hook(trace => $txn_logger);

    my $method = SOAP::Data->name("ns:NumberToWords");
    my @params = ( SOAP::Data->name("ubiNum" => $number) );
    my $response = $soap->call($method => @params);

    # 恢复原日志回调(若复用SOAP对象则必须执行)
    $soap->transport->{'_hooks'}->{'trace'}->[0] = $original_logger;

    if (!$response->fault) {
        say STDOUT "NumberToWords = " . $response->result;
    }
    else {
        say STDERR "error: " . (defined $response->faultstring? $response->faultstring : $soap->transport->status);
    }
}

getWords(444, '123abc');

方案二:通过自定义HTTP请求头传递事务ID

在请求中添加自定义HTTP头携带txn_id,在日志回调中从请求/响应对象提取该ID:

1. 修改日志回调函数

sub log_transport {
    my ($in) = @_;
    my $txn_id;
    if (ref($in) eq "HTTP::Request") {
        # 从请求头提取txn_id
        $txn_id = $in->header('X-Txn-ID');
        # INSERT INTO logs ( txn_id, request ) VALUES ( ?, ? )
        say STDERR "txn_id: $txn_id, Request content: ", $in->content;
    }
    elsif (ref($in) eq "HTTP::Response") {
        # 从响应关联的请求中提取txn_id
        $txn_id = $in->request->header('X-Txn-ID');
        # UPDATE logs SET response = ? WHERE txn_id = ?
        say STDERR "txn_id: $txn_id, Response content: ", $in->content;  
    }
}

2. 修改getWords函数添加请求头

sub getWords
{
    my ($number, $txn_id) = @_ ;

    # 设置自定义HTTP头携带txn_id
    $soap->transport->http_request->header('X-Txn-ID' => $txn_id);

    my $method = SOAP::Data->name("ns:NumberToWords");
    my @params = ( SOAP::Data->name("ubiNum" => $number) );
    my $response = $soap->call($method => @params);

    if (!$response->fault) {
        say STDOUT "NumberToWords = " . $response->result;
    }
    else {
        say STDERR "error: " . (defined $response->faultstring? $response->faultstring : $soap->transport->status);
    }
}

说明

  • 方案二无需修改日志回调的绑定逻辑,实现更简洁,适合大多数场景
  • 两种方案均避免了使用$soap->outputxml(1)->call()的方式

内容的提问来源于stack exchange,提问作者h q

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:02:54