Guzzle und PSR-7

Guzzle verwendet PSR-7 als HTTP-Nachrichtenschnittstelle. Dadurch kann Guzzle mit jeder anderen Bibliothek zusammenarbeiten, die PSR-7-Nachrichtenschnittstellen verwendet.

Guzzle ist ein HTTP-Client, der HTTP-Anfragen an einen Server sendet und HTTP-Antworten empfängt. Sowohl Anfragen als auch Antworten werden als Nachrichten bezeichnet.

Guzzle stützt sich auf das guzzlehttp/psr7 Composer-Paket für seine Nachrichtenimplementierung von PSR-7.

Sie können eine Anfrage mit der Klasse GuzzleHttp\Psr7\Request erstellen:

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

Sie können eine Antwort mit der Klasse GuzzleHttp\Psr7\Response erstellen:

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

Überschriften

Sowohl Anfrage- als auch Antwortnachrichten enthalten HTTP-Header.

Zugriff auf Überschriften

Mit der Methode hasHeader() können Sie überprüfen, ob eine Anfrage oder eine Antwort eine bestimmte Kopfzeile hat.

use GuzzleHttp\Psr7;

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

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

Sie können alle Header-Werte als Array von Strings mit getHeader() abrufen.

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

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

Sie können die Kopfzeilen einer Nachricht mit der Methode getHeaders() durchlaufen.

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

Komplexe Überschriften

Einige Header enthalten zusätzliche Schlüssel-Wert-Paar-Informationen. Link-Header enthalten beispielsweise einen Link und mehrere Schlüssel-Wert-Paare:

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

Guzzle bietet eine praktische Funktion, mit der diese Art von Headern analysiert werden kann:

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

Wird ausgegeben:

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

Das Ergebnis enthält einen Hash von Schlüssel-Wert-Paaren. Kopfzeilenwerte, die keinen Schlüssel haben haben (z.B. der Link), werden numerisch indiziert, während Headerteile, die ein Schlüssel-Wert-Paar bilden Wertpaar bilden, als Schlüssel-Wert-Paar hinzugefügt werden.

Body

Sowohl Request- als auch Response-Nachrichten können einen Body enthalten.

Sie können den Text einer Nachricht mit der Methode getBody() abrufen:

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

Der in Anfrage- und Antwortobjekten verwendete Body ist ein Psr\Http\Message\StreamInterface. Dieser Stream wird sowohl für das Hochladen von Daten als auch zum Herunterladen von Daten verwendet. Guzzle speichert standardmäßig den Body einer Nachricht einer Nachricht in einem Stream, der PHP temp streams verwendet. Wenn die Größe des Textes 2 MB überschreitet, schaltet der Stream automatisch auf die Speicherung der Daten auf der Festplatte statt im Speicher zu speichern (um Ihre Anwendung vor einer Erschöpfung des Speichers zu schützen).

Der einfachste Weg, einen Body für eine Nachricht zu erstellen, ist die Verwendung der streamFor Methode aus der GuzzleHttp\Psr7\Utils Klasse -- Utils::streamFor. Diese Methode akzeptiert Strings, Ressourcen, Callables, Iteratoren, andere Streamables und gibt eine Instanz von Psr\Http\Message\StreamInterface.

Der Text einer Anfrage oder Antwort kann in eine Zeichenkette umgewandelt werden, oder Sie können nach Bedarf Bytes aus dem Stream lesen und schreiben.

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

Anfragen

Anfragen werden von einem Client an einen Server gesendet. Anfragen beinhalten die Methode, die die auf eine Ressource angewendet werden soll, den Bezeichner der Ressource und die zu verwendende Protokoll Version zu verwenden.

Anfragemethoden

Wenn Sie eine Anfrage erstellen, müssen Sie die gewünschte HTTP-Methode angeben ausführen möchten. Sie können jede beliebige Methode angeben, auch eine benutzerdefinierte Methode die möglicherweise nicht Teil von RFC 7231 ist (wie "MOVE").

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

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

Sie können eine Anfrage mit Methoden auf einem Client erstellen und senden, die der gewünschten HTTP-Methode entsprechen.

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

Zum Beispiel:

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

Request URI

Die Anfrage-URI wird durch ein Psr\Http\Message\UriInterface Objekt dargestellt. Guzzle bietet eine Implementierung dieser Schnittstelle unter Verwendung des GuzzleHttp\Psr7\Uri Klasse.

Bei der Erstellung einer Anfrage können Sie den URI als String oder eine Instanz von Psr\Http\Message\UriInterface angeben.

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

Schema

Das Schema einer Anfrage gibt das Protokoll an, das beim Senden der Anfrage verwendet werden soll. Bei der Verwendung von Guzzle kann das Schema auf "http" oder "https" eingestellt werden.

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

Host

Der Host ist über den URI, der zur Anfrage gehört, oder über den Host-Header zugänglich.

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

Port

