使用 'br' 编码获取页面内容并通过 php curl 对其进行解码

sae*_*ati 6 php compression curl brotli

我想通过 php curl获取此页面的内容:

我的卷曲样本:

function curll($url,$headers=null){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);


    if ($headers){

        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }

    curl_setopt($ch, CURLOPT_ENCODING, '');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0');
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);

    $response = curl_exec($ch);

    $res['headerout'] = curl_getinfo($ch,CURLINFO_HEADER_OUT);
    $res['rescode'] = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if ($response === false) {
        $res['content'] = $response;
        $res['error'] = array(curl_errno($ch),curl_error($ch));
        return $res;
    }

    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $res['headerin'] = substr($response, 0, $header_size);
    $res['content'] = substr($response, $header_size);

    return $res;

}
Run Code Online (Sandbox Code Playgroud)

回复:

array (size=4)
  'headerout' => string 'GET /wallets HTTP/1.1
Host: www.cryptocompare.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: br
Accept-Language: en-US,en;q=0.5
Connection: keep-alive
Upgrade-Insecure-Requests: 1

' (length=327)
  'rescode' => string '200' (length=3)
  'content' => boolean false
  'error' => 
    array (size=2)
      0 => int 23
      1 => string 'Unrecognized content encoding type. libcurl understands deflate, gzip content encodings.' (length=88)
Run Code Online (Sandbox Code Playgroud)

响应编码是br响应内容是false

我知道使用gzipordeflate作为编码会给我带来内容。然而我想到的内容只是通过br编码的方式展现出来的。

我在这个页面上读到支持Curl V7.57.0Brotli Compression功能。我目前已经7.59.0安装了版本,但是 Curl 在接收br encoding.

现在我想知道如何获取br带有编码的页面内容并通过 php curl 解压缩它?

Tri*_*IER 2

我遇到了完全相同的问题,因为一台服务器只能返回 brotli,而我的 PHP Curl 捆绑版本不支持 Brotli。我必须使用 PHP 扩展:https://github.com/kjdev/php-ext-brotli

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'URL');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output_brized = curl_exec($ch);

$output_ok = brotli_uncompress($output_brized);
Run Code Online (Sandbox Code Playgroud)

我检查过,在 Windows 上使用 PHP 7.4.9 捆绑 Curl 版本 7.70.0,将选项设置CURLOPT_ENCODING''(就像您所做的那样)强制捆绑 Curl 使用一个附加标头执行请求,accept-encoding: deflate, gzip这些标头是捆绑 Curl 可以解码的内容编码。如果我省略此选项,则只有 2 个标头:Host: www.google.comaccept: */*

事实上,在 PHP 源代码(https://github.com/php/php-src/search?q=CURLOPT_ENCODING)中搜索此CURLOPT_ENCODING选项不会导致任何可能设置默认值或更改 PHP 值的情况。PHP 将选项值发送给 Curl 而不改变它,所以我观察到的是我捆绑的 Curl 版本的默认行为。

然后我发现 Curl 从 2018 年 11 月开始支持 Brotli 版本 7.57.0 ( https://github.com/curl/curl/blob/bf1571eb6ff24a8299da7da84408da31f0094f66/docs/libcurl/symbols-in-versions ) ( https://github.com/ curl/curl/blob/fd1ce3d4b085e7982975f29904faebf398f66ecd/docs/HISTORY.md--with-brotli )但需要使用标志(https://github.com/curl/curl/blob/9325ab2cf98ceca3cf3985313587c94dc1325c81/configure.ac )进行编译,这可能不是用于我的PHP版本。

不幸的是,没有curl_getopt()函数可以获取选项的默认值。但是,phpinfo()提供了一个有价值的信息,因为我得到了一行BROTLI => No,确认我的版本没有使用 Brotli 支持进行编译。您可能需要检查您的 phpinfo 以了解您的 Curl 捆绑版本是否应该支持 Brotli。如果没有,请使用我的解决方案。如果确实如此,则需要进行更多调查以确定它是否是错误或误用。

如果你想知道你的 Curl 发送了什么,你必须使用像 Charles/Fiddler 这样的代理或使用 Curl 详细模式。

另外,为了完整起见,在 HTTP1/1 规范(https://www.rfc-editor.org/rfc/rfc2616#page-102)中说:

   If an Accept-Encoding field is present in a request, and if the
   server cannot send a response which is acceptable according to the
   Accept-Encoding header, then the server SHOULD send an error response
   with the 406 (Not Acceptable) status code.

   If no Accept-Encoding field is present in a request, the server MAY
   assume that the client will accept any content coding.
Run Code Online (Sandbox Code Playgroud)

因此,如果您的 PHP 版本的行为与我的相同,则该网站应该收到Accept-Encoding不包含内容br,因此不应回复br内容,而应该回复 gzip 或 deflate 内容,或者,如果无法执行此操作所以,回复了 a406 Not Acceptable而不是 200。