PHP SoapClient 超时

发布于 2024-09-14 19:36:46 字数 131 浏览 2 评论 0原文

无论如何,SoapClient 请求是否会超时并引发异常。截至目前,我得到 PHP 服务器响应超时,在我的例子中是 60 秒。基本上我想要的是,如果在一定时间内没有来自 Web 服务的任何回复,则会抛出异常,我可以捕获它。 60秒警告不是我想要的。

Is there anyway for a SoapClient Request to time out and throw an exception. As of now, I get PHP Server response timeout, in my case 60 seconds. Basically what I want is, if there isn't any reply from the Web Service within certain time, an exception would be thrown and I could catch it. The 60 seconds warning is not what I want.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

飘逸的'云 2024-09-21 19:36:46
ini_set("default_socket_timeout", 15);
$client = new SoapClient($wsdl, array(......));

connection_timeout 选项定义超时(以秒为单位)
到 SOAP 服务的连接。该选项不定义超时
对于响应慢的服务。限制等待呼叫的时间
完成default_socket_timeout 设置可用。

ini_set("default_socket_timeout", 15);
$client = new SoapClient($wsdl, array(......));

The connection_timeout option defines a timeout in seconds for the
connection to the SOAP service. This option does not define a timeout
for services with slow responses. To limit the time to wait for calls
to finish the default_socket_timeout setting is available.

記柔刀 2024-09-21 19:36:46

无效答案。请参阅 https://stackoverflow.com/a/12119215/441739


虽然 Andrei 链接到了一个不错的解决方案,但这个解决方案的代码较少,但却得出了一个很好的解决方案:

* 使用 PHP5 SoapClient 扩展处理超时(通过安东尼奥·拉米雷斯;2010 年 2 月 2 日)

示例代码:
//
// 设置连接超时(示例中为十五秒)
//
$client = new SoapClient($wsdl, array("connection_timeout" => 15));

如果您需要更细粒度的 HTTP 控制,还有流上下文。请参阅 new SoapClient( )文档。从表面上看,SoapClient 使用 HTTP 和 SSL 传输。

Invalid answer. Please see https://stackoverflow.com/a/12119215/441739 instead.


While Andrei linked to a decent solution, this one has less code yet arrives at a good solution:

* Handling Timeouts with PHP5 SoapClient Extension (by Antonio Ramirez; 02 Feb 2010)

Example code:
//
// setting a connection timeout (fifteen seconds on the example)
//
$client = new SoapClient($wsdl, array("connection_timeout" => 15));

And there is also the stream context, if you need more fine-grained HTTP control. See the stream_context option for new SoapClient()Docs. Under the surface SoapClient uses the HTTP and SSL transports.

·深蓝 2024-09-21 19:36:46

查看

如果您感觉舒服并且您的环境允许您延长课程)。

它基本上扩展了SoapClient类,用可以处理超时的curl替换了HTTP传输:

class SoapClientTimeout extends SoapClient
{
    private $timeout;

    public function __setTimeout($timeout)
    {
        if (!is_int($timeout) && !is_null($timeout))
        {
            throw new Exception("Invalid timeout value");
        }

        $this->timeout = $timeout;
    }

    public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
    {
        if (!$this->timeout)
        {
            // Call via parent because we require no timeout
            $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        }
        else
        {
            // Call via Curl and use the timeout
            $curl = curl_init($location);

            curl_setopt($curl, CURLOPT_VERBOSE, FALSE);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
            curl_setopt($curl, CURLOPT_HEADER, FALSE);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
            curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);

            $response = curl_exec($curl);

            if (curl_errno($curl))
            {
                throw new Exception(curl_error($curl));
            }

            curl_close($curl);
        }

        // Return?
        if (!$one_way)
        {
            return ($response);
        }
    }
}

Have a look at

if you are comfortable and your environment allows you to extend classes.

It basically extends the SoapClient class, replaces the HTTP transport with curl which can handle the timeouts:

class SoapClientTimeout extends SoapClient
{
    private $timeout;

    public function __setTimeout($timeout)
    {
        if (!is_int($timeout) && !is_null($timeout))
        {
            throw new Exception("Invalid timeout value");
        }

        $this->timeout = $timeout;
    }

    public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
    {
        if (!$this->timeout)
        {
            // Call via parent because we require no timeout
            $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        }
        else
        {
            // Call via Curl and use the timeout
            $curl = curl_init($location);

            curl_setopt($curl, CURLOPT_VERBOSE, FALSE);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
            curl_setopt($curl, CURLOPT_HEADER, FALSE);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
            curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);

            $response = curl_exec($curl);

            if (curl_errno($curl))
            {
                throw new Exception(curl_error($curl));
            }

            curl_close($curl);
        }

        // Return?
        if (!$one_way)
        {
            return ($response);
        }
    }
}
眼趣 2024-09-21 19:36:46

接受的答案将破坏 SoapClient 必须提供的所有功能。比如设置正确的内容标题、身份验证等。

这将是问题的更好解决方案

class MySoapClient extends \SoapClient
{
    private $timeout = 10;

