web-dev-qa-db-fra.com

Requêtes HTTP avec file_get_contents, obtenant le code de réponse

J'essaie d'utiliser file_get_contents avec stream_context_create pour faire des demandes POST. Mon code jusqu'ici:

    $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);

Cela fonctionne bien, cependant, lorsqu'une erreur HTTP se produit, un avertissement est émis:

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

et retourne faux. 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
66
georg

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

file_get_contents("http://example.com");
var_dump($http_response_header);
122
Alles

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 masquer la sortie d'erreur, les deux commentaires sont ok, ignore_errors = true ou @ (je préfère @)

3
hamboy75

Aucune des réponses (y compris celle acceptée par OP) ne répond en réalité 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 ma prise:

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 une réponse non -200, mais vous pourrez facilement y travailler, par exemple. ajoutez une simple classe Response et return new Response((int) $status, $response); si cela convient mieux à votre cas d'utilisation.

Par exemple, pour faire un JSON POST sur un noeud final d'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 dans la mappe de contexte http - cela empêchera la fonction de générer des erreurs pour les codes d'état non 2xx.

Il s'agit probablement de la "bonne" quantité de suppression d'erreur pour la plupart des cas d'utilisation. Je ne recommande pas d'utiliser l'opérateur de suppression d'erreur @, car cela supprime également les erreurs telles que le simple fait de passer de mauvais arguments, ce qui pourrait masquer par inadvertance un bogue en appelant le code.

2
mindplay.dk

Je vais à cette page avec une sorte de problème différent, alors publiant 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. Ce correctif simple et évident m'a donc aidé:

// Suppress the warning messages
error_reporting(0);

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

Et si nécessaire, annulez le signalement des erreurs après cela:

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