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";
}

Σύνθετες επικεφαλίδες

Ορισμένες επικεφαλίδες περιέχουν πρόσθετες πληροφορίες ζεύγους τιμών κλειδιών. Για παράδειγμα, οι επικεφαλίδες Σύνδεσμος περιέχουν έναν σύνδεσμο και διάφορα ζεύγη τιμών κλειδιών:

<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',
  ),
)

Το αποτέλεσμα περιέχει έναν κατακερματισμό από ζεύγη τιμών κλειδιών. Τιμές κεφαλίδας που δεν έχουν κλειδί (δηλ. ο σύνδεσμος) δεικτοδοτούνται αριθμητικά, ενώ τα τμήματα κεφαλίδων που σχηματίζουν ένα κλειδί προστίθενται ως ζεύγος τιμών κλειδιών.

Σώμα

Τόσο τα μηνύματα αίτησης όσο και τα μηνύματα απόκρισης μπορούν να περιέχουν ένα σώμα.

Μπορείτε να ανακτήσετε το σώμα ενός μηνύματος χρησιμοποιώντας τη μέθοδο getBody():

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

Το σώμα που χρησιμοποιείται στα αντικείμενα αίτησης και απόκρισης είναι ένα Psr\Http\Message\StreamInterface. Αυτή η ροή χρησιμοποιείται τόσο για τη μεταφόρτωση δεδομένων όσο και τη λήψη δεδομένων. Το Guzzle, από προεπιλογή, θα αποθηκεύει το σώμα του ενός μηνύματος σε μια ροή που χρησιμοποιεί τις προσωρινές ροές της PHP. Όταν το μέγεθος του σώματος υπερβαίνει τα 2 MB, η ροή θα μεταβεί αυτόματα στην αποθήκευση δεδομένων στο δίσκο αντί στη μνήμη (προστατεύοντας την εφαρμογή σας από την εξάντληση της μνήμης).

Ο ευκολότερος τρόπος για να δημιουργήσετε ένα σώμα για ένα μήνυμα είναι να χρησιμοποιήσετε το streamFor από την κλάση GuzzleHttp\Psr7\Utils -- Utils::streamFor. Αυτή η μέθοδος δέχεται συμβολοσειρές, πόρους, callables, iterators, άλλα streamables, και επιστρέφει μια περίπτωση της Psr\Http\Message\StreamInterface.

Το σώμα μιας αίτησης ή απόκρισης μπορεί να μετατραπεί σε συμβολοσειρά ή μπορείτε να διαβάζετε και να γράφετε bytes από τη ροή ανάλογα με τις ανάγκες.

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 που θέλετε να χρησιμοποιήσετε.

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 **/])
ΕΠΙΛΟΓΕΣ
$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, το scheme μπορεί να οριστεί σε "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 ενότητα 3.3

Συμβολοσειρά ερώτησης

Η συμβολοσειρά ερωτήματος μιας αίτησης μπορεί να προσπελαστεί χρησιμοποιώντας την getQuery() του αντικειμένου URI που ανήκει στην αίτηση.

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

Τα περιεχόμενα της συμβολοσειράς ερωτήσεων θα φιλτραριστούν αυτόματα για να διασφαλιστεί ότι μόνο οι επιτρεπόμενοι χαρακτήρες είναι παρόντες στη συμβολοσειρά ερωτήματος. Οποιοσδήποτε χαρακτήρας που δεν επιτρέπονται στη συμβολοσειρά ερωτήματος, θα κωδικοποιούνται σε ποσοστά σύμφωνα με το RFC 3986 τμήμα 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(). Αυτές οι μέθοδοι μπορούν να χρησιμοποιηθούν από τη ροή συνεργάτες για να καθορίσουν αν μια ροή είναι ικανή να ικανοποιήσει τις απαιτήσεις τους.

Κάθε περίπτωση ροής έχει διάφορες δυνατότητες: μπορεί να είναι μόνο για ανάγνωση, write-only, read-write, να επιτρέπουν αυθαίρετη τυχαία πρόσβαση (αναζητώντας προς τα εμπρός ή προς τα πίσω σε οποιαδήποτε θέση), ή να επιτρέπουν μόνο διαδοχική πρόσβαση (για παράδειγμα στην περίπτωση μιας υποδοχής ή ενός σωλήνα).

Το Guzzle χρησιμοποιεί το πακέτο guzzlehttp/psr7 για να παρέχει υποστήριξη ροής. Περισσότερα πληροφορίες σχετικά με τη χρήση ροών, τη δημιουργία ροών, τη μετατροπή ροών σε PHP πόρους ροής, και διακοσμητές ροής μπορούν να βρεθούν στην ενότητα Guzzle PSR-7 documentation.

Δημιουργία ροών

Ο καλύτερος τρόπος για να δημιουργήσετε μια ροή είναι να χρησιμοποιήσετε το GuzzleHttp\Psr7\Utils::streamFor method. Αυτή η μέθοδος δέχεται συμβολοσειρές, πόρους που επιστρέφονται από την fopen(), ένα αντικείμενο που υλοποιεί την __toString(), επαναλήπτες, callables και instances του 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

Μπορείτε να δημιουργήσετε ροές από επαναλήπτες. Ο επαναλήπτης μπορεί να δώσει οποιονδήποτε αριθμό bytes ανά επανάληψη. Κάθε πλεονάζον bytes που επιστρέφεται από τον επαναλήπτη που δεν ήταν ζητηθεί από έναν καταναλωτή ροής, θα αποθηκευτεί μέχρι μια επόμενη ανάγνωση.

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(), και μπορεί προαιρετικά να εκθέσει άλλα προσαρμοσμένα δεδομένα.

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 παρέχει αρκετούς ενσωματωμένους διακοσμητές που παρέχουν πρόσθετες ροές λειτουργικότητα.