PERL WCF Web服务调用失败
问题描述:
我正在使用PERL将Web服务调用到我们供应商提供的Web服务之一。 Web服务使用SOAP 1.2和WSHttpBinding。PERL WCF Web服务调用失败
我能够成功地调用Web服务中的大部分调用,除了RetrieveReport调用。 RetrieveReport调用应该是流式传输文件。不过,我收到了下面的回复。
调用RetrieveReport的一个示例是使用C#代码提及使用以下绑定提供的。不过,我不知道如何在PERL中做到这一点。如果任何人可以提供任何帮助,我提前感谢你。
C#应用程序配置结合
<binding name="WSHttpBinding_IBIStreamService" closeTimeout="00:02:00"
openTimeout="00:02:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="2147483647"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true" />
</security>
</binding>
Perl代码
my $reportKey = 'report_key';
my $reportUri = 'report_uri';
my $xml = new XML::Simple;
my $userAgent = LWP::UserAgent->new(agent => 'https://service.com/services/BIDataService');
my $message = <<'.';
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://service.com/dataservices/bistream/2/IBIStreamService/RetrieveReport</a:Action>
<h:ReportKey xmlns:h="http://service.com/dataservices/bistream/2" xmlns="http://service.com/dataservices/bistream/2">[ReportKey]</h:ReportKey>
<a:To s:mustUnderstand="1">[ReportRetrievalUri]</a:To>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RetrieveReportRequest xmlns="http://service.com/dataservices/bistream/2" />
</s:Body>
</s:Envelope>
.
# Replace the dynamic values
$message =~ s/\[ReportKey\]/$reportKey/g;
$message =~ s/\[ReportRetrievalUri\]/$reportUri/g;
my $request = HTTP::Request->new(POST => $uri);
$request->header(SOAPAction => '"http://service.com/dataservices/bistream/2/IBIStreamService/RetrieveReport"');
$request->content($message);
$request->content_type("application/soap+xml; charset=utf-8");
print "-- CONTENT --\n\n";
print $request->content . "\n\n";
my $response = $userAgent->request($request);
if ($response->is_success) {
print "--SUCCESS--\n" . $response->decoded_content . "\n";
} else {
print "--FAILURE--\n" . $response->status_line, "\n";
print $response->error_as_HTML;
}
响应从卖方
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value>a:ActionNotSupported</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The message with Action \'http://service.com/dataservices/bistream/2/IBIStreamService/RetrieveReport\' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</s:Text>
</s:Reason>
</s:Fault>
</s:Body>
</s:Envelope>
WSDL来源
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions name="BIStreamService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:i0="http://service.com/dataservices/bistream/2" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
<wsp:Policy wsu:Id="WSHttpBinding_IBIStreamService_policy">
<wsp:ExactlyOne>
<wsp:All>
<wsaw:UsingAddressing/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsdl:import namespace="http://service.com/dataservices/bistream/2" location="https://service.com/services/BIStreamingService?wsdl=wsdl0"/>
<wsdl:types/>
<wsdl:binding name="WSHttpBinding_IBIStreamService" type="i0:IBIStreamService">
<wsp:PolicyReference URI="#WSHttpBinding_IBIStreamService_policy"/>
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="RetrieveReport">
<soap12:operation soapAction="http://service.com/dataservices/bistream/2/IBIStreamService/RetrieveReport" style="document"/>
<wsdl:input name="RetrieveReportRequest">
<soap12:header message="i0:RetrieveReportRequest_Headers" part="ReportKey" use="literal"/>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output name="StreamReportResponse">
<soap12:header message="i0:StreamReportResponse_Headers" part="Status" use="literal"/>
<soap12:header message="i0:StreamReportResponse_Headers" part="StatusMessage" use="literal"/>
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="BasicHttpBinding_IBIStreamService" type="i0:IBIStreamService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="RetrieveReport">
<soap:operation soapAction="http://service.com/dataservices/bistream/2/IBIStreamService/RetrieveReport" style="document"/>
<wsdl:input name="RetrieveReportRequest">
<soap:header message="i0:RetrieveReportRequest_Headers" part="ReportKey" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="StreamReportResponse">
<soap:header message="i0:StreamReportResponse_Headers" part="Status" use="literal"/>
<soap:header message="i0:StreamReportResponse_Headers" part="StatusMessage" use="literal"/>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="BIStreamService">
<wsdl:port name="WSHttpBinding_IBIStreamService" binding="tns:WSHttpBinding_IBIStreamService">
<soap12:address location="https://service.com/services/BIStreamingService"/>
<wsa10:EndpointReference>
<wsa10:Address>https://service.com/services/BIStreamingService</wsa10:Address>
</wsa10:EndpointReference>
</wsdl:port>
<wsdl:port name="BasicHttpBinding_IBIStreamService" binding="tns:BasicHttpBinding_IBIStreamService">
<soap:address location="https://service.com/services/BIStreamingService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
答
我发现了问题。
报表Web服务有两个URL。一个执行报告,另一个执行报告检索。我修改了LWP :: UserAgent-> new(agent =>'')和HTTP :: Request-> new(POST =>''),在检索报告时指向https://service.com/services/BIStreamingService,现在它工作。
谢谢!
用LWP手工操作SOAP非常困难。为什么不使用[XML :: Compile :: WSDL](https://metacpan.org/pod/distribution/XML-Compile-WSDL11/lib/XML/Compile/WSDL11.pod)或[SOAP :: Lite ](http://p3rl.org/SOAP::Lite)呢? – simbabque
我有几个安装XML :: Compile :: WSDL的问题。我尝试了SOAP :: Lite,但供应商的Web服务是非常自定义的,我很难让它在SOAP :: Lite中正常工作。提供完整的XML代码更容易,提交并用LWP解析它。 –