2010-08-17 11 views
19

Existe-t-il une requête SoapClient pour expirer et lancer une exception? A partir de maintenant, je reçois le délai de réponse de PHP Server, dans mon cas 60 secondes. Fondamentalement ce que je veux est, s'il n'y a aucune réponse du service Web dans un certain temps, une exception serait levée et je pourrais l'attraper. L'avertissement de 60 secondes n'est pas ce que je veux.PHP SoapClient Timeout

Répondre

16

Jetez un oeil à

si vous êtes à l'aise et votre environnement vous permet d'étendre les classes.

Il étend essentiellement la classe SoapClient, remplace le transport HTTP avec boucle qui peut gérer les délais d'attente:

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); 
     } 
    } 
} 
+0

Merci. Ce serait un endroit pour voir. Voyons s'il y en a d'autres. –

+2

J'ai essayé ceci en PHP 5.4.6, mais il semble qu'ils aient changé la signature de '_doRequest()' sans autre avis. '$ request' ne contient plus le XML brut, mais plutôt une chaîne comme' 141201299690460051141201717499383133141201717499423132141201717499443131141201717499463131141201717499483135false'. Quelqu'un peut-il nous éclairer là-dessus? –

+0

Ceci casserait tous les internes du SoapClient. –

44

Alors que Andrei lié à une solution décente, celui-ci a moins de code arrive encore à une bonne solution:

code Exemple:

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

Et il existe également le contexte de flux, si vous avez besoin d'un contrôle HTTP plus précis. Voir l'option stream_context pour new SoapClient()Docs. Sous la surface SoapClient utilise les transports HTTP et SSL.

+1

Lorsque j'utilise ceci, j'obtiens 'l'option client SOAP inconnu 'Exception – DanFromGermany

+0

@DanFromGermany, quelle version de PHP utilisez-vous? Passez-vous des options autres que celles indiquées ci-dessus? –

+1

PHP 5.3, je passe aussi '' soap_version '=> SOAP_1_1, 'mais j'utilise' Zend_Soap_Client', mais il étend juste 'SoapClient' – DanFromGermany

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

L'option connection_timeout définit un délai d'attente en secondes pour la connexion au service SOAP. Cette option ne définit pas de délai d'attente pour les services avec des réponses lentes. Pour limiter le délai d'attente des appels pour terminer le paramètre default_socket_timeout est disponible.

+0

Ceci est la réponse. :) –

+0

C'est une bonne réponse tant que le délai d'expiration du socket n'est pas dépassé. Sinon, le serveur lancera un délai de connexion et l'exécution s'arrêtera ... – Nico

+1

Notez également qu'il existe toujours ce bogue PHP non résolu: https://bugs.php.net/bug.php?id=41631. Donc 'default_socket_timeout' peut ne pas fonctionner avec les connexions HTTPS –

1

Vous pouvez installer ce compositeur par: https://github.com/ideaconnect/idct-soap-client

Il étend la SoapClient standard et donne des options pour régler la quantité de réitérations, la connexion et les délais d'attente de lecture.

2

La réponse acceptée va casser toutes les fonctionnalités que SoapClient a à offrir. Comme la définition des en-têtes de contenu correct, l'authentification, etc.

Ce serait une meilleure solution au problème

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; 
    } 

} 
+0

Pour un filet de sécurité supplémentaire, vous devriez essayer/attraper l'appel parent (par exemple, certaines applications/frameworks pourraient lancer des exceptions sur les avertissements via un error_handler personnalisé) qui laisserait le 'default_socket_timeout' non réinitialisé – staabm

+0

Le paramètre connection_timeout lui-même devrait avoir une valeur par défaut beaucoup plus petit que 10secs. – staabm

Questions connexes