psr7.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. ================
  2. Guzzle and PSR-7
  3. ================
  4. Guzzle utilizes PSR-7 as the HTTP message interface. This allows Guzzle to work
  5. with any other library that utilizes PSR-7 message interfaces.
  6. Guzzle is an HTTP client that sends HTTP requests to a server and receives HTTP
  7. responses. Both requests and responses are referred to as messages.
  8. Guzzle relies on the ``guzzlehttp/psr7`` Composer package for its message
  9. implementation of PSR-7.
  10. You can create a request using the ``GuzzleHttp\Psr7\Request`` class:
  11. .. code-block:: php
  12. use GuzzleHttp\Psr7\Request;
  13. $request = new Request('GET', 'http://httpbin.org/get');
  14. // You can provide other optional constructor arguments.
  15. $headers = ['X-Foo' => 'Bar'];
  16. $body = 'hello!';
  17. $request = new Request('PUT', 'http://httpbin.org/put', $headers, $body);
  18. You can create a response using the ``GuzzleHttp\Psr7\Response`` class:
  19. .. code-block:: php
  20. use GuzzleHttp\Psr7\Response;
  21. // The constructor requires no arguments.
  22. $response = new Response();
  23. echo $response->getStatusCode(); // 200
  24. echo $response->getProtocolVersion(); // 1.1
  25. // You can supply any number of optional arguments.
  26. $status = 200;
  27. $headers = ['X-Foo' => 'Bar'];
  28. $body = 'hello!';
  29. $protocol = '1.1';
  30. $response = new Response($status, $headers, $body, $protocol);
  31. Headers
  32. =======
  33. Both request and response messages contain HTTP headers.
  34. Accessing Headers
  35. -----------------
  36. You can check if a request or response has a specific header using the
  37. ``hasHeader()`` method.
  38. .. code-block:: php
  39. use GuzzleHttp\Psr7;
  40. $request = new Psr7\Request('GET', '/', ['X-Foo' => 'bar']);
  41. if ($request->hasHeader('X-Foo')) {
  42. echo 'It is there';
  43. }
  44. You can retrieve all the header values as an array of strings using
  45. ``getHeader()``.
  46. .. code-block:: php
  47. $request->getHeader('X-Foo'); // ['bar']
  48. // Retrieving a missing header returns an empty array.
  49. $request->getHeader('X-Bar'); // []
  50. You can iterate over the headers of a message using the ``getHeaders()``
  51. method.
  52. .. code-block:: php
  53. foreach ($request->getHeaders() as $name => $values) {
  54. echo $name . ': ' . implode(', ', $values) . "\r\n";
  55. }
  56. Complex Headers
  57. ---------------
  58. Some headers contain additional key value pair information. For example, Link
  59. headers contain a link and several key value pairs:
  60. ::
  61. <http://foo.com>; rel="thing"; type="image/jpeg"
  62. Guzzle provides a convenience feature that can be used to parse these types of
  63. headers:
  64. .. code-block:: php
  65. use GuzzleHttp\Psr7;
  66. $request = new Psr7\Request('GET', '/', [
  67. 'Link' => '<http:/.../front.jpeg>; rel="front"; type="image/jpeg"'
  68. ]);
  69. $parsed = Psr7\parse_header($request->getHeader('Link'));
  70. var_export($parsed);
  71. Will output:
  72. .. code-block:: php
  73. array (
  74. 0 =>
  75. array (
  76. 0 => '<http:/.../front.jpeg>',
  77. 'rel' => 'front',
  78. 'type' => 'image/jpeg',
  79. ),
  80. )
  81. The result contains a hash of key value pairs. Header values that have no key
  82. (i.e., the link) are indexed numerically while headers parts that form a key
  83. value pair are added as a key value pair.
  84. Body
  85. ====
  86. Both request and response messages can contain a body.
  87. You can retrieve the body of a message using the ``getBody()`` method:
  88. .. code-block:: php
  89. $response = GuzzleHttp\get('http://httpbin.org/get');
  90. echo $response->getBody();
  91. // JSON string: { ... }
  92. The body used in request and response objects is a
  93. ``Psr\Http\Message\StreamInterface``. This stream is used for both
  94. uploading data and downloading data. Guzzle will, by default, store the body of
  95. a message in a stream that uses PHP temp streams. When the size of the body
  96. exceeds 2 MB, the stream will automatically switch to storing data on disk
  97. rather than in memory (protecting your application from memory exhaustion).
  98. The easiest way to create a body for a message is using the ``stream_for``
  99. function from the ``GuzzleHttp\Psr7`` namespace --
  100. ``GuzzleHttp\Psr7\stream_for``. This function accepts strings, resources,
  101. callables, iterators, other streamables, and returns an instance of
  102. ``Psr\Http\Message\StreamInterface``.
  103. The body of a request or response can be cast to a string or you can read and
  104. write bytes off of the stream as needed.
  105. .. code-block:: php
  106. use GuzzleHttp\Stream\Stream;
  107. $response = $client->request('GET', 'http://httpbin.org/get');
  108. echo $response->getBody()->read(4);
  109. echo $response->getBody()->read(4);
  110. echo $response->getBody()->read(1024);
  111. var_export($response->eof());
  112. Requests
  113. ========
  114. Requests are sent from a client to a server. Requests include the method to
  115. be applied to a resource, the identifier of the resource, and the protocol
  116. version to use.
  117. Request Methods
  118. ---------------
  119. When creating a request, you are expected to provide the HTTP method you wish
  120. to perform. You can specify any method you'd like, including a custom method
  121. that might not be part of RFC 7231 (like "MOVE").
  122. .. code-block:: php
  123. // Create a request using a completely custom HTTP method
  124. $request = new \GuzzleHttp\Psr7\Request('MOVE', 'http://httpbin.org/move');
  125. echo $request->getMethod();
  126. // MOVE
  127. You can create and send a request using methods on a client that map to the
  128. HTTP method you wish to use.
  129. :GET: ``$client->get('http://httpbin.org/get', [/** options **/])``
  130. :POST: ``$client->post('http://httpbin.org/post', [/** options **/])``
  131. :HEAD: ``$client->head('http://httpbin.org/get', [/** options **/])``
  132. :PUT: ``$client->put('http://httpbin.org/put', [/** options **/])``
  133. :DELETE: ``$client->delete('http://httpbin.org/delete', [/** options **/])``
  134. :OPTIONS: ``$client->options('http://httpbin.org/get', [/** options **/])``
  135. :PATCH: ``$client->patch('http://httpbin.org/put', [/** options **/])``
  136. For example:
  137. .. code-block:: php
  138. $response = $client->patch('http://httpbin.org/patch', ['body' => 'content']);
  139. Request URI
  140. -----------
  141. The request URI is represented by a ``Psr\Http\Message\UriInterface`` object.
  142. Guzzle provides an implementation of this interface using the
  143. ``GuzzleHttp\Psr7\Uri`` class.
  144. When creating a request, you can provide the URI as a string or an instance of
  145. ``Psr\Http\Message\UriInterface``.
  146. .. code-block:: php
  147. $response = $client->request('GET', 'http://httpbin.org/get?q=foo');
  148. Scheme
  149. ------
  150. The `scheme <http://tools.ietf.org/html/rfc3986#section-3.1>`_ of a request
  151. specifies the protocol to use when sending the request. When using Guzzle, the
  152. scheme can be set to "http" or "https".
  153. .. code-block:: php
  154. $request = new Request('GET', 'http://httpbin.org');
  155. echo $request->getUri()->getScheme(); // http
  156. echo $request->getUri(); // http://httpbin.org
  157. Host
  158. ----
  159. The host is accessible using the URI owned by the request or by accessing the
  160. Host header.
  161. .. code-block:: php
  162. $request = new Request('GET', 'http://httpbin.org');
  163. echo $request->getUri()->getHost(); // httpbin.org
  164. echo $request->getHeader('Host'); // httpbin.org
  165. Port
  166. ----
  167. No port is necessary when using the "http" or "https" schemes.
  168. .. code-block:: php
  169. $request = new Request('GET', 'http://httpbin.org:8080');
  170. echo $request->getUri()->getPort(); // 8080
  171. echo $request->getUri(); // http://httpbin.org:8080
  172. Path
  173. ----
  174. The path of a request is accessible via the URI object.
  175. .. code-block:: php
  176. $request = new Request('GET', 'http://httpbin.org/get');
  177. echo $request->getUri()->getPath(); // /get
  178. The contents of the path will be automatically filtered to ensure that only
  179. allowed characters are present in the path. Any characters that are not allowed
  180. in the path will be percent-encoded according to
  181. `RFC 3986 section 3.3 <https://tools.ietf.org/html/rfc3986#section-3.3>`_
  182. Query string
  183. ------------
  184. The query string of a request can be accessed using the ``getQuery()`` of the
  185. URI object owned by the request.
  186. .. code-block:: php
  187. $request = new Request('GET', 'http://httpbin.org/?foo=bar');
  188. echo $request->getUri()->getQuery(); // foo=bar
  189. The contents of the query string will be automatically filtered to ensure that
  190. only allowed characters are present in the query string. Any characters that
  191. are not allowed in the query string will be percent-encoded according to
  192. `RFC 3986 section 3.4 <https://tools.ietf.org/html/rfc3986#section-3.4>`_
  193. Responses
  194. =========
  195. Responses are the HTTP messages a client receives from a server after sending
  196. an HTTP request message.
  197. Start-Line
  198. ----------
  199. The start-line of a response contains the protocol and protocol version,
  200. status code, and reason phrase.
  201. .. code-block:: php
  202. $client = new \GuzzleHttp\Client();
  203. $response = $client->request('GET', 'http://httpbin.org/get');
  204. echo $response->getStatusCode(); // 200
  205. echo $response->getReasonPhrase(); // OK
  206. echo $response->getProtocolVersion(); // 1.1
  207. Body
  208. ----
  209. As described earlier, you can get the body of a response using the
  210. ``getBody()`` method.
  211. .. code-block:: php
  212. $body = $response->getBody();
  213. echo $body;
  214. // Cast to a string: { ... }
  215. $body->seek(0);
  216. // Rewind the body
  217. $body->read(1024);
  218. // Read bytes of the body
  219. Streams
  220. =======
  221. Guzzle uses PSR-7 stream objects to represent request and response message
  222. bodies. These stream objects allow you to work with various types of data all
  223. using a common interface.
  224. HTTP messages consist of a start-line, headers, and a body. The body of an HTTP
  225. message can be very small or extremely large. Attempting to represent the body
  226. of a message as a string can easily consume more memory than intended because
  227. the body must be stored completely in memory. Attempting to store the body of a
  228. request or response in memory would preclude the use of that implementation from
  229. being able to work with large message bodies. The StreamInterface is used in
  230. order to hide the implementation details of where a stream of data is read from
  231. or written to.
  232. The PSR-7 ``Psr\Http\Message\StreamInterface`` exposes several methods
  233. that enable streams to be read from, written to, and traversed effectively.
  234. Streams expose their capabilities using three methods: ``isReadable()``,
  235. ``isWritable()``, and ``isSeekable()``. These methods can be used by stream
  236. collaborators to determine if a stream is capable of their requirements.
  237. Each stream instance has various capabilities: they can be read-only,
  238. write-only, read-write, allow arbitrary random access (seeking forwards or
  239. backwards to any location), or only allow sequential access (for example in the
  240. case of a socket or pipe).
  241. Guzzle uses the ``guzzlehttp/psr7`` package to provide stream support. More
  242. information on using streams, creating streams, converting streams to PHP
  243. stream resource, and stream decorators can be found in the
  244. `Guzzle PSR-7 documentation <https://github.com/guzzle/psr7/blob/master/README.md>`_.
  245. Creating Streams
  246. ----------------
  247. The best way to create a stream is using the ``GuzzleHttp\Psr7\stream_for``
  248. function. This function accepts strings, resources returned from ``fopen()``,
  249. an object that implements ``__toString()``, iterators, callables, and instances
  250. of ``Psr\Http\Message\StreamInterface``.
  251. .. code-block:: php
  252. use GuzzleHttp\Psr7;
  253. $stream = Psr7\stream_for('string data');
  254. echo $stream;
  255. // string data
  256. echo $stream->read(3);
  257. // str
  258. echo $stream->getContents();
  259. // ing data
  260. var_export($stream->eof());
  261. // true
  262. var_export($stream->tell());
  263. // 11
  264. You can create streams from iterators. The iterator can yield any number of
  265. bytes per iteration. Any excess bytes returned by the iterator that were not
  266. requested by a stream consumer will be buffered until a subsequent read.
  267. .. code-block:: php
  268. use GuzzleHttp\Psr7;
  269. $generator = function ($bytes) {
  270. for ($i = 0; $i < $bytes; $i++) {
  271. yield '.';
  272. }
  273. };
  274. $iter = $generator(1024);
  275. $stream = Psr7\stream_for($iter);
  276. echo $stream->read(3); // ...
  277. Metadata
  278. --------
  279. Streams expose stream metadata through the ``getMetadata()`` method. This
  280. method provides the data you would retrieve when calling PHP's
  281. `stream_get_meta_data() function <http://php.net/manual/en/function.stream-get-meta-data.php>`_,
  282. and can optionally expose other custom data.
  283. .. code-block:: php
  284. use GuzzleHttp\Psr7;
  285. $resource = fopen('/path/to/file', 'r');
  286. $stream = Psr7\stream_for($resource);
  287. echo $stream->getMetadata('uri');
  288. // /path/to/file
  289. var_export($stream->isReadable());
  290. // true
  291. var_export($stream->isWritable());
  292. // false
  293. var_export($stream->isSeekable());
  294. // true
  295. Stream Decorators
  296. -----------------
  297. Adding custom functionality to streams is very simple with stream decorators.
  298. Guzzle provides several built-in decorators that provide additional stream
  299. functionality.
  300. - `AppendStream <https://github.com/guzzle/psr7#appendstream>`_
  301. - `BufferStream <https://github.com/guzzle/psr7#bufferstream>`_
  302. - `CachingStream <https://github.com/guzzle/psr7#cachingstream>`_
  303. - `DroppingStream <https://github.com/guzzle/psr7#droppingstream>`_
  304. - `FnStream <https://github.com/guzzle/psr7#fnstream>`_
  305. - `InflateStream <https://github.com/guzzle/psr7#inflatestream>`_
  306. - `LazyOpenStream <https://github.com/guzzle/psr7#lazyopenstream>`_
  307. - `LimitStream <https://github.com/guzzle/psr7#limitstream>`_
  308. - `NoSeekStream <https://github.com/guzzle/psr7#noseekstream>`_
  309. - `PumpStream <https://github.com/guzzle/psr7#pumpstream>`_