【问题标题】:Curl request with headers - separate body a from a header [duplicate]带有标头的卷曲请求-将正文a与标头分开[重复]
【发布时间】:2012-05-10 05:12:56
【问题描述】:

我有密码

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);        
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    $ret = curl_exec($ch);
    $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

现在我想从 $ret 中提取没有标题的正文。知道怎么做吗?

【问题讨论】:

    标签: php


    【解决方案1】:

    借鉴@Geoffrey 在this thread 中的出色回答...

    此线程提供的其他一些解决方案没有正确地做到这一点。

    • CURLOPT_FOLLOWLOCATION 开启或服务器以 100 代码响应时,在 \r\n\r\n 上的拆分不可靠。
    • 通过CURLINFO_HEADER_SIZE 检测标头的大小也并不总是可靠的,尤其是在使用代理或在某些相同的重定向场景中。

    获取headers最可靠的方法是使用CURLOPT_HEADERFUNCTION然后你可以删除curl_setopt($ch, CURLOPT_HEADER, 1);,你的body就干净了,没有headers。

    这是使用 PHP 闭包执行此操作的一种非常简洁的方法。它还将所有标头转换为小写,以便在服务器和 HTTP 版本之间进行一致的处理。

    $ch = curl_init();
    $headers = [];
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    
    // Run the following function for each header received
    // Note: Does NOT handle multiple instances of the same header. Later one will overwrite.
    //       Consider handling that scenario if you need it.
    curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $header) use (&$headers) {
        $len = strlen($header);
        $header = explode(':', $header, 2);
        if (count($header) >= 2)
            $headers[strtolower(trim($header[0]))] = trim($header[1]);
        return $len;
    });
    
    $data = curl_exec($ch);
    print_r($headers);
    

    【讨论】:

    • 这应该是评论,而不是答案。如果是重复的问题,vote to close 同样如此。如果不是,请针对这个特定问题定制答案。
    • 这很好用。
    • 我找到的最佳答案。谢谢
    【解决方案2】:

    raina77ow 的反应很好。从 cmets 看来,有一些条件会导致“爆炸”不起作用。我找到了一种更适合我的方法,我想分享一下。

    通过调用 curl_getinfo($ch, CURLINFO_HEADER_SIZE) 可以得到响应头的长度。所以我做了以下事情:

    // Original Code
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);        
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
    $ret = curl_exec($ch);
    $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    // Added Code
    $header_len = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $header = substr($ret, 0, $header_len);
    $body = substr($ret, $header_len);
    
    // Back to Original Code
    curl_close($ch);
    

    这对我来说非常有用。我希望它可以帮助别人。

    【讨论】:

    • 看来CURLOPT_BINARYTRANSFER 不再做任何事情了。 see this SO question
    • 完美答案...终于从那些只被 '\n\n' 分割的糟糕脚本中解救出来了
    【解决方案3】:

    这个怎么样:

    list($headers, $content) = explode("\r\n\r\n", $ret, 2);
    

    ...哪个应该在 $content 变量中为您提供请求的正文?

    【讨论】:

    • 在 HTTP/1.1 时失败。存在 100 个继续标题。
    • 您可以使用curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); 删除Continue-Header。
    • 这在使用 CURLOPT_FOLLOWLOCATION 并且获取一个带有 301 或 302 重定向的地址时也是无效的。
    • 这对于 GET 请求是可靠的,但对于 POST 等情况,请参阅 natiupiru 的回答。
    • 该死的 100 Continue gotcha 花了我一天的大部分时间!
    猜你喜欢
    • 2015-10-29
    • 2014-08-04
    • 2020-12-23
    • 2015-02-01
    • 1970-01-01
    • 2016-05-06
    • 2012-03-05
    • 2018-09-10
    相关资源
    最近更新 更多