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

PHP 實現輕量級 HTTP Client 類:支援 GET/POST、Cookie、Referer、Header 獲取

     編輯:PHP 相關知識

設計目標

  • 零依賴,僅使用 PHP 內建 stream_context + file_get_contents
  • 支援 GET/POST、自定義 Header、Cookie、Referer、User-Agent
  • 自動記錄請求/回應 Header,便於除錯
  • 靜態工廠模式 HttpClient::init(),鏈式調用友好

完整類代碼

<?php
class HttpClient {
    public ?string $buffer   = null; // 回應內容
    public ?string $referer  = null; // 請求 Referer
    public ?string $response = null; // 回應 Header(原始字串)
    public ?string $request  = null; // 請求 Header(原始字串)

    private array $args = [];

    /** 靜態工廠 */
    public static function init(?array $args = []): self {
        return new self($args);
    }

    private function __construct(array $args = []) {
        $this->args = $args;
        if (!empty($this->args['debugging'])) {
            ob_end_clean();
            set_time_limit(0);
            header('Content-Type: text/plain; charset=utf-8');
        }
    }

    /** 組裝通用 Header */
    private function buildHeader(string $host, ?string $cookie = null, ?string $contentType = null, ?int $contentLength = null): string {
        $ua = $this->args['userAgent'] ?? $_SERVER['HTTP_USER_AGENT'] ?? 'PHP-HttpClient/1.0';
        $header  = "Host: {$host}\r\n";
        $header .= "Connection: close\r\n";
        $header .= "Accept: */*\r\n";
        $header .= "User-Agent: {$ua}\r\n";
        $header .= "DNT: 1\r\n";
        if ($cookie)        $header .= "Cookie: {$cookie}\r\n";
        if ($this->referer) $header .= "Referer: {$this->referer}\r\n";
        if ($contentType)   $header .= "Content-Type: {$contentType}\r\n";
        if ($contentLength) $header .= "Content-Length: {$contentLength}\r\n";
        return $header;
    }

    /** GET 請求 */
    public function get(string $url, ?string $query = null, ?string $cookie = null): ?string {
        $parsed = parse_url($url);
        $host = $parsed['host'] ?? '';
        $url .= (isset($parsed['query']) ? '&' : '?') . $query;

        $header = $this->buildHeader($host, $cookie);
        $this->request = $header;

        $context = stream_context_create([
            'http' => [
                'method'  => 'GET',
                'header'  => $header,
                'timeout' => $this->args['timeout'] ?? 30,
                'ignore_errors' => true,
            ],
        ]);

        $this->response = implode("\r\n", get_headers($url, 1) ?? []);
        $this->buffer = @file_get_contents($url, false, $context);
        return $this->buffer;
    }

    /** POST 請求 */
    public function post(string $url, ?string $data = null, ?string $cookie = null): ?string {
        $parsed = parse_url($url);
        $host = $parsed['host'] ?? '';

        $header = $this->buildHeader($host, $cookie, 'application/x-www-form-urlencoded', $data ? strlen($data) : null);
        $this->request = $header;

        $context = stream_context_create([
            'http' => [
                'method'  => 'POST',
                'header'  => $header,
                'content' => $data,
                'timeout' => $this->args['timeout'] ?? 30,
                'ignore_errors' => true,
            ],
        ]);

        $this->response = implode("\r\n", get_headers($url, 1) ?? []);
        $this->buffer = @file_get_contents($url, false, $context);
        return $this->buffer;
    }
}

使用示例

<?php
require 'HttpClient.php';

$client = HttpClient::init([
    'debugging' => true,
    'userAgent' => 'MyBot/2.0',
    'timeout'   => 15,
]);

// 簡單 GET
$client->get('https://www.baidu.com', 'wd=php');
echo "=== Request Header ===\n{$client->request}\n";
echo "=== Response Header ===\n{$client->response}\n";
echo "=== Body (first 500) ===\n" . mb_substr($client->buffer, 0, 500) . "\n";

// 攜帶 Cookie 與 Referer
$client->referer = 'https://www.google.com/';
$client->get('https://httpbin.org/cookies/set', 'session=abc123', 'uid=1; role=admin');
echo $client->buffer; // httpbin 回顯設定的 Cookie

// POST 表單
$client->post('https://httpbin.org/post', 'username=john&password=secret');
echo $client->buffer;

優缺點與適用場景

優點缺點
零擴展依賴,PHP 5.3+ 即可運行 無法精細控制 SSL 憑證驗證(需 cURL)
代碼極簡,易嵌入舊專案 不支援並發請求
自動記錄 Header,除錯方便 大檔案下載會全量載入記憶體
支援自定義 User-Agent、Cookie、Referer 重定向處理依賴 get_headers,非透明

進階擴展建議

  1. 加入 JSON 輔助: postJson($url, $data) 內部 json_encode + 設定 Content-Type: application/json。
  2. 檔案上傳: 構建 multipart/form-data body,需手動拼裝 boundary。
  3. 錯誤異常化: 依 $this->response 解析 HTTP 狀態碼,非 2xx 拋出 HttpException。
  4. PSR-18 相容: 實作 Psr\Http\Client\ClientInterface,無縫接入現代框架。
  5. 中介軟體管道: 允許註冊 beforeRequest/afterResponse 回調,統一處理簽名、日誌、重試。

總結

這個 HttpClient 類適合「不想引入 Composer 依賴、只需基本 GET/POST、需快速除錯 Header」的輕量場景。生產環境高併發、複雜 TLS、並發需求請直接使用 Guzzle 或 Symfony HttpClient。理解 stream_context 機制,也能在無 cURL 環境(如某些受限虛擬主機)下優雅完成 HTTP 交互。

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