Bei Verwendung der Schemata "http" oder "https" ist kein Port erforderlich.

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

Pfad

Der Pfad einer Anfrage ist über das URI-Objekt zugänglich.

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

Der Inhalt des Pfades wird automatisch gefiltert, um sicherzustellen, dass nur erlaubte Zeichen im Pfad vorhanden sind. Alle Zeichen, die im Pfad nicht erlaubt sind im Pfad werden prozentual kodiert gemäß RFC 3986 Abschnitt 3.3

Abfrage-String

Auf den Query-String einer Anfrage kann mit der getQuery() des URI-Objekts zugegriffen werden, das zur Anfrage gehört.

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

Der Inhalt der Abfragezeichenfolge wird automatisch gefiltert, um sicherzustellen, dass nur zulässige Zeichen in der Abfragezeichenfolge vorhanden sind. Alle Zeichen, die nicht erlaubt sind, werden prozentual kodiert gemäß RFC 3986 Abschnitt 3.4

Antworten

Antworten sind die HTTP-Nachrichten, die ein Client von einem Server erhält, nachdem er eine HTTP-Anforderungsnachricht gesendet hat.

Start-Line

Die Startzeile einer Antwort enthält das Protokoll und die Protokollversion, den Statuscode und den Grund.

$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

Wie bereits beschrieben, können Sie den Body einer Antwort mit der Methode getBody() abrufen.

$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 verwendet PSR-7-Stream-Objekte zur Darstellung von Anfrage- und Antwortnachrichten Körper darzustellen. Mit diesen Stream-Objekten können Sie mit verschiedenen Datentypen arbeiten, die alle mit einer gemeinsamen Schnittstelle.

HTTP-Nachrichten bestehen aus einer Startzeile, Kopfzeilen und einem Textkörper. Der Körper einer HTTP Nachricht kann sehr klein oder extrem groß sein. Der Versuch, den Body einer Nachricht einer Nachricht als Zeichenkette darzustellen, kann leicht mehr Speicher als beabsichtigt verbrauchen, da der Body vollständig im Speicher abgelegt werden muss. Der Versuch, den Body einer Anfrage oder Antwort im Speicher zu speichern, würde die Verwendung dieser Implementierung ausschließen mit großen Nachrichtenkörpern arbeiten zu können. Das StreamInterface wird verwendet, um um die Implementierungsdetails zu verbergen, woher ein Datenstrom gelesen oder in den geschrieben wird.

Die PSR-7 Psr\Http\Message\StreamInterface stellt mehrere Methoden zur Verfügung, mit denen Streams effektiv gelesen, beschrieben und durchlaufen werden können.

Streams legen ihre Fähigkeiten mit drei Methoden offen: isReadable(), isWritable(), und isSeekable(). Diese Methoden können von Stream Kollaborateuren verwendet werden, um festzustellen, ob ein Stream ihre Anforderungen erfüllen kann.

Jede Stream-Instanz verfügt über verschiedene Fähigkeiten: Sie kann schreibgeschützt sein, schreibgeschützt oder schreibgeschützt sein, beliebige Zufallszugriffe erlauben (vorwärts oder vorwärts oder rückwärts zu einem beliebigen Ort) oder nur sequentiellen Zugriff erlauben (zum Beispiel im Fall eines Sockets oder einer Pipe).

Guzzle verwendet das guzzlehttp/psr7 Paket, um Stream-Unterstützung zu bieten. Mehr Informationen über die Verwendung von Streams, die Erstellung von Streams, die Umwandlung von Streams in PHP Stream-Ressource und Stream-Dekoratoren finden Sie in der Guzzle PSR-7 Dokumentation.

Erstellen von Streams

Der beste Weg, einen Stream zu erstellen, ist die GuzzleHttp\Psr7\Utils::streamFor Methode. Diese Methode akzeptiert Strings, Ressourcen, die von fopen() zurückgegeben werden, ein Objekt, das __toString() implementiert, Iteratoren, Callables, und Instanzen von 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

Sie können Streams aus Iteratoren erstellen. Der Iterator kann eine beliebige Anzahl von Bytes pro Iteration liefern. Alle überschüssigen Bytes, die vom Iterator zurückgegeben werden und nicht nicht von einem Stream-Konsumenten angefordert wurden, werden bis zu einem späteren Lesevorgang zwischengespeichert.

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

Metadaten

Streams stellen Stream-Metadaten über die Methode getMetadata() zur Verfügung. Diese Methode stellt die Daten zur Verfügung, die Sie abrufen würden, wenn Sie PHP's stream_get_meta_data() function, und kann optional auch andere benutzerdefinierte Daten bereitstellen.

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

Das Hinzufügen benutzerdefinierter Funktionen zu Streams ist mit Stream-Dekoratoren sehr einfach. Guzzle bietet mehrere eingebaute Dekoratoren, die zusätzliche Stream Funktionalität bieten.