1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Buffer-Oriented Parsing</title> 5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../../index.html" title="Chapter 1. Boost.Beast"> 8<link rel="up" href="../using_http.html" title="HTTP"> 9<link rel="prev" href="buffer_oriented_serializing.html" title="Buffer-Oriented Serializing"> 10<link rel="next" href="chunked_encoding.html" title="Chunked Encoding"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="buffer_oriented_serializing.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_http.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="chunked_encoding.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h3 class="title"> 27<a name="beast.using_http.buffer_oriented_parsing"></a><a class="link" href="buffer_oriented_parsing.html" title="Buffer-Oriented Parsing">Buffer-Oriented 28 Parsing</a> 29</h3></div></div></div> 30<p> 31 A subclass of <a class="link" href="../ref/boost__beast__http__basic_parser.html" title="http::basic_parser"><code class="computeroutput"><span class="identifier">basic_parser</span></code></a> can be invoked directly, 32 without using the provided stream operations. This could be useful for implementing 33 algorithms on objects whose interface does not conform to <a class="link" href="../concepts/streams.html" title="Streams"><span class="emphasis"><em>Stream</em></span></a>. 34 For example, a <a href="http://zeromq.org/" target="_top"><span class="bold"><strong>ZeroMQ</strong></span> 35 socket</a>. The basic parser interface is interactive; the caller invokes 36 the function <a class="link" href="../ref/boost__beast__http__basic_parser/put.html" title="http::basic_parser::put"><code class="computeroutput"><span class="identifier">basic_parser</span><span class="special">::</span><span class="identifier">put</span></code></a> repeatedly with buffers until 37 an error occurs or the parsing is done. The function <a class="link" href="../ref/boost__beast__http__basic_parser/put_eof.html" title="http::basic_parser::put_eof"><code class="computeroutput"><span class="identifier">basic_parser</span><span class="special">::</span><span class="identifier">put_eof</span></code></a> Is used when the caller 38 knows that there will never be more data (for example, if the underlying 39 connection is closed), 40 </p> 41<h5> 42<a name="beast.using_http.buffer_oriented_parsing.h0"></a> 43 <span class="phrase"><a name="beast.using_http.buffer_oriented_parsing.parser_options"></a></span><a class="link" href="buffer_oriented_parsing.html#beast.using_http.buffer_oriented_parsing.parser_options">Parser 44 Options</a> 45 </h5> 46<p> 47 The parser provides a few options which may be set before parsing begins: 48 </p> 49<div class="table"> 50<a name="beast.using_http.buffer_oriented_parsing.parser_options0"></a><p class="title"><b>Table 1.24. Parser Options</b></p> 51<div class="table-contents"><table class="table" summary="Parser Options"> 52<colgroup> 53<col> 54<col> 55<col> 56</colgroup> 57<thead><tr> 58<th> 59 <p> 60 Name 61 </p> 62 </th> 63<th> 64 <p> 65 Default 66 </p> 67 </th> 68<th> 69 <p> 70 Description 71 </p> 72 </th> 73</tr></thead> 74<tbody> 75<tr> 76<td> 77 <p> 78 <a class="link" href="../ref/boost__beast__http__basic_parser/eager/overload2.html" title="http::basic_parser::eager (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">eager</span></code></a> 79 </p> 80 </td> 81<td> 82 <p> 83 <code class="computeroutput"><span class="keyword">false</span></code> 84 </p> 85 </td> 86<td> 87 <p> 88 Normally the parser returns after successfully parsing a structured 89 element (header, chunk header, or chunk body) even if there are 90 octets remaining in the input. This is necessary when attempting 91 to parse the header first, or when the caller wants to inspect 92 information which may be invalidated by subsequent parsing, such 93 as a chunk extension. The <code class="computeroutput"><span class="identifier">eager</span></code> 94 option controls whether the parser keeps going after parsing structured 95 element if there are octets remaining in the buffer and no error 96 occurs. This option is automatically set or cleared during certain 97 stream operations to improve performance with no change in functionality. 98 </p> 99 </td> 100</tr> 101<tr> 102<td> 103 <p> 104 <a class="link" href="../ref/boost__beast__http__basic_parser/skip/overload2.html" title="http::basic_parser::skip (2 of 2 overloads)"><code class="computeroutput"><span class="identifier">skip</span></code></a> 105 </p> 106 </td> 107<td> 108 <p> 109 <code class="computeroutput"><span class="keyword">false</span></code> 110 </p> 111 </td> 112<td> 113 <p> 114 This option controls whether or not the parser expects to see an 115 HTTP body, regardless of the presence or absence of certain fields 116 such as Content-Length or a chunked Transfer-Encoding. Depending 117 on the request, some responses do not carry a body. For example, 118 a 200 response to a <a href="https://tools.ietf.org/html/rfc7231#section-4.3.6" target="_top">CONNECT</a> 119 request from a tunneling proxy, or a response to a <a href="https://tools.ietf.org/html/rfc7231#section-4.3.2" target="_top">HEAD</a> 120 request. In these cases, callers may use this function inform the 121 parser that no body is expected. The parser will consider the message 122 complete after the header has been received. 123 </p> 124 </td> 125</tr> 126<tr> 127<td> 128 <p> 129 <a class="link" href="../ref/boost__beast__http__basic_parser/body_limit.html" title="http::basic_parser::body_limit"><code class="computeroutput"><span class="identifier">body_limit</span></code></a> 130 </p> 131 </td> 132<td> 133 <p> 134 1MB/8MB 135 </p> 136 </td> 137<td> 138 <p> 139 This function sets the maximum allowed size of the content body. 140 When a body larger than the specified size is detected, an error 141 is generated and parsing terminates. This setting helps protect 142 servers from resource exhaustion attacks. The default limit when 143 parsing requests is 1MB, and for parsing responses 8MB. 144 </p> 145 </td> 146</tr> 147<tr> 148<td> 149 <p> 150 <a class="link" href="../ref/boost__beast__http__basic_parser/header_limit.html" title="http::basic_parser::header_limit"><code class="computeroutput"><span class="identifier">header_limit</span></code></a> 151 </p> 152 </td> 153<td> 154 <p> 155 8KB 156 </p> 157 </td> 158<td> 159 <p> 160 This function sets the maximum allowed size of the header including 161 all field name, value, and delimiter characters and also including 162 the CRLF sequences in the serialized input. 163 </p> 164 </td> 165</tr> 166</tbody> 167</table></div> 168</div> 169<br class="table-break"><div class="section"> 170<div class="titlepage"><div><div><h4 class="title"> 171<a name="beast.using_http.buffer_oriented_parsing.read_from_std_istream"></a><a class="link" href="buffer_oriented_parsing.html#beast.using_http.buffer_oriented_parsing.read_from_std_istream" title="Read From std::istream ">Read 172 From std::istream </a> 173</h4></div></div></div> 174<p> 175 The standard library provides the type <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code> 176 for performing high level read operations on character streams. The variable 177 <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">cin</span></code> is based on this input stream. This 178 example uses the buffer oriented interface of <a class="link" href="../ref/boost__beast__http__basic_parser.html" title="http::basic_parser"><code class="computeroutput"><span class="identifier">basic_parser</span></code></a> to build a stream 179 operation which parses an HTTP message from a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code>: 180 </p> 181<pre class="programlisting"><span class="comment">/** Read a message from a `std::istream`. 182 183 This function attempts to parse a complete HTTP/1 message from the stream. 184 185 @param is The `std::istream` to read from. 186 187 @param buffer The buffer to use. 188 189 @param msg The message to store the result. 190 191 @param ec Set to the error, if any occurred. 192*/</span> 193<span class="keyword">template</span><span class="special"><</span> 194 <span class="keyword">class</span> <span class="identifier">Allocator</span><span class="special">,</span> 195 <span class="keyword">bool</span> <span class="identifier">isRequest</span><span class="special">,</span> 196 <span class="keyword">class</span> <span class="identifier">Body</span><span class="special">></span> 197<span class="keyword">void</span> 198<span class="identifier">read_istream</span><span class="special">(</span> 199 <span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&</span> <span class="identifier">is</span><span class="special">,</span> 200 <span class="identifier">basic_flat_buffer</span><span class="special"><</span><span class="identifier">Allocator</span><span class="special">>&</span> <span class="identifier">buffer</span><span class="special">,</span> 201 <span class="identifier">message</span><span class="special"><</span><span class="identifier">isRequest</span><span class="special">,</span> <span class="identifier">Body</span><span class="special">,</span> <span class="identifier">fields</span><span class="special">>&</span> <span class="identifier">msg</span><span class="special">,</span> 202 <span class="identifier">error_code</span><span class="special">&</span> <span class="identifier">ec</span><span class="special">)</span> 203<span class="special">{</span> 204 <span class="comment">// Create the message parser</span> 205 <span class="comment">//</span> 206 <span class="comment">// Arguments passed to the parser's constructor are</span> 207 <span class="comment">// forwarded to the message constructor. Here, we use</span> 208 <span class="comment">// a move construction in case the caller has constructed</span> 209 <span class="comment">// their message in a non-default way.</span> 210 <span class="comment">//</span> 211 <span class="identifier">parser</span><span class="special"><</span><span class="identifier">isRequest</span><span class="special">,</span> <span class="identifier">Body</span><span class="special">></span> <span class="identifier">p</span><span class="special">{</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">msg</span><span class="special">)};</span> 212 213 <span class="keyword">do</span> 214 <span class="special">{</span> 215 <span class="comment">// Extract whatever characters are presently available in the istream</span> 216 <span class="keyword">if</span><span class="special">(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">rdbuf</span><span class="special">()-></span><span class="identifier">in_avail</span><span class="special">()</span> <span class="special">></span> <span class="number">0</span><span class="special">)</span> 217 <span class="special">{</span> 218 <span class="comment">// Get a mutable buffer sequence for writing</span> 219 <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">prepare</span><span class="special">(</span> 220 <span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">>(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">rdbuf</span><span class="special">()-></span><span class="identifier">in_avail</span><span class="special">()));</span> 221 222 <span class="comment">// Now get everything we can from the istream</span> 223 <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">commit</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">>(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">readsome</span><span class="special">(</span> 224 <span class="keyword">reinterpret_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">b</span><span class="special">.</span><span class="identifier">data</span><span class="special">()),</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">size</span><span class="special">())));</span> 225 <span class="special">}</span> 226 <span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span> <span class="special">==</span> <span class="number">0</span><span class="special">)</span> 227 <span class="special">{</span> 228 <span class="comment">// Our buffer is empty and we need more characters, </span> 229 <span class="comment">// see if we've reached the end of file on the istream</span> 230 <span class="keyword">if</span><span class="special">(!</span> <span class="identifier">is</span><span class="special">.</span><span class="identifier">eof</span><span class="special">())</span> 231 <span class="special">{</span> 232 <span class="comment">// Get a mutable buffer sequence for writing</span> 233 <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">b</span> <span class="special">=</span> <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">prepare</span><span class="special">(</span><span class="number">1024</span><span class="special">);</span> 234 235 <span class="comment">// Try to get more from the istream. This might block.</span> 236 <span class="identifier">is</span><span class="special">.</span><span class="identifier">read</span><span class="special">(</span><span class="keyword">reinterpret_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">b</span><span class="special">.</span><span class="identifier">data</span><span class="special">()),</span> <span class="identifier">b</span><span class="special">.</span><span class="identifier">size</span><span class="special">());</span> 237 238 <span class="comment">// If an error occurs on the istream then return it to the caller.</span> 239 <span class="keyword">if</span><span class="special">(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">fail</span><span class="special">()</span> <span class="special">&&</span> <span class="special">!</span> <span class="identifier">is</span><span class="special">.</span><span class="identifier">eof</span><span class="special">())</span> 240 <span class="special">{</span> 241 <span class="comment">// We'll just re-use io_error since std::istream has no error_code interface.</span> 242 <span class="identifier">ec</span> <span class="special">=</span> <span class="identifier">make_error_code</span><span class="special">(</span><span class="identifier">errc</span><span class="special">::</span><span class="identifier">io_error</span><span class="special">);</span> 243 <span class="keyword">return</span><span class="special">;</span> 244 <span class="special">}</span> 245 246 <span class="comment">// Commit the characters we got to the buffer.</span> 247 <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">commit</span><span class="special">(</span><span class="keyword">static_cast</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">>(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">gcount</span><span class="special">()));</span> 248 <span class="special">}</span> 249 <span class="keyword">else</span> 250 <span class="special">{</span> 251 <span class="comment">// Inform the parser that we've reached the end of the istream.</span> 252 <span class="identifier">p</span><span class="special">.</span><span class="identifier">put_eof</span><span class="special">(</span><span class="identifier">ec</span><span class="special">);</span> 253 <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span> 254 <span class="keyword">return</span><span class="special">;</span> 255 <span class="keyword">break</span><span class="special">;</span> 256 <span class="special">}</span> 257 <span class="special">}</span> 258 259 <span class="comment">// Write the data to the parser</span> 260 <span class="keyword">auto</span> <span class="keyword">const</span> <span class="identifier">bytes_used</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">put</span><span class="special">(</span><span class="identifier">buffer</span><span class="special">.</span><span class="identifier">data</span><span class="special">(),</span> <span class="identifier">ec</span><span class="special">);</span> 261 262 <span class="comment">// This error means that the parser needs additional octets.</span> 263 <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span> <span class="special">==</span> <span class="identifier">error</span><span class="special">::</span><span class="identifier">need_more</span><span class="special">)</span> 264 <span class="identifier">ec</span> <span class="special">=</span> <span class="special">{};</span> 265 <span class="keyword">if</span><span class="special">(</span><span class="identifier">ec</span><span class="special">)</span> 266 <span class="keyword">return</span><span class="special">;</span> 267 268 <span class="comment">// Consume the buffer octets that were actually parsed.</span> 269 <span class="identifier">buffer</span><span class="special">.</span><span class="identifier">consume</span><span class="special">(</span><span class="identifier">bytes_used</span><span class="special">);</span> 270 <span class="special">}</span> 271 <span class="keyword">while</span><span class="special">(!</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">is_done</span><span class="special">());</span> 272 273 <span class="comment">// Transfer ownership of the message container in the parser to the caller.</span> 274 <span class="identifier">msg</span> <span class="special">=</span> <span class="identifier">p</span><span class="special">.</span><span class="identifier">release</span><span class="special">();</span> 275<span class="special">}</span> 276</pre> 277<div class="tip"><table border="0" summary="Tip"> 278<tr> 279<td rowspan="2" align="center" valign="top" width="25"><img alt="[Tip]" src="../../../../../../doc/src/images/tip.png"></td> 280<th align="left">Tip</th> 281</tr> 282<tr><td align="left" valign="top"><p> 283 Parsing from a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code> could be implemented using 284 an alternate strategy: adapt the <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span></code> 285 interface to a <a href="../../../../../../doc/html/boost_asio/reference/SyncReadStream.html" target="_top"><span class="emphasis"><em>SyncReadStream</em></span></a>, 286 enabling use with the library's existing stream algorithms. This is left 287 as an exercise for the reader. 288 </p></td></tr> 289</table></div> 290</div> 291</div> 292<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 293<td align="left"></td> 294<td align="right"><div class="copyright-footer">Copyright © 2016-2019 Vinnie 295 Falco<p> 296 Distributed under the Boost Software License, Version 1.0. (See accompanying 297 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 298 </p> 299</div></td> 300</tr></table> 301<hr> 302<div class="spirit-nav"> 303<a accesskey="p" href="buffer_oriented_serializing.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../using_http.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="chunked_encoding.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a> 304</div> 305</body> 306</html> 307