web-dev-qa-db-fra.com

Définition du délai d'attente de Curl dans PHP

J'exécute une requête curl sur une base de données eXist via php. Le jeu 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 supposé ê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 requête curl se termine systématiquement avant la fin de la requête (<1000 à la demande via un navigateur). Est-ce que quelqu'un sait si c'est le bon moyen de définir des délais d'attente en boucle?

205
Moki

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

CURLOPT_CONNECTTIMEOUT - Le nombre de secondes à attendre pendant la tentative de connexion. Utilisez 0 pour attendre indéfiniment.
CURLOPT_TIMEOUT - Nombre maximal de secondes pendant lesquelles les fonctions cURL peuvent être exécutées.

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

de plus, n'oubliez pas d'augmenter le temps d'exécution du script php:

set_time_limit(0);// to infinity for example
311
msangel

Hmm, il me semble que CURLOPT_TIMEOUT définit le temps que toute fonction cURL est autorisée à exécuter. Je pense que vous devriez plutôt regarder plutôt CURLOPT_CONNECTTIMEOUT, car cela indique à cURL le délai maximal d’attente de la fin de la connexion.

56
Chad Birch

Votre code définit le délai d'attente à 1000 secondes. En millisecondes, utilisez CURLOPT_TIMEOUT_MS.

26
Matt Humphreys

Il y a une bizarrerie avec cela qui pourrait être pertinent pour certaines personnes ... Des commentaires PHP docs.

Si vous souhaitez que cURL expire en moins d'une seconde, vous pouvez utiliser CURLOPT_TIMEOUT_MS, bien qu'il existe un bogue/"fonctionnalité" sur les "systèmes de type Unix" provoquant l'expiration immédiate de libcurl si la valeur est <1000 ms. avec l'erreur "Erreur cURL (28): le délai d'attente a été atteint". L'explication de ce comportement est la suivante:

"Si libcurl est conçu pour utiliser le résolveur de noms de systèmes standard, cette partie du transfert utilisera toujours la résolution en une seconde pour les délais avec un délai minimum de une seconde."

Cela signifie pour PHP développeurs: "Vous ne pouvez pas utiliser cette fonction sans l'avoir testée au préalable, car vous ne pouvez pas savoir si libcurl utilise le résolveur de nom de système standard (mais vous pouvez en être assez sûr. ) "

Le problème est que, sur (Li | U) nix, lorsque libcurl utilise le résolveur de noms standard, un SIGALRM est généré lors de la résolution du nom, ce que libcurl considère comme une alarme de dépassement de délai.

La solution consiste à désactiver les signaux à l'aide de CURLOPT_NOSIGNAL. Voici un exemple de script qui se demande lui-même, ce qui entraîne un délai de 10 secondes pour vous permettre de 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

26
Simon East

Vous devrez vous assurer des délais d'attente entre vous et le fichier. Dans ce cas, PHP et Curl.

Pour indiquer à Curl de ne jamais expirer lorsqu'un transfert est encore actif, vous devez définir CURLOPT_TIMEOUT sur 0 au lieu de 1000.

curl_setopt($ch, CURLOPT_TIMEOUT, 0);

En PHP, encore une fois, vous devez supprimer les délais, sinon PHP lui-même (après 30 secondes par défaut) tuera le script à la demande de Curl. Cela seul devrait résoudre votre problème.
De plus, si vous avez besoin d'intégrité des données, vous pouvez ajouter une couche de sécurité en utilisant ignore_user_abort:

# The maximum execution time, in seconds. If set to zero, no time limit is imposed.
set_time_limit(0);

# Make sure to keep alive the script when a client disconnect.
ignore_user_abort(true);

Une déconnexion du client interrompt l'exécution du script et peut endommager des données,
par exemple. requête de base de données non transitoire, création d'un fichier de configuration, etc., alors que dans votre cas, il téléchargerait un fichier partiel ... et vous pourriez, ou non, vous en soucier.

Répondre à cette ancienne question parce que ce fil est au sommet des recherches de moteur pour CURL_TIMEOUT.

10
MarcoP

Vous ne pouvez pas exécuter la demande à partir d'un navigateur, il attendra que le serveur qui exécute la demande CURL réponde. Le navigateur expire probablement dans 1-2 minutes, le délai d’expiration réseau par défaut.

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

8
Brent Baisley

Si vous utilisez PHP en tant qu'application fastCGI, vérifiez les paramètres de délai d'expiration de fastCGI. Voir: PHP curl put 500 error

3
wbinky