首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 獲取遠端 URL HTTP 狀態碼完整方案:get_headers + cURL 雙重保障

     編輯:PHP 綜合知識

檢測遠端 URL 可用性、監控服務存活、爬蟲預檢都需要獲取 HTTP 狀態碼。PHP 提供 get_headers() 簡便方法與 cURL 完整控制兩種方案,本文整合雙重實現,支援僅取狀態碼與完整 Header 解析兩種模式。

整合函式實現

<?php
/**
 * 獲取遠端 URL HTTP 狀態資訊
 * 
 * @param string $url 目標 URL
 * @param bool   $fullHeader true=回傳完整 header 陣列, false=僅回傳狀態碼
 * @return array|int|false 成功回傳狀態碼或 header 陣列,失敗回傳 false
 */
function getHttpStatus(string $url, bool $fullHeader = false) {
    // 方案一:get_headers (簡單、無需擴充)
    $headers = @get_headers($url, 1);  // 第 2 參數 1 = 關聯陣列格式
    
    if ($headers !== false) {
        if ($fullHeader) {
            return $headers;  // 完整 header 陣列
        }
        // 解析狀態行:HTTP/1.1 200 OK
        $statusLine = $headers[0] ?? '';
        if (preg_match('#HTTP/\d\.\d\s+(\d{3})#', $statusLine, $matches)) {
            return (int)$matches[1];
        }
    }
    
    // 方案二:cURL 兜底 (支援更多協定、超時控制、重導向處理)
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => $url,
        CURLOPT_HEADER         => true,      // 包含 header
        CURLOPT_NOBODY         => true,      // HEAD 請求,不下載 body
        CURLOPT_RETURNTRANSFER => true,      // 回傳字串
        CURLOPT_TIMEOUT        => 10,        // 連線超時 10 秒
        CURLOPT_CONNECTTIMEOUT => 5,         // 建立連線超時 5 秒
        CURLOPT_FOLLOWLOCATION => true,      // 追蹤 3xx 重導向
        CURLOPT_MAXREDIRS      => 5,         // 最大重導向次數
        CURLOPT_SSL_VERIFYPEER => false,     // 開發環境跳過 SSL 驗證
        CURLOPT_USERAGENT      => 'PHP-HTTP-Status-Checker/1.0',
    ]);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlError = curl_error($ch);
    curl_close($ch);
    
    if ($curlError) {
        error_log("cURL error for {$url}: {$curlError}");
        return false;
    }
    
    if ($fullHeader && $response) {
        // 解析原始 header 字串為關聯陣列
        return parseRawHeaders($response);
    }
    
    return $httpCode ?: false;
}

/**
 * 解析 cURL 原始 header 字串
 */
function parseRawHeaders(string $rawHeaders): array {
    $headers = [];
    $lines = explode("\n", $rawHeaders);
    
    foreach ($lines as $line) {
        $line = trim($line);
        if ($line === '') continue;
        
        if (str_starts_with($line, 'HTTP/')) {
            $headers[0] = $line;  // 狀態行
        } elseif (strpos($line, ':') !== false) {
            [$key, $value] = explode(':', $line, 2);
            $key = trim($key);
            $value = trim($value);
            // 處理重複 header (如 Set-Cookie)
            if (isset($headers[$key])) {
                $headers[$key] = (array)$headers[$key];
                $headers[$key][] = $value;
            } else {
                $headers[$key] = $value;
            }
        }
    }
    return $headers;
}
?>

使用範例

<?php
// 1. 僅獲取狀態碼 (預設)
$code = getHttpStatus('https://www.example.com');
var_dump($code); // int(200)

// 2. 獲取完整 Header
$headers = getHttpStatus('https://www.example.com', true);
/*
array(10) {
  [0]=> "HTTP/1.1 200 OK"
  ["Server"]=> "nginx"
  ["Date"]=> "Mon, 15 Jan 2024 06:21:35 GMT"
  ["Content-Type"]=> "text/html; charset=UTF-8"
  ["Content-Length"]=> "26898"
  ["Last-Modified"]=> "Mon, 15 Jan 2024 06:16:00 GMT"
  ["Connection"]=> "keep-alive"
  ["Vary"]=> "Accept-Encoding"
  ["ETag"]=> ""5779ff20-6912""
  ["Accept-Ranges"]=> "bytes"
}
*/

// 3. 批次檢測多個 URL
$urls = [
    'https://api.service.com/health',
    'https://cdn.example.com/assets/app.js',
    'https://webhook.receiver.com/endpoint',
];

foreach ($urls as $url) {
    $status = getHttpStatus($url);
    $status === 200 
        ? print("✅ {$url} - OK\n") 
        : print("❌ {$url} - FAILED ({$status})\n");
}
?>

方案對比與選擇建議

特性get_headers()cURL
相依性核心內建需 curl 擴充
協定支援HTTP/HTTPSHTTP/HTTPS/FTP/SMTP/...
重導向處理自動追蹤 (不可控)可配置策略
超時控制受 default_socket_timeout 影響精確控制連線/執行超時
自定 Header支援 (stream context)完整支援
效能較輕量功能豐富但較重
錯誤診斷有限詳細錯誤代碼/訊息

進階:非同步並發檢測 (cURL Multi)

function checkUrlsConcurrent(array $urls, int $maxConcurrent = 10): array {
    $mh = curl_multi_init();
    $handles = [];
    $results = [];
    
    // 初始化 handles
    foreach ($urls as $i => $url) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_HEADER => true,
            CURLOPT_NOBODY => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 5,
            CURLOPT_FOLLOWLOCATION => true,
        ]);
        curl_multi_add_handle($mh, $ch);
        $handles[$i] = $ch;
    }
    
    // 執行並發
    $running = null;
    do {
        curl_multi_exec($mh, $running);
        curl_multi_select($mh, 0.1); // 等待活動
    } while ($running > 0);
    
    // 收集結果
    foreach ($handles as $i => $ch) {
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        $results[$urls[$i]] = $error ? false : $httpCode;
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }
    curl_multi_close($mh);
    
    return $results;
}

// 100 個 URL 並發檢測,僅需單次最慢請求的時間
$results = checkUrlsConcurrent($urls, 20);

常見狀態碼快速參考

分類代碼含義處理建議
2xx 成功200OK正常處理
201CreatedPOST 建立成功
204No Content成功但無回應內容
3xx 重導向301Moved Permanently更新 URL 為 Location
302Found暫時重導向
304Not Modified快取有效
4xx 客戶端錯誤400Bad Request檢查請求參數
401Unauthorized需認證
403Forbidden權限不足
404Not Found資源不存在
429Too Many Requests限流,需退避重試
5xx 伺服器錯誤500Internal Server Error記錄日誌、告警
502Bad Gateway上游服務異常
503Service Unavailable暫時不可用,重試

雙重方案確保相容性與穩健性:get_headers() 輕量快速,cURL 功能完整可控,生產環境建議以 cURL 為主、get_headers 為備援。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved