zhanguangcheng/php-http-client

一个简单而强大的PHP HTTP客户端库。

0.1.0 2023-12-26 06:07 UTC

This package is auto-updated.

Last update: 2024-09-26 07:51:21 UTC


README

README.md | 中文 README.md

一个简单而强大的PHP HTTP客户端库。

特性

  • 发送 GET, POST, PATCH, PUT, DELETE 等请求
  • 文件上传和下载
  • 请求重试
  • cURL 处理复用,提高性能
  • 并发请求
  • Cookie 保持
  • 支持 gzip
  • 用户认证

文件结构

/
├─src
│   HttpClient.php      HTTP client
│   Request.php         Request
│   Response.php        Response
│   Options.php         Request options
│   CookieJar.php       Cookie keep
├─tests                 Test cases
│   ...

安装

要求

  • PHP >= 8.0
  • curl 扩展
  • json 扩展
composer require zhanguangcheng/php-http-client

基本用法

use Zane\HttpClient\HttpClient;

$client = HttpClient::create();

$response = $client->get('https://httpbin.org/get');
$statusCode = $response->getStatusCode();
// $statusCode = 200
$contentType = $response->getHeaderLine('content-type');
// $contentType = 'application/json'
$content = $response->getContent();
// $content = '{"args":{}, "headers":{"Accept": "*/*", ...}}'
$content = $response->toArray();
// $content = ['args' => [], 'headers' => ['Accept' => '*/*', ...]]

配置

HttpClient 包含许多选项来控制请求的执行方式,包括重试、并发、代理、认证、Cookie 保持等。这些选项可以全局定义(适用于所有请求)和针对单个请求定义(覆盖任何全局选项)。

您可以使用 HttpClient::create($options) 创建带有选项的客户端,其中 $options 是全局选项。

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create([
    Options::BASE_URL => 'https://httpbin.org',
    Options::HEADERS => ['header-name' => 'header-value'],
    Options::MAX_REDIRECTS => 7,
    Options::MAX_RETRY => 3,
    Options::TIMEOUT => 3,
]);

或者,结合 Options 类的获取器和设置器

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create(
    (new Options())
        ->setBaseUrl('https://...')
        ->setHeaders(['header-name' => 'header-value'])
        ->toArray()
);

使用选项发送请求

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create();

$client->get('https://httpbin.org/get', ['query-foo' => 'query-bar'], [
    Options::HEADERS => ['header-name' => 'header-value'],
    Options::MAX_REDIRECTS => 7,
    Options::MAX_RETRY => 3,
    Options::TIMEOUT => 3,
]);

发送请求

发送不同方法

use Zane\HttpClient\HttpClient;

$client = HttpClient::create();

$client->get('https://httpbin.org', ['query' => 'value']);
$client->post('https://httpbin.org', ['body' => 'value']);
$client->put('https://httpbin.org', ['body' => 'value']);
$client->patch('https://httpbin.org', ['body' => 'value']);
$client->delete('https://httpbin.org', ['body' => 'value']);
$client->request('GET', 'https://httpbin.org');

查询字符串参数

您可以将它们手动添加到请求的URL中,或者将它们定义为具有 Options::QUERY 选项的关联数组,这将与URL合并。

use Zane\HttpClient\Options;

// it makes an HTTP GET request to https://httpbin.org/get?token=...&name=...
$response = $client->get('https://httpbin.org/get', [
    // these values are automatically encoded before including them in the URL
    'token' => '...',
    'name' => '...',
]);

$response = $client->post('https://httpbin.org/post', [], [
    Options::QUERY => [
        'token' => '...',
        'name' => '...',
    ]
]);

发送请求头

您可以使用 Options::HEADERS 选项定义要发送的请求头。

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/headers', [
    Options::HEADERS => [
        'Accept' => 'application/json',
        'X-Foo' => 'Bar',
    ],
]);

发送请求体

使用 post()put()patch()delete() 方法的第二个参数发送请求体。

// defining data using a regular string
$response = $client->post('https://httpbin.org/post', 'raw data');

// defining data using an array of parameters
$response = $client->post('https://httpbin.org/post', ['parameter1' => 'value1', '...']);

// using a resource to get the data from it
$response = $client->post('https://httpbin.org/post', fopen('/path/to/file', 'r'));

// using a CURLFile object to upload a file
$response = $client->post('https://httpbin.org/post', [
    'file' => new \CURLFile('/path/to/file'),
]);

您还可以使用 Options::BODY 选项定义要发送的请求体。

use Zane\HttpClient\Options;

$response = $client->request('POST', 'https://httpbin.org/post', [
    Options::BODY => 'raw data',
]);

当使用 POST 方法上传数据时,如果您没有明确定义 Content-Type 请求头,将默认添加 Content-Type:application/x-www-form-urlencoded 请求头。如果您想自定义请求类型,可以使用 Options::CONTENT_TYPE 选项,例如使用 JSON 格式。

use Zane\HttpClient\Options;

$response = $client->post('https://httpbin.org/post', ['parameter1' => 'value1', '...'], [
    Options::CONTENT_TYPE => Options::TYPE_JSON,
]);

Gzip 压缩

如果安装了 zlib 扩展,将默认发送 Accept-Encoding: gzip 请求头。在获取响应内容时,如果服务器支持 gzip 压缩且响应头包含 Content-Encoding: gzip,则将自动解压缩响应内容。

$response = $client->get('https://httpbin.org/gzip');
$content = $response->getContent();
// $content = '{"args":{}, "headers":{"Accept": "*/*", ...}}'

您还可以关闭 gzip 压缩。

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/gzip', [
    Options::ACCEPT_GZIP => false,
]);

重定向

默认情况下,HTTP 客户端在发送请求时会跟踪重定向,默认跟踪 5 个重定向。使用 Options::MAX_REDIRECTS 设置来配置此行为。

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/redirect/3', [], [
    Options::MAX_REDIRECTS => 0,
]);

重试失败的请求

有时,请求因网络问题或临时服务器错误而失败。您可以使用 Options::MAX_RETRY 选项自动重试失败的请求。默认情况下,失败的请求将重试最多 3 次,第一次重试的延迟为 1 秒;第二次重试的延迟为 3 秒;第三次重试的延迟为 5 秒。重试的条件是:请求超时或响应状态码为 423、425、429、500、502、503、504、507 和 510 之一。

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/get', [], [
    Options::MAX_RETRY => 3,
]);

用户认证

HttpClient 支持不同的认证机制。它们可以在配置中全局定义(适用于所有请求)和针对单个请求定义(覆盖任何全局认证)。

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create([
    // HTTP Basic authentication
    Options::AUTH_BASIC => ['username', 'password'],
    // HTTP Bearer authentication
    Options::AUTH_BEARER => 'token',
    // HTTP custom authentication
    Options::HEADERS => [
        'Authorization' => 'token',
    ],
])

请求代理

HttpClient 支持使用 HTTP 代理发送请求。它们可以在配置中全局定义(应用于所有请求)和按请求定义(覆盖任何全局代理)

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create([
    Options::PROXY => 'https://...',
]);

Cookie 保持

使用 CookieJar 类来保持响应中的 Cookie,并在后续请求中发送它们

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create();

$jar = new CookieJar();

$response = $client->get('https://httpbin.org/cookies/set', ['name' => 'value'], [
    Options::COOKIE_JAR => $jar,
]);

$response = $client->get('https://httpbin.org/cookies', [], [
    Options::COOKIE_JAR => $jar,
]);
var_dump($response->toArray());
// ['cookies' => ['name' => 'value']]

文件下载

使用 HttpClientdownload() 方法下载文件,您可以使用 Options::ON_PROGRESS 选项来监控下载进度

use Zane\HttpClient\Options;

$client->download('https://httpbin.org/image/png', '/path/to/file.png', [
    Options::ON_PROGRESS => function ($ch, $downloadTotal, $downloaded) {
        // ...
    },
]);

HTTPS 证书验证

证书下载地址: https://curl.haxx.se/docs/caextract.html

默认情况下,使用系统的 CA 证书,例如 php 配置文件中的 curl.cainfoopenssl.cafile 配置

[curl]
curl.cainfo = /path/to/cacert.pem

[openssl]
openssl.cafile = /path/to/cacert.pem

您也可以使用 Options::CAFILE 选项指定 HTTPS 证书

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/get', [], [
    Options::CAFILE => '/path/to/cacert.pem',
]);

关闭证书验证(在生产环境中不推荐使用)

use Zane\HttpClient\Options;

$response = $client->get('https://httpbin.org/get', [], [
    Options::VERIFY_HOST => false,
    Options::VERIFY_PEER => false,
]);

并发请求

HttpClient::create($options, $concurrency) 的第二个参数设置为并发请求的数量,使用 addRequest($method, $url, $options) 方法添加请求,然后使用 send() 方法发送请求,响应数组与请求数组顺序相同。您还可以使用 Options::MAX_RETRY 选项设置在重试并发请求时的失败请求。

use Zane\HttpClient\HttpClient;
use Zane\HttpClient\Options;

$client = HttpClient::create([], 10);

for ($i = 0; $i < 100; $i++) {
    $client->addRequest('GET', 'https://httpbin.org/get', [
        Options::QUERY => ['index' => $i],
    ]);
}
$responses = $client->send();
foreach ($responses as $response) {
    $content = $response->getContent();
    // ...
}

处理响应

HttpClient 返回的所有响应都是类型为 Response 的对象,并提供以下方法

$response = $client->request('GET', 'https://...');

// gets the HTTP status code of the response
$statusCode = $response->getStatusCode();

// gets the HTTP request error code. using function curl_errno()
$statusCode = $response->getErrorCode();

// gets the HTTP request error message. using function curl_error()
$statusCode = $response->getErrorMessage();

// gets the HTTP response headers as a string
$headers = $response->getHeaderLine('content-type');

// gets the HTTP response headers as an array of strings
$headers = $response->getHeader('content-type');

// gets the HTTP headers as string[][] with the header names lower-cased
$headers = $response->getHeaders();

// gets the response body as a string
$content = $response->getContent();

// casts the response JSON content to a PHP array
$content = $response->toArray();

// returns info coming from the transport layer, such as "request_header",
// "retry_count", "total_time", "redirect_url", etc.
$httpInfo = $response->getInfo();

// you can get individual info too
$startTime = $response->getInfo('request_header');

// gets the request options
$options = $response->getOptions();
$options->getQuery();

测试

运行以下命令以运行测试

vendor/bin/phpunit

100% 代码覆盖率

code coverage

参考资料