| 1 | // |
| 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) |
| 3 | // |
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| 6 | // |
| 7 | // Official repository: https://github.com/boostorg/beast |
| 8 | // |
| 9 | |
| 10 | #ifndef BOOST_BEAST_HTTP_BASIC_PARSER_HPP |
| 11 | #define BOOST_BEAST_HTTP_BASIC_PARSER_HPP |
| 12 | |
| 13 | #include <boost/beast/core/detail/config.hpp> |
| 14 | #include <boost/beast/core/error.hpp> |
| 15 | #include <boost/beast/core/string.hpp> |
| 16 | #include <boost/beast/http/field.hpp> |
| 17 | #include <boost/beast/http/verb.hpp> |
| 18 | #include <boost/beast/http/detail/basic_parser.hpp> |
| 19 | #include <boost/asio/buffer.hpp> |
| 20 | #include <boost/optional.hpp> |
| 21 | #include <boost/assert.hpp> |
| 22 | #include <cstdint> |
| 23 | #include <limits> |
| 24 | #include <memory> |
| 25 | #include <type_traits> |
| 26 | #include <utility> |
| 27 | |
| 28 | namespace boost { |
| 29 | namespace beast { |
| 30 | namespace http { |
| 31 | |
| 32 | /** A parser for decoding HTTP/1 wire format messages. |
| 33 | |
| 34 | This parser is designed to efficiently parse messages in the |
| 35 | HTTP/1 wire format. It allocates no memory when input is |
| 36 | presented as a single contiguous buffer, and uses minimal |
| 37 | state. It will handle chunked encoding and it understands |
| 38 | the semantics of the Connection, Content-Length, and Upgrade |
| 39 | fields. |
| 40 | The parser is optimized for the case where the input buffer |
| 41 | sequence consists of a single contiguous buffer. The |
| 42 | @ref beast::basic_flat_buffer class is provided, which guarantees |
| 43 | that the input sequence of the stream buffer will be represented |
| 44 | by exactly one contiguous buffer. To ensure the optimum performance |
| 45 | of the parser, use @ref beast::basic_flat_buffer with HTTP algorithms |
| 46 | such as @ref read, @ref read_some, @ref async_read, and @ref async_read_some. |
| 47 | Alternatively, the caller may use custom techniques to ensure that |
| 48 | the structured portion of the HTTP message (header or chunk header) |
| 49 | is contained in a linear buffer. |
| 50 | |
| 51 | The interface to the parser uses virtual member functions. |
| 52 | To use this class, derive your type from @ref basic_parser. When |
| 53 | bytes are presented, the implementation will make a series of zero |
| 54 | or more calls to virtual functions, which the derived class must |
| 55 | implement. |
| 56 | |
| 57 | Every virtual function must be provided by the derived class, |
| 58 | or else a compilation error will be generated. The implementation |
| 59 | will make sure that `ec` is clear before each virtual function |
| 60 | is invoked. If a virtual function sets an error, it is propagated |
| 61 | out of the parser to the caller. |
| 62 | |
| 63 | @tparam isRequest A `bool` indicating whether the parser will be |
| 64 | presented with request or response message. |
| 65 | |
| 66 | @note If the parser encounters a field value with obs-fold |
| 67 | longer than 4 kilobytes in length, an error is generated. |
| 68 | */ |
| 69 | template<bool isRequest> |
| 70 | class basic_parser |
| 71 | : private detail::basic_parser_base |
| 72 | { |
| 73 | boost::optional<std::uint64_t> |
| 74 | body_limit_ = |
| 75 | boost::optional<std::uint64_t>( |
| 76 | default_body_limit(is_request{})); // max payload body |
| 77 | std::uint64_t len_ = 0; // size of chunk or body |
| 78 | std::uint64_t len0_ = 0; // content length if known |
| 79 | std::unique_ptr<char[]> buf_; // temp storage |
| 80 | std::size_t buf_len_ = 0; // size of buf_ |
| 81 | std::size_t skip_ = 0; // resume search here |
| 82 | std::uint32_t = 8192; // max header size |
| 83 | unsigned short status_ = 0; // response status |
| 84 | state state_ = state::nothing_yet; // initial state |
| 85 | unsigned f_ = 0; // flags |
| 86 | |
| 87 | // limit on the size of the stack flat buffer |
| 88 | static std::size_t constexpr max_stack_buffer = 8192; |
| 89 | |
| 90 | // Message will be complete after reading header |
| 91 | static unsigned constexpr flagSkipBody = 1<< 0; |
| 92 | |
| 93 | // Consume input buffers across semantic boundaries |
| 94 | static unsigned constexpr flagEager = 1<< 1; |
| 95 | |
| 96 | // The parser has read at least one byte |
| 97 | static unsigned constexpr flagGotSome = 1<< 2; |
| 98 | |
| 99 | // Message semantics indicate a body is expected. |
| 100 | // cleared if flagSkipBody set |
| 101 | // |
| 102 | static unsigned constexpr flagHasBody = 1<< 3; |
| 103 | |
| 104 | static unsigned constexpr flagHTTP11 = 1<< 4; |
| 105 | static unsigned constexpr flagNeedEOF = 1<< 5; |
| 106 | static unsigned constexpr flagExpectCRLF = 1<< 6; |
| 107 | static unsigned constexpr flagConnectionClose = 1<< 7; |
| 108 | static unsigned constexpr flagConnectionUpgrade = 1<< 8; |
| 109 | static unsigned constexpr flagConnectionKeepAlive = 1<< 9; |
| 110 | static unsigned constexpr flagContentLength = 1<< 10; |
| 111 | static unsigned constexpr flagChunked = 1<< 11; |
| 112 | static unsigned constexpr flagUpgrade = 1<< 12; |
| 113 | static unsigned constexpr flagFinalChunk = 1<< 13; |
| 114 | |
| 115 | static constexpr |
| 116 | std::uint64_t |
| 117 | default_body_limit(std::true_type) |
| 118 | { |
| 119 | // limit for requests |
| 120 | return 1 * 1024 * 1024; // 1MB |
| 121 | } |
| 122 | |
| 123 | static constexpr |
| 124 | std::uint64_t |
| 125 | default_body_limit(std::false_type) |
| 126 | { |
| 127 | // limit for responses |
| 128 | return 8 * 1024 * 1024; // 8MB |
| 129 | } |
| 130 | |
| 131 | template<bool OtherIsRequest> |
| 132 | friend class basic_parser; |
| 133 | |
| 134 | #ifndef BOOST_BEAST_DOXYGEN |
| 135 | friend class basic_parser_test; |
| 136 | #endif |
| 137 | |
| 138 | protected: |
| 139 | /// Default constructor |
| 140 | basic_parser() = default; |
| 141 | |
| 142 | /** Move constructor |
| 143 | |
| 144 | @note |
| 145 | |
| 146 | After the move, the only valid operation on the |
| 147 | moved-from object is destruction. |
| 148 | */ |
| 149 | basic_parser(basic_parser &&) = default; |
| 150 | |
| 151 | /// Move assignment |
| 152 | basic_parser& operator=(basic_parser &&) = default; |
| 153 | |
| 154 | public: |
| 155 | /// `true` if this parser parses requests, `false` for responses. |
| 156 | using is_request = |
| 157 | std::integral_constant<bool, isRequest>; |
| 158 | |
| 159 | /// Destructor |
| 160 | virtual ~basic_parser() = default; |
| 161 | |
| 162 | /// Copy constructor |
| 163 | basic_parser(basic_parser const&) = delete; |
| 164 | |
| 165 | /// Copy assignment |
| 166 | basic_parser& operator=(basic_parser const&) = delete; |
| 167 | |
| 168 | /// Returns `true` if the parser has received at least one byte of input. |
| 169 | bool |
| 170 | got_some() const |
| 171 | { |
| 172 | return state_ != state::nothing_yet; |
| 173 | } |
| 174 | |
| 175 | /** Returns `true` if the message is complete. |
| 176 | |
| 177 | The message is complete after the full header is prduced |
| 178 | and one of the following is true: |
| 179 | |
| 180 | @li The skip body option was set. |
| 181 | |
| 182 | @li The semantics of the message indicate there is no body. |
| 183 | |
| 184 | @li The semantics of the message indicate a body is expected, |
| 185 | and the entire body was parsed. |
| 186 | */ |
| 187 | bool |
| 188 | is_done() const |
| 189 | { |
| 190 | return state_ == state::complete; |
| 191 | } |
| 192 | |
| 193 | /** Returns `true` if a the parser has produced the full header. |
| 194 | */ |
| 195 | bool |
| 196 | () const |
| 197 | { |
| 198 | return state_ > state::fields; |
| 199 | } |
| 200 | |
| 201 | /** Returns `true` if the message is an upgrade message. |
| 202 | |
| 203 | @note The return value is undefined unless |
| 204 | @ref is_header_done would return `true`. |
| 205 | */ |
| 206 | bool |
| 207 | upgrade() const |
| 208 | { |
| 209 | return (f_ & flagConnectionUpgrade) != 0; |
| 210 | } |
| 211 | |
| 212 | /** Returns `true` if the last value for Transfer-Encoding is "chunked". |
| 213 | |
| 214 | @note The return value is undefined unless |
| 215 | @ref is_header_done would return `true`. |
| 216 | */ |
| 217 | bool |
| 218 | chunked() const |
| 219 | { |
| 220 | return (f_ & flagChunked) != 0; |
| 221 | } |
| 222 | |
| 223 | /** Returns `true` if the message has keep-alive connection semantics. |
| 224 | |
| 225 | This function always returns `false` if @ref need_eof would return |
| 226 | `false`. |
| 227 | |
| 228 | @note The return value is undefined unless |
| 229 | @ref is_header_done would return `true`. |
| 230 | */ |
| 231 | bool |
| 232 | keep_alive() const; |
| 233 | |
| 234 | /** Returns the optional value of Content-Length if known. |
| 235 | |
| 236 | @note The return value is undefined unless |
| 237 | @ref is_header_done would return `true`. |
| 238 | */ |
| 239 | boost::optional<std::uint64_t> |
| 240 | content_length() const; |
| 241 | |
| 242 | /** Returns the remaining content length if known |
| 243 | |
| 244 | If the message header specifies a Content-Length, |
| 245 | the return value will be the number of bytes remaining |
| 246 | in the payload body have not yet been parsed. |
| 247 | |
| 248 | @note The return value is undefined unless |
| 249 | @ref is_header_done would return `true`. |
| 250 | */ |
| 251 | boost::optional<std::uint64_t> |
| 252 | content_length_remaining() const; |
| 253 | |
| 254 | /** Returns `true` if the message semantics require an end of file. |
| 255 | |
| 256 | Depending on the contents of the header, the parser may |
| 257 | require and end of file notification to know where the end |
| 258 | of the body lies. If this function returns `true` it will be |
| 259 | necessary to call @ref put_eof when there will never be additional |
| 260 | data from the input. |
| 261 | */ |
| 262 | bool |
| 263 | need_eof() const |
| 264 | { |
| 265 | return (f_ & flagNeedEOF) != 0; |
| 266 | } |
| 267 | |
| 268 | /** Set the limit on the payload body. |
| 269 | |
| 270 | This function sets the maximum allowed size of the payload body, |
| 271 | before any encodings except chunked have been removed. Depending |
| 272 | on the message semantics, one of these cases will apply: |
| 273 | |
| 274 | @li The Content-Length is specified and exceeds the limit. In |
| 275 | this case the result @ref error::body_limit is returned |
| 276 | immediately after the header is parsed. |
| 277 | |
| 278 | @li The Content-Length is unspecified and the chunked encoding |
| 279 | is not specified as the last encoding. In this case the end of |
| 280 | message is determined by the end of file indicator on the |
| 281 | associated stream or input source. If a sufficient number of |
| 282 | body payload octets are presented to the parser to exceed the |
| 283 | configured limit, the parse fails with the result |
| 284 | @ref error::body_limit |
| 285 | |
| 286 | @li The Transfer-Encoding specifies the chunked encoding as the |
| 287 | last encoding. In this case, when the number of payload body |
| 288 | octets produced by removing the chunked encoding exceeds |
| 289 | the configured limit, the parse fails with the result |
| 290 | @ref error::body_limit. |
| 291 | |
| 292 | Setting the limit after any body octets have been parsed |
| 293 | results in undefined behavior. |
| 294 | |
| 295 | The default limit is 1MB for requests and 8MB for responses. |
| 296 | |
| 297 | @param v An optional integral value representing the body limit. |
| 298 | If this is equal to `boost::none`, then the body limit is disabled. |
| 299 | */ |
| 300 | void |
| 301 | body_limit(boost::optional<std::uint64_t> v) |
| 302 | { |
| 303 | body_limit_ = v; |
| 304 | } |
| 305 | |
| 306 | /** Set a limit on the total size of the header. |
| 307 | |
| 308 | This function sets the maximum allowed size of the header |
| 309 | including all field name, value, and delimiter characters |
| 310 | and also including the CRLF sequences in the serialized |
| 311 | input. If the end of the header is not found within the |
| 312 | limit of the header size, the error @ref error::header_limit |
| 313 | is returned by @ref put. |
| 314 | |
| 315 | Setting the limit after any header octets have been parsed |
| 316 | results in undefined behavior. |
| 317 | */ |
| 318 | void |
| 319 | (std::uint32_t v) |
| 320 | { |
| 321 | header_limit_ = v; |
| 322 | } |
| 323 | |
| 324 | /// Returns `true` if the eager parse option is set. |
| 325 | bool |
| 326 | eager() const |
| 327 | { |
| 328 | return (f_ & flagEager) != 0; |
| 329 | } |
| 330 | |
| 331 | /** Set the eager parse option. |
| 332 | |
| 333 | Normally the parser returns after successfully parsing a structured |
| 334 | element (header, chunk header, or chunk body) even if there are octets |
| 335 | remaining in the input. This is necessary when attempting to parse the |
| 336 | header first, or when the caller wants to inspect information which may |
| 337 | be invalidated by subsequent parsing, such as a chunk extension. The |
| 338 | `eager` option controls whether the parser keeps going after parsing |
| 339 | structured element if there are octets remaining in the buffer and no |
| 340 | error occurs. This option is automatically set or cleared during certain |
| 341 | stream operations to improve performance with no change in functionality. |
| 342 | |
| 343 | The default setting is `false`. |
| 344 | |
| 345 | @param v `true` to set the eager parse option or `false` to disable it. |
| 346 | */ |
| 347 | void |
| 348 | eager(bool v) |
| 349 | { |
| 350 | if(v) |
| 351 | f_ |= flagEager; |
| 352 | else |
| 353 | f_ &= ~flagEager; |
| 354 | } |
| 355 | |
| 356 | /// Returns `true` if the skip parse option is set. |
| 357 | bool |
| 358 | skip() const |
| 359 | { |
| 360 | return (f_ & flagSkipBody) != 0; |
| 361 | } |
| 362 | |
| 363 | /** Set the skip parse option. |
| 364 | |
| 365 | This option controls whether or not the parser expects to see an HTTP |
| 366 | body, regardless of the presence or absence of certain fields such as |
| 367 | Content-Length or a chunked Transfer-Encoding. Depending on the request, |
| 368 | some responses do not carry a body. For example, a 200 response to a |
| 369 | CONNECT request from a tunneling proxy, or a response to a HEAD request. |
| 370 | In these cases, callers may use this function inform the parser that |
| 371 | no body is expected. The parser will consider the message complete |
| 372 | after the header has been received. |
| 373 | |
| 374 | @param v `true` to set the skip body option or `false` to disable it. |
| 375 | |
| 376 | @note This function must called before any bytes are processed. |
| 377 | */ |
| 378 | void |
| 379 | skip(bool v); |
| 380 | |
| 381 | /** Write a buffer sequence to the parser. |
| 382 | |
| 383 | This function attempts to incrementally parse the HTTP |
| 384 | message data stored in the caller provided buffers. Upon |
| 385 | success, a positive return value indicates that the parser |
| 386 | made forward progress, consuming that number of |
| 387 | bytes. |
| 388 | |
| 389 | In some cases there may be an insufficient number of octets |
| 390 | in the input buffer in order to make forward progress. This |
| 391 | is indicated by the code @ref error::need_more. When |
| 392 | this happens, the caller should place additional bytes into |
| 393 | the buffer sequence and call @ref put again. |
| 394 | |
| 395 | The error code @ref error::need_more is special. When this |
| 396 | error is returned, a subsequent call to @ref put may succeed |
| 397 | if the buffers have been updated. Otherwise, upon error |
| 398 | the parser may not be restarted. |
| 399 | |
| 400 | @param buffers An object meeting the requirements of |
| 401 | <em>ConstBufferSequence</em> that represents the next chunk of |
| 402 | message data. If the length of this buffer sequence is |
| 403 | one, the implementation will not allocate additional memory. |
| 404 | The class @ref beast::basic_flat_buffer is provided as one way to |
| 405 | meet this requirement |
| 406 | |
| 407 | @param ec Set to the error, if any occurred. |
| 408 | |
| 409 | @return The number of octets consumed in the buffer |
| 410 | sequence. The caller should remove these octets even if the |
| 411 | error is set. |
| 412 | */ |
| 413 | template<class ConstBufferSequence> |
| 414 | std::size_t |
| 415 | put(ConstBufferSequence const& buffers, error_code& ec); |
| 416 | |
| 417 | #if ! BOOST_BEAST_DOXYGEN |
| 418 | std::size_t |
| 419 | put(net::const_buffer buffer, |
| 420 | error_code& ec); |
| 421 | #endif |
| 422 | |
| 423 | /** Inform the parser that the end of stream was reached. |
| 424 | |
| 425 | In certain cases, HTTP needs to know where the end of |
| 426 | the stream is. For example, sometimes servers send |
| 427 | responses without Content-Length and expect the client |
| 428 | to consume input (for the body) until EOF. Callbacks |
| 429 | and errors will still be processed as usual. |
| 430 | |
| 431 | This is typically called when a read from the |
| 432 | underlying stream object sets the error code to |
| 433 | `net::error::eof`. |
| 434 | |
| 435 | @note Only valid after parsing a complete header. |
| 436 | |
| 437 | @param ec Set to the error, if any occurred. |
| 438 | */ |
| 439 | void |
| 440 | put_eof(error_code& ec); |
| 441 | |
| 442 | protected: |
| 443 | /** Called after receiving the request-line. |
| 444 | |
| 445 | This virtual function is invoked after receiving a request-line |
| 446 | when parsing HTTP requests. |
| 447 | It can only be called when `isRequest == true`. |
| 448 | |
| 449 | @param method The verb enumeration. If the method string is not |
| 450 | one of the predefined strings, this value will be @ref verb::unknown. |
| 451 | |
| 452 | @param method_str The unmodified string representing the verb. |
| 453 | |
| 454 | @param target The request-target. |
| 455 | |
| 456 | @param version The HTTP-version. This will be 10 for HTTP/1.0, |
| 457 | and 11 for HTTP/1.1. |
| 458 | |
| 459 | @param ec An output parameter which the function may set to indicate |
| 460 | an error. The error will be clear before this function is invoked. |
| 461 | */ |
| 462 | virtual |
| 463 | void |
| 464 | on_request_impl( |
| 465 | verb method, |
| 466 | string_view method_str, |
| 467 | string_view target, |
| 468 | int version, |
| 469 | error_code& ec) = 0; |
| 470 | |
| 471 | /** Called after receiving the status-line. |
| 472 | |
| 473 | This virtual function is invoked after receiving a status-line |
| 474 | when parsing HTTP responses. |
| 475 | It can only be called when `isRequest == false`. |
| 476 | |
| 477 | @param code The numeric status code. |
| 478 | |
| 479 | @param reason The reason-phrase. Note that this value is |
| 480 | now obsolete, and only provided for historical or diagnostic |
| 481 | purposes. |
| 482 | |
| 483 | @param version The HTTP-version. This will be 10 for HTTP/1.0, |
| 484 | and 11 for HTTP/1.1. |
| 485 | |
| 486 | @param ec An output parameter which the function may set to indicate |
| 487 | an error. The error will be clear before this function is invoked. |
| 488 | */ |
| 489 | virtual |
| 490 | void |
| 491 | on_response_impl( |
| 492 | int code, |
| 493 | string_view reason, |
| 494 | int version, |
| 495 | error_code& ec) = 0; |
| 496 | |
| 497 | /** Called once for each complete field in the HTTP header. |
| 498 | |
| 499 | This virtual function is invoked for each field that is received |
| 500 | while parsing an HTTP message. |
| 501 | |
| 502 | @param name The known field enum value. If the name of the field |
| 503 | is not recognized, this value will be @ref field::unknown. |
| 504 | |
| 505 | @param name_string The exact name of the field as received from |
| 506 | the input, represented as a string. |
| 507 | |
| 508 | @param value A string holding the value of the field. |
| 509 | |
| 510 | @param ec An output parameter which the function may set to indicate |
| 511 | an error. The error will be clear before this function is invoked. |
| 512 | */ |
| 513 | virtual |
| 514 | void |
| 515 | on_field_impl( |
| 516 | field name, |
| 517 | string_view name_string, |
| 518 | string_view value, |
| 519 | error_code& ec) = 0; |
| 520 | |
| 521 | /** Called once after the complete HTTP header is received. |
| 522 | |
| 523 | This virtual function is invoked once, after the complete HTTP |
| 524 | header is received while parsing a message. |
| 525 | |
| 526 | @param ec An output parameter which the function may set to indicate |
| 527 | an error. The error will be clear before this function is invoked. |
| 528 | */ |
| 529 | virtual |
| 530 | void |
| 531 | (error_code& ec) = 0; |
| 532 | |
| 533 | /** Called once before the body is processed. |
| 534 | |
| 535 | This virtual function is invoked once, before the content body is |
| 536 | processed (but after the complete header is received). |
| 537 | |
| 538 | @param content_length A value representing the content length in |
| 539 | bytes if the length is known (this can include a zero length). |
| 540 | Otherwise, the value will be `boost::none`. |
| 541 | |
| 542 | @param ec An output parameter which the function may set to indicate |
| 543 | an error. The error will be clear before this function is invoked. |
| 544 | */ |
| 545 | virtual |
| 546 | void |
| 547 | on_body_init_impl( |
| 548 | boost::optional<std::uint64_t> const& content_length, |
| 549 | error_code& ec) = 0; |
| 550 | |
| 551 | /** Called each time additional data is received representing the content body. |
| 552 | |
| 553 | This virtual function is invoked for each piece of the body which is |
| 554 | received while parsing of a message. This function is only used when |
| 555 | no chunked transfer encoding is present. |
| 556 | |
| 557 | @param body A string holding the additional body contents. This may |
| 558 | contain nulls or unprintable characters. |
| 559 | |
| 560 | @param ec An output parameter which the function may set to indicate |
| 561 | an error. The error will be clear before this function is invoked. |
| 562 | |
| 563 | @see on_chunk_body_impl |
| 564 | */ |
| 565 | virtual |
| 566 | std::size_t |
| 567 | on_body_impl( |
| 568 | string_view body, |
| 569 | error_code& ec) = 0; |
| 570 | |
| 571 | /** Called each time a new chunk header of a chunk encoded body is received. |
| 572 | |
| 573 | This function is invoked each time a new chunk header is received. |
| 574 | The function is only used when the chunked transfer encoding is present. |
| 575 | |
| 576 | @param size The size of this chunk, in bytes. |
| 577 | |
| 578 | @param extensions A string containing the entire chunk extensions. |
| 579 | This may be empty, indicating no extensions are present. |
| 580 | |
| 581 | @param ec An output parameter which the function may set to indicate |
| 582 | an error. The error will be clear before this function is invoked. |
| 583 | */ |
| 584 | virtual |
| 585 | void |
| 586 | ( |
| 587 | std::uint64_t size, |
| 588 | string_view extensions, |
| 589 | error_code& ec) = 0; |
| 590 | |
| 591 | /** Called each time additional data is received representing part of a body chunk. |
| 592 | |
| 593 | This virtual function is invoked for each piece of the body which is |
| 594 | received while parsing of a message. This function is only used when |
| 595 | no chunked transfer encoding is present. |
| 596 | |
| 597 | @param remain The number of bytes remaining in this chunk. This includes |
| 598 | the contents of passed `body`. If this value is zero, then this represents |
| 599 | the final chunk. |
| 600 | |
| 601 | @param body A string holding the additional body contents. This may |
| 602 | contain nulls or unprintable characters. |
| 603 | |
| 604 | @param ec An output parameter which the function may set to indicate |
| 605 | an error. The error will be clear before this function is invoked. |
| 606 | |
| 607 | @return This function should return the number of bytes actually consumed |
| 608 | from the `body` value. Any bytes that are not consumed on this call |
| 609 | will be presented in a subsequent call. |
| 610 | |
| 611 | @see on_body_impl |
| 612 | */ |
| 613 | virtual |
| 614 | std::size_t |
| 615 | on_chunk_body_impl( |
| 616 | std::uint64_t remain, |
| 617 | string_view body, |
| 618 | error_code& ec) = 0; |
| 619 | |
| 620 | /** Called once when the complete message is received. |
| 621 | |
| 622 | This virtual function is invoked once, after successfully parsing |
| 623 | a complete HTTP message. |
| 624 | |
| 625 | @param ec An output parameter which the function may set to indicate |
| 626 | an error. The error will be clear before this function is invoked. |
| 627 | */ |
| 628 | virtual |
| 629 | void |
| 630 | on_finish_impl(error_code& ec) = 0; |
| 631 | |
| 632 | private: |
| 633 | |
| 634 | boost::optional<std::uint64_t> |
| 635 | content_length_unchecked() const; |
| 636 | |
| 637 | template<class ConstBufferSequence> |
| 638 | std::size_t |
| 639 | put_from_stack( |
| 640 | std::size_t size, |
| 641 | ConstBufferSequence const& buffers, |
| 642 | error_code& ec); |
| 643 | |
| 644 | void |
| 645 | maybe_need_more( |
| 646 | char const* p, std::size_t n, |
| 647 | error_code& ec); |
| 648 | |
| 649 | void |
| 650 | parse_start_line( |
| 651 | char const*& p, char const* last, |
| 652 | error_code& ec, std::true_type); |
| 653 | |
| 654 | void |
| 655 | parse_start_line( |
| 656 | char const*& p, char const* last, |
| 657 | error_code& ec, std::false_type); |
| 658 | |
| 659 | void |
| 660 | parse_fields( |
| 661 | char const*& p, char const* last, |
| 662 | error_code& ec); |
| 663 | |
| 664 | void |
| 665 | ( |
| 666 | error_code& ec, std::true_type); |
| 667 | |
| 668 | void |
| 669 | ( |
| 670 | error_code& ec, std::false_type); |
| 671 | |
| 672 | void |
| 673 | parse_body(char const*& p, |
| 674 | std::size_t n, error_code& ec); |
| 675 | |
| 676 | void |
| 677 | parse_body_to_eof(char const*& p, |
| 678 | std::size_t n, error_code& ec); |
| 679 | |
| 680 | void |
| 681 | (char const*& p, |
| 682 | std::size_t n, error_code& ec); |
| 683 | |
| 684 | void |
| 685 | parse_chunk_body(char const*& p, |
| 686 | std::size_t n, error_code& ec); |
| 687 | |
| 688 | void |
| 689 | do_field(field f, |
| 690 | string_view value, error_code& ec); |
| 691 | }; |
| 692 | |
| 693 | } // http |
| 694 | } // beast |
| 695 | } // boost |
| 696 | |
| 697 | #include <boost/beast/http/impl/basic_parser.hpp> |
| 698 | #ifdef BOOST_BEAST_HEADER_ONLY |
| 699 | #include <boost/beast/http/impl/basic_parser.ipp> |
| 700 | #endif |
| 701 | |
| 702 | #endif |
| 703 | |