【问题标题】:PHP file_get_contents() and setting request headersPHP file_get_contents() 和设置请求标头
【发布时间】:2016-06-23 00:52:42
【问题描述】:

使用 PHP,是否可以发送带有 file_get_contents() 的 HTTP 标头?

我知道您可以从您的php.ini 文件中发送用户代理。但是,您还可以将HTTP_ACCEPTHTTP_ACCEPT_LANGUAGEHTTP_CONNECTION等其他信息与file_get_contents()一起发送吗?

或者是否有其他功能可以做到这一点?

【问题讨论】:

    标签: php http-headers


    【解决方案1】:

    实际上,在进一步阅读file_get_contents() 函数后:

    // Create a stream
    $opts = [
        "http" => [
            "method" => "GET",
            "header" => "Accept-language: en\r\n" .
                "Cookie: foo=bar\r\n"
        ]
    ];
    
    // DOCS: https://www.php.net/manual/en/function.stream-context-create.php
    $context = stream_context_create($opts);
    
    // Open the file using the HTTP headers set above
    // DOCS: https://www.php.net/manual/en/function.file-get-contents.php
    $file = file_get_contents('http://www.example.com/', false, $context);
    

    您也许可以按照这种模式来实现您想要的,不过我还没有亲自测试过。 (如果它不起作用,请随时查看我的其他答案)

    【讨论】:

    • 这是此页面上唯一有用的答案
    • 我希望这里有更多的人能给出这个问题的实际答案,而不是仅仅指向 cURL 页面。谢谢。
    • 突然好奇:file_get_contents()默认用户代理是什么?它指定一个吗?
    • @Raptor ini_set('user_agent', 'SomeBrowser v42.0.4711'); 转到 user-agent.me 并从那里复制你的.. 或编辑 php.ini 以全局更改它
    【解决方案2】:

    这对我有用(Dominic 只差一行)。

    $url = "";
    
    $options = array(
      'http'=>array(
        'method'=>"GET",
        'header'=>"Accept-language: en\r\n" .
                  "Cookie: foo=bar\r\n" .  // check function.stream-context-create on php.net
                  "User-Agent: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.102011-10-16 20:23:10\r\n" // i.e. An iPad 
      )
    );
    
    $context = stream_context_create($options);
    $file = file_get_contents($url, false, $context);
    

    【讨论】:

    • 您不应冒充浏览器的用户代理。相反,为您的工具创建一个用户代理字符串。 www-archive.mozilla.org/build/revised-user-agent-strings.html 可以提供一些关于格式的想法。
    • @Vince 我认为在某些情况下它可能会双向工作。像这样将代理标头设置为字符串,在我的情况下有效(WAF 需要非空用户代理才能通过请求)
    • @Vince 两者都可以使用的PHP docs state 和“用户代理”header 将覆盖user_agent 数组元素,如果两者都指定的话。
    • 注意:切勿在包含特殊字符(如 \n 或 \r)的字符串中使用单引号。 PHP 不会正确解释它们,并且在发送标头的情况下,您的标头将无法正确发送。
    • @Fanky 最简单的可能是“YourTool/1.0.0”。当你发布一个新版本时,你也可以升级用户代理版本,“YourTool/1.3.5”。
    【解决方案3】:

    您可以使用此变量在file_get_contents() 函数之后检索响应标头。

    代码:

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

    输出:

    array(9) {
      [0]=>
      string(15) "HTTP/1.1 200 OK"
      [1]=>
      string(35) "Date: Sat, 12 Apr 2008 17:30:38 GMT"
      [2]=>
      string(29) "Server: Apache/2.2.3 (CentOS)"
      [3]=>
      string(44) "Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT"
      [4]=>
      string(27) "ETag: "280100-1b6-80bfd280""
      [5]=>
      string(20) "Accept-Ranges: bytes"
      [6]=>
      string(19) "Content-Length: 438"
      [7]=>
      string(17) "Connection: close"
      [8]=>
      string(38) "Content-Type: text/html; charset=UTF-8"
    }
    

    【讨论】:

    • 这根本没有回答问题。
    • 也许不是,但它回答了标题中隐含的相反问题,即如何从 file_get_contents 中读取响应标头。这就是谷歌在调查那个问题时的落脚点。
    【解决方案4】:

    使用 php cURL 库可能是正确的方法,因为这个库比简单的file_get_contents(...) 有更多的功能。

    一个例子:

    <?php
    $ch = curl_init();
    $headers = array('HTTP_ACCEPT: Something', 'HTTP_ACCEPT_LANGUAGE: fr, en, da, nl', 'HTTP_CONNECTION: Something');
    
    curl_setopt($ch, CURLOPT_URL, "http://localhost"); # URL to post to
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 ); # return into a variable
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header ); # custom headers, see above
    $result = curl_exec( $ch ); # run!
    curl_close($ch);
    ?>
    

    【讨论】:

    • 您展示的 sn-p 也很容易通过 file_get_contents 实现,我还没有遇到过只能通过 cURL 实现的用例。
    • 变量 $header 不存在,也许你打算写 $headers ?可能值得纠正。
    【解决方案5】:

    是的。

    当在 URL 上调用 file_get_contents 时,应该使用 stream_create_context 函数,该函数在 php.net 上有很好的记录。

    这在 php.net 的用户 cmets 部分的以下页面上或多或少地完全涵盖:http://php.net/manual/en/function.stream-context-create.php

    【讨论】:

      【解决方案6】:

      如果您不需要 HTTPS 并且您的系统上没有 curl 可用,您可以使用 fsockopen

      此函数打开一个连接,您可以从中读取和写入,就像使用普通文件句柄一样。

      【讨论】:

      • 是的,但这也意味着 OP 必须手动实现 HTTP 协议。此外,OP 没有询问file_get_contents 的替代方案,所以这有点离题。
      【解决方案7】:

      不幸的是,file_get_contents() 看起来并没有真正提供那种程度的控制。 cURL 扩展通常是最先出现的,但对于非常简单直接的 HTTP 请求,我强烈推荐 PECL_HTTP 扩展 (http://pecl.php.net/package/pecl_http)。 (它比 cURL 更容易使用)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-11
        • 2016-11-26
        • 1970-01-01
        • 2020-06-25
        相关资源
        最近更新 更多