@@ -363,14 +363,25 @@ struct http_async_connection
363
363
// Here we handle the body data ourself and append to an
364
364
// ever-growing string buffer.
365
365
auto self = this ->shared_from_this ();
366
- this ->parse_body (
366
+ typename protocol_base::buffer_type::const_iterator begin =
367
+ this ->part_begin ;
368
+ typename protocol_base::buffer_type::const_iterator end = begin;
369
+ std::advance (end, remainder );
370
+ string_type body_string (begin, end);
371
+ if (check_parse_body_complete (body_string)) {
372
+ this ->append_body (remainder );
373
+ handle_received_data (body, get_body, callback,
374
+ boost::asio::error::eof, bytes_transferred);
375
+ } else {
376
+ this ->parse_body (
367
377
delegate_,
368
378
request_strand_.wrap ([=] (boost::system ::error_code const &ec,
369
379
std::size_t bytes_transferred) {
370
380
self->handle_received_data (body, get_body, callback,
371
381
ec, bytes_transferred);
372
382
}),
373
383
remainder );
384
+ }
374
385
}
375
386
return ;
376
387
case body:
@@ -428,17 +439,25 @@ struct http_async_connection
428
439
ec, bytes_transferred);
429
440
}));
430
441
} else {
431
- // Here we don't have a body callback. Let's make sure that we
432
- // deal with the remainder from the headers part in case we do
433
- // have data that's still in the buffer.
434
- this ->parse_body (
442
+ string_type body_string (this ->partial_parsed );
443
+ body_string.append (this ->part .begin (), bytes_transferred);
444
+ if (check_parse_body_complete (body_string)) {
445
+ this ->append_body (bytes_transferred);
446
+ handle_received_data (body, get_body, callback,
447
+ boost::asio::error::eof, bytes_transferred);
448
+ } else {
449
+ // Here we don't have a body callback. Let's make sure that we
450
+ // deal with the remainder from the headers part in case we do
451
+ // have data that's still in the buffer.
452
+ this ->parse_body (
435
453
delegate_,
436
454
request_strand_.wrap ([=] (boost::system ::error_code const &ec,
437
455
std::size_t bytes_transferred) {
438
456
self->handle_received_data (body, get_body, callback,
439
457
ec, bytes_transferred);
440
458
}),
441
459
bytes_transferred);
460
+ }
442
461
}
443
462
}
444
463
return ;
@@ -476,6 +495,50 @@ struct http_async_connection
476
495
}
477
496
}
478
497
498
+ inline bool check_parse_body_complete (string_type& body_string)
499
+ {
500
+ if (this ->is_chunk_encoding ) {
501
+ return parse_chunk_encoding_complete (body_string);
502
+ }
503
+ if (this ->is_content_length && this ->content_length >= 0 ) {
504
+ return parse_content_length_complete (body_string, this ->content_length );
505
+ }
506
+ return false ;
507
+ }
508
+
509
+ inline bool parse_content_length_complete (string_type& body_string, size_t content_length){
510
+ return body_string.length () >= content_length;
511
+ }
512
+
513
+ bool parse_chunk_encoding_complete (string_type& body_string) {
514
+ string_type body;
515
+ string_type crlf = " \r\n " ;
516
+
517
+ typename string_type::iterator begin = body_string.begin ();
518
+ for (typename string_type::iterator iter =
519
+ std::search (begin, body_string.end (), crlf.begin (), crlf.end ());
520
+ iter != body_string.end ();
521
+ iter =
522
+ std::search (begin, body_string.end (), crlf.begin (), crlf.end ())) {
523
+ string_type line (begin, iter);
524
+ if (line.empty ()) {
525
+ std::advance (iter, 2 );
526
+ begin = iter;
527
+ continue ;
528
+ }
529
+ std::stringstream stream (line);
530
+ int len;
531
+ stream >> std::hex >> len;
532
+ std::advance (iter, 2 );
533
+ if (!len) return true ;
534
+ if (len <= body_string.end () - iter) {
535
+ std::advance (iter, len + 2 );
536
+ }
537
+ begin = iter;
538
+ }
539
+ return false ;
540
+ }
541
+
479
542
string_type parse_chunk_encoding (string_type& body_string) {
480
543
string_type body;
481
544
string_type crlf = " \r\n " ;
0 commit comments