Happy New Year!
编程

在PHP中使用Curl压缩 HTTP 请求

481 2023-04-26 22:13:00

压缩是提升网页性能的一个重要且有效的手段。对于文本资源如HTML文件、CSS/JS 文件、SVG 文件等,传输之前在服务器上对资源进行压缩,并在浏览器中解压缩可以极大减少带宽及传输时间。

对服务器和浏览器来说,压缩过程是不太透明的,服务器在发送给浏览器器前对资源进行压缩,浏览器在渲染之前进行解压缩。服务端软件和前端开发者不需要处理压缩/解压缩过程。

近年来开发出了一些压缩算法,浏览器和服务器可以通过 HTTP 头部商讨合适的压缩算法。

发出 HTTP 请求时,浏览器会在HTTP header 的 Accetpt-Encoding 中说明它支持的编码算法。如果服务器支持其中一种指定的压缩算法,它可能就会压缩响应并在HTTP header 的 Content-Enconding 中予以说明。IANA 维护着一个已注册编码算法清单

 

维基百科页面大约是 529KB,如果使用 Brolti(br) 算法压缩,则只有92KB。HTML 页面,SVG 文件,CSS/JS 文件及其他基于文本的文件压缩性良好,而且压缩/解压所消耗的计算成本相对于网络传输时间较小。

虽然浏览器在获取资源时默认使用压缩功能,PHP 的 HTTP 客户端却非如此。Curl, 这个常用的HTTP客户端支持编码协商和不透明的压缩请求,但需要启用。

$ch = curl_init('https://en.wikipedia.org/wiki/PHP');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);

上面是向维基百科上的PHP页面发出HTTP请求的简化示例。默认情况下,Curl不使用HTTP压缩,这会导致更大的传输大小和请求时间:

curl_getinfo($ch, CURLINFO_TOTAL_TIME); // 0.81 sec
curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD_T); // 548 KB

CURLINFO_SIZE_DOWNLOAD_T值显示Curl从远程服务器下载548KB的数据。由于Curl(通过Accept-Encoding头)没有说明支持压缩,服务器没有压缩响应。

使用CURLOPT_ENCODING选项,可以显式指定Accept ENCODING标头的值。不需要手动解码响应,因为Curl会自动解码。请注意,设置CURLOPT_ENCODING选项与手动设置Accept ENCODING标头不同。如果手动设置,Curl不会自动解码响应。

CURLOPT_ENCODING值接受一些已知不直观的值类型。

CURLOPT_ENCODING=null:重置值,禁用标头和自动解码。

CURLOPT_ENCODING=“”:Curl根据支持的算法自动发送适当的标头,并自动解码响应。

CURLOPT_ENCODING=“identity”:客户端希望服务器不会以任何方式对响应进行编码。

CURLOPT_ENCODING=“gzip”:客户端能够使用gzip算法。

CURLOPT_ENCODING=“br”:客户端能够使用Brotli-br算法。

CURLOPT_ENCODING选项实际上接受任何字符串值,如果响应的Content-ENCODING标头包含已知的编码算法,则Curl将尝试对其进行解码。

CURLOPT_ENCODING最有用、最合适的值是一个空字符串(“”)。它启用编码,但没有明确说明算法。这有效地启用了Curl支持和选择的所有算法。

  $ch = curl_init('https://en.wikipedia.org/wiki/PHP');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_ENCODING, '');
  curl_exec($ch);

使用 CURLOPT_ENCODING="" 选项,Curl现在用一个合适的Accept-Encoding头发出HTTP请求,列出它支持的所有算法。

稍后可以使用curl_getinfo函数检索发送的标头:

$ch = curl_init('https://en.wikipedia.org/wiki/PHP');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_exec($ch);

$headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
var_dump($headers);
  string(103) "GET /wiki/PHP HTTP/2
  Host: en.wikipedia.org
  accept: */*
+ accept-encoding: deflate, gzip, br, zstd

The server can opt to compress the response in one of the compression algorithms it supports. This greatly reduces the transfer time and size:

curl_getinfo($ch, CURLINFO_TOTAL_TIME); // 0.31 sec
curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD_T); // 90 KB

Curl根据在编译时设置的选项来选择它支持的压缩算法。

在大多数发行版中,PHP Curl是使用gzip、deflat和br(Brotli)编译的。然而,也可以通过编译libcurl时加入zstd支持,并使用新的libcurl头文件重新编译PHP来添加对zstd的支持。

PHP