Guzzle e PSR-7

Guzzle utiliza a PSR-7 como interface de mensagem HTTP. Isto permite ao Guzzle trabalhar com qualquer outra biblioteca que utilize as interfaces de mensagens PSR-7.

Guzzle é um cliente HTTP que envia pedidos HTTP para um servidor e recebe respostas HTTP. Tanto os pedidos como as respostas são referidos como mensagens.

Guzzle confia no guzzlehttp/psr7 Composer package for its message implementation of PSR-7.

Pode criar um pedido usando a classe GuzzleHttp\Psr7\Request class:

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);

Pode criar uma resposta usando a classe GuzzleHttp\Psr7\Response class:

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);

Headers

Tanto as mensagens de pedido como as de resposta contêm cabeçalhos HTTP.

Accessing Headers

Pode verificar se um pedido ou resposta tem um cabeçalho específico usando o método hasHeader().

use GuzzleHttp\Psr7;

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

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

Pode recuperar todos os valores do cabeçalho como um conjunto de cordas usando getHeader().

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

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

Pode iterar sobre os cabeçalhos de uma mensagem usando o método getHeaders().

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

Cabeçalhos complexos

Alguns cabeçalhos contêm informação adicional sobre o par de valores chave. Por exemplo, os cabeçalhos de ligação contêm uma ligação e vários pares de valores chave:

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

Guzzle fornece uma característica de conveniência que pode ser usada para analisar este tipo de cabeçalhos:

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);

Vai sair:

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

O resultado contém um haxixe de pares de valores chave. Valores de cabeçalho que não têm chave (ou seja, a ligação) são indexados numericamente enquanto os cabeçalhos formam uma chave são adicionados como um par de valores chave.

Body

Tanto as mensagens de pedido como as de resposta podem conter um corpo.

Pode recuperar o corpo de uma mensagem usando o método getBody():

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

O corpo utilizado nos objectos de pedido e resposta é um Psr\Http\Message\StreamInterface. Este fluxo é utilizado para ambos carregamento de dados e descarregamento de dados. O Guzzle irá, por defeito, armazenar o corpo de uma mensagem num fluxo que utiliza fluxos de temperatura PHP. Quando o tamanho do corpo exceder 2 MB, o fluxo mudará automaticamente para o armazenamento de dados em disco em vez de na memória (protegendo a sua aplicação do esgotamento da memória).

A maneira mais fácil de criar um corpo para uma mensagem é usando o streamFor método da classe GuzzleHttp\Psr7\Utils class -- Utils::streamFor. Este método aceita cordas, recursos, chamadas, iteradores, outras transmissões, e devolve uma instância de Psr\Http\Message\StreamInterface.

O corpo de um pedido ou resposta pode ser lançado a uma corda ou pode ler e escrever bytes fora do fluxo, conforme necessário.

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());

Pedidos

Os pedidos são enviados por um cliente para um servidor. Os pedidos incluem o método para ser aplicado a um recurso, o identificador do recurso, e o protocolo versão a utilizar.

Request Methods

Ao criar um pedido, espera-se que forneça o método HTTP que deseja para actuar. Pode especificar qualquer método que deseje, incluindo um método personalizado que pode não fazer parte do RFC 7231 (como "MOVE").

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

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

Pode criar e enviar um pedido utilizando métodos num cliente que mapeie para o método HTTP que deseja utilizar.

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 **/])
OPÇÕES
$client->options('http://httpbin.org/get', [/** options **/])
PATCH
$client->patch('http://httpbin.org/put', [/** options **/])

Por exemplo:

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

Request URI

O pedido URI é representado por um objecto Psr\Http\Message\UriInterface object. Guzzle fornece uma implementação desta interface usando o objecto GuzzleHttp\Psr7\Uri class.

Ao criar um pedido, pode fornecer o URI como uma string ou uma instância de Psr\Http\Message\UriInterface.

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

Scheme

O esquema de um pedido especifica o protocolo a utilizar ao enviar o pedido. Ao utilizar o Guzzle, o pode ser definido para "http" ou "https".

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

Host

