Create a gist now

Instantly share code, notes, and snippets.

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.

Show comment Hide comment
@RobThree

RobThree Nov 7, 2012

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

Owner

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.

Show comment Hide comment
@RobThree

RobThree Nov 20, 2012

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

Owner

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.

Show comment Hide comment
@pabloleone

pabloleone May 14, 2013

not working!

not working!

@staabm

This comment has been minimized.

Show comment Hide comment
@staabm

staabm Aug 6, 2014

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

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.

Show comment Hide comment
@QuestionDevelopment

QuestionDevelopment 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/

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.

Show comment Hide comment
@rodriguezrod1

This comment has been minimized.

Show comment Hide comment
@rodriguezrod1

rodriguezrod1 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

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