entity-bodies.rst 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. ===========================
  2. Request and response bodies
  3. ===========================
  4. `Entity body <http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html>`_ is the term used for the body of an HTTP
  5. message. The entity body of requests and responses is inherently a
  6. `PHP stream <http://php.net/manual/en/book.stream.php>`_ in Guzzle. The body of the request can be either a string or
  7. a PHP stream which are converted into a ``Guzzle\Http\EntityBody`` object using its factory method. When using a
  8. string, the entity body is stored in a `temp PHP stream <http://www.php.net/manual/en/wrappers.php.php>`_. The use of
  9. temp PHP streams helps to protect your application from running out of memory when sending or receiving large entity
  10. bodies in your messages. When more than 2MB of data is stored in a temp stream, it automatically stores the data on
  11. disk rather than in memory.
  12. EntityBody objects provide a great deal of functionality: compression, decompression, calculate the Content-MD5,
  13. calculate the Content-Length (when the resource is repeatable), guessing the Content-Type, and more. Guzzle doesn't
  14. need to load an entire entity body into a string when sending or retrieving data; entity bodies are streamed when
  15. being uploaded and downloaded.
  16. Here's an example of gzip compressing a text file then sending the file to a URL:
  17. .. code-block:: php
  18. use Guzzle\Http\EntityBody;
  19. $body = EntityBody::factory(fopen('/path/to/file.txt', 'r+'));
  20. echo $body->read(1024);
  21. $body->seek(0, SEEK_END);
  22. $body->write('foo');
  23. echo $body->ftell();
  24. $body->rewind();
  25. // Send a request using the body
  26. $response = $client->put('http://localhost:8080/uploads', null, $body)->send();
  27. The body of the request can be specified in the ``Client::put()`` or ``Client::post()`` method, or, you can specify
  28. the body of the request by calling the ``setBody()`` method of any
  29. ``Guzzle\Http\Message\EntityEnclosingRequestInterface`` object.
  30. Compression
  31. -----------
  32. You can compress the contents of an EntityBody object using the ``compress()`` method. The compress method accepts a
  33. filter that must match to one of the supported
  34. `PHP stream filters <http://www.php.net/manual/en/filters.compression.php>`_ on your system (e.g. `zlib.deflate`,
  35. ``bzip2.compress``, etc). Compressing an entity body will stream the entire entity body through a stream compression
  36. filter into a temporary PHP stream. You can uncompress an entity body using the ``uncompress()`` method and passing
  37. the PHP stream filter to use when decompressing the stream (e.g. ``zlib.inflate``).
  38. .. code-block:: php
  39. use Guzzle\Http\EntityBody;
  40. $body = EntityBody::factory(fopen('/tmp/test.txt', 'r+'));
  41. echo $body->getSize();
  42. // >>> 1048576
  43. // Compress using the default zlib.deflate filter
  44. $body->compress();
  45. echo $body->getSize();
  46. // >>> 314572
  47. // Decompress the stream
  48. $body->uncompress();
  49. echo $body->getSize();
  50. // >>> 1048576
  51. Decorators
  52. ----------
  53. Guzzle provides several EntityBody decorators that can be used to add functionality to an EntityBody at runtime.
  54. IoEmittingEntityBody
  55. ~~~~~~~~~~~~~~~~~~~~
  56. This decorator will emit events when data is read from a stream or written to a stream. Add an event subscriber to the
  57. entity body's ``body.read`` or ``body.write`` methods to receive notifications when data data is transferred.
  58. .. code-block:: php
  59. use Guzzle\Common\Event;
  60. use Guzzle\Http\EntityBody;
  61. use Guzzle\Http\IoEmittingEntityBody;
  62. $original = EntityBody::factory(fopen('/tmp/test.txt', 'r+'));
  63. $body = new IoEmittingEntityBody($original);
  64. // Listen for read events
  65. $body->getEventDispatcher()->addListener('body.read', function (Event $e) {
  66. // Grab data from the event
  67. $entityBody = $e['body'];
  68. // Amount of data retrieved from the body
  69. $lengthOfData = $e['length'];
  70. // The actual data that was read
  71. $data = $e['read'];
  72. });
  73. // Listen for write events
  74. $body->getEventDispatcher()->addListener('body.write', function (Event $e) {
  75. // Grab data from the event
  76. $entityBody = $e['body'];
  77. // The data that was written
  78. $data = $e['write'];
  79. // The actual amount of data that was written
  80. $data = $e['read'];
  81. });
  82. ReadLimitEntityBody
  83. ~~~~~~~~~~~~~~~~~~~
  84. The ReadLimitEntityBody decorator can be used to transfer a subset or slice of an existing EntityBody object. This can
  85. be useful for breaking a large file into smaller pieces to be sent in chunks (e.g. Amazon S3's multipart upload API).
  86. .. code-block:: php
  87. use Guzzle\Http\EntityBody;
  88. use Guzzle\Http\ReadLimitEntityBody;
  89. $original = EntityBody::factory(fopen('/tmp/test.txt', 'r+'));
  90. echo $original->getSize();
  91. // >>> 1048576
  92. // Limit the size of the body to 1024 bytes and start reading from byte 2048
  93. $body = new ReadLimitEntityBody($original, 1024, 2048);
  94. echo $body->getSize();
  95. // >>> 1024
  96. echo $body->ftell();
  97. // >>> 0
  98. CachingEntityBody
  99. ~~~~~~~~~~~~~~~~~
  100. The CachingEntityBody decorator is used to allow seeking over previously read bytes on non-seekable read streams. This
  101. can be useful when transferring a non-seekable entity body fails due to needing to rewind the stream (for example,
  102. resulting from a redirect). Data that is read from the remote stream will be buffered in a PHP temp stream so that
  103. previously read bytes are cached first in memory, then on disk.
  104. .. code-block:: php
  105. use Guzzle\Http\EntityBody;
  106. use Guzzle\Http\CachingEntityBody;
  107. $original = EntityBody::factory(fopen('http://www.google.com', 'r'));
  108. $body = new CachingEntityBody($original);
  109. $body->read(1024);
  110. echo $body->ftell();
  111. // >>> 1024
  112. $body->seek(0);
  113. echo $body->ftell();
  114. // >>> 0