Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PHP SoapClient with timeout
<?php
//Drop-in replacement for PHP's SoapClient class supporting connect and response/transfer timeout
//Usage: Exactly as PHP's SoapClient class, except that 3 new options are available:
// timeout The response/transfer timeout in milliseconds; 0 == default SoapClient / CURL timeout
// connecttimeout The connection timeout; 0 == default SoapClient / CURL timeout
// sslverifypeer FALSE to stop SoapClient from verifying the peer's certificate
class SoapClientTimeout extends SoapClient
{
private $timeout = 0;
private $connecttimeout = 0;
private $sslverifypeer = true;
public function __construct($wsdl, $options) {
//"POP" our own defined options from the $options array before we call our parent constructor
//to ensure we don't pass unknown/invalid options to our parent
if (isset($options['timeout'])) {
$this->__setTimeout($options['timeout']);
unset($options['timeout']);
}
if (isset($options['connecttimeout'])) {
$this->__setConnectTimeout($options['connecttimeout']);
unset($options['connecttimeout']);
}
if (isset($options['sslverifypeer'])) {
$this->__setSSLVerifyPeer($options['sslverifypeer']);
unset($options['sslverifypeer']);
}
//Now call parent constructor
parent::__construct($wsdl, $options);
}
public function __setTimeout($timeoutms)
{
if (!is_int($timeoutms) && !is_null($timeoutms) || $timeoutms<0)
throw new Exception("Invalid timeout value");
$this->timeout = $timeoutms;
}
public function __getTimeout()
{
return $this->timeout;
}
public function __setConnectTimeout($connecttimeoutms)
{
if (!is_int($connecttimeoutms) && !is_null($connecttimeoutms) || $connecttimeoutms<0)
throw new Exception("Invalid connecttimeout value");
$this->connecttimeout = $connecttimeoutms;
}
public function __getConnectTimeout()
{
return $this->connecttimeout;
}
public function __setSSLVerifyPeer($sslverifypeer)
{
if (!is_bool($sslverifypeer))
throw new Exception("Invalid sslverifypeer value");
$this->sslverifypeer = $sslverifypeer;
}
public function __getSSLVerifyPeer()
{
return $this->sslverifypeer;
}
public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
{
if (($this->timeout===0) && ($this->connecttimeout===0))
{
// 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);
if ($curl === false)
throw new Exception('Curl initialisation failed');
$options = array(
CURLOPT_VERBOSE => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $request,
CURLOPT_HEADER => false,
CURLOPT_NOSIGNAL => true, //http://www.php.net/manual/en/function.curl-setopt.php#104597
CURLOPT_HTTPHEADER => array(sprintf('Content-Type: %s', $version == 2 ? 'application/soap+xml' : 'text/xml'), sprintf('SOAPAction: %s', $action)),
CURLOPT_SSL_VERIFYPEER => $this->sslverifypeer
);
if ($this->timeout>0) {
if (defined('CURLOPT_TIMEOUT_MS')) { //Timeout in MS supported?
$options[CURLOPT_TIMEOUT_MS] = $this->timeout;
} else { //Round(up) to second precision
$options[CURLOPT_TIMEOUT] = ceil($this->timeout/1000);
}
}
if ($this->connecttimeout>0) {
if (defined('CURLOPT_CONNECTTIMEOUT_MS')) { //ConnectTimeout in MS supported?
$options[CURLOPT_CONNECTTIMEOUT_MS] = $this->connecttimeout;
} else { //Round(up) to second precision
$options[CURLOPT_CONNECTTIMEOUT] = ceil($this->connecttimeout/1000);
}
}
if (curl_setopt_array($curl, $options) === false)
throw new Exception('Failed setting CURL options');
$response = curl_exec($curl);
if (curl_errno($curl))
throw new Exception(curl_error($curl));
curl_close($curl);
}
// Return?
if (!$one_way)
return ($response);
}
}
@RobThree

This comment has been minimized.

Copy link
Owner Author

RobThree commented Nov 7, 2012

Hmm, need to combine this with http://tcsoftware.net/downloads/php/download.php?file=SoapClientAuth for the ultimate SoapClient class :P

@RobThree

This comment has been minimized.

Copy link
Owner Author

RobThree commented Nov 20, 2012

Made first attempt: https://gist.github.com/4117914
Needs some refactoring and lots of testing...

@pabloleone

This comment has been minimized.

Copy link

pabloleone commented May 14, 2013

not working!

@staabm

This comment has been minimized.

Copy link

staabm commented Aug 6, 2014

to mimic the behaviour php should have for SoapClient, this client should per default respect default_socket_timeout, no?

@QuestionDevelopment

This comment has been minimized.

Copy link

QuestionDevelopment commented Aug 12, 2014

staabm : read the following post to understand why the default_socket_timeout does not work if data has already been sent : http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls/

@reyx

This comment has been minimized.

@rodriguezrod1

This comment has been minimized.

Copy link

rodriguezrod1 commented Apr 14, 2016

Please , as I pass parameters to this class after that I declare ? example :

$fecha_soap = date ( 'Y-m-d\TH:i:s' ) ;
$xml = '
soapenv:Body
tem:ConsultaSaldo
tem:consulta
poin:ClaveVenta0104/poin:ClaveVenta
poin:ComercioId2783/poin:ComercioId
poin:FechaHoraTransaccion' . $fecha_soap . '/poin:FechaHoraTransaccion
poin:PasswordPpay35085*/poin:Password
poin:TerminalId197/poin:TerminalId
poin:TransaccionId1/poin:TransaccionId
/tem:consulta
/tem:ConsultaSaldo
/soapenv:Body
' ;

$wsdl = "https://col.pointpay.net/WCF/PointPay.Bridge.webService.WebServiceCO.svc?wsdl" ;
$location = "https://col.pointpay.net/WCF/PointPay.Bridge.webService.WebServiceCO.svc" ;

$soap_client = new SoapClientTimeout($wsdl , array ( "timeout" => 10, "connecttimeout"=> 15 ));

$imagen = $soap_client-> __doRequest ( $xml , $location , "ConsultaSaldo" , 2 , FALSE );

print_r ( $imagen ) ;

Fatal error: Uncaught exception 'Exception' with message 'Resolving timed out after 12 milliseconds' in /var/www/html/recargas/index_soap.php:131 Stack trace: #0 /var/www/html/recargas/index_soap.php(179): SoapClientTimeout->__doRequest(' ...', 'https://col.poi...', 'ConsultaSaldo', 2, false) #1 {main} thrown in /var/www/html/recargas/index_soap.php on line 131

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.