在PHP中处理Soap超时

Rob*_*Rob 32 php error-handling soap web-services

我正在开发一个项目,我正在使用SOAP Web服务验证来自用户的信息.我目前正在处理错误,假设我收到来自Web服务的响应,但还需要处理服务超时或不可用的边缘情况.

在超时或服务不可用的情况下,我需要假装请求成功(Web服务批准了该信息),但我不清楚抛出了什么异常.

一些伪代码:

// $client is PHP's SoapClient class
try {
  $response = $client->SomeSoapRequest();
}
catch(SoapFault $e){
  // handle issues returned by the web service
}
catch(Exception $e){
  // handle PHP issues with the request
}
Run Code Online (Sandbox Code Playgroud)

我似乎无法找到的是:

  1. 超时是一个SoapFault吗?如果是这样,区分超时错误和Web服务问题(如类型错误等)的最佳方法是什么?我发现一个页面提到了一个错误,其中消息是"错误加载标题"的效果,但没有提到这是否是Soap错误.
  2. 服务不可用性如何可能发生?PHP异常似乎有意义(从Web服务返回SoapFault,其中不可用性是套接字问题或类似问题)?
  3. 是否存在可以测试超时的现有服务(例如示例)?大多数与超时相关的讨论似乎与通过扩展默认超时设置来防止超时有关,这在这种情况下并不理想.

小智 32

1)如果超时,PHP会使用faultcode="HTTP"和抛出SoapFault异常faultstring="Error Fetching http headers".

2)在我看来,区分超时错误和Web服务问题的最佳方法是查看SoapFault类的成员faultcodefaultstring成员. 特别地,该元件旨在由软件使用以提供用于识别故障的算法机制. 正如您还可以阅读PHP手册注释,没有方法来读取属性,因此您必须直接访问它(例如.),因为该方法不起作用. 的SOAP 1.1规格定义了四个可能的值字段:
faultcode
faultcode$e->faultcodegetCode()
faultcode

  • VersionMismatch:处理方发现SOAP Envelope元素的名称空间无效
  • MustUnderstand:SOAP Header元素的直接子元素,处理方未理解或未遵守,包含值为"1"的SOAP mustUnderstand属性
  • 客户端:客户端类错误表示消息未正确形成或未包含相应信息才能成功.例如,消息可能缺少正确的身份验证或支付信息.通常表明不应该在没有变化的情况下重新发送消息.
  • 服务器:服务器类错误表示无法处理消息的原因不是直接归因于消息本身的内容,而是处理消息.例如,处理可以包括与没有响应的上游处理器通信.该消息可能在稍后的时间点成功.

除了这些代码之外,PHP还使用HTTP代码来识别协议级别发生的错误(例如:套接字错误); 例如,如果add_soap_faultext/soap/php_http.c源代码中搜索,则可以看到生成某些类型的错误.
通过在PHP SOAP扩展源文件中搜索add_soap_faultsoap_server_fault函数,我构建了以下PHP SoapFault异常列表:

HTTP
----
Unable to parse URL
Unknown protocol. Only http and https are allowed.
SSL support is not available in this build
Could not connect to host
Failed Sending HTTP SOAP request
Failed to create stream??
Error Fetching http headers
Error Fetching http body: No Content-Length: connection closed or chunked data
Redirection limit reached: aborting
Didn't recieve an xml document
Unknown Content-Encoding
Can't uncompress compressed response
Error build soap request


VersionMismatch
---------------
Wrong Version


Client
------
A SOAP 1.2 envelope can contain only Header and Body
A SOAP Body element cannot have non Namespace qualified attributes
A SOAP Envelope element cannot have non Namespace qualified attributes
A SOAP Header element cannot have non Namespace qualified attributes
Bad Request
Body must be present in a SOAP envelope
Can't find response data
DTD are not supported by SOAP
encodingStyle cannot be specified on the Body
encodingStyle cannot be specified on the Envelope
encodingStyle cannot be specified on the Header
Error cannot find parameter
Error could not find "location" property
Error finding "uri" property
looks like we got "Body" with several functions call
looks like we got "Body" without function call
looks like we got no XML document
looks like we got XML without "Envelope" element
Missing parameter
mustUnderstand value is not boolean
SoapClient::__doRequest() failed
SoapClient::__doRequest() returned non string value
Unknown Data Encoding Style
Unknown Error
DataEncodingUnknown


MustUnderstand
--------------
Header not understood


Server
------
Couldn't find WSDL
DTD are not supported by SOAP
Unknown SOAP version
WSDL generation is not supported yet
Run Code Online (Sandbox Code Playgroud)

3)要模拟超时条件,请尝试使用以下代码:

soapclient.php

<?php

ini_set('default_socket_timeout', 10);

$client = new SoapClient(null, 
  array(
    'location' => "http://localhost/soapserver.php",
    'uri'      => "http://localhost/soapserver.php",
    'trace'    => 1
  )
);

try {
    echo $return = $client->__soapCall("add",array(41, 51));
} catch (SoapFault $e) {
    echo "<pre>SoapFault: ".print_r($e, true)."</pre>\n";
    //echo "<pre>faultcode: '".$e->faultcode."'</pre>";
    //echo "<pre>faultstring: '".$e->getMessage()."'</pre>";
}

?>
Run Code Online (Sandbox Code Playgroud)

soapserver.php

<?php

function add($a, $b) {
  return $a + $b;
}

sleep(20);

$soap = new SoapServer(null, array('uri' => 'http://localhost/soapserver.php'));
$soap->addFunction("add");
$soap->handle();

?>
Run Code Online (Sandbox Code Playgroud)

请注意脚本中的sleep调用,其SoapServer.php时间(20)最长,而不是为脚本中的default_socket_timeout参数指定的时间(10)SoapClient.php.
如果你想模拟服务不可用,例如,你可以改变location从协议httphttpssoapclient.php脚本,假设你的Web服务器没有为SSL配置; 通过这样做,PHP应该抛出"无法连接到主机"SoapFault.


tob*_*ych 7

貌似default_socket_timeout通过HTTPS进行SOAP调用时,没有考虑到:

在撰写本文时错误开放.正如博客文章评论Robert Ludwick在删除的答案中提到的Timing Out PHP Soap Calls(2009年10月21日;由Robert F. Ludwick发布)指出,该帖子讨论的解决方法(覆盖SoapClient::__doRequest()卷曲请求)适用于此还有bug.

另一个相关的错误是:


博客文章中提到的代码经过了一些更改,可以在Github上获得HTTP身份验证的最新形式:

在任何情况下,不再需要变通方法,因为PHP SOAPClient扩展中已修复此问题.


Tou*_*Pal 4

处理服务超时

$client = new SoapClient($wsdl, array("connection_timeout"=>10));

// SET SOCKET TIMEOUT
if(defined('RESPONSE_TIMEOUT') &&  RESPONSE_TIMEOUT != '') {
 ini_set('default_socket_timeout', RESPONSE_TIMEOUT);
}
Run Code Online (Sandbox Code Playgroud)