Guzzle e PSR-7

Guzzle utilizza PSR-7 come interfaccia dei messaggi HTTP. Questo permette a Guzzle di lavorare con qualsiasi altra libreria che utilizza le interfacce dei messaggi PSR-7.

Guzzle è un client HTTP che invia richieste HTTP a un server e riceve risposte HTTP. Sia le richieste che le risposte sono chiamate messaggi.

Guzzle si basa sul pacchetto guzzlehttp/psr7 Composer per la sua implementazione dei messaggi di PSR-7.

Potete creare una richiesta usando la classe 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);

Potete creare una risposta usando la classe 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);

Intestazioni

Sia i messaggi di richiesta che quelli di risposta contengono intestazioni HTTP.

Accesso alle intestazioni

Puoi controllare se una richiesta o una risposta ha una specifica intestazione usando il metodo hasHeader().

use GuzzleHttp\Psr7;

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

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

Puoi recuperare tutti i valori dell'intestazione come un array di stringhe usando getHeader().

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

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

Puoi iterare le intestazioni di un messaggio usando il metodo getHeaders().

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

Intestazioni complesse

Alcune intestazioni contengono informazioni aggiuntive sulla coppia chiave-valore. Per esempio, le intestazioni Link contengono un link e diverse coppie di valori chiave:

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

Guzzle fornisce una funzione di convenienza che può essere utilizzata per analizzare questi tipi di intestazioni:

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

Uscirà:

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

Il risultato contiene un hash di coppie chiave-valore. I valori di intestazione che non hanno chiave (cioè il collegamento) sono indicizzati numericamente mentre le parti di intestazione che formano una coppia chiave sono aggiunte come coppia chiave-valore.

Body

Sia i messaggi di richiesta che quelli di risposta possono contenere un corpo.

Puoi recuperare il corpo di un messaggio usando il metodo getBody():

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

Il corpo usato negli oggetti richiesta e risposta è un Psr\Http\Message\StreamInterface. Questo flusso è usato sia per l'upload e il download dei dati. Guzzle, per default, memorizza il corpo di un messaggio in uno stream che utilizza gli stream temporanei di PHP. Quando la dimensione del corpo supera i 2 MB, lo stream passerà automaticamente a memorizzare i dati su disco piuttosto che in memoria (proteggendo la vostra applicazione dall'esaurimento della memoria).

Il modo più semplice per creare un corpo per un messaggio è usare il streamFor dalla classe GuzzleHttp\Psr7\Utils. Utils::streamFor. Questo metodo accetta stringhe, risorse, callable, iteratori, altri streamable, e restituisce un'istanza di Psr\Http\Message\StreamInterface.

Il corpo di una richiesta o di una risposta può essere convertito in una stringa o si possono leggere e scrivere byte dal flusso come necessario.

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

Richieste

Le richieste sono inviate da un client a un server. Le richieste includono il metodo da essere applicato ad una risorsa, l'identificatore della risorsa e il protocollo da utilizzare.

Metodi di richiesta

Quando si crea una richiesta, ci si aspetta che si fornisca il metodo HTTP che si desidera da eseguire. Si può specificare qualsiasi metodo che si desidera, incluso un metodo personalizzato che potrebbe non essere parte di RFC 7231 (come "MOVE").

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

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

È possibile creare e inviare una richiesta utilizzando metodi su un client che mappano il metodo HTTP che si desidera utilizzare.

GET
$client->get('http://httpbin.org/get', [/** opzioni **/])
POST
$client->post('http://httpbin.org/post', [/** opzioni **/])
TESTA
$client->head('http://httpbin.org/get', [/** opzioni **/])
PUT
$client->put('http://httpbin.org/put', [/** opzioni **/])
CANCELLARE
$client->delete('http://httpbin.org/delete', [/** opzioni **/])
OPZIONI
$client->options('http://httpbin.org/get', [/** options **/])
PATCH
$client->patch('http://httpbin.org/put', [/** opzioni **/])

Per esempio:

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

Richiesta URI

L'URI di richiesta è rappresentato da un oggetto Psr\Http\Message\UriInterface. Guzzle fornisce un'implementazione di questa interfaccia utilizzando l'oggetto GuzzleHttp\Psr7\Uri classe.

Quando si crea una richiesta, si può fornire l'URI come una stringa o un'istanza di Psr\Http\Message\UriInterface.

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

