PHP apache_response_headers()函数

PHP apache_response_headers() 函数

apache_response_headers() 函数用于获取 Apache 服务器的所有 HTTP 响应头信息。响应头是服务器发送给客户端的 HTTP 头部信息,包含了关于响应的元数据。

提示: 该函数仅在 Apache 服务器环境下可用。它返回由 header() 函数设置的响应头,以及 Apache 自动添加的一些响应头。
注意: apache_response_headers()apache_request_headers() 是不同的函数。前者获取服务器发送的响应头,后者获取客户端发送的请求头。

语法

apache_response_headers ( ) : array|false

该函数没有参数。

返回值

函数返回一个包含所有 HTTP 响应头的关联数组,失败则返回 FALSE

返回的数组格式如下:

  • 键名(Key):HTTP 响应头的名称(如 "Content-Type", "Cache-Control", "Server" 等)
  • 键值(Value):对应响应头的值

典型的响应头可能包括:

  • Content-Type - 响应内容的类型
  • Content-Length - 响应内容的长度
  • Cache-Control - 缓存控制指令
  • Server - 服务器信息
  • Date - 响应生成的日期和时间
  • Expires - 响应过期时间

示例 1:获取所有 HTTP 响应头

下面的示例演示如何使用 apache_response_headers() 函数获取所有 HTTP 响应头并打印出来。

<?php
// 设置一些响应头
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('X-Powered-By: PHP/8.0');

// 获取所有 HTTP 响应头
$responseHeaders = apache_response_headers();

// 检查是否成功获取
if ($responseHeaders !== false) {
    echo "<h3>HTTP 响应头信息:</h3>";
    echo "<table class='table table-bordered'>";
    echo "<thead><tr><th>响应头名称</th><th>值</th></tr></thead>";
    echo "<tbody>";

    // 遍历并打印所有响应头
    foreach ($responseHeaders as $header => $value) {
        echo "<tr><td><strong>$header</strong></td><td>$value</td></tr>";
    }

    echo "</tbody></table>";

    // 显示响应头总数
    echo "<p>总共 " . count($responseHeaders) . " 个响应头</p>";
} else {
    echo "无法获取 HTTP 响应头信息。请确保在 Apache 服务器环境下运行。";
}
?>

运行结果示例:

HTTP 响应头信息:
响应头名称
Content-Typetext/html; charset=utf-8
Cache-Controlno-cache, must-revalidate
ExpiresMon, 26 Jul 1997 05:00:00 GMT
X-Powered-ByPHP/8.0
ServerApache/2.4.41
DateMon, 14 Jun 2023 10:30:00 GMT

总共 6 个响应头

示例 2:检查特定 HTTP 响应头

下面的示例演示如何检查特定的 HTTP 响应头,如 "Content-Type" 或缓存相关的响应头。

<?php
// 根据条件设置不同的响应头
$isApiRequest = isset($_GET['api']);

if ($isApiRequest) {
    // API 请求 - 设置 JSON 响应
    header('Content-Type: application/json; charset=utf-8');
    header('Access-Control-Allow-Origin: *');
    header('X-API-Version: 1.0');
} else {
    // 普通 HTML 请求
    header('Content-Type: text/html; charset=utf-8');
    header('X-Frame-Options: DENY');
}

// 设置缓存控制
$noCache = isset($_GET['nocache']);
if ($noCache) {
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Pragma: no-cache');
    header('Expires: 0');
} else {
    header('Cache-Control: public, max-age=3600');
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
}

// 获取响应头
$responseHeaders = apache_response_headers();

