理解多部分消息的PHP SOAP客户端?

ole*_*vre 14 php soap web-services

有这样的野兽吗?PHP附带的简单SOAP客户端不了解多部分消息.提前致谢.

Ste*_*rig 13

本机PHP SoapClient类不支持多部分消息(并且在所有WS-*事务中都受到很大限制)而且我认为PHP编写的库NuSOAPZend_Soap都不能处理这种SOAP消息.

我可以想到两个解决方案:

  • 扩展SoapClient类并覆盖SoapClient::__doRequest()方法以获取实际的响应字符串,然后您可以随心所欲地解析它.

    class MySoapClient extends SoapClient
    {
        public function __doRequest($request, $location, $action, $version, $one_way = 0)
        {
            $response = parent::__doRequest($request, $location, $action, $version, $one_way);
            // parse $response, extract the multipart messages and so on
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这可能有点棘手 - 但值得一试.

  • 为PHP使用更复杂的SOAP客户端库.第一个也是唯一一个我想到的是WSO2 WSF/PHP,其中包括SOAP MTOM,WS-Addressing,WS-Security,WS-SecurityPolicy,WS-Secure Conversation和WS-ReliableMessaging,代价是必须安装本机PHP延期.


fun*_*der 5

尽管这个答案已经在这里给出了很多,但我还是整理了一个通用的解决方案,请记住,XML 可以在没有包装器的情况下出现。

class SoapClientExtended extends SoapClient
{
    /**
     * Sends SOAP request using a predefined XML
     *
     * Overwrites the default method SoapClient::__doRequest() to make it work
     * with multipart responses.
     *
     * @param string $request      The XML content to send
     * @param string $location The URL to request.
     * @param string $action   The SOAP action. [optional] default=''
     * @param int    $version  The SOAP version. [optional] default=1
     * @param int    $one_way  [optional] ( If one_way is set to 1, this method
     *                         returns nothing. Use this where a response is
     *                         not expected. )
     *
     * @return string The XML SOAP response.
     */
    public function __doRequest(
        $request, $location, $action, $version, $one_way = 0
    ) {
        $result = parent::__doRequest($request, $location, $action, $version, $one_way);

        $headers = $this->__getLastResponseHeaders();

        // Do we have a multipart request?
        if (preg_match('#^Content-Type:.*multipart\/.*#mi', $headers) !== 0) {
            // Make all line breaks even.
            $result = str_replace("\r\n", "\n", $result);

            // Split between headers and content.
            list(, $content) = preg_split("#\n\n#", $result);
            // Split again for multipart boundary.
            list($result, ) = preg_split("#\n--#", $content);
        }

        return $result;
    }
}
Run Code Online (Sandbox Code Playgroud)

SoapClientExtended仅当您使用选项初始化时,这才有效trace => true