Schema

Lo schema di una richiesta specifica il protocollo da usare per inviare la richiesta. Quando si usa Guzzle, lo schema può essere impostato a "http" o "https".

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

Host

L'host è accessibile utilizzando l'URI posseduto dalla richiesta o accedendo all'intestazione Host.

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

Port

Nessuna porta è necessaria quando si usa lo schema "http" o "https".

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

Path

Il percorso di una richiesta è accessibile tramite l'oggetto URI.

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

Il contenuto del percorso verrà filtrato automaticamente per assicurare che solo caratteri consentiti siano presenti nel percorso. Qualsiasi carattere che non è permesso nel percorso sarà codificato in percentuale secondo RFC 3986 sezione 3.3

Query string

Si può accedere alla stringa di query di una richiesta usando il getQuery() dell'oggetto URI posseduto dalla richiesta.

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

Il contenuto della stringa della query sarà automaticamente filtrato per assicurare che solo i caratteri consentiti siano presenti nella stringa della query. Qualsiasi carattere che non sono consentiti nella stringa di interrogazione sarà codificato in percentuale secondo RFC 3986 sezione 3.4

Risposte

Le risposte sono i messaggi HTTP che un client riceve da un server dopo aver inviato un messaggio di richiesta HTTP.

Start-Line

La riga iniziale di una risposta contiene il protocollo e la versione del protocollo, il codice di stato e la frase di motivazione.

$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

Come descritto in precedenza, si può ottenere il corpo di una risposta usando il metodo 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 usa oggetti PSR-7 stream per rappresentare i corpi dei messaggi di richiesta e di risposta corpi dei messaggi. Questi oggetti stream vi permettono di lavorare con vari tipi di dati utilizzando un'interfaccia comune.

I messaggi HTTP consistono in una linea iniziale, intestazioni e un corpo. Il corpo di un messaggio HTTP può essere molto piccolo o estremamente grande. Il tentativo di rappresentare il corpo di un messaggio come una stringa può facilmente consumare più memoria del previsto perché il corpo deve essere memorizzato completamente in memoria. Il tentativo di memorizzare il corpo di una richiesta o risposta in memoria precluderebbe l'uso di quell'implementazione essere in grado di lavorare con grandi corpi di messaggi. La StreamInterface è usata per fine di nascondere i dettagli di implementazione di dove un flusso di dati viene letto da o scritto.

Il PSR-7 Psr\Http\Message\StreamInterface espone diversi metodi che permettono di leggere, scrivere e attraversare efficacemente i flussi.

I flussi espongono le loro capacità utilizzando tre metodi: isReadable(), isWritable(), e isSeekable(). Questi metodi possono essere usati dagli stream per determinare se un flusso è in grado di soddisfare i loro requisiti.

Ogni istanza di flusso ha varie capacità: possono essere di sola lettura, solo scrittura, lettura-scrittura, consentire un accesso casuale arbitrario (cercando in avanti o all'indietro verso qualsiasi posizione), o permettere solo l'accesso sequenziale (per esempio nel caso di un socket o di una pipe).

Guzzle usa il pacchetto guzzlehttp/psr7 per fornire il supporto ai flussi. Più informazioni sull'uso dei flussi, sulla creazione di flussi, sulla conversione dei flussi in PHP stream, e i decoratori di stream possono essere trovati nel file Guzzle PSR-7 documentation.

Creare flussi

Il modo migliore per creare uno stream è usare il GuzzleHttp\Psr7\Utils::streamFor . Questo metodo accetta stringhe, risorse restituite da fopen(), un oggetto che implementa __toString(), iteratori, callable e istanze di 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

Potete creare flussi da iteratori. L'iteratore può produrre qualsiasi numero di byte per iterazione. Qualsiasi byte in eccesso restituito dall'iteratore che non sia stato richiesto da un consumatore di stream verrà bufferizzato fino ad una successiva lettura.

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

Metadata

Gli stream espongono i metadati dello stream attraverso il metodo getMetadata(). Questo fornisce i dati che si recuperano quando si chiama il metodo stream_get_meta_data() function, e può opzionalmente esporre altri dati personalizzati.

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

Decoratori di flusso

Aggiungere funzionalità personalizzate agli stream è molto semplice con i decoratori di stream. Guzzle fornisce diversi decoratori incorporati che forniscono ulteriori funzionalità.