96 votes

Demandes HTTP avec file_get_contents, obtention du code de réponse

J'essaie d'utiliser file_get_contents en même temps que stream_context_create pour effectuer des requêtes POST. Mon code jusqu'à présent :

    $options = array('http' => array(
        'method'  => 'POST',
        'content' => $data,
        'header'  => 
            "Content-Type: text/plain\r\n" .
            "Content-Length: " . strlen($data) . "\r\n"
    ));
    $context  = stream_context_create($options);
    $response = file_get_contents($url, false, $context);

Il fonctionne bien, mais lorsqu'une erreur HTTP se produit, il affiche un avertissement :

file_get_contents(...): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request

et renvoie false. Y a-t-il un moyen de :

  • supprimer un avertissement (je prévois de lancer ma propre exception en cas d'échec)
  • obtenir les informations d'erreur (au moins, le code de réponse) à partir du flux

163voto

Alles Points 1646

http://php.net/manual/en/reserved.variables.httpresponseheader.php

file_get_contents("http://example.com", false, stream_context_create(['http' => ['ignore_errors' => true]]));
var_dump($http_response_header);

34voto

mindplay.dk Points 2555

Aucune des réponses (y compris celle acceptée par le PO) ne satisfait réellement aux deux exigences :

  • supprimer un avertissement (je prévois de lancer ma propre exception en cas d'échec)
  • obtenir les informations d'erreur (au moins, le code de réponse) à partir du flux

Voici mon point de vue :

function fetch(string $method, string $url, string $body, array $headers = []) {
    $context = stream_context_create([
        "http" => [
            // http://docs.php.net/manual/en/context.http.php
            "method"        => $method,
            "header"        => implode("\r\n", $headers),
            "content"       => $body,
            "ignore_errors" => true,
        ],
    ]);

    $response = file_get_contents($url, false, $context);

    /**
     * @var array $http_response_header materializes out of thin air
     */

    $status_line = $http_response_header[0];

    preg_match('{HTTP\/\S*\s(\d{3})}', $status_line, $match);

    $status = $match[1];

    if ($status !== "200") {
        throw new RuntimeException("unexpected response status: {$status_line}\n" . $response);
    }

    return $response;
}

Cela lancera pour un non 200 mais vous pouvez facilement travailler à partir de là, par exemple en ajoutant une simple Response et return new Response((int) $status, $response); si cela correspond mieux à votre cas d'utilisation.

Par exemple, pour faire un JSON POST à un point de terminaison de l'API :

$response = fetch(
    "POST",
    "http://example.com/",
    json_encode([
        "foo" => "bar",
    ]),
    [
        "Content-Type: application/json",
        "X-API-Key: 123456789",
    ]
);

Notez l'utilisation de "ignore_errors" => true en el http context map - ceci empêchera la fonction de lancer des erreurs pour les codes d'état non-2xx.

Il s'agit très probablement de la "bonne" quantité de suppression d'erreurs pour la plupart des cas d'utilisation - je ne recommande pas l'utilisation de l'option @ l'opérateur de suppression d'erreur, car cela supprimera également les erreurs telles que le simple passage de mauvais arguments, ce qui pourrait cacher par inadvertance un bogue dans le code d'appel.

8voto

hamboy75 Points 23

Ajout de quelques lignes supplémentaires à la réponse acceptée pour obtenir le code http

function getHttpCode($http_response_header)
{
    if(is_array($http_response_header))
    {
        $parts=explode(' ',$http_response_header[0]);
        if(count($parts)>1) //HTTP/1.0 <code> <text>
            return intval($parts[1]); //Get code
    }
    return 0;
}

@file_get_contents("http://example.com");
$code=getHttpCode($http_response_header);

pour cacher la sortie d'erreur les deux commentaires sont ok, ignore_errors = true ou @ (je préfère @)

-1voto

Kaarel Points 1

Je suis allé sur cette page avec un problème différent, alors je poste ma réponse. Mon problème était que j'essayais simplement de supprimer la notification d'avertissement et d'afficher un message d'avertissement personnalisé pour l'utilisateur, donc cette solution simple et évidente m'a aidé :

// Suppress the warning messages
error_reporting(0);

$contents = file_get_contents($url);
if ($contents === false) {
  print 'My warning message';
}

Et si nécessaire, retournez le rapport d'erreur après cela :

// Enable warning messages again
error_reporting(-1);

-4voto

Besen Points 1

@file_get_contents y ignore_errors = true ne sont pas les mêmes : le premier ne renvoie rien ; le second supprime les messages d'erreur, mais renvoie la réponse du serveur (par exemple, 400 Bad request).

J'utilise une fonction comme celle-ci :

$result = file_get_contents(
  $url_of_API, 
  false, 
  stream_context_create([
    'http' => [
      'content' => json_encode(['value1' => $value1, 'value2' => $value2]), 
      'header' => 'Authorization: Basic XXXXXXXXXXXXXXX', 
      'ignore_errors' => 1, 
      'method' => 'POST', 
      'timeout' => 10
    ]
  ])
);

return json_decode($result)->status;

Il renvoie 200 (Ok) ou 400 (mauvaise demande).

Cela fonctionne parfaitement et c'est plus facile que cURL.

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