Existe-t-il un moyen d'obtenir à la fois les en-têtes et le corps d'une demande cURL en utilisant PHP? J'ai trouvé que cette option:
curl_setopt($ch, CURLOPT_HEADER, true);
va renvoyer le corps et les en-têtes , mais je dois ensuite l'analyser pour obtenir le corps. Existe-t-il un moyen d'obtenir les deux de manière plus utilisable (et sécurisée)?
Notez que pour une "demande unique", je veux dire éviter d'émettre une demande HEAD avant GET / POST.
Réponses:
Une solution à cela a été publiée dans les commentaires de la documentation PHP: http://www.php.net/manual/en/function.curl-exec.php#80442
Exemple de code:
Avertissement: comme indiqué dans les commentaires ci-dessous, cela peut ne pas être fiable lorsqu'il est utilisé avec des serveurs proxy ou lors de la gestion de certains types de redirections. @ La réponse de Geoffrey peut les gérer de manière plus fiable.
la source
list($header, $body) = explode("\r\n\r\n", $response, 2)
, mais cela peut prendre un peu plus de temps, selon la taille de votre demande.list($header, $body) = explode("\r\n\r\n", $response, 2)
que la variante de travail100
(Continuer). Pour cet en-tête, vous pouvez définir l'option de demande correctement définie:,curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
désactiver l'envoi de cette réponse d'en-tête. Quant à302
cela, cela ne devrait pas se produire, car l'en-tête 302 est une redirection, il n'attend pas de corps, mais je sais, parfois les serveurs envoient du corps avec une302
réponse, mais il sera de toute façon ignoré par les navigateurs, jusqu'à présent, pourquoi curl devrait-il gérer cela? )CURLOPT_VERBOSE
est destiné à la sortie des informations de processusSTDERR
(peut déranger en CLI) et pour le problème discuté est inutile.La plupart des autres solutions proposées par ce fil ne le font pas correctement.
\r\n\r\n
n'est pas fiable lorsqu'ilCURLOPT_FOLLOWLOCATION
est activé ou lorsque le serveur répond avec un code 100.\n
pour les nouvelles lignes.CURLINFO_HEADER_SIZE
n'est également pas toujours fiable, en particulier lorsque des proxys sont utilisés ou dans certains des mêmes scénarios de redirection.La méthode la plus correcte utilise
CURLOPT_HEADERFUNCTION
.Voici une méthode très propre pour effectuer cela en utilisant des fermetures PHP. Il convertit également tous les en-têtes en minuscules pour une gestion cohérente sur les serveurs et les versions HTTP.
Cette version conservera les en-têtes en double
Ceci est conforme aux RFC822 et RFC2616, veuillez ne pas suggérer de modifications pour utiliser les
mb_
fonctions de chaîne, c'est incorrect!la source
$headers = [];
php est-il valide?Curl a une option intégrée pour cela, appelée CURLOPT_HEADERFUNCTION. La valeur de cette option doit être le nom d'une fonction de rappel. Curl passera l'en-tête (et l'en-tête uniquement!) À cette fonction de rappel, ligne par ligne (donc la fonction sera appelée pour chaque ligne d'en-tête, en commençant par le haut de la section d'en-tête). Votre fonction de rappel peut alors tout faire (et doit renvoyer le nombre d'octets de la ligne donnée). Voici un code de travail testé:
Ce qui précède fonctionne avec tout, différents protocoles et proxys aussi, et vous n'avez pas à vous soucier de la taille de l'en-tête, ni à définir de nombreuses options de boucles différentes.
PS: pour gérer les lignes d'en-tête avec une méthode objet, procédez comme suit:
la source
est-ce que tu cherches?
la source
A server that does not understand or is unable to comply with any of the expectation values in the Expect field of a request MUST respond with appropriate error status. The server MUST respond with a 417 (Expectation Failed) status if any of the expectations cannot be met or, if there are other problems with the request, some other 4xx status.
100
en commentaire sous la réponse "correcte" .Définissez simplement les options:
CURLOPT_HEADER, 0
CURLOPT_RETURNTRANSFER, 1
et utilisez curl_getinfo avec CURLINFO_HTTP_CODE (ou pas de paramètre opt et vous aurez un tableau associatif avec toutes les informations que vous voulez)
Plus sur: http://php.net/manual/fr/function.curl-getinfo.php
la source
curl_getinfo()
.Si vous voulez spécifiquement le
Content-Type
, il y a une option spéciale cURL pour le récupérer:la source
Fonctionne avec
HTTP/1.1 100 Continue
avant les autres en-têtes.Si vous avez besoin de travailler avec des serveurs buggy qui n'envoient que LF au lieu de CRLF comme sauts de ligne, vous pouvez utiliser
preg_split
comme suit:la source
$parts = explode("\r\n\r\nHTTP/", $response);
avoir le 3ème paramètre pour exploser en 2?HTTP/1.1 100 Continue
peut apparaître plusieurs fois.HTTP/1.1 100 Continue
peut apparaître plusieurs fois. Il voit le cas s'il n'apparaît qu'une seule fois, mais il se trompe dans le cas commun. Par exemple,HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK...\r\n\r\n...
son code ne fonctionne pas correctementMa voie est
Si nécessaire, appliquez une boucle for et supprimez la limite d'explosion.
la source
Voici ma contribution au débat ... Cela renvoie un tableau unique avec les données séparées et les en-têtes répertoriés. Cela fonctionne sur la base que CURL renverra des données de bloc d'en-têtes [ligne vierge]
la source
Le problème avec de nombreuses réponses ici est que cela
"\r\n\r\n"
peut légitimement apparaître dans le corps du HTML, vous ne pouvez donc pas être sûr de diviser correctement les en-têtes.Il semble que la seule façon de stocker les en-têtes séparément avec un appel à
curl_exec
est d'utiliser un rappel comme suggéré ci-dessus dans https://stackoverflow.com/a/25118032/3326494Et pour obtenir (de manière fiable) uniquement le corps de la demande, vous devez passer la valeur de l'en-
Content-Length
tête àsubstr()
une valeur de départ négative.la source
list($head, $body) = explode("\r\n\r\n", $response, 2);
cependant CURL le fait déjà pour vous si vous utilisezcurl_setopt($ch, CURLOPT_HEADERFUNCTION, $myFunction);
Juste au cas où vous ne pourriez / n'utilisez pas
CURLOPT_HEADERFUNCTION
ou d'autres solutions;la source
Renvoie les en-têtes de réponse avec un paramètre de référence:
la source
$rtn=explode("\r\n\r\nHTTP/", $rtn, 2);
raison? Le troisième paramètre d'explosion ne devrait-il pas être supprimé?explode("\r\n\r\n", $parts, 2);
les deux ont donc raison.Si vous n'avez pas vraiment besoin d'utiliser curl;
Quelles sorties
Voir http://php.net/manual/en/reserved.variables.httpresponseheader.php
la source