Guzzle и PSR-7

Guzzle использует PSR-7 в качестве интерфейса сообщений HTTP. Это позволяет Guzzle работать с любой другой библиотекой, использующей интерфейс сообщений PSR-7.

Guzzle - это HTTP-клиент, который отправляет HTTP-запросы на сервер и получает HTTP-ответы. И запросы, и ответы называются сообщениями.

Guzzle полагается на пакет guzzlehttp/psr7 Composer для реализации сообщений PSR-7.

Вы можете создать запрос, используя класс GuzzleHttp\Psr7\Request:

use GuzzleHttp\Psr7\Request;

$request = new Request('GET', 'http://httpbin.org/get');

// You can provide other optional constructor arguments.
$headers = ['X-Foo' => 'Bar'];
$body = 'hello!';
$request = new Request('PUT', 'http://httpbin.org/put', $headers, $body);

Вы можете создать ответ, используя класс GuzzleHttp\Psr7\Response:

use GuzzleHttp\Psr7\Response;

// The constructor requires no arguments.
$response = new Response();
echo $response->getStatusCode(); // 200
echo $response->getProtocolVersion(); // 1.1

// You can supply any number of optional arguments.
$status = 200;
$headers = ['X-Foo' => 'Bar'];
$body = 'hello!';
$protocol = '1.1';
$response = new Response($status, $headers, $body, $protocol);

Заголовки

Сообщения запроса и ответа содержат HTTP-заголовки.

Доступ к заголовкам

Вы можете проверить, имеет ли запрос или ответ определенный заголовок, используя метод hasHeader().

use GuzzleHttp\Psr7;

$request = new Psr7\Request('GET', '/', ['X-Foo' => 'bar']);

if ($request->hasHeader('X-Foo')) {
    echo 'It is there';
}

Вы можете получить все значения заголовков как массив строк, используя getHeader().

$request->getHeader('X-Foo'); // ['bar']

// Retrieving a missing header returns an empty array.
$request->getHeader('X-Bar'); // []

Вы можете перебирать заголовки сообщения, используя метод getHeaders().

foreach ($request->getHeaders() as $name => $values) {
    echo $name . ': ' . implode(', ', $values) . "\r\n";
}

Сложные заголовки

Некоторые заголовки содержат дополнительную информацию о парах ключ-значение. Например, заголовки Link содержат ссылку и несколько пар ключ-значение:

<http://foo.com>; rel="thing"; type="image/jpeg"

Guzzle предоставляет удобную функцию, которую можно использовать для разбора этих типов заголовков:

use GuzzleHttp\Psr7;

$request = new Psr7\Request('GET', '/', [
    'Link' => '<http:/.../front.jpeg>; rel="front"; type="image/jpeg"'
]);

$parsed = Psr7\Header::parse($request->getHeader('Link'));
var_export($parsed);

Будет выводить:

array (
  0 =>
  array (
    0 => '<http:/.../front.jpeg>',
    'rel' => 'front',
    'type' => 'image/jpeg',
  ),
)

Результат содержит хэш пар ключ-значение. Значения заголовков, которые не имеют ключа (т.е. ссылка) индексируются численно, в то время как части заголовков, образующие пару ключ-значение добавляются как пара ключ-значение.

Body

Сообщения запроса и ответа могут содержать тело.

Вы можете получить тело сообщения с помощью метода getBody():

$response = GuzzleHttp\get('http://httpbin.org/get');
echo $response->getBody();
// JSON string: { ... }

Тело, используемое в объектах запроса и ответа, представляет собой Psr\Http\Message\StreamInterface. Этот поток используется как для загрузки данных и выгрузки данных. По умолчанию Guzzle будет хранить тело сообщения в потоке, который использует временные потоки PHP. Когда размер тела сообщения превысит 2 МБ, поток автоматически переключится на хранение данных на диске а не в памяти (защищая ваше приложение от истощения памяти).

Самый простой способ создать тело сообщения - это использовать streamFor из класса GuzzleHttp\Psr7\Utils. Utils::streamFor. Этот метод принимает строки, ресурсы, callables, итераторы, другие streamables, и возвращает экземпляр Psr\Http\Message\StreamInterface.

