get_headers() 函数用于获取指定 URL 的 HTTP 响应头信息。这是一个非常有用的函数,可以检查远程服务器返回的 HTTP 响应头,而无需实际下载整个响应体。
get_headers() 函数通常用于检查 URL 的有效性、获取文件信息、检查重定向、验证 HTTP 状态码等场景。
get_headers() 和 apache_response_headers() 是不同的函数。前者获取远程URL的响应头,后者获取当前脚本的响应头。
get_headers ( string $url [, int $format = 0 [, resource $context ]] ) : array|false
参数说明:
| 参数 | 说明 | 必需 | 默认值 |
|---|---|---|---|
$url |
要获取响应头的目标 URL | 是 | 无 |
$format |
指定返回数组的格式。如果设置为 1,函数将解析响应头并返回关联数组 | 否 | 0 |
$context |
使用 stream_context_create() 创建的上下文资源,可用于设置 HTTP 选项 | 否 | null |
函数返回一个包含 HTTP 响应头的索引数组或关联数组,失败则返回 FALSE。
当 $format 参数为 0(默认)时,返回索引数组,每个元素是一个完整的响应头字符串。
当 $format 参数为 1 时,返回关联数组,键名为响应头名称,键值为对应的值。
Array
(
[0] => HTTP/1.1 200 OK
[1] => Date: Mon, 14 Jun 2023 10:30:00 GMT
[2] => Server: Apache/2.4.41
[3] => Content-Type: text/html; charset=UTF-8
[4] => Content-Length: 12345
)
Array
(
[0] => HTTP/1.1 200 OK
[Date] => Mon, 14 Jun 2023 10:30:00 GMT
[Server] => Apache/2.4.41
[Content-Type] => text/html; charset=UTF-8
[Content-Length] => 12345
)
下面的示例演示如何使用 get_headers() 函数获取 URL 的 HTTP 响应头。
<?php
// 目标URL
$url = 'https://www.example.com';
// 获取响应头(默认格式)
$headers = get_headers($url);
// 检查是否成功
if ($headers !== false) {
echo "<h3>URL: $url 的响应头信息:</h3>";
echo "<div style='max-height: 300px; overflow-y: auto; border: 1px solid #ddd; padding: 10px;'>";
echo "<pre>";
// 打印所有响应头
foreach ($headers as $header) {
echo htmlspecialchars($header) . "\n";
}
echo "</pre></div>";
// 显示第一个元素(状态行)
if (!empty($headers[0])) {
echo "<p class='mt-3'><strong>状态行:</strong> " . htmlspecialchars($headers[0]) . "</p>";
}
} else {
echo "无法获取 URL 的响应头信息。";
}
?>
下面的示例演示如何使用 $format = 1 参数获取关联数组格式的响应头。
<?php
// 目标URL
$url = 'https://www.example.com';
// 获取响应头(关联数组格式)
$headers = get_headers($url, 1);
// 检查是否成功
if ($headers !== false) {
echo "<h3>URL: $url 的响应头(关联数组格式):</h3>";
// 获取状态码
if (isset($headers[0])) {
$statusLine = $headers[0];
echo "<p><strong>状态行:</strong> $statusLine</p>";
// 提取状态码
if (preg_match('/HTTP\/\d\.\d\s+(\d+)/', $statusLine, $matches)) {
$statusCode = $matches[1];
echo "<p><strong>状态码:</strong> $statusCode</p>";
// 判断状态码类型
if ($statusCode >= 200 && $statusCode < 300) {
echo "<p class='text-success'><strong>状态:</strong> 成功</p>";
} elseif ($statusCode >= 300 && $statusCode < 400) {
echo "<p class='text-warning'><strong>状态:</strong> 重定向</p>";
} elseif ($statusCode >= 400) {
echo "<p class='text-danger'><strong>状态:</strong> 客户端错误</p>";
} elseif ($statusCode >= 500) {
echo "<p class='text-danger'><strong>状态:</strong> 服务器错误</p>";
}
}
}
// 显示响应头表格
echo "<table class='table table-bordered table-striped mt-3'>";
echo "<thead><tr><th>响应头名称</th><th>值</th></tr></thead>";
echo "<tbody>";
foreach ($headers as $name => $value) {
// 跳过数字索引(状态行)
if (is_numeric($name)) {
continue;
}
// 处理值为数组的情况(当有多个相同名称的响应头时)
if (is_array($value)) {
$value = implode(', ', $value);
}
echo "<tr><td><strong>$name</strong></td><td>$value</td></tr>";
}
echo "</tbody></table>";
} else {
echo "无法获取 URL 的响应头信息。";
}
?>
下面的示例演示如何使用 get_headers() 函数检查 URL 的状态码和重定向信息。
<?php
/**
* 检查URL状态和重定向
* @param string $url 要检查的URL
* @return array 包含状态信息的数组
*/
function checkUrlStatus($url) {
$result = [
'url' => $url,
'status_code' => 0,
'status_message' => '',
'redirect_count' => 0,
'final_url' => '',
'headers' => []
];
// 设置上下文以跟随重定向
$context = stream_context_create([
'http' => [
'method' => 'HEAD', // 使用HEAD方法,只获取头部
'follow_location' => 1, // 跟随重定向
'max_redirects' => 5, // 最大重定向次数
'timeout' => 10 // 超时时间(秒)
]
]);
// 获取响应头
$headers = @get_headers($url, 1, $context);
if ($headers === false) {
$result['status_message'] = '无法连接到URL';
return $result;
}
// 获取状态码
if (isset($headers[0])) {
$statusLine = $headers[0];
// 提取状态码
if (preg_match('/HTTP\/\d\.\d\s+(\d+)\s+(.+)/', $statusLine, $matches)) {
$result['status_code'] = (int)$matches[1];
$result['status_message'] = $matches[2];
}
}
// 检查重定向
$redirectHistory = [];
if (isset($headers['Location'])) {
$locations = is_array($headers['Location']) ? $headers['Location'] : [$headers['Location']];
$result['redirect_count'] = count($locations);
$result['final_url'] = end($locations);
$redirectHistory = $locations;
} else {
$result['final_url'] = $url;
}
$result['headers'] = $headers;
return $result;
}
// 测试多个URL
$urls = [
'https://www.example.com',
'https://httpbin.org/redirect/2',
'https://httpbin.org/status/404',
'https://httpbin.org/status/500',
'https://nonexistent-domain-12345.com'
];
echo "<h3>URL状态检查结果:</h3>";
echo "<div class='table-responsive'>";
echo "<table class='table table-bordered table-hover'>";
echo "<thead class='table-dark'>";
echo "<tr><th>URL</th><th>状态码</th><th>状态</th><th>重定向次数</th><th>最终URL</th></tr>";
echo "</thead><tbody>";
foreach ($urls as $url) {
$status = checkUrlStatus($url);
// 根据状态码设置颜色
$statusClass = '';
if ($status['status_code'] >= 200 && $status['status_code'] < 300) {
$statusClass = 'table-success';
} elseif ($status['status_code'] >= 300 && $status['status_code'] < 400) {
$statusClass = 'table-warning';
} elseif ($status['status_code'] >= 400) {
$statusClass = 'table-danger';
} elseif ($status['status_code'] == 0) {
$statusClass = 'table-secondary';
}
echo "<tr class='$statusClass'>";
echo "<td><a href='{$status['url']}' target='_blank'>{$status['url']}</a></td>";
echo "<td><strong>{$status['status_code']}</strong></td>";
echo "<td>{$status['status_message']}</td>";
echo "<td>{$status['redirect_count']}</td>";
echo "<td>{$status['final_url']}</td>";
echo "</tr>";
}
echo "</tbody></table>";
echo "</div>";
?>
下面的示例演示如何使用 get_headers() 函数获取远程文件的信息,如文件大小、最后修改时间等。
<?php
/**
* 获取远程文件信息
* @param string $fileUrl 远程文件的URL
* @return array 文件信息数组
*/
function getRemoteFileInfo($fileUrl) {
$info = [
'exists' => false,
'size' => 0,
'size_formatted' => '0 B',
'last_modified' => '',
'content_type' => '',
'status_code' => 0
];
// 获取响应头
$headers = @get_headers($fileUrl, 1);
if ($headers === false) {
return $info;
}
// 获取状态码
if (isset($headers[0])) {
if (preg_match('/HTTP\/\d\.\d\s+(\d+)/', $headers[0], $matches)) {
$info['status_code'] = (int)$matches[1];
$info['exists'] = ($info['status_code'] == 200);
}
}
// 获取文件大小
if (isset($headers['Content-Length'])) {
$size = is_array($headers['Content-Length']) ?
end($headers['Content-Length']) : $headers['Content-Length'];
$info['size'] = (int)$size;
$info['size_formatted'] = formatBytes($info['size']);
}
// 获取最后修改时间
if (isset($headers['Last-Modified'])) {
$lastModified = is_array($headers['Last-Modified']) ?
end($headers['Last-Modified']) : $headers['Last-Modified'];
$info['last_modified'] = $lastModified;
}
// 获取内容类型
if (isset($headers['Content-Type'])) {
$contentType = is_array($headers['Content-Type']) ?
end($headers['Content-Type']) : $headers['Content-Type'];
$info['content_type'] = $contentType;
}
return $info;
}
/**
* 格式化字节大小
* @param int $bytes 字节数
* @param int $precision 精度
* @return string 格式化后的字符串
*/
function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, $precision) . ' ' . $units[$pow];
}
// 测试文件URL(这里使用示例URL,实际使用时需要替换)
$fileUrls = [
'https://www.example.com/index.html',
'https://raw.githubusercontent.com/php/php-src/master/LICENSE',
'https://www.w3.org/TR/PNG/iso_8859-1.txt',
'https://nonexistent.example.com/file.txt'
];
echo "<h3>远程文件信息检查:</h3>";
echo "<div class='table-responsive'>";
echo "<table class='table table-bordered'>";
echo "<thead class='table-primary'>";
echo "<tr>";
echo "<th>文件URL</th>";
echo "<th>存在</th>";
echo "<th>大小</th>";
echo "<th>类型</th>";
echo "<th>最后修改</th>";
echo "</tr>";
echo "</thead><tbody>";
foreach ($fileUrls as $fileUrl) {
$fileInfo = getRemoteFileInfo($fileUrl);
echo "<tr>";
echo "<td><a href='$fileUrl' target='_blank'>" . htmlspecialchars($fileUrl) . "</a></td>";
// 存在状态
if ($fileInfo['exists']) {
echo "<td><span class='badge bg-success'>是</span></td>";
} else {
echo "<td><span class='badge bg-danger'>否</span></td>";
}
// 文件大小
echo "<td>{$fileInfo['size_formatted']}</td>";
// 内容类型
echo "<td><code>" . htmlspecialchars($fileInfo['content_type']) . "</code></td>";
// 最后修改时间
echo "<td>" . htmlspecialchars($fileInfo['last_modified']) . "</td>";
echo "</tr>";
}
echo "</tbody></table>";
echo "</div>";
// 显示详细信息
echo "<h4 class='mt-4'>使用示例:</h4>";
echo "<div class='alert alert-info'>";
echo "<strong>注意:</strong> 这个函数使用 HEAD 请求获取文件信息,不会下载整个文件,因此对于大文件检查非常高效。";
echo "</div>";
?>
下面的示例演示如何使用 $context 参数定制 HTTP 请求,如设置超时、用户代理、请求方法等。
<?php
// 目标URL
$url = 'https://httpbin.org/headers';
// 创建上下文选项
$options = [
'http' => [
'method' => 'GET', // 请求方法
'timeout' => 5, // 超时时间(秒)
'header' => [ // 自定义请求头
'User-Agent: MyCustomAgent/1.0',
'Accept: application/json',
'X-Custom-Header: MyValue',
'Accept-Language: en-US,en;q=0.9'
],
'ignore_errors' => true // 忽略HTTP错误,继续获取响应头
],
'ssl' => [
'verify_peer' => false, // 不验证SSL证书(仅用于测试)
'verify_peer_name' => false
]
];
// 创建上下文
$context = stream_context_create($options);
// 获取响应头
$headers = get_headers($url, 1, $context);
if ($headers !== false) {
echo "<h3>自定义HTTP请求的响应头:</h3>";
// 显示状态
if (isset($headers[0])) {
echo "<p><strong>状态:</strong> {$headers[0]}</p>";
}
// 显示响应头
echo "<table class='table table-bordered'>";
echo "<thead><tr><th>响应头</th><th>值</th></tr></thead>";
echo "<tbody>";
foreach ($headers as $name => $value) {
if (is_numeric($name)) {
continue;
}
if (is_array($value)) {
$value = implode(', ', $value);
}
echo "<tr><td><strong>$name</strong></td><td>$value</td></tr>";
}
echo "</tbody></table>";
// 显示请求信息
echo "<h4 class='mt-4'>请求配置:</h4>";
echo "<pre>";
echo "URL: $url\n";
echo "方法: GET\n";
echo "超时: 5秒\n";
echo "自定义请求头:\n";
echo " - User-Agent: MyCustomAgent/1.0\n";
echo " - Accept: application/json\n";
echo " - X-Custom-Header: MyValue\n";
echo " - Accept-Language: en-US,en;q=0.9";
echo "</pre>";
} else {
echo "请求失败或超时。";
}
?>
get_headers() 可能会因为网络问题而阻塞。建议使用上下文参数设置超时时间。follow_location 为 1 来启用。@ 或检查返回值。检查链接是否有效,返回正确的 HTTP 状态码。
跟踪 URL 的重定向链,获取最终目标 URL。
获取远程文件的大小、类型和最后修改时间。
检测远程服务器使用的 Web 服务器软件和版本。