123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- ================
- Guzzle and PSR-7
- ================
- Guzzle utilizes PSR-7 as the HTTP message interface. This allows Guzzle to work
- with any other library that utilizes PSR-7 message interfaces.
- Guzzle is an HTTP client that sends HTTP requests to a server and receives HTTP
- responses. Both requests and responses are referred to as messages.
- Guzzle relies on the ``guzzlehttp/psr7`` Composer package for its message
- implementation of PSR-7.
- You can create a request using the ``GuzzleHttp\Psr7\Request`` class:
- .. code-block:: php
- 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);
- You can create a response using the ``GuzzleHttp\Psr7\Response`` class:
- .. code-block:: php
- 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
- =======
- Both request and response messages contain HTTP headers.
- Accessing Headers
- -----------------
- You can check if a request or response has a specific header using the
- ``hasHeader()`` method.
- .. code-block:: php
- use GuzzleHttp\Psr7;
- $request = new Psr7\Request('GET', '/', ['X-Foo' => 'bar']);
- if ($request->hasHeader('X-Foo')) {
- echo 'It is there';
- }
- You can retrieve all the header values as an array of strings using
- ``getHeader()``.
- .. code-block:: php
- $request->getHeader('X-Foo'); // ['bar']
- // Retrieving a missing header returns an empty array.
- $request->getHeader('X-Bar'); // []
- You can iterate over the headers of a message using the ``getHeaders()``
- method.
- .. code-block:: php
- foreach ($request->getHeaders() as $name => $values) {
- echo $name . ': ' . implode(', ', $values) . "\r\n";
- }
- Complex Headers
- ---------------
- Some headers contain additional key value pair information. For example, Link
- headers contain a link and several key value pairs:
- ::
- <http://foo.com>; rel="thing"; type="image/jpeg"
- Guzzle provides a convenience feature that can be used to parse these types of
- headers:
- .. code-block:: php
- 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);
- Will output:
- .. code-block:: php
- array (
- 0 =>
- array (
- 0 => '<http:/.../front.jpeg>',
- 'rel' => 'front',
- 'type' => 'image/jpeg',
- ),
- )
- The result contains a hash of key value pairs. Header values that have no key
- (i.e., the link) are indexed numerically while headers parts that form a key
- value pair are added as a key value pair.
- Body
- ====
- Both request and response messages can contain a body.
- You can retrieve the body of a message using the ``getBody()`` method:
- .. code-block:: php
- $response = GuzzleHttp\get('http://httpbin.org/get');
- echo $response->getBody();
- // JSON string: { ... }
- The body used in request and response objects is a
- ``Psr\Http\Message\StreamInterface``. This stream is used for both
- uploading data and downloading data. Guzzle will, by default, store the body of
- a message in a stream that uses PHP temp streams. When the size of the body
- exceeds 2 MB, the stream will automatically switch to storing data on disk
- rather than in memory (protecting your application from memory exhaustion).
- The easiest way to create a body for a message is using the ``stream_for``
- function from the ``GuzzleHttp\Psr7`` namespace --
- ``GuzzleHttp\Psr7\stream_for``. This function accepts strings, resources,
- callables, iterators, other streamables, and returns an instance of
- ``Psr\Http\Message\StreamInterface``.
- The body of a request or response can be cast to a string or you can read and
- write bytes off of the stream as needed.
- .. code-block:: php
- 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());
- Requests
- ========
- Requests are sent from a client to a server. Requests include the method to
- be applied to a resource, the identifier of the resource, and the protocol
- version to use.
- Request Methods
- ---------------
- When creating a request, you are expected to provide the HTTP method you wish
- to perform. You can specify any method you'd like, including a custom method
- that might not be part of RFC 7231 (like "MOVE").
- .. code-block:: php
- // Create a request using a completely custom HTTP method
- $request = new \GuzzleHttp\Psr7\Request('MOVE', 'http://httpbin.org/move');
- echo $request->getMethod();
- // MOVE
- You can create and send a request using methods on a client that map to the
- HTTP method you wish to use.
- :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 **/])``
- For example:
- .. code-block:: php
- $response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);
- Request URI
- -----------
- The request URI is represented by a ``Psr\Http\Message\UriInterface`` object.
- Guzzle provides an implementation of this interface using the
- ``GuzzleHttp\Psr7\Uri`` class.
- When creating a request, you can provide the URI as a string or an instance of
- ``Psr\Http\Message\UriInterface``.
- .. code-block:: php
- $response = $client->request('GET', 'http://httpbin.org/get?q=foo');
- Scheme
- ------
- The `scheme <http://tools.ietf.org/html/rfc3986#section-3.1>`_ of a request
- specifies the protocol to use when sending the request. When using Guzzle, the
- scheme can be set to "http" or "https".
- .. code-block:: php
- $request = new Request('GET', 'http://httpbin.org');
- echo $request->getUri()->getScheme(); // http
- echo $request->getUri(); // http://httpbin.org
- Host
- ----
- The host is accessible using the URI owned by the request or by accessing the
- Host header.
- .. code-block:: php
- $request = new Request('GET', 'http://httpbin.org');
- echo $request->getUri()->getHost(); // httpbin.org
- echo $request->getHeader('Host'); // httpbin.org
- Port
- ----
- No port is necessary when using the "http" or "https" schemes.
- .. code-block:: php
- $request = new Request('GET', 'http://httpbin.org:8080');
- echo $request->getUri()->getPort(); // 8080
- echo $request->getUri(); // http://httpbin.org:8080
- Path
- ----
- The path of a request is accessible via the URI object.
- .. code-block:: php
- $request = new Request('GET', 'http://httpbin.org/get');
- echo $request->getUri()->getPath(); // /get
- The contents of the path will be automatically filtered to ensure that only
- allowed characters are present in the path. Any characters that are not allowed
- in the path will be percent-encoded according to
- `RFC 3986 section 3.3 <https://tools.ietf.org/html/rfc3986#section-3.3>`_
- Query string
- ------------
- The query string of a request can be accessed using the ``getQuery()`` of the
- URI object owned by the request.
- .. code-block:: php
- $request = new Request('GET', 'http://httpbin.org/?foo=bar');
- echo $request->getUri()->getQuery(); // foo=bar
- The contents of the query string will be automatically filtered to ensure that
- only allowed characters are present in the query string. Any characters that
- are not allowed in the query string will be percent-encoded according to
- `RFC 3986 section 3.4 <https://tools.ietf.org/html/rfc3986#section-3.4>`_
- Responses
- =========
- Responses are the HTTP messages a client receives from a server after sending
- an HTTP request message.
- Start-Line
- ----------
- The start-line of a response contains the protocol and protocol version,
- status code, and reason phrase.
- .. code-block:: php
- $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
- ----
- As described earlier, you can get the body of a response using the
- ``getBody()`` method.
- .. code-block:: php
- $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 uses PSR-7 stream objects to represent request and response message
- bodies. These stream objects allow you to work with various types of data all
- using a common interface.
- HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
- message can be very small or extremely large. 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. Attempting to store the body of a
- request or response in memory would preclude the use of that implementation from
- being able to work with large message bodies. The StreamInterface is used in
- order to hide the implementation details of where a stream of data is read from
- or written to.
- The PSR-7 ``Psr\Http\Message\StreamInterface`` exposes several methods
- that enable streams to be read from, written to, and traversed effectively.
- Streams expose their capabilities using three methods: ``isReadable()``,
- ``isWritable()``, and ``isSeekable()``. These methods can be used by stream
- collaborators to determine if a stream is capable of their requirements.
- Each stream instance has various capabilities: they can be read-only,
- write-only, read-write, allow arbitrary random access (seeking forwards or
- backwards to any location), or only allow sequential access (for example in the
- case of a socket or pipe).
- Guzzle uses the ``guzzlehttp/psr7`` package to provide stream support. More
- information on using streams, creating streams, converting streams to PHP
- stream resource, and stream decorators can be found in the
- `Guzzle PSR-7 documentation <https://github.com/guzzle/psr7/blob/master/README.md>`_.
- Creating Streams
- ----------------
- The best way to create a stream is using the ``GuzzleHttp\Psr7\stream_for``
- function. This function accepts strings, resources returned from ``fopen()``,
- an object that implements ``__toString()``, iterators, callables, and instances
- of ``Psr\Http\Message\StreamInterface``.
- .. code-block:: php
- use GuzzleHttp\Psr7;
- $stream = Psr7\stream_for('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
- You can create streams from iterators. The iterator can yield any number of
- bytes per iteration. Any excess bytes returned by the iterator that were not
- requested by a stream consumer will be buffered until a subsequent read.
- .. code-block:: php
- 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); // ...
- Metadata
- --------
- Streams expose stream metadata through the ``getMetadata()`` method. This
- method provides the data you would retrieve when calling PHP's
- `stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_,
- and can optionally expose other custom data.
- .. code-block:: php
- 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
- Stream Decorators
- -----------------
- Adding custom functionality to streams is very simple with stream decorators.
- Guzzle provides several built-in decorators that provide additional stream
- functionality.
- - `AppendStream <https://github.com/guzzle/psr7#appendstream>`_
- - `BufferStream <https://github.com/guzzle/psr7#bufferstream>`_
- - `CachingStream <https://github.com/guzzle/psr7#cachingstream>`_
- - `DroppingStream <https://github.com/guzzle/psr7#droppingstream>`_
- - `FnStream <https://github.com/guzzle/psr7#fnstream>`_
- - `InflateStream <https://github.com/guzzle/psr7#inflatestream>`_
- - `LazyOpenStream <https://github.com/guzzle/psr7#lazyopenstream>`_
- - `LimitStream <https://github.com/guzzle/psr7#limitstream>`_
- - `NoSeekStream <https://github.com/guzzle/psr7#noseekstream>`_
- - `PumpStream <https://github.com/guzzle/psr7#pumpstream>`_
|