Тело запроса или ответа может быть приведено к строке, или вы можете читать и записывать байты из потока по мере необходимости.

use GuzzleHttp\Stream\Stream;
$response = $client->request('GET', 'http://httpbin.org/get');

echo $response->getBody()->read(4);
echo $response->getBody()->read(4);
echo $response->getBody()->read(1024);
var_export($response->eof());

Запросы

Запросы отправляются от клиента к серверу. Запросы включают метод, который для применения к ресурсу, идентификатор ресурса и версию протокола. версию протокола для использования.

Методы запроса

При создании запроса вы должны указать метод HTTP, который вы хотите для выполнения запроса. Вы можете указать любой метод, включая пользовательский метод который может не входить в RFC 7231 (например, "MOVE").

// Create a request using a completely custom HTTP method
$request = new \GuzzleHttp\Psr7\Request('MOVE', 'http://httpbin.org/move');

echo $request->getMethod();
// MOVE

Вы можете создать и отправить запрос, используя методы на клиенте, которые соответствуют методу HTTP, который вы хотите использовать.

ПОЛУЧИТЬ
$client->get('http://httpbin.org/get', [/** options **/]).
ПОСТ
$client->post('http://httpbin.org/post', [/** options **/]).
ГЛАВНОЕ
$client->head('http://httpbin.org/get', [/** options **/]).
PUT
$client->put('http://httpbin.org/put', [/** options **/]).
УДАЛИТЬ
$client->delete('http://httpbin.org/delete', [/** options **/]).
ВАРИАНТЫ
$client->options('http://httpbin.org/get', [/** options **/]).
PATCH
$client->patch('http://httpbin.org/put', [/** options **/]).

Например:

$response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);

URI запроса

URI запроса представлен объектом Psr\Http\Message\UriInterface. Guzzle предоставляет реализацию этого интерфейса, используя объект GuzzleHttp\Psr7\Uri класса.

При создании запроса вы можете предоставить URI в виде строки или экземпляра Psr\Http\Message\UriInterface.

$response = $client->request('GET', 'http://httpbin.org/get?q=foo');

Схема

схема запроса определяет протокол, который будет использоваться при отправке запроса. При использовании Guzzle схема может быть установлена на "http" или "https".

$request = new Request('GET', 'http://httpbin.org');
echo $request->getUri()->getScheme(); // http
echo $request->getUri(); // http://httpbin.org

Host

Хост доступен с помощью URI, принадлежащего запросу, или путем доступа к заголовку Host.

$request = new Request('GET', 'http://httpbin.org');
echo $request->getUri()->getHost(); // httpbin.org
echo $request->getHeader('Host'); // httpbin.org

Порт

При использовании схем "http" или "https" порт не требуется.

$request = new Request('GET', 'http://httpbin.org:8080');
echo $request->getUri()->getPort(); // 8080
echo $request->getUri(); // http://httpbin.org:8080

Path

Путь запроса доступен через объект URI.

$request = new Request('GET', 'http://httpbin.org/get');
echo $request->getUri()->getPath(); // /get

Содержимое пути будет автоматически отфильтровано, чтобы убедиться, что только в пути присутствуют только разрешенные символы. Любые недопустимые символы в пути, будут закодированы в процентах в соответствии с RFC 3986 section 3.3

Строка запроса

Строку запроса можно получить с помощью getQuery() объекта URI, принадлежащего запросу.

$request = new Request('GET', 'http://httpbin.org/?foo=bar');
echo $request->getUri()->getQuery(); // foo=bar

Содержимое строки запроса будет автоматически отфильтровано, чтобы убедиться, что в строке запроса присутствовали только разрешенные символы. Любые символы, которые не разрешены в строке запроса, будут закодированы в процентах в соответствии с RFC 3986 section 3.4

Ответы

Ответы - это HTTP-сообщения, которые клиент получает от сервера после отправки сообщения HTTP-запроса.

Start-Line