if ($responseHeaders !== false) {
    echo "<h3>当前响应头配置:</h3>";

    // 检查内容类型
    if (isset($responseHeaders['Content-Type'])) {
        $contentType = $responseHeaders['Content-Type'];
        echo "内容类型: <code>$contentType</code><br>";

        if (strpos($contentType, 'application/json') !== false) {
            echo "当前为 API 响应模式<br>";
        } elseif (strpos($contentType, 'text/html') !== false) {
            echo "当前为 HTML 响应模式<br>";
        }
    }

    // 检查缓存控制
    if (isset($responseHeaders['Cache-Control'])) {
        $cacheControl = $responseHeaders['Cache-Control'];
        echo "缓存控制: <code>$cacheControl</code><br>";

        if (strpos($cacheControl, 'no-cache') !== false || strpos($cacheControl, 'no-store') !== false) {
            echo "缓存已被禁用<br>";
        } else {
            echo "缓存已启用<br>";
        }
    }

    // 检查自定义响应头
    $customHeaders = array_filter($responseHeaders, function($key) {
        return strpos($key, 'X-') === 0;
    }, ARRAY_FILTER_USE_KEY);

    if (!empty($customHeaders)) {
        echo "<h4>自定义响应头:</h4>";
        foreach ($customHeaders as $header => $value) {
            echo "<strong>$header</strong>: $value<br>";
        }
    }
} else {
    echo "无法获取响应头信息";
}
?>

示例 3:调试和验证响应头设置

下面的示例演示如何使用 apache_response_headers() 来调试和验证响应头是否正确设置。

<?php
// 响应头调试函数
function debugResponseHeaders() {
    $headers = apache_response_headers();

    if ($headers === false) {
        return "无法获取响应头信息(可能不在Apache环境下)";
    }

    $output = "<div style='background:#f8f9fa;padding:10px;border:1px solid #ddd;'>";
    $output .= "<h4 style='margin-top:0;'>响应头调试信息</h4>";
    $output .= "<ul style='margin-bottom:0;'>";

    foreach ($headers as $name => $value) {
        $output .= "<li><strong>$name</strong>: $value</li>";
    }

    $output .= "</ul></div>";

    return $output;
}

// 验证响应头设置
function validateResponseHeaders($expectedHeaders) {
    $actualHeaders = apache_response_headers();

    if ($actualHeaders === false) {
        return "无法验证响应头:无法获取当前响应头";
    }

    $issues = [];
    $actualHeadersLower = array_change_key_case($actualHeaders, CASE_LOWER);

    foreach ($expectedHeaders as $expectedName => $expectedValue) {
        $expectedNameLower = strtolower($expectedName);

        if (!isset($actualHeadersLower[$expectedNameLower])) {
            $issues[] = "缺少响应头: $expectedName";
        } elseif ($actualHeadersLower[$expectedNameLower] !== $expectedValue) {
            $issues[] = "响应头 '$expectedName' 值不匹配。期望: '$expectedValue', 实际: '{$actualHeadersLower[$expectedNameLower]}'";
        }
    }

    return empty($issues) ? "所有响应头验证通过" : implode("<br>", $issues);
}

// 设置一些响应头
header('Content-Type: text/html; charset=utf-8');
header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: DENY');

// 输出调试信息
echo debugResponseHeaders();
echo "<hr>";

// 验证响应头
$expected = [
    'Content-Type' => 'text/html; charset=utf-8',
    'X-Content-Type-Options' => 'nosniff',
    'X-Frame-Options' => 'DENY'
];

echo "<h4>响应头验证结果:</h4>";
echo validateResponseHeaders($expected);
?>

示例 4:apache_response_headers() 与 headers_list() 的比较

apache_response_headers()headers_list() 都可以获取响应头,但有一些区别:

  • apache_response_headers() - 获取Apache处理后的所有响应头(包括Apache自动添加的)
  • headers_list() - 获取PHP脚本通过header()函数设置的所有响应头
<?php
// 设置一些响应头
header('Content-Type: text/html; charset=utf-8');
header('X-Custom-Header: MyValue');
header('Cache-Control: no-cache');

// 获取两种方式的结果
$apacheHeaders = apache_response_headers();
$phpHeaders = headers_list();