    public function __construct($wsdl, array $options)
    {
        // Defines a timeout in seconds for the connection to the SOAP service.
        // This option does not define a timeout for services with slow responses.
        // To limit the time to wait for calls to finish the default_socket_timeout setting is available.
        if (!isset($options['connection_timeout'])) {
            $options['connection_timeout'] = $this->timeout;
        }

        parent::__construct($wsdl, $options);
    }

    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;
    }

    public function __doRequest($request, $location, $action, $version, $one_way = 0)
    {
        $original = ini_get('default_socket_timeout');
        ini_set('default_socket_timeout', $this->timeout);
        $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        ini_set('default_socket_timeout', $original);

        return $response;
    }

}

The accepted answer will break all functionalities that SoapClient has to offer. Like setting the correct content headers, authentication etc.

This would be a better solution to the problem

class MySoapClient extends \SoapClient
{
    private $timeout = 10;

    public function __construct($wsdl, array $options)
    {
        // Defines a timeout in seconds for the connection to the SOAP service.
        // This option does not define a timeout for services with slow responses.
        // To limit the time to wait for calls to finish the default_socket_timeout setting is available.
        if (!isset($options['connection_timeout'])) {
            $options['connection_timeout'] = $this->timeout;
        }

        parent::__construct($wsdl, $options);
    }

    public function setTimeout($timeout)
    {
        $this->timeout = $timeout;
    }

    public function __doRequest($request, $location, $action, $version, $one_way = 0)
    {
        $original = ini_get('default_socket_timeout');
        ini_set('default_socket_timeout', $this->timeout);
        $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        ini_set('default_socket_timeout', $original);

        return $response;
    }

}
┈┾☆殇 2024-09-21 19:36:46

您还可以使用 stream_context_create() 并添加 < http 数组的 code>timeout 选项:

$context = stream_context_create(
    array(
        'http' => array(
            "timeout" => 10,
        ),
    )
);

这是 PHP 手册页

SoapHandler 初始化应该是:

$soapHandler = new SoapClient($wsdl, [
    //more params, if needed..
    
    'stream_context' => $context,
]);

You could also use stream_context_create() and add the timeout option to the http array:

$context = stream_context_create(
    array(
        'http' => array(
            "timeout" => 10,
        ),
    )
);

Here is the PHP manual page

The SoapHandler initialization then should be:

$soapHandler = new SoapClient($wsdl, [
    //more params, if needed..
    
    'stream_context' => $context,
]);
得不到的就毁灭 2024-09-21 19:36:46

您可以通过 Composer 安装它:
https://github.com/ideaconnect/idct-soap-client

它扩展了标准 SoapClient 并提供设置重试次数、连接和读取超时的选项。

You can install this through composer:
https://github.com/ideaconnect/idct-soap-client

It extends the standard SoapClient and gives options to set the amount of retries, connection and read timeouts.

银河中√捞星星 2024-09-21 19:36:46

我在使用 SOAPClient 时使用以下逻辑:

public function executeSoapCall($method, $params)
{
    try {
        $client = $this->tryGetSoapClient();

        $timeout = ini_get('default_socket_timeout');
        ini_set('default_socket_timeout', 60);//set new timeout value - 60 seconds
        $client->__soapCall($method, $params);//execute SOAP call
        ini_set('default_socket_timeout', $timeout);//revert timeout back
    } catch (\Throwable $e) {
        if (isset($timeout)) {
            ini_set('default_socket_timeout', $timeout);//revert timeout back
        }
    }
}
protected function tryGetSoapClient()
{
    $timeout = ini_get('default_socket_timeout');//get timeout (need to be reverted back afterwards)
    ini_set('default_socket_timeout', 10);//set new timeout value - 10 seconds
    try {
        $client = new \SoapClient($this->wsdl, $this->options);//get SOAP client
    } catch (\Throwable $e) {
        ini_set('default_socket_timeout', 10);//revert back in case of exception
        throw $e;
    }
    $this->iniSetTimeout($timeout);//revert back

    return $client;
}

这有助于我等待最多 10 秒的连接建立时间和 60 秒的调用执行时间。

I am using the following logic when working with SOAPClient:

public function executeSoapCall($method, $params)
{
    try {
        $client = $this->tryGetSoapClient();

        $timeout = ini_get('default_socket_timeout');
        ini_set('default_socket_timeout', 60);//set new timeout value - 60 seconds
        $client->__soapCall($method, $params);//execute SOAP call
        ini_set('default_socket_timeout', $timeout);//revert timeout back
    } catch (\Throwable $e) {
        if (isset($timeout)) {
            ini_set('default_socket_timeout', $timeout);//revert timeout back
        }
    }
}
protected function tryGetSoapClient()
{
    $timeout = ini_get('default_socket_timeout');//get timeout (need to be reverted back afterwards)
    ini_set('default_socket_timeout', 10);//set new timeout value - 10 seconds
    try {
        $client = new \SoapClient($this->wsdl, $this->options);//get SOAP client
    } catch (\Throwable $e) {
        ini_set('default_socket_timeout', 10);//revert back in case of exception
        throw $e;
    }
    $this->iniSetTimeout($timeout);//revert back

    return $client;
}

This helps me to wait up to 10 seconds for connection establishment, and 60 seconds for the call execution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文