04 - Guzzle и PSR-7
Guzzle использует PSR-7 в качестве интерфейса HTTP сообщений. Это позволяет Guzzleработать с любой другой библиотекой, которая использует PSR-7 сообщений интерфейсов.
Guzzle является HTTP-клиентом, который отправляет HTTP-запросы к серверу и получает ответы HTTP. Оба запросы и ответы называются сообщениями.
Guzzle опирается на Composer пакет guzzlehttp/psr7
для его реализации сообщения PSR-7.
Вы можете создать запрос с помощью класса GuzzleHttp\Psr7\Request
:
use GuzzleHttp\Psr7\Request; $request = new Request('GET', 'http://httpbin.org/get'); // Вы можете предоставить другие необязательные аргументы конструктора.. $headers = ['X-Foo' => 'Bar']; $body = 'hello!'; $request = new Request('PUT', 'http://httpbin.org/put', $headers, $body);
Вы можете создать ответ, используя класс GuzzleHttp\Psr7\Response
:
use GuzzleHttp\Psr7\Response; // Конструктор не требует никаких аргументов. $response = new Response(); echo $response->getStatusCode(); // 200 echo $response->getProtocolVersion(); // 1.1 // Вы можете поставить любое количество дополнительных аргументов. $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'] // Получение отсутствующий заголовок возвращает пустой массив. $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\parse_header($request->getHeader('Link')); var_export($parsed);
Выведет:
array ( 0 => array ( 0 => '<http:/.../front.jpeg>', 'rel' => 'front', 'type' => 'image/jpeg', ), )
Результат содержит хэш пар ключ-значение. значения заголовков, которые не имеют ключа (например, ссылка) индексируются численно в то время как заголовки частей, которые образуют пару ключей значение добавляется в качестве ключевой пары значений.
Тело
Оба сообщения запроса и ответа могут содержать тело.
Вы можете получить тело сообщения, используя методgetBody()
:
$response = GuzzleHttp\get('http://httpbin.org/get'); echo $response->getBody(); // JSON string: { ... }
Тело используемое в объектах запроса и ответа является Psr\Http\Message\StreamInterface
.Этот поток используется как для загрузки и выгрузки данных. Guzzleбудет, по умолчанию, сохранить тело сообщения в потоке, который использует PHP временные потоки. Когда размер тела превышает 2 МБ, поток будет автоматически переключаться на хранение данных на диске, а не в памяти (защита приложения от истощения памяти).
Самый простой способ создать тело для сообщения использует stream_for
функцию из пространства имен GuzzleHttp\Psr7
-- GuzzleHttp\Psr7\stream_for
. Эта функция принимает строки, ресурсы, вызываемых объектов итераторы, другие потоковые объекты, и возвращает экземпляр 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").
// Создать запрос, используя полностью настраиваемой метод HTTP $request = new \GuzzleHttp\Psr7\Request('MOVE', 'http://httpbin.org/move'); echo $request->getMethod(); // MOVE
Вы можете создать и отправить запрос, с использованием методов клиента, которые сопоставляются методам HTTP, который вы хотите использовать.
- GET
$client->get('http://httpbin.org/get', [/** options **/])
- POST
$client->post('http://httpbin.org/post', [/** options **/])
- HEAD
$client->head('http://httpbin.org/get', [/** options **/])
- PUT
$client->put('http://httpbin.org/put', [/** options **/])
- DELETE
$client->delete('http://httpbin.org/delete', [/** options **/])
- 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/get
Хост
Хост доступен с использованием URI, принадлежащий запросу или путем доступа к заголовка хоста.
$request = new Request('GET', 'http://httpbin.org'); echo $request->getUri()->getHost(); // httpbin.org echo $request->getHeader('Host'); // httpbin.org
Порт
Ни один порт не требуется при использовании "HTTP" или "HTTPS" схемы.
$request = $client->createRequest('GET', 'http://httpbin.org:8080'); echo $request->getUri()->getPort(); // 8080 echo $request->getUri(); // http://httpbin.org:8080
Путь
Путь запроса доступен через объект 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.
Начальная линия
Начальная линия ответа содержит протокол и версию протокола, код состояния и сообщение состояния.
$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
Тело
Как было описано ранее, вы можете получить тело ответа с использованием метода getBody()
.
$body = $response->getBody()) { echo $body; // Приведение к строке: { ... } $body->seek(0); // Перемотать тело $body->read(1024); // Прочитать байты из тела
Потоки
Guzzle использует объекты потока PSR-7 для представления запроса и тела ответного сообщения. Эти объекты потока позволяют работать с различными типами любых данных, используя общий интерфейс.
HTTP сообщения состоят из начальной строки, заголовков и тела. Тело HTTP сообщения может быть очень маленьким или очень большим. Attempting to represent the body of a message as a string can easily consume more memory than intended because the body must be stored completely in memory. Попытка представить тело сообщения в виде строки может легко потреблять больше памяти, чем предполагалось, потому что тело должно быть полностью хранится в памяти. Попытка сохранить тело запроса или ответа в памяти исключает использование этой реализации от возможности работать с большими телами сообщений. Интерфейс потока используется для того, чтобы скрыть детали реализации, где поток данных считывается или записывается.
PSR-7 Psr\Http\Message\StreamInterface
предоставляет несколько методов, которые позволяют читать, записывать, и эффективно перемещать потоки.
Потоговые объекты демонстрируют свои возможности, используя три метода: isReadable()
, isWritable()
и isSeekable()
. Эти методы могут быть использованы пользователями потоковыми, чтобы определить, удволетворяет ли поток их требованиям.
Каждый экземпляр потока имеет различные возможности: они могут быть только для чтения, только для записи, чтения и записи, позволяют произвольный доступ (поиск вперед или назад в любое место), или разрешить только последовательный доступ (например, в случае socket или pipe).
Guzzle использует guzzlehttp/psr7
пакет для оказания поддержки потока. Более подробную информацию об использовании потоков, создавая потоки, преобразования потоков в PHP поток ресурсов, и декораторов потоков могут быть найдены в Guzzle PSR-7 documentation.
Создание потоков
Лучший способ для создания потока использует функцию GuzzleHttp\Psr7\stream_for
. Эта функция принимает потоки, ресурсы, возвращенные из fopen()
, объект, который реализует __toString()
,итераторы, вызываемых объектов, и экземпляры Psr\Http\Message\StreamInterface
.
use GuzzleHttp\Psr7; $stream = Psr7\stream_for('string data'); echo $stream; // строковые данные 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\stream_for($iter); echo $stream->read(3); // ...
Метаданные
Потоковый объект выставит метаданные потока с помощью метода getMetadata()
method. Этот метод выдает данные, которые вы бы при вызове извлечения PHP функции stream_get_meta_data(), и опционально может выставить другие пользовательские данные.
use GuzzleHttp\Psr7; $resource = fopen('/path/to/file', 'r'); $stream = Psr7\stream_for($resource); echo $stream->getMetadata('uri'); // /path/to/file var_export($stream->isReadable()); // true var_export($stream->isWritable()); // false var_export($stream->isSeekable()); // true
Декораторы потоков
Добавление пользовательских функций для потоков очень просто с потоковыми декораторов. Guzzle предоставляет несколько встроенных декораторов, которые обеспечивают дополнительные функциональные возможности потока.