带有file_get_contents的HTTP请求,获取响应代码


87

我试图file_get_contents一起使用stream_context_create以发出POST请求。到目前为止,我的代码:

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

它工作正常,但是,当发生HTTP错误时,它会发出警告:

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

并返回false。有没有办法:

  • 禁止显示警告(如果发生故障,我打算抛出自己的异常)
  • 从流中获取错误信息(至少是响应代码)

Answers:



19

答案(包括OP接受的答案)均未真正满足以下两个要求:

  • 禁止显示警告(如果发生故障,我打算抛出自己的异常)
  • 从流中获取错误信息(至少是响应代码)

这是我的看法:

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

这将导致无200响应,但是您可以从那里轻松进行工作,例如,添加一个简单的Response类,return new Response((int) $status, $response);如果更适合您的用例。

例如,对POSTAPI端点执行JSON :

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

注意"ignore_errors" => truehttp上下文映射中的使用-这将防止该函数针对非2xx状态代码抛出错误。

对于大多数用例,这很可能是“正确的”错误抑制量-我不建议使用@错误抑制运算符,因为这还会抑制错误,例如仅传递错误的参数,这可能会无意中隐藏错误。调用代码。


5

在接受的响应中添加几行以获取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);

隐藏错误输出,两个注释都可以,ignore_errors = true或@(我更喜欢@)


-1

我转到此页面时遇到了其他问题,因此请发布我的答案。我的问题是我只是想抑制警告通知并为用户显示自定义警告消息,因此此简单而明显的修复方法对我有帮助:

// Suppress the warning messages
error_reporting(0);

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

如果需要,请在此之后返回错误报告:

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

-2

@file_get_contents并且ignore_errors = true是不一样的:第一个不返回任何东西;第二个抑制错误消息,但返回服务器响应(例如400 Bad Request)。

我使用这样的功能:

$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(确定)或400(错误请求)。

它运行完美,并且比cURL更容易。


以及如何解决这个问题?您能解释一下如何获取响应代码吗?
Nico Haase

@Nico您如何看待我的解决方案?
贝森

这仍然很糟糕,因为您没有解析JSON结果并读取了一个随机字段status-它与API调用的HTTP状态代码没有关系
Nico Haase

很明显,我连接的RESTful API返回了一个JSON响应,并且我需要知道的目的(200或400)包含在“状态”字段中。这就是我所需要的,这就是我所得到的。如果您需要知道HTTP状态代码,只需执行以下操作:return $ http_response_header [0]; 但是请注意,它不适用于@file_get_contents。
贝森

这如何回答最初的问题?您为什么认为这个$http_response_header[0]被高度推崇的答案不起作用file_get_contents
Nico Haase
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.