web-dev-qa-db-fra.com

PHP Délai d'attente SoapClient

Existe-t-il de toute façon une demande SoapClient pour expirer et lancer une exception. À partir de maintenant, le délai de réponse du serveur PHP est dépassé, dans mon cas, de 60 secondes. Fondamentalement, ce que je veux, c’est que s’il n’ya pas de réponse du service Web dans un certain délai, une exception serait levée et je pourrais l’attraper. L'avertissement de 60 secondes n'est pas ce que je veux.

23
Shamim Hafiz

Jettes un coup d'oeil à

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

Il étend fondamentalement la classe SoapClient, remplace le transport HTTP par curl 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);
        }
    }
}
17

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

Exemple de code:

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

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

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

L'option connection_timeout définit un délai d'expiration en secondes pour le fichier connexion au service SOAP. Cette option ne définit pas de délai d'attente pour les services à réponse lente. Pour limiter le temps d'attente pour les appels pour terminer, le paramètre default_socket_timeout est disponible.

31
gdtv

La réponse acceptée annulera toutes les fonctionnalités offertes par SoapClient. Comme définir les bons en-têtes de contenu, 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;
    }

}
4
Sander Visser

Vous pouvez l’installer par le biais du composeur: https://github.com/ideaconnect/idct-soap-client

Il étend le standard SoapClient et offre des options permettant de définir le nombre de tentatives, les délais de connexion et de lecture.

1
Bartosz Pachołek

J'utilise la logique suivante lorsque je travaille avec 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;
}

Cela m'aide à attendre jusqu'à 10 secondes pour l'établissement de la connexion et 60 secondes pour l'exécution de l'appel.

0
Dmytro Lukachuk