File_get_contents ile HTTP istekleri, yanıt kodunu alıyor


88

POST istekleri yapmak için file_get_contentsile birlikte kullanmaya çalışıyorum stream_context_create. Şimdiye kadarki kodum:

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

İyi çalışıyor, ancak bir HTTP hatası oluştuğunda bir uyarı veriyor:

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

ve yanlış döndürür. Aşağıdakileri yapmanın bir yolu var mı:

  • bir uyarıyı bastırma (başarısızlık durumunda kendi istisnamı atmayı planlıyorum)
  • hata bilgisini (en azından yanıt kodunu) akıştan alın

Yanıtlar:



21

Cevapların hiçbiri (OP tarafından kabul edilen cevap dahil) aslında iki gerekliliği karşılamıyor:

  • bir uyarıyı bastırma (başarısızlık durumunda kendi istisnamı atmayı planlıyorum)
  • hata bilgisini (en azından yanıt kodunu) akıştan alın

İşte benim almam:

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;
}

Bu, 200yanıt vermeme anlamına gelir , ancak oradan kolayca çalışabilirsiniz, örneğin basit bir Responsesınıf ekleyin ve return new Response((int) $status, $response);bu sizin kullanım durumunuza daha iyi uyuyorsa.

Örneğin, POSTbir API uç noktasına JSON yapmak için:

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

Bağlam haritasında kullanımına dikkat "ignore_errors" => trueedin http- bu, işlevin 2xx dışı durum kodları için hata atmasını önleyecektir.

Bu, çoğu kullanım durumu için büyük olasılıkla "doğru" miktarda hata bastırmadır - @hata bastırma operatörünü kullanmanızı önermiyorum , çünkü bu aynı zamanda yanlış argümanları iletmek gibi hataları da ortadan kaldırır ve bu da yanlışlıkla bir hatayı gizleyebilir. arama kodu.


5

Http kodunu almak için kabul edilen yanıta birkaç satır daha ekleyerek

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

hata çıktısını gizlemek için her iki yorum da tamamdır, ignore_errors = true veya @ (@ tercih ederim)


-1

Bu sayfaya farklı bir sorunla gidiyorum, bu yüzden cevabımı gönderiyorum. Sorunum, yalnızca uyarı bildirimini bastırmaya ve kullanıcı için özelleştirilmiş bir uyarı mesajı görüntülemeye çalışmamdı, bu nedenle bu basit ve bariz düzeltme bana yardımcı oldu:

// Suppress the warning messages
error_reporting(0);

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

Ve gerekirse, bundan sonra hata bildirimini geri çevirin:

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

-2

@file_get_contents ve ignore_errors = true aynı değildir: ilki hiçbir şey döndürmez; ikincisi hata mesajlarını bastırır, ancak sunucu yanıtı döndürür (ör. 400 Hatalı istek).

Bunun gibi bir işlev kullanıyorum:

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

200 (Tamam) veya 400 (Kötü istek) döndürür.

Mükemmel çalışıyor ve cURL'den daha kolay.


Ve bu soruyu nasıl çözer? Yanıt kodunu nasıl alacağınızı açıklar mısınız?
Nico Haase

@Nico Çözümüm hakkında ne düşünüyorsunuz?
Besen

Bir JSON sonuç değil ayrıştırmak ve adlandırılmış rastgele alan okurken O, hala kötü olanından statusAPI çağrısı için HTTP durum kodu hiçbir bağlantısı yoktur -
Nico Haase

Bağlandığım RESTful API'nin bir JSON yanıtı döndürdüğü ve amacım için bilmem gereken şeyin (200 veya 400) "durum" alanında bulunduğu aşikar. Tüm ihtiyacım olan bu ve tüm sahip olduğum bu. HTTP durum kodunu bilmeniz gerekiyorsa, şunu yapın: $ http_response_header [0] döndür; Ancak @file_get_contents ile çalışmadığını unutmayın.
Besen

Ve bu orijinal soruyu nasıl yanıtlıyor? $http_response_header[0]Yüksek oy alan bir yanıtın neden işe yaramadığını düşünüyorsunuz file_get_contents?
Nico Haase
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.