Skip to content

HTTP-клиент

В этом документе описывается общий интерфейс для отправки HTTP-запросов и получения HTTP-ответов.

Ключевые слова «ДОЛЖЕН», «НЕ ДОЛЖЕН», «ТРЕБУЕТСЯ», «ДОЛЖЕН», «НЕ ДОЛЖЕН», «СЛЕДУЕТ», «НЕ ДОЛЖЕН», «РЕКОМЕНДУЕТСЯ», «МОЖЕТ» и «ДОПОЛНИТЕЛЬНО» в этом документе: интерпретировать, как описано в RFC 2119.

Цель

Цель этого PSR — позволить разработчикам создавать библиотеки, отделенные от реализаций HTTP-клиентов. Это сделает библиотеки более пригодными для повторного использования, поскольку уменьшит количество зависимостей и снизит вероятность конфликтов версий.

Вторая цель состоит в том, чтобы HTTP-клиенты могли быть заменены в соответствии с Принцип подстановки Лисков. Это означает, что все клиенты ДОЛЖНЫ вести себя одинаково при отправке запроса.

Определения

  • Клиент — Клиент — это библиотека, которая реализует эту спецификацию для отправки сообщений HTTP-запроса, совместимого с PSR-7, и возврата ответного сообщения HTTP, совместимого с PSR-7, в вызывающую библиотеку.
  • Библиотека вызовов. Библиотека вызовов — это любой код, использующий Клиент. Он не реализует интерфейсы этой спецификации, но использует объект, который их реализует (Клиент).

Клиент

Клиент — это объект, реализующий ClientInterface.

Клиент МОЖЕТ:

  • Выбирать отправку измененного HTTP-запроса по сравнению с тем, который был предоставлен. Например, он может сжимать тело исходящего сообщения.
  • Выбирать изменение полученного HTTP-ответа перед его возвратом в вызывающую библиотеку. Например, он может распаковать тело входящего сообщения.

Если Клиент решает изменить либо HTTP-запрос, либо HTTP-ответ, он ДОЛЖЕН гарантировать, что объект остается внутренне согласованным. Например, если Клиент решает распаковать тело сообщения, он ДОЛЖЕН также удалить заголовок «Content-Encoding» и настроить заголовок «Content-Length».

Обратите внимание, что в результате, поскольку объекты PSR-7 неизменяемы, Вызывающая библиотека НЕ ДОЛЖНА предполагать, что объект, переданный в ClientInterface::sendRequest(), будет тем же самым объектом PHP, который фактически отправлен. Например, объект Request, возвращаемый исключением, МОЖЕТ быть другим объектом, чем тот, который был передан в sendRequest(), поэтому сравнение по ссылке (===) невозможно.

Клиент ДОЛЖЕН:

  • Собрать заново многоэтапный ответ HTTP 1xx, чтобы в библиотеку вызовов возвращался действительный ответ HTTP с кодом состояния 200 или выше.

Обработка ошибок

Клиент НЕ ДОЛЖЕН рассматривать правильно сформированный HTTP-запрос или HTTP-ответ как состояние ошибки. Например, коды состояния ответа в диапазоне 400 и 500 НЕ ДОЛЖНЫ вызывать исключение и ДОЛЖНЫ быть возвращены в вызывающую библиотеку как обычно.

Клиент ДОЛЖЕН генерировать экземпляр Psr\Http\Client\ClientExceptionInterface тогда и только тогда, когда он вообще не может отправить HTTP-запрос или если ответ HTTP не может быть преобразован в объект ответа PSR-7.

Если запрос не может быть отправлен, потому что сообщение запроса не является правильно сформированным HTTP-запросом или в нем отсутствует какая-либо важная часть информации (например, хост или метод), клиент ДОЛЖЕН выдать экземпляр Psr\Http\Client\RequestExceptionInterface.

Если запрос не может быть отправлен из-за какого-либо сбоя сети, включая тайм-аут, Клиент ДОЛЖЕН создать экземпляр Psr\Http\Client\NetworkExceptionInterface.

Клиенты МОГУТ генерировать более конкретные исключения, чем определенные здесь (например, TimeOutException или HostNotFoundException), при условии, что они реализуют соответствующий интерфейс, определенный выше.

Интерфейсы

ClientInterface

namespace Psr\Http\Client;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

interface ClientInterface
{
    /**
     * Отправляет запрос PSR-7 и возвращает ответ PSR-7.
     *
     * @param RequestInterface $request
     *
     * @return ResponseInterface
     *
     * @throws \Psr\Http\Client\ClientExceptionInterface Если при обработке запроса произошла ошибка.
     */
    public function sendRequest(RequestInterface $request): ResponseInterface;
}

ClientExceptionInterface

namespace Psr\Http\Client;

/**
 * Каждое исключение, связанное с HTTP-клиентом, ДОЛЖНО реализовывать этот интерфейс.
 */
interface ClientExceptionInterface extends \Throwable
{
}

RequestExceptionInterface

namespace Psr\Http\Client;

use Psr\Http\Message\RequestInterface;

/**
 * Исключение для случаев, когда запрос не выполнен.
 *
 * Примеры:
 *      - Запрос недействителен (например, отсутствует метод)
 *      - Ошибки запроса во время выполнения (например, поток тела не доступен для поиска)
 */
interface RequestExceptionInterface extends ClientExceptionInterface
{
    /**
     * Возвращает запрос.
     *
     * Объект запроса МОЖЕТ быть объектом, отличным от объекта, переданного в ClientInterface::sendRequest().
     *
     * @return RequestInterface
     */
    public function getRequest(): RequestInterface;
}

NetworkExceptionInterface

namespace Psr\Http\Client;

use Psr\Http\Message\RequestInterface;

/**
 * Бросается, когда запрос не может быть выполнен из-за проблем с сетью.
 *
 * Объект ответа отсутствует, поскольку это исключение генерируется, когда ответ не получен.
 *
 * Пример: имя целевого хоста не может быть разрешено или соединение не удалось.
 */
interface NetworkExceptionInterface extends ClientExceptionInterface
{
    /**
     * Возвращает запрос.
     *
     * Объект запроса МОЖЕТ быть объектом, отличным от объекта, переданного в ClientInterface::sendRequest().
     *
     * @return RequestInterface
     */
    public function getRequest(): RequestInterface;
}