@@ -246,6 +246,10 @@ struct http_async_protocol_handler {
246246 response_parser_type::http_header_line_done);
247247typename headers_container<Tag>::type headers;
248248 std::pair<string_type, string_type> header_pair;
249+ // init params
250+ is_content_length =false ;
251+ content_length = -1 ;
252+ is_chunk_end =false ;
249253while (!boost::empty (input_range)) {
250254std::tie (parsed_ok, result_range) = headers_parser.parse_until (
251255 response_parser_type::http_header_colon, input_range);
@@ -266,6 +270,16 @@ struct http_async_protocol_handler {
266270 }
267271trim (header_pair.second );
268272 headers.insert (header_pair);
273+ if (!is_content_length &&
274+ boost::iequals (header_pair.first ," Content-Length" )) {
275+ try {
276+ content_length =std::stoll (header_pair.second );
277+ is_content_length =true ;
278+ }
279+ catch (std::exception&) {
280+ // is_content_length = false;
281+ }
282+ }
269283 }
270284// determine if the body parser will need to handle chunked encoding
271285typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
@@ -325,6 +339,49 @@ struct http_async_protocol_handler {
325339 parsed_ok,std::distance (std::end (result_range), part_end));
326340 }
327341
342+ inline bool check_parse_body_complete ()const {
343+ if (this ->is_chunk_encoding ) {
344+ return parse_chunk_encoding_complete ();
345+ }
346+ if (this ->is_content_length &&this ->content_length >=0 ) {
347+ return parse_content_length_complete ();
348+ }
349+ return false ;
350+ }
351+
352+ inline bool parse_content_length_complete ()const {
353+ return this ->partial_parsed .length () >=this -> content_length;
354+ }
355+
356+ bool parse_chunk_encoding_complete ()const {
357+ string_type body;
358+ string_type crlf =" \r\n " ;
359+
360+ typename string_type::const_iterator begin = partial_parsed.begin ();
361+ for (typename string_type::const_iterator iter =
362+ std::search (begin, partial_parsed.end (), crlf.begin (), crlf.end ());
363+ iter != partial_parsed.end ();
364+ iter =
365+ std::search (begin, partial_parsed.end (), crlf.begin (), crlf.end ())) {
366+ string_typeline (begin, iter);
367+ if (line.empty ()) {
368+ std::advance (iter,2 );
369+ begin = iter;
370+ continue ;
371+ }
372+ std::stringstreamstream (line);
373+ int len;
374+ stream >> std::hex >> len;
375+ std::advance (iter,2 );
376+ if (!len)return true ;
377+ if (len <= partial_parsed.end () - iter) {
378+ std::advance (iter, len +2 );
379+ }
380+ begin = iter;
381+ }
382+ return false ;
383+ }
384+
328385template <class Delegate ,class Callback >
329386void parse_body (Delegate& delegate_, Callback callback,size_t bytes) {
330387// TODO(dberris): we should really not use a string for the partial body
@@ -333,8 +390,12 @@ struct http_async_protocol_handler {
333390std::advance (it, bytes);
334391 partial_parsed.append (part_begin, it);
335392 part_begin = part.begin ();
336- delegate_->read_some (
337- boost::asio::mutable_buffers_1 (part.data (), part.size ()), callback);
393+ if (check_parse_body_complete ()) {
394+ callback (boost::asio::error::eof, bytes);
395+ }else {
396+ delegate_->read_some (
397+ boost::asio::mutable_buffers_1 (part.data (), part.size ()), callback);
398+ }
338399 }
339400
340401typedef response_parser<Tag> response_parser_type;
@@ -353,6 +414,9 @@ struct http_async_protocol_handler {
353414typename buffer_type::const_iterator part_begin;
354415 string_type partial_parsed;
355416bool is_chunk_encoding;
417+ bool is_chunk_end;
418+ bool is_content_length;
419+ long long content_length;
356420};
357421
358422}// namespace impl