strictphp / http-clients

提供各种 http 客户端实现,以提升开发者和 DevOps 的体验。

v0.1.4 2024-07-12 08:21 UTC

This package is auto-updated.

Last update: 2024-09-12 09:15:21 UTC


README

HTTP 客户端包提供了一系列 HTTP 客户端,可用于在 PHP 应用程序中管理 HTTP 请求和响应。该包包含一个 ClientsFactory,通过允许您定义一系列 ClientFactoryContract 实现来简化客户端的创建。

功能

  • 使用 PSR 容器进行依赖注入。
  • CacheResponseClient:利用 PSR-6(simple-cache)进行响应缓存,通过为后续请求提供缓存响应来提高开发速度。
  • CustomizeRequestClient:您可以在发送请求之前修改请求。
  • EventClient:依赖于 PSR-14(event-dispatcher),允许您在请求之前、期间或之后附加事件,这对于日志记录或其他操作很有用。
  • RetryClient:如果 sendRequest 调用抛出异常,它将尝试再次发送请求。
  • SleepClient:允许您在请求之间引入等待间隔,这对于与需要速率限制的外部 API 交互可能是必要的。
  • StoreClient:将您的 REQest 保存为 PHPStorm REQ.http 文件,并将相应的 RESponse 保存为后缀为 RES.<code>.[headers|xml|txt|json|html|pdf] 的文件。

安装

您可以通过 Composer 安装 HTTP 客户端包。

composer require strictphp/http-clients

用法

ClientsFactory 通过允许您使用依赖注入定义一系列 ClientFactoryContract 实现来简化客户端的创建。

示例

use Psr\Container\ContainerInterface;
use Psr\Http\Client\ClientInterface;
use StrictPhp\HttpClients\Clients\CacheResponse\CacheResponseClientFactory;
use StrictPhp\HttpClients\Clients\CustomizeRequest\CustomizeRequestClientFactory;
use StrictPhp\HttpClients\Clients\Event\EventClientFactory;
use StrictPhp\HttpClients\Clients\Retry\RetryClientFactory;
use StrictPhp\HttpClients\Clients\Sleep\SleepClientFactory;
use Strictphp\HttpClients\Factories\ClientsFactory;
use Strictphp\HttpClients\Iterators\FactoryToServiceIterator;

// Assuming $client is the main client like GuzzleHttp\Client
/** @var ClientInterface $client */
/** @var ContainerInterface $container */

// the order of classes is important, see image below
$clients = [
    CacheResponseClientFactory::class, // used like first
    RetryClientFactory::class,
    SleepClientFactory::class,
    EventClientFactory::class,
    CustomizeRequestClientFactory::class,
    // Other client factories...
];

/**
 * This iterator change array<class-string<ClientFactoryContract>> to array<ClientFactoryContract>
 */
$toService = new FactoryToServiceIterator($container, $clients);

$clientFactory = new ClientsFactory($client);
$client = $clientFactory->create($toService);
// Alternatively, you can use second parameter of constructor:
$clientFactory = new ClientsFactory($client, $toService);
$client = $clientFactory->create();

以下示例演示了如何使用提供的 HTTP 客户端类和 ClientsFactory 在 PHP 应用程序中有效地管理 HTTP 请求和响应。

image

ConfigManager

ConfigManager 旨在为每个主机(IP、域名)设置不同的配置。每个 HTTP 客户端都可以在其命名空间中包含 Config 类。

设置默认配置

use StrictPhp\HttpClients\Managers\ConfigManager;
use StrictPhp\HttpClients\Clients\Sleep;

// set up for SleepClient
$config = new Sleep\SleepConfig(1000, 2000);

/** @var ConfigManager $configManager */
$configManager->addDefault($config);

设置给定域的覆盖配置

use StrictPhp\HttpClients\Managers\ConfigManager;
use StrictPhp\HttpClients\Clients\Sleep;

// set up for SleepClient
$config = new Sleep\SleepConfig(1000, 2000);

/** @var ConfigManager $configManager */
$configManager->add('strictphp.com', $config);

您应将 DI 容器设置为提供 ConfigManager 作为单例。

客户端

  • 每个客户端都可以使用其自己的 Factory 类(在其命名空间中)构建。Factory 使用一个 DI 容器,该容器应解析:用于 HTTP/s 通信的 ClientInterface 和 ConfigManaer
  • 每个客户端都可以由 ConfigManager 进行配置。

CacheResponseClient (文件)

