web-dev-qa-db-fra.com

Erreur lors de l'extraction des en-têtes HTTP dans SoapClient

J'essaye d'appeler un WS sur https sur un hôte distant: port distant et j'obtiens:

Erreur de récupération en-têtes HTTP

using PHP5 SoapClient; Je peux obtenir la liste des fonctions en faisant $client->__getFunctions() mais quand j’appelle $client->myFunction(...) j’obtiens toujours cette erreur. 

J'ai cherché dans Google pour augmenter default_socket_timeout dans php.ini mais cela n'a pas fonctionné.

Quelqu'un peut-il me proposer une solution?

EDIT: voici le code:

$wsdl="myWSDL";

$client = new SoapClient($wsdl,array('connection_timeout'=>5,'trace'=>true,'soap_version'=>SOAP_1_2));

var_dump($client->__getFunctions());

try {
    $response=$client->myFunction("1","2","3");
         } catch (SoapFault $fault) {
    var_dump($fault);
    }

}

... toujours en faute.

36
Cris

Cette erreur est souvent constatée lorsque la valeur default_socket_timeout est dépassée pour la réponse SOAP. ( Voir ce lien .)

Note du constructeur SoapClient: l'option connection_timeout est utilisée pour définir une valeur de délai d'expiration pour la connexion au service, pas pour le délai d'expiration de sa réponse.

Vous pouvez l'augmenter comme ceci:

ini_set('default_socket_timeout', 600); // or whatever new value you want

Cela devrait vous dire si le délai d'attente est en cause ou si vous avez un problème différent. Gardez à l'esprit que vous ne devriez pas utiliser cette solution comme solution permanente, mais plutôt pour voir si l'erreur est supprimée avant de passer à la recherche de la raison pour laquelle le service SOAP répond si lentement. Si le service est toujours aussi lent, vous devrez peut-être envisager un traitement hors ligne/par lots.

54
cmbuckley

