http-interop/http-factory-discovery

用于定位可用的 HTTP 工厂实现

1.6.0 2023-11-06 13:40 UTC

This package is auto-updated.

Last update: 2024-09-06 15:23:27 UTC


README

Latest Stable Version License Build Status Code Coverage Scrutinizer Code Quality

自动发现提供 HTTP 功能的实现。允许在最小的工作量下快速切换不同的实现。

支持自动发现 HTTP 工厂HTTP 客户端

默认情况下,可以发现以下实现

HTTP 工厂

HTTP 客户端

可以注册其他额外的实现

安装

composer require http-interop/http-factory-discovery

使用方法

HTTP 工厂

use Http\Factory\Discovery\HttpFactory;

/** @var \Psr\Http\Message\RequestFactoryInterface */
$requestFactory = HttpFactory::requestFactory();

/** @var \Psr\Http\Message\ResponseFactoryInterface */
$responseFactory = HttpFactory::responseFactory();

/** @var \Psr\Http\Message\ServerRequestFactoryInterface */
$serverRequestFactory = HttpFactory::serverRequestFactory();

/** @var \Psr\Http\Message\StreamFactoryInterface */
$streamFactory = HttpFactory::streamFactory();

/** @var \Psr\Http\Message\UriFactoryInterface */
$uriFactory = HttpFactory::uriFactory();

/** @var \Psr\Http\Message\UploadedFileFactoryInterface */
$uploadedFileFactory = HttpFactory::uploadedFileFactory();

HTTP 客户端

use Http\Factory\Discovery\HttpClient;

/** @var \Psr\Http\Client\ClientInterface */
$client = HttpClient::client();

最佳实践

因为此包充当 服务定位器,因此应将其用于补充 依赖注入

HTTP 工厂

使用 HTTP 工厂的示例之一是编写 PSR-15 中间件

namespace Acme\Middleware;

use Http\Factory\Discovery\HttpFactory;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as Handler;

class CatchErrors extends MiddlewareInterface
{
    /** @var ResponseFactoryInterface */
    private $responseFactory;

    /** @var StreamFactoryInterface */
    private $streamFactory;

    public function __construct(
        ResponseFactoryInterface $responseFactory = null,
        StreamFactoryInterface $streamFactory = null
    ) {
        $this->responseFactory = $responseFactory ?? HttpFactory::responseFactory();
        $this->streamFactory = $streamFactory ?? HttpFactory::streamFactory();
    }

    public function process(Request $request, Handler $handler): Response
    {
        try {
            return $handler->handle($request);
        } catch (\Throwable $error) {
            $stream = $this->streamFactory->createStream($e->getMessage());

            $response = $this->responseFactory->createResponse(500);
            $response = $response->withHeader('content-type', 'text/plain');
            $response = $response->withBody($stream);

            return $response;
        }
    }
}

HTTP 客户端

同时使用 HTTP 客户端和 HTTP 工厂的示例是编写发送 HTTP 请求的功能。

namespace Acme;

use Http\Factory\Discovery\HttpClient;
use Http\Factory\Discovery\HttpFactory;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;

class Api
{
    /** @var ClientInterface */
    private $client;

    /** @var RequestFactoryInterface */
    private $requestFactory;

    public function __construct(
        ClientInterface $client = null,
        RequestFactoryInterface $requestFactory = null
    ) {
        $this->client = $client ?? HttpClient::client();
        $this->requestFactory = $requestFactory ?? HttpFactory::requestFactory();
    }

    public function query(): string
    {
        $request = $this->requestFactory->createRequest('GET', 'http://acme.com/api');

        return $this->client->sendRequest($request)->getBody()->getContents();
    }
}

注册额外的实现

可以注册额外的实现

HTTP 工厂

use Acme\RequestFactory;
use Http\Factory\Discovery\FactoryLocator;
use Psr\Http\Message\RequestFactoryInterface;

FactoryLocator::register(RequestFactoryInterface::class, RequestFactory::class);

HTTP 客户端

use Acme\Client;
use Http\Factory\Discovery\ClientLocator;
use Psr\Http\Client\ClientInterface;

ClientLocator::register(ClientInterface::class, Client::class);

如果不想使用它们,也可以取消注册实现

HTTP 工厂

use Http\Factory\Discovery\FactoryLocator;
use Http\Factory\Guzzle\UriFactory;
use Psr\Http\Message\UriFactoryInterface;

FactoryLocator::unregister(UriFactoryInterface::class, UriFactory::class);

HTTP 客户端

use Http\Factory\Discovery\ClientLocator;
use Http\Adapter\Guzzle6\Client;
use Psr\Http\Client\ClientInterface;

ClientLocator::unregister(ClientInterface::class, Client::class);

清除缓存

可以清除已发现实现的缓存

HTTP 工厂

use Http\Factory\Discovery\HttpFactory;
use Psr\Http\Message\UriFactoryInterface;

// Clear a single interface
HttpFactory::clearCache(UriFactoryInterface::class);

// Clear all interfaces
HttpFactory::clearCache();

HTTP 客户端

use Http\Factory\Discovery\HttpClient;
use Psr\Http\Client\ClientInterface;

// Clear a single interface
HttpClient::clearCache(ClientInterface::class);

// Clear all interfaces
HttpClient::clearCache();

注意:当调用 FactoryLocator::unregister()ClientLocator::unregister() 时,会自动清除缓存。