08_chunked_encoding.qbk 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. [/
  2. Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. Official repository: https://github.com/boostorg/beast
  6. ]
  7. [section Chunked Encoding]
  8. For message payloads whose size is not known ahead of time, HTTP
  9. version 1.1 defines the
  10. [@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked]]
  11. transfer coding. This coding consists of zero or more
  12. [@https://tools.ietf.org/html/rfc7230#section-4.1 ['chunked bodies]],
  13. followed by a
  14. [@https://tools.ietf.org/html/rfc7230#section-4.1 ['last chunk]].
  15. Each chunked body may contain optional application-defined, connection-specific
  16. [@https://tools.ietf.org/html/rfc7230#section-4.1.1 ['chunk-extensions]].
  17. The last chunk may contain additional HTTP field values in a section
  18. of the last chunk called a
  19. [@https://tools.ietf.org/html/rfc7230#section-4.1.2 ['chunk-trailer]].
  20. The field values are "promised" in the header as a comma delimited list
  21. of field names in the
  22. [@https://tools.ietf.org/html/rfc7230#section-4.4 [*Trailer]]
  23. field value. Clients indicate their willingness to accept trailers
  24. by including the "trailers" token in the
  25. [@https://tools.ietf.org/html/rfc7230#section-4.3 [*TE]]
  26. field value.
  27. [heading Serializing Chunks]
  28. The __serializer__ automatically applies the chunked transfer encoding
  29. when a message returns `true` from
  30. [link beast.ref.boost__beast__http__message.chunked.overload1 `message::chunked`].
  31. The boundaries between chunks emitted by the serializer are implementation
  32. defined. Chunk extensions and trailers are omitted. Applications which
  33. need precise control over the chunk boundaries, extensions, and trailers
  34. may use a set of helper classes which enable manual emission of message
  35. payloads using chunk encoding.
  36. To use these helper classes, first serialize the header portion of the
  37. message using the standard interface. Then prepare the buffers, chunk
  38. extensions, and desired trailers, and use them with these helpers:
  39. [table Chunking Helpers
  40. [[Name][Description]]
  41. [
  42. [[link beast.ref.boost__beast__http__chunk_body `chunk_body`]]
  43. [
  44. A buffer sequence representing a complete chunk body.
  45. ]
  46. ][
  47. [[link beast.ref.boost__beast__http__chunk_crlf `chunk_crlf`]]
  48. [
  49. A buffer sequence representing the CRLF (`"\r\n"`) delimiter.
  50. This class is used when the caller desires to emit the
  51. chunk body in two or more individual stream operations.
  52. ]
  53. ][
  54. [
  55. [link beast.ref.boost__beast__http__chunk_extensions `chunk_extensions`]
  56. [link beast.ref.boost__beast__http__basic_chunk_extensions `basic_chunk_extensions`]
  57. ]
  58. [
  59. This is a simple, allocating container which lets callers
  60. easily build up a set of chunk extensions.
  61. ]
  62. ][
  63. [[link beast.ref.boost__beast__http__chunk_header `chunk_header`]]
  64. [
  65. A buffer sequence representing a hex-encoded chunk size,
  66. followed by an optional set of chunk extensions, including
  67. the terminating CRLF (`"\r\n"`) delimiter which precedes
  68. the chunk body. This class is used when the caller desires
  69. to emit the chunk body in two or more individual stream
  70. operations.
  71. ]
  72. ][
  73. [[link beast.ref.boost__beast__http__chunk_last `chunk_last`]]
  74. [
  75. A buffer sequence representing a last chunk. The last chunk
  76. indicates the end of the chunked message payload, and may
  77. contain optional trailer fields.
  78. ]
  79. ][
  80. [
  81. [link beast.ref.boost__beast__http__make_chunk `make_chunk`]
  82. [link beast.ref.boost__beast__http__make_chunk_last `make_chunk_last`]
  83. ]
  84. [
  85. These helper functions are used to construct a chunk
  86. or last chunk directly at call sites.
  87. ]
  88. ]]
  89. We demonstrate the use of these objects first by declaring a function
  90. which returns the next buffer sequence to use as a chunk body:
  91. [http_snippet_17]
  92. This example demonstrates sending a complete chunked message payload
  93. manually. No chunk extensions or trailers are emitted:
  94. [http_snippet_18]
  95. The following code sends additional chunks, and sets chunk extensions
  96. using the helper container. The container automatically quotes values
  97. in the serialized output when necessary:
  98. [http_snippet_19]
  99. Callers can take over the generation and management of the extensions
  100. buffer by passing a non-owning string. Note that this requires the
  101. string contents to adhere to the correct syntax for chunk extensions,
  102. including the needed double quotes for values which contain spaces:
  103. [http_snippet_20]
  104. The next code sample emits a chunked response which promises two
  105. trailer fields and delivers them in the last chunk. The implementation
  106. allocates memory using the default or a passed-in allocator to hold
  107. the state information required to serialize the trailer:
  108. [http_snippet_21]
  109. Using a custom allocator to serialize the last chunk:
  110. [http_snippet_22]
  111. Alternatively, callers can take over the generation and lifetime
  112. management of the serialized trailer fields by passing in a non-owning
  113. string:
  114. [http_snippet_23]
  115. For the ultimate level of control, a caller can manually compose the
  116. chunk itself by first emitting a header with the correct chunk body
  117. size, and then by emitting the chunk body in multiple calls to the
  118. stream write function. In this case the caller is responsible for
  119. also emitting the terminating CRLF (`"\r\n"`):
  120. [http_snippet_24]
  121. [heading Parsing Chunks]
  122. The __parser__ automatically removes the chunked transfer coding when
  123. it is the last encoding in the list. However, it also discards the
  124. chunk extensions and does not provide a way to determine the boundaries
  125. between chunks. Advanced applications which need to access the chunk
  126. extensions or read complete individual chunks may use a callback
  127. interface provided by __parser__:
  128. [table Chunking Parse Callbacks
  129. [[Name][Description]]
  130. [
  131. [[link beast.ref.boost__beast__http__parser.on_chunk_header `on_chunk_header`]]
  132. [
  133. Set a callback to be invoked on each chunk header.
  134. The callback will be invoked once for every chunk in the message
  135. payload, as well as once for the last chunk. The invocation
  136. happens after the chunk header is available but before any body
  137. octets have been parsed.
  138. The extensions are provided in raw, validated form, use
  139. [link beast.ref.boost__beast__http__basic_chunk_extensions.parse `chunk_extensions::parse`]
  140. to parse the extensions into a structured container for easier access.
  141. The implementation type-erases the callback without requiring
  142. a dynamic allocation. For this reason, the callback object is
  143. passed by a non-constant reference.
  144. The function object will be called with this equivalent signature:
  145. ```
  146. void
  147. callback(
  148. std::uint64_t size, // Size of the chunk, zero for the last chunk
  149. string_view extensions, // The chunk-extensions in raw form
  150. error_code& ec); // May be set by the callback to indicate an error
  151. ```
  152. ]
  153. ][
  154. [[link beast.ref.boost__beast__http__parser.on_chunk_body `on_chunk_body`]]
  155. [
  156. Set a callback to be invoked on chunk body data.
  157. The callback will be invoked one or more times to provide
  158. buffers corresponding to the chunk body for the current chunk.
  159. The callback receives the number of octets remaining in this
  160. chunk body including the octets in the buffer provided.
  161. The callback must return the number of octets actually consumed.
  162. Any octets not consumed will be presented again in a subsequent
  163. invocation of the callback.
  164. The implementation type-erases the callback without requiring
  165. a dynamic allocation. For this reason, the callback object is
  166. passed by a non-constant reference.
  167. The function object will be called with this equivalent signature:
  168. ```
  169. std::size_t
  170. callback(
  171. std::uint64_t remain, // Octets remaining in this chunk, includes `body`
  172. string_view body, // A buffer holding some or all of the remainder of the chunk body
  173. error_code& ec); // May be set by the callback to indicate an error
  174. ```
  175. ]
  176. ]]
  177. This example will read a message header from the stream, and then manually
  178. read each chunk. It recognizes the chunk boundaries and outputs the contents
  179. of each chunk as it comes in. Any chunk extensions are printed, each extension
  180. on its own line. Finally, any trailers promised in the header are printed.
  181. [example_chunk_parsing]
  182. Given the HTTP response as input on the left, the output of the function shown
  183. above is shown on the right:
  184. [table Chunk Parsing Example Output
  185. [[Input][Output]]
  186. [
  187. [
  188. ```
  189. HTTP/1.1 200 OK\r\n
  190. Server: test\r\n
  191. Trailer: Expires, Content-MD5\r\n
  192. Transfer-Encoding: chunked\r\n
  193. \r\n
  194. 5\r\n
  195. First\r\n
  196. d;quality=1.0\r\n
  197. Hello, world!\r\n
  198. e;file=abc.txt;quality=0.7\r\n
  199. The Next Chunk\r\n
  200. 8;last\r\n
  201. Last one\r\n
  202. 0\r\n
  203. Expires: never\r\n
  204. Content-MD5: f4a5c16584f03d90\r\n
  205. \r\n
  206. ```
  207. ]
  208. [
  209. ```
  210. Chunk Body: First
  211. Extension: quality = 1.0
  212. Chunk Body: Hello, world!
  213. Extension: file = abc.txt
  214. Extension: quality = 0.7
  215. Chunk Body: The Next Chunk
  216. Extension: last
  217. Chunk Body: Last one
  218. Expires: never
  219. Content-MD5: f4a5c16584f03d90
  220. ```
  221. ]
  222. ]]
  223. [endsect]