echo "<div class='row'>";
echo "<div class='col-md-6'>";
echo "<h4>apache_response_headers() 结果:</h4>";
if ($apacheHeaders !== false) {
    echo "<ul>";
    foreach ($apacheHeaders as $name => $value) {
        echo "<li><strong>$name</strong>: $value</li>";
    }
    echo "</ul>";
    echo "<p>总数: " . count($apacheHeaders) . "</p>";
} else {
    echo "<p class='text-danger'>无法获取Apache响应头</p>";
}
echo "</div>";

echo "<div class='col-md-6'>";
echo "<h4>headers_list() 结果:</h4>";
echo "<ul>";
foreach ($phpHeaders as $header) {
    echo "<li>$header</li>";
}
echo "</ul>";
echo "<p>总数: " . count($phpHeaders) . "</p>";
echo "</div>";
echo "</div>";

// 比较差异
echo "<h4 class='mt-4'>比较分析:</h4>";
echo "<ul>";
echo "<li><code>apache_response_headers()</code> 通常包含更多响应头,因为Apache会自动添加一些(如Server、Date等)</li>";
echo "<li><code>headers_list()</code> 只返回通过PHP的<code>header()</code>函数设置的响应头</li>";
echo "<li>如果同一个响应头被多次设置,<code>apache_response_headers()</code> 返回最后设置的值,而<code>headers_list()</code>可能包含多个值</li>";
echo "</ul>";
?>

备选方案:在其他服务器环境下

如果你需要在非 Apache 服务器环境下获取响应头信息,可以使用以下方法:

<?php
/**
 * 获取响应头信息的兼容函数
 * @return array 包含响应头信息的数组
 */
function getResponseHeadersCompatible() {
    // 优先使用 apache_response_headers()
    if (function_exists('apache_response_headers')) {
        $headers = apache_response_headers();
        if ($headers !== false && !empty($headers)) {
            return $headers;
        }
    }

    // 使用 headers_list() 作为备选
    $headers = [];
    $headersList = headers_list();

    foreach ($headersList as $header) {
        // 分割响应头名称和值
        if (strpos($header, ':') !== false) {
            list($name, $value) = explode(':', $header, 2);
            $headers[trim($name)] = trim($value);
        }
    }

    return $headers;
}

// 使用兼容函数
$responseHeaders = getResponseHeadersCompatible();

echo "<h3>响应头信息(兼容版本):</h3>";
if (!empty($responseHeaders)) {
    foreach ($responseHeaders as $header => $value) {
        echo "<strong>$header</strong>: $value<br>";
    }
} else {
    echo "没有设置响应头或无法获取响应头信息";
}

// 另一种方法:模拟响应头(用于测试)
function simulateResponseHeaders() {
    $simulated = [
        'Content-Type' => 'text/html; charset=utf-8',
        'X-Powered-By' => 'PHP/' . PHP_VERSION,
        'Server' => 'WebServer',
        'Date' => gmdate('D, d M Y H:i:s') . ' GMT'
    ];

    // 添加实际设置的响应头
    foreach (headers_list() as $header) {
        if (strpos($header, ':') !== false) {
            list($name, $value) = explode(':', $header, 2);
            $simulated[trim($name)] = trim($value);
        }
    }

    return $simulated;
}
?>

注意事项和限制

  • 服务器要求apache_response_headers() 函数仅在 Apache 服务器环境下有效。
  • 调用时机:响应头通常在脚本执行过程中设置,但在某些情况下可能需要刷新输出缓冲区后才能看到所有响应头。
  • 大小写敏感性:HTTP 响应头名称是大小写不敏感的,但函数返回的数组键名会保留原始大小写。
  • 输出影响:如果已经向客户端发送了输出,某些响应头可能无法再修改。
  • PHP 版本:该函数自 PHP 4.3.0 版本开始可用。
  • 与headers_list()的区别headers_list()只返回PHP设置的响应头,而apache_response_headers()返回所有响应头(包括Apache添加的)。

相关函数