O anfitrião é acessível utilizando o URI de propriedade do pedido ou acedendo ao cabeçalho do anfitrião.

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

Port

Não é necessário porto quando se utilizam os esquemas "http" ou "https".

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

Path

O caminho de um pedido é acessível através do objecto URI.

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

O conteúdo do caminho será automaticamente filtrado para garantir que apenas os caracteres permitidos estão presentes no caminho. Quaisquer caracteres que não sejam permitidos no caminho será codificado em percentagem de acordo com RFC 3986 section 3.3

Query string

A cadeia de consulta de um pedido pode ser acedida usando a getQuery() do objecto URI propriedade do pedido.

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

O conteúdo da cadeia de consulta será automaticamente filtrado para garantir que só os caracteres permitidos estão presentes na cadeia de consulta. Quaisquer caracteres que não são permitidos na cadeia de consulta serão codificados por percentagem de acordo com RFC 3986 section 3.4

Responses

As respostas são as mensagens HTTP que um cliente recebe de um servidor depois de enviar uma mensagem de pedido HTTP.

Start-Line

A linha de partida de uma resposta contém o protocolo e a versão do protocolo, o código de estado e a frase do motivo.

$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

Como descrito anteriormente, pode-se obter o corpo de uma resposta usando o método getBody().

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

Streams

Guzzle utiliza objectos do fluxo PSR-7 para representar a mensagem de pedido e resposta corpos. Estes objectos de fluxo permitem-lhe trabalhar com vários tipos de dados, todos utilizando uma interface comum.

As mensagens HTTP consistem de uma linha de partida, cabeçalhos, e um corpo. O corpo de um HTTP A mensagem pode ser muito pequena ou extremamente grande. Tentativa de representar o corpo de uma mensagem como um fio pode facilmente consumir mais memória do que a pretendida porque o corpo deve ser armazenado completamente na memória. Tentativa de armazenar o corpo de um pedido ou resposta em memória impediria a utilização dessa implementação de ser capaz de trabalhar com grandes corpos de mensagens. A StreamInterface é utilizada em ordem para ocultar os detalhes de implementação de onde um fluxo de dados é lido ou escrito para.

A PSR-7 Psr\Http\Message\StreamInterface expõe vários métodos que permitem a leitura, a escrita e a travessia de fluxos eficazmente.

Os fluxos expõem as suas capacidades usando três métodos: isReadable(), isWritable(), e isSeekable(). Estes métodos podem ser utilizados por stream colaboradores para determinar se um fluxo é capaz de satisfazer as suas necessidades.

Cada instância de fluxo tem várias capacidades: podem ser apenas de leitura, apenas escrita, leitura-escrita, permitir o acesso arbitrário aleatório (procurando para trás para qualquer local), ou permitir apenas o acesso sequencial (por exemplo, no caso de uma tomada ou tubo).

Guzzle usa o pacote guzzlehttp/psr7 para fornecer suporte de fluxo. Mais informação sobre a utilização de fluxos, criação de fluxos, conversão de fluxos para PHP recurso de fluxo, e decoradores de fluxo podem ser encontrados no Guzzle PSR-7 documentation.

Creating Streams

A melhor maneira de criar um fluxo é usando o GuzzleHttp\Psr7\Utils::streamFor método. Este método aceita strings, recursos devolvidos de fopen(), um objecto que implementa __toString(), iteradores, chamadas, e instâncias de 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

É possível criar correntes a partir de iteradores. O iterador pode render qualquer número de bytes por iteração. Qualquer excesso de bytes devolvidos pelo iterador que não tenham sido solicitado por um consumidor do fluxo será tamponado até uma leitura posterior.

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); // ...

Metadados

Os fluxos expõem metadados do fluxo através do método getMetadata(). Este fornece os dados que recuperaria quando chamasse PHP's stream_get_meta_data() function, e, opcionalmente, pode expor outros dados personalizados.

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

Stream Decorators

Adicionar funcionalidade personalizada aos fluxos é muito simples com decoradores de fluxos. O Guzzle fornece vários decoradores incorporados que fornecem fluxo adicional funcionalidade.