Je voulais juste partager la solution à ce problème dans ma situation spécifique (j'avais des symptômes identiques). Dans mon scénario, il s'est avéré que le certificat SSL fourni par le service Web n'était plus fiable. En fait, il s’est avéré être dû à un nouveau pare-feu installé par le client qui interférait avec la demande SOAP, mais le résultat final était que le certificat n’était pas correctement servi/approuvé.

Il a été un peu difficile à repérer, car l’appel SoapClient (même avec trace = 1) ne donne pas d’informations très utiles.

J'ai pu prouver le certificat non approuvé en utilisant:

openssl s_client -connect <web service Host>:<port>

Je sais que ce ne sera pas la solution au problème de tout le monde, mais j'espère que cela aidera quelqu'un. Quoi qu'il en soit, je pense qu'il est important de comprendre que la cause de cette erreur (faultcode: "HTTP" faultstring: "Erreur de récupération des en-têtes http") va généralement être un problème de réseau/socket/protocole/communication plutôt que simplement "ne permet pas assez temps pour la demande ". Je ne peux pas imaginer que l’extension de la valeur default_socket_timeout résoudra ce problème très souvent, et même s’il le faisait, il serait sûrement préférable de résoudre la question de savoir POURQUOI elle est si lente au départ.

11
Manachi

Je suppose que c'est trop tard, mais j'ai le même problème. J'essaie le délai d'attente du socket mais cela ne fonctionne pas. Mon problème était que le client et le serveur étaient dans le même serveur physique. Avec le code client fonctionnant sur le même serveur physique, j'obtiens cette erreur, mais avec le même code client déplacé vers mon hôte local, demandant le serveur (le client et le serveur ont été exécutés de deux manières différentes), tout fonctionne correctement.

Peut-être que cela peut aider quelqu'un d'autre!

7
Jonathan Huet

'keep_alive' a travaillé pour moi:

new SoapClient($api_url, array('keep_alive' => false));
4
Thiago Sathler

La configuration qui a fonctionné pour moi définissait à mon script php les paramètres suivants:

ini_set('default_socket_timeout', 5000);
$client = new \SoapClient($url,array(
    'trace' =>true,
    'connection_timeout' => 5000,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'keep_alive' => false,
));

Commentez s'il vous plaît.

La définition de paramètre la plus importante, selon mon expérience avec ce problème était

ini_set('default_socket_timeout', 5000);

Au cours de mes tests, j'ai défini le paramètre default_socket_timeout à 5 secondes et l'erreur «Erreur de récupération des en-têtes http» a été générée instantanément.

J'espère que ça t'aide!

J'ai rencontré le même problème et essayé toutes les solutions ci-dessus. Malheureusement, rien ne fonctionne.

  1. Socket Timeout (non travaillé)
  2. Agent utilisateur (non travaillé)
  3. Configuration de SoapClient, cache_wsdl et Keep-Alive etc .. 

Tout ce jeu d'en-têtes que nous passons. J'ai résolu mon problème en ajoutant la propriété compression header. Cela nécessite en fait lorsque vous attendez une réponse au format gzip compressé.

//set the Headers of Soap Client. 
$client = new SoapClient($wsdlUrl, array(
    'trace' => true, 
    'keep_alive' => true,
    'connection_timeout' => 5000,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'compression'   => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
));

J'espère que ça aide.

Bonne chance.

2
Sanjay Mohnani

Par souci d'exhaustivité, je souhaitais simplement ajouter que, semblable à Manachi, j'avais reçu ce message, car le certificat client que j'utilisais nécessitait une phrase secrète et que j'avais accidentellement un caractère supplémentaire à la fin de la phrase secrète. Ce post est juste pour offrir une autre suggestion pour ce qu'il faut examiner. Si l'hôte requiert l'utilisation d'un certificat client (via le paramètre local_cert), assurez-vous de fournir le chemin correct vers le certificat et la phrase secrète correcte (le cas échéant). Si vous ne le faites pas, il est fort probable que vous verrez le même message d'erreur.

1
borq

Aucune des techniques ci-dessus n'a fonctionné pour moi.

Lorsque j'ai analysé l'en-tête de requête de __getLastRequestHeaders, j'ai constaté ce qui suit:

POST /index.php/api/index/index/?SID=012345 HTTP/1.1 Host: www.XYZ.com

L'URL de l'API que j'utilisais était différente, comme www.ABC.com. J'ai remplacé l'URL de l'API par www.XYZ.com/index.php/api?wsdl, puis cela a fonctionné.

Les deux URL ont renvoyé le même WSDL du même serveur, mais une seule a autorisé la connexion.

1
humbads

J'ai eu le même problème et j'ai essayé ce qui suit en désactivant keep_alive.

$api_proxy = new SoapClient($api_url, array('trace' => true, 'keep_alive' => false));

Cependant, cela n'a pas fonctionné pour moi. Ce qui a fonctionné pour moi a été de désactiver le cache SOAP. Il semble avoir mis en cache les mauvaises demandes et, après la désactivation, j'ai remarqué que mes demandes s'exécutaient plus rapidement.

Sur un serveur Linux, vous pouvez le trouver dans votre fichier /etc/php.ini.

Recherchez soap.wsdl_cache_enabled=1 et remplacez-le par soap.wsdl_cache_enabled=0.

N'oubliez pas de recharger Apache .service httpd reload

0
MagentoMan

Une autre cause possible de cette erreur pourrait être certaines opérations OpenSSL laissant des erreurs non effacées. Placez cette partie de code avant la demande SOAP pour les effacer:

while (openssl_error_string()) {}
0
Furgas

Veuillez vérifier la réponse en-tête HTTP. Dans mon cas, l'en-tête suivant a été défini sur le site API:

<IfModule mod_headers.c>
    Header set Connection keep-alive
</IfModule>

Il semble que le PHP SoapClient ne puisse pas gérer cette option. En conséquence, le corps de la réponse était vide, mais la longueur du contenu dans l'en-tête de réponse a été définie correctement.

Supprimer cette ligne ou le changer en "fermer" résolu mon problème.

0
Matthias Kleine

J'ai eu ce problème et j'ai vérifié, et dans mon cas, était le pare-feu. Le PHP ne montre pas l'erreur correctement. Pour exécuter la demande, le pare-feu a répondu:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
<html
...
<h1>Direct Access IP is not allowed</h1>
...
</html>

SoapClient attend l'enveloppe SOAP mais reçoit un code HTML. C’est pourquoi PHP répond par: "Erreur lors de la récupération des en-têtes HTTP", car il ne peut pas comprendre ce qu’il a reçu en réponse. Pour résoudre le problème, contactez votre administrateur réseau pour vérifier si un pare-feu, un NAT ou un proxy ne vous gêne pas, puis demandez-leur de prendre les dispositions nécessaires.

0
Mauro