SoapServer maps functions incorectly when the wsdl

2019-05-25 04:49发布

I'm not sure if this is php bug (bad implementation) or my bug (bad understanding of the SOAP protocol / SoapServer as this is the first time I'm using SoapServer)

I've noticed that if there are two or more operations with the same wsdl:part (even if the wsdl:message , operation and soapAction are different), The SoapServer will allways call the first function. In this example, I've two functions multiply2 and multiply4 both having num (int) as input parameter. earlier today, If I change the part name (service1.wsdl) the functions are mapped correctly.

Although, I don't mind using different names it looks to me like a bug. Am I missing something or should I open a bug ?

This is simple example I've crated:

Very simple php class

<?php
class Multi
{
    function multiply2($num) { return ($num * 2 ); }
    function multiply4($num){ return ($num * 4 );  }
}
?>

And slightly changed SoapServer (with added logging - adapted from this post) but the issue appears when I'm using the plain SoapServer as well:

$server = new overloadedSoapServer("service.wsdl", array('soap_version' => SOAP_1_2,'encoding' => SOAP_ENCODED));
$server->setClass("multi");

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $server->handle();
} 

This is the client code:

ini_set("soap.wsdl_cache_enabled", "0");
$client = new SoapClient('service.wsdl');
$client1 = new SoapClient('service1.wsdl');
echo "<pre>\nFrom service.wsdl:";
echo  "\n".$client->multiply2(10);
echo  "\n".$client->multiply4(10);
echo "</pre>";
echo "<pre>\nFrom service1.wsdl:";
echo  "\n".$client1->multiply2(10);
echo  "\n".$client1->multiply4(10);
echo "</pre>";

service.wsdl and service1.wsdl are basically the same file, with two exception:

  1. their endpoint are different (service.wsdl points to http://tests.simsimy.info/web/service.php and service1.php to http://tests.simsimy.info/web/service1.php each endpoint uses the appropriate wsdl to load the SoapServer)
  2. in service.wsdl multiply2Request and multiply4Request have the as part name - num, while in service1.wsdl the names are different (num2 and num4)

This is the full wsdl of service.wsdl

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://tests.simsimy.info/web/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="service"
    targetNamespace="http://tests.simsimy.info/web/">
    <wsdl:message name="multiply2Request">
        <wsdl:part name="num" type="xsd:int"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="multiply2Response">
        <wsdl:part name="res" type="xsd:int"></wsdl:part>
    </wsdl:message>

    <wsdl:message name="multiply4Request">
        <wsdl:part name="num" type="xsd:int"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="multiply4Response">
        <wsdl:part name="res" type="xsd:int"></wsdl:part>
    </wsdl:message>
    <wsdl:portType name="dd">
        <wsdl:operation name="multiply2">
            <wsdl:input message="tns:multiply2Request"></wsdl:input>
            <wsdl:output message="tns:multiply2Response"></wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="multiply4">
            <wsdl:input message="tns:multiply4Request"></wsdl:input>
            <wsdl:output message="tns:multiply4Response"></wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="serviceSOAP" type="tns:dd">
        <soap:binding style="document"
            transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="multiply2">
            <soap:operation soapAction="http://tests.simsimy.info/web/multiply2" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="multiply4">
            <soap:operation soapAction="http://tests.simsimy.info/web/multiply4" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="multiply_service">
        <wsdl:port binding="tns:serviceSOAP" name="serviceSOAP">
            <soap:address location="http://tests.simsimy.info/web/service.php" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

The changed part in service1.wsdl :

<wsdl:message name="multiply2Request">
        <wsdl:part name="num2" type="xsd:int"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="multiply2Response">
        <wsdl:part name="res" type="xsd:int"></wsdl:part>
    </wsdl:message>

    <wsdl:message name="multiply4Request">
        <wsdl:part name="num4" type="xsd:int"></wsdl:part>
    </wsdl:message>
    <wsdl:message name="multiply4Response">
        <wsdl:part name="res" type="xsd:int"></wsdl:part>
    </wsdl:message>

When I run the client code I get the following ouput:

From service.wsdl:
20
20

From service1.wsdl:
20
40

1条回答
仙女界的扛把子
2楼-- · 2019-05-25 05:16

You can change the binding style in your wsdl from 'document' to 'rpc'.

First I thought it is a cache problem as your posted server code above does not contains the ini_set() to disabled the cache. But is isn't a cache problem.

Having traced http traffic. Client seems working porperly it is a SoapServer problem. (Like you mentioned).. Further investigating ...

A bug report has already been filed - although it is currently unclear if it is a bug.

Workarounds are mentioned in the bug report too. You can change the binding style to rpc if this is ok for you:

Change

<soap:binding style="document"

to

<soap:binding style="rpc"

This workaround works for me. You will find a very interesting article on how binding styles work here. This may help you to decide whether rpc binding style is ok for you or not.

查看更多
登录 后发表回答