251 votes

Configurer le délai d'attente de Curl en PHP

Je lance une requête curl sur une base de données eXist via php. L'ensemble de données est très volumineux et, par conséquent, la base de données prend constamment beaucoup de temps pour renvoyer une réponse XML. Pour résoudre ce problème, nous avons mis en place une requête curl, avec ce qui est censé être un long délai d'attente.

$ch = curl_init();
$headers["Content-Length"] = strlen($postString);
$headers["User-Agent"] = "Curl/1.0";

curl_setopt($ch, CURLOPT_URL, $requestUrl);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, 'admin:');
curl_setopt($ch,CURLOPT_TIMEOUT,1000);
$response = curl_exec($ch);
curl_close($ch);

Cependant, la demande curl se termine systématiquement avant que la demande ne soit terminée (<1000 lorsqu'elle est demandée par un navigateur). Quelqu'un sait-il si c'est la bonne façon de définir les délais d'attente dans curl ?

381voto

msangel Points 1716

Voir la documentation : http://www.php.net/manual/en/function.curl-setopt.php

CURLOPT_CONNECTTIMEOUT - Le nombre de secondes à attendre lors de la tentative de connexion. Utilisez 0 pour attendre indéfiniment.
CURLOPT_TIMEOUT - Le nombre maximum de secondes pour permettre aux fonctions cURL de s'exécuter.

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); 
curl_setopt($ch, CURLOPT_TIMEOUT, 400); //timeout in seconds

N'oubliez pas non plus d'agrandir le temps d'exécution du php script self :

set_time_limit(0);// to infinity for example

16 votes

Vous n'avez pas besoin set_time_limit(0); si le script est en cours d'exécution sur la console.

6 votes

@PedroLobito ce que vous mentionnez est la configuration par défaut du php on cli, mais il est possible que celle-ci ait été modifiée.

4 votes

@cherouvim a évidemment raison ici (il suffit d'exécuter php -d max_execution_time=1 -r 'while(true){$r=1*1;}' ou quelque chose pour observer en action que la cli n'a pas un drapeau magique "toujours illimité".

58voto

Chad Birch Points 39087

Hmm, il me semble que CURLOPT_TIMEOUT définit le temps que toute fonction cURL est autorisée à prendre pour s'exécuter. Je pense que vous devriez plutôt regarder CURLOPT_CONNECTTIMEOUT à la place, car cela indique à cURL le temps maximum à attendre pour que la connexion soit terminée.

0 votes

Alors que le Documents en PHP dites CURLOPT_TIMEOUT concerne le temps que prend la fonction, le Documentation de la bibliothèque curl sous-jacente semblent dire qu'il s'agit du temps que prend la demande, ce qui est une distinction intéressante - je ne sais pas trop comment lire cela !

0 votes

Je pense que c'est la meilleure interprétation : stackoverflow.com/questions/27776129/

41voto

Simon Points 4467

Il y a une bizarrerie avec ceci qui pourrait être pertinente pour certaines personnes... Extrait des commentaires de la documentation PHP.

Si vous souhaitez que le délai d'expiration de cURL soit inférieur à une seconde, vous pouvez utiliser la commande suivante CURLOPT_TIMEOUT_MS Il existe cependant un bogue/une "fonctionnalité" sur les "systèmes de type Unix" qui entraîne le dépassement immédiat du délai d'attente de libcurl si la valeur est < 1000 ms, avec l'erreur "cURL Error (28) : Timeout was reached". L'explication de ce comportement est la suivante :

"Si libcurl est construit pour utiliser le résolveur de noms du système standard, cette partie du transfert utilisera toujours la résolution à la seconde près pour les délais d'attente avec un délai d'attente minimum autorisé d'une seconde."

Ce que cela signifie pour les développeurs PHP est "Vous ne pouvez pas utiliser cette fonction sans la tester d'abord, parce que vous ne pouvez pas dire si libcurl utilise le résolveur de nom du système standard (mais vous pouvez être presque sûr qu'il le fait)".

Le problème est que sur (Li|U)nix, lorsque libcurl utilise le résolveur de noms standard, un SIGALRM est levé pendant la résolution du nom, ce que libcurl pense être l'alarme de dépassement de temps.

La solution consiste à désactiver les signaux en utilisant CURLOPT_NOSIGNAL. Voici un exemple de script qui se demande lui-même en provoquant un délai de 10 secondes afin que vous puissiez tester les délais d'attente :

if (!isset($_GET['foo'])) {
    // Client
    $ch = curl_init('http://localhost/test/test_timeout.php?foo=bar');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
    $data = curl_exec($ch);
    $curl_errno = curl_errno($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_errno > 0) {
        echo "cURL Error ($curl_errno): $curl_error\n";
    } else {
        echo "Data received: $data\n";
    }
} else {
    // Server
    sleep(10);
    echo "Done.";
}

De http://www.php.net/manual/en/function.curl-setopt.php#104597

0 votes

Bonjour, ce code fonctionne mais le fichier source fait 7MB et ce téléchargement ne me fait que 52KB, qu'est-ce qui peut bien se passer ? L'URL est quelque chose comme webserver.tld/dossier/téléchargement/

0 votes

Simon East, pouvez-vous m'aider ? stackoverflow.com/questions/30861112/

0 votes

Il est à noter que vous êtes en attendant une erreur de timeout avec ce script

31voto

Matt Humphreys Points 89

Votre code fixe le délai d'attente à 1000 secondes . Pour les millisecondes, utilisez CURLOPT_TIMEOUT_MS .

8voto

Brent Baisley Points 10223

Vous ne pouvez pas exécuter la requête à partir d'un navigateur, car il y aura un délai d'attente pour que le serveur qui exécute la requête CURL réponde. Le navigateur est probablement en train d'attendre 1 à 2 minutes, le délai d'attente par défaut du réseau.

Vous devez l'exécuter à partir de la ligne de commande/terminal.

2 votes

+1 -- le délai d'attente est probablement externe à curl. Vous pouvez en fait contourner le timeout du navigateur en vous assurant de sortir périodiquement quelque chose ; les navigateurs réinitialisent généralement leur timeout à chaque fois qu'ils reçoivent plus de données. Mais c'est un hack ; l'exécution via CLI est (presque ?) toujours préférable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X