详细信息
cURL 库有一个选项可以返回有关请求的详细信息,这在调试时非常有用;这可以通过将 CURLOPT_VERBOSE 选项设置为 true 来启用:
curl_setopt($ch, CURLOPT_VERBOSE, true);
这允许我们查看请求类型,但它还允许我们提取其他有用的详细信息,例如有关 TLS 握手和 SSL 证书的信息。
HTTP 响应的格式
在 HTTP 协议中,响应头在响应正文之前发送,并且以纯文本形式显示如下:
HTTP/1.1 200 OK Date: Fri, 22 Jan 2021 12:41:43 GMT Server: Apache Upgrade: h2 Connection: Upgrade, Keep-Alive Vary: Accept-Encoding Keep-Alive: timeout=5, max=100 Transfer-Encoding: chunked Content-Type: text/plain; charset=utf-8 <p>Hallo World</p>
响应头和响应体由两对 CRLF(回车+换行符)分隔。
在 PHP 中,CRLF 用 \r\n 表示;我们可以使用以下命令输出 CRLF:
echo "\r\n";
每个标头由单个 CRLF 分隔,而响应的标头和正文部分由 CRLFCRLF 分隔(相当于 PHP 中的 \r\n\r\n)。
这个想法是允许 HTTP 客户端在决定是否应该使客户端缓存失效之前检查缓存标头,例如 last-modified 和 etag。
如果客户端确定缓存副本已过期,则通常会使用新的 GET 请求重新下载资源。
支持 HEAD 的主要好处是客户端避免了重新下载未更改的资源,同时服务器也避免了在生成和上传客户端之前已经下载的资源上浪费资源。
远非所有支持 HEAD 请求的网络资源。
事实上,如果我们使用的是服务器端脚本语言,例如 PHP,那么我们将必须手动添加对动态生成页面的缓存支持——一个好的 CMS 系统已经支持客户端缓存,而用户无需做任何事情。
解析响应头
为了轻松处理响应头,将它们放在关联数组中会很有帮助;但是,由于我们在使用 cURL 时无法使用响应标头,因此我们首先需要将它们从响应中删除。
- 执行请求后获取headers:
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $headers = substr($response, 0, $header_size); $body = substr($response, $header_size);
现在我们将响应标头和响应正文存储在单独的变量中。
- 现在我们可以遍历 $headers 变量中的行,在此过程中创建一个数组。
使用 strtok 函数可能是最快的方法:
//Define the $response_headers array for later use $response_headers = []; //Get the first line (The Status Code) $line = strtok($headers, "\r\n"); $status_code = trim($line); //Parse the string, saving it into an array instead while (($line = strtok("\r\n")) !== false) { if(false !== ($matches = explode(':', $line, 2))) { $response_headers["{$matches[0]}"] = trim($matches[1]); } }
- 由于标头现在存储为使用标头名称作为键的关联数组,我们现在可以使用 isset 检查是否返回给定标头:
if (isset($response_headers['allow'])) { echo '<p>The allow header was present, here is its contents:'; var_dump($response_headers['allow']); exit(); }
如何使用 HEAD 请求
HEAD 请求类似于 GET ,但它具体意味着服务器应该只返回请求资源的 HTTP 响应头,而不包括响应体;有时,由于错误和粗心大意,身体可能会被包括在内,但客户通常会忽略它。
向资源发送 HEAD 请求的主要优点是客户端将能够在决定是否应请求完整资源之前比较缓存标头。
服务器可以在允许头中通知客户端给定资源支持的请求方法,每个方法用逗号分隔:
allow: GET, HEAD
根据 rfc7231#section-7.4.1 :如果客户端使用了不受支持的请求方法,则服务器应以 405 Method Not Allowed 状态响应,然后必须包含允许标头以显示支持的方法。
我们可能已经注意到,并非所有服务器或者 Web 应用程序都正确使用了允许标头。
当服务器收到 HEAD 请求时,它应该只返回给定资源的响应头。
如果内容仍然返回(也就是响应体),客户端应该忽略它。
客户端可以发送 HTTP HEAD 请求,通过将响应标头与缓存副本的时间戳进行比较来检查资源是否已更新。
如果缓存副本已过时,它通常会失效,并且将执行对资源的新 GET 请求。
当服务器响应 HEAD 请求时,应排除响应的正文部分。
虽然这对缓存机制非常有用,但它对开发人员在他们的应用程序中测试请求和响应标头时也很有用。
在 PHP 中,我们可以通过将 CURLOPT_NOBODY 选项设置为 true 来通过 cURL 扩展发送 HEAD 请求;要将响应返回给我们,还应使用 CURLOPT_RETURNTRANSFER:
$url = 'https://onitroad.com/Examples/ip.php'; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_HEADER, true); $response = curl_exec($ch); if (curl_errno($ch)) { echo 'Error:' . curl_error($ch); exit(); } curl_close($ch); //Output the response: echo $response;
CURLOPT_HEADER 选项用于在响应中包含响应头。
没有它,响应将为空。