Начальная строка ответа содержит протокол и версию протокола, код состояния и фразу причины.

$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'http://httpbin.org/get');

echo $response->getStatusCode(); // 200
echo $response->getReasonPhrase(); // OK
echo $response->getProtocolVersion(); // 1.1

Body

Как было описано ранее, вы можете получить тело ответа с помощью метода getBody().

$body = $response->getBody();
echo $body;
// Cast to a string: { ... }
$body->seek(0);
// Rewind the body
$body->read(1024);
// Read bytes of the body

Потоки

Guzzle использует объекты потока PSR-7 для представления сообщений запроса и ответа тела. Эти потоковые объекты позволяют работать с различными типами данных, используя общий интерфейс. используя общий интерфейс.

HTTP-сообщения состоят из начальной строки, заголовков и тела. Тело HTTP может быть очень маленьким или очень большим. Попытка представить тело сообщения в виде строки может занять больше памяти, чем предполагалось, поскольку тело должно быть полностью сохранено в памяти. Попытка сохранить тело запроса или ответа в памяти исключает возможность использования этой реализации для работы с большими телами сообщений. для работы с большими телами сообщений. Интерфейс StreamInterface используется для того, чтобы для того, чтобы скрыть детали реализации того, откуда считывается поток данных или записывается в него.

PSR-7 Psr\Http\Message\StreamInterface раскрывает несколько методов, которые позволяют эффективно читать, записывать и обходить потоки.

Потоки раскрывают свои возможности с помощью трех методов: isReadable(), isWritable(), и isSeekable(). Эти методы могут быть использованы для определения того, способен ли поток удовлетворять их требованиям.

Каждый экземпляр потока имеет различные возможности: они могут быть только для чтения, только для записи, для чтения и записи, допускать произвольный произвольный доступ (поиск вперед или назад к любому месту), или только последовательный доступ (например, в случае случае сокета или трубы).

Guzzle использует пакет guzzlehttp/psr7 для обеспечения поддержки потоков. Подробнее информацию об использовании потоков, создании потоков, преобразовании потоков в PHP о ресурсах потоков и декораторах потоков можно найти в разделе документации Guzzle PSR-7.

Создание потоков

Лучший способ создать поток - использовать GuzzleHttp\Psr7\Utils::streamFor метод. Этот метод принимает строки, ресурсы, возвращаемые из fopen(), объект, реализующий __toString(), итераторы, callables, и экземпляры Psr\Http\Message\StreamInterface.

use GuzzleHttp\Psr7;

$stream = Psr7\Utils::streamFor('string data');
echo $stream;
// string data
echo $stream->read(3);
// str
echo $stream->getContents();
// ing data
var_export($stream->eof());
// true
var_export($stream->tell());
// 11

Вы можете создавать потоки из итераторов. Итератор может выдавать любое количество байтов за итерацию. Любые избыточные байты, возвращенные итератором, которые не были запрошены потребителем потока, будут буферизованы до следующего чтения.

use GuzzleHttp\Psr7;

$generator = function ($bytes) {
    for ($i = 0; $i < $bytes; $i++) {
        yield '.';
    }
};

$iter = $generator(1024);
$stream = Psr7\Utils::streamFor($iter);
echo $stream->read(3); // ...

Метаданные

Потоки предоставляют метаданные потока через метод getMetadata(). Этот метод предоставляет данные, которые вы могли бы получить при вызове функции PHP stream_get_meta_data() function, и, по желанию, может предоставлять другие пользовательские данные.

use GuzzleHttp\Psr7;

$resource = Psr7\Utils::tryFopen('/path/to/file', 'r');
$stream = Psr7\Utils::streamFor($resource);
echo $stream->getMetadata('uri');
// /path/to/file
var_export($stream->isReadable());
// true
var_export($stream->isWritable());
// false
var_export($stream->isSeekable());
// true

Декораторы потоков

Добавление пользовательской функциональности в потоки очень просто с помощью декораторов потоков. Guzzle предоставляет несколько встроенных декораторов, которые обеспечивают дополнительную функциональность потоков функциональность.