CacheResponseClient 利用 PSR-6(simple-cache)进行响应缓存,通过为后续请求提供缓存响应来提高开发速度。以下是优点和考虑因素:

  • 开发效率:通过缓存响应加快开发速度,减少在开发期间重复 API 调用的需要。
  • 本地测试:在生产环境中启用 saveOnly 选项以缓存响应并下载到本地主机进行测试,确保一致性和性能。
  • 定制:通过在 CacheKeyMakerAction.php 中实现自己的合同来自定义缓存键的制备。

自定义响应客户端 (文件)

内容可能有所更改。

您可以定义自定义响应文件。

构造函数中的第1个参数可以是

  • SerializableResponse 创建的序列化路径,该文件扩展名为 shttp,表示 序列化 http
  • 纯文本文件的路径,这仅用于正文

您需要设置容器依赖项以添加所需的内容。

自定义请求客户端 (文件)

在将请求发送到HTTPClient之前修改请求。您可以抛出ClientExceptionInterface。此客户端可用于测试应用程序中的错误处理机制并使用缓存的*.shttp文件。

use Psr\Http\Message\RequestInterface;
use StrictPhp\HttpClients\Clients\CustomizeRequest\CustomizeRequestConfig;
use StrictPhp\HttpClients\Managers\ConfigManager;

/** @var ConfigManager $configManager */
$configManager->add('www.example.com', new CustomizeRequestConfig(function(RequestInterface $request): RequestInterface {
    return $request->withHeader('uuid', generate_uuid());
}));

事件客户端 (文件)

依赖于PSR-14(事件分发器)

您可以在请求之前、失败或请求成功时附加事件。这对于日志记录非常有用。

重试客户端 (文件)

重试客户端旨在通过定义尝试次数和允许列表(基于异常)来重试失败的请求。

睡眠客户端 (文件)

SleepClient 允许您在请求之间引入等待间隔,这对于与需要速率限制的外部API交互可能是必要的。

存储客户端 (文件)

StoreClient 保存请求和响应,不依赖于 PSR-14

编写自己的客户端

您可以通过实现这些接口简单地编写自己的客户端

  • 客户端必须实现 Psr\Http\Client\ClientInterface
  • 配置必须实现 StrictPhp\HttpClients\Contracts\ConfigInteface
  • 客户端工厂实现 StrictPhp\HttpClients\Contracts\ClientFactoryContract

以下是一个实现示例

测试

您可以通过 SaveResponse 保存扩展名为 *.shttp 的文件或使用我们的 PSR16 实现 CachePsr16Service。您可以通过 CustomResponseClient 在测试中使用此文件。

use StrictPhp\HttpClients\Clients\CustomResponse\CustomResponseClient;
/** @var \Psr\Http\Message\RequestInterface $request */
$client = new CustomResponseClient(__DIR__ . '/dir/filename.shttp');
$response = $client->sendRequest($request);

$response instanceof \Psr\Http\Message\ResponseInterface;

配置

namespace My;

use StrictPhp\HttpClients\Contracts\ConfigInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use StrictPhp\HttpClients\Entities\AbstractConfig;

/**
 * parameters of constructor must have to filled default values  
 */
class Config extends AbstractConfig 
{
    public function __construct(
        private readonly int $optionA = 1,
        private readonly int int $optionB = 2,
    ) {
    }    

    public function initFromDefaultConfig(ConfigInterface $object): void 
    {
        // if you want to pass an object reference from the default configuration
        /** @see \StrictPhp\HttpClients\Clients\CacheResponse\CacheResponseConfig */
        
        // or empty
        /** @see \StrictPhp\HttpClients\Clients\Sleep\SleepConfig */
    }
    
}

客户端

namespace My;

use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use StrictPhp\HttpClients\Managers\ConfigManager;
use My\Config;

class MyClient implements ClientInterface 
{
    public function __construct(
        private ClientInterface $client,
        private ConfigManager $configManager,
    ) {
    }    


    public function sendRequest(RequestInterface $request): ResponseInterface
    {
        $host = $request->getUri()->getHost();
        $config = $this->configManager->get(Config::class, $host);
        $config->optionA;
        $config->optionB;
        
        // do anything
        $response = $this->client->sendRequest($request)
        // do anything
        
        return $response;
    }
    
}

客户端工厂

namespace My;

use StrictPhp\HttpClients\Contracts\ClientFactoryContract;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use My\Config;

class ClientFactory implements ClientFactoryContract 
{
    public function __construct(
        private ConfigManager $configManager,
    ) {
    } 
    
    public function create(ClientInterface $client): ClientInterface
    {
        return new MyClient($client, $this->configManager);
    }
    
}