@@ -246,6 +246,10 @@ struct http_async_protocol_handler {
246
246
response_parser_type::http_header_line_done);
247
247
typename headers_container<Tag>::type headers;
248
248
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 ;
249
253
while (!boost::empty (input_range)) {
250
254
std::tie (parsed_ok, result_range) = headers_parser.parse_until (
251
255
response_parser_type::http_header_colon, input_range);
@@ -266,6 +270,10 @@ struct http_async_protocol_handler {
266
270
}
267
271
trim (header_pair.second );
268
272
headers.insert (header_pair);
273
+ if (boost::iequals (header_pair.first ," Content-Length" )) {
274
+ is_content_length =true ;
275
+ content_length =std::stoi (header_pair.second );
276
+ }
269
277
}
270
278
// determine if the body parser will need to handle chunked encoding
271
279
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
@@ -325,6 +333,49 @@ struct http_async_protocol_handler {
325
333
parsed_ok,std::distance (std::end (result_range), part_end));
326
334
}
327
335
336
+ inline bool check_parse_body_complete ()const {
337
+ if (this ->is_chunk_encoding ) {
338
+ return parse_chunk_encoding_complete ();
339
+ }
340
+ if (this ->is_content_length &&this ->content_length >=0 ) {
341
+ return parse_content_length_complete ();
342
+ }
343
+ return false ;
344
+ }
345
+
346
+ inline bool parse_content_length_complete ()const {
347
+ return this ->partial_parsed .length () >=this -> content_length;
348
+ }
349
+
350
+ bool parse_chunk_encoding_complete ()const {
351
+ string_type body;
352
+ string_type crlf =" \r\n " ;
353
+
354
+ typename string_type::const_iterator begin = partial_parsed.begin ();
355
+ for (typename string_type::const_iterator iter =
356
+ std::search (begin, partial_parsed.end (), crlf.begin (), crlf.end ());
357
+ iter != partial_parsed.end ();
358
+ iter =
359
+ std::search (begin, partial_parsed.end (), crlf.begin (), crlf.end ())) {
360
+ string_typeline (begin, iter);
361
+ if (line.empty ()) {
362
+ std::advance (iter,2 );
363
+ begin = iter;
364
+ continue ;
365
+ }
366
+ std::stringstreamstream (line);
367
+ int len;
368
+ stream >> std::hex >> len;
369
+ std::advance (iter,2 );
370
+ if (!len)return true ;
371
+ if (len <= partial_parsed.end () - iter) {
372
+ std::advance (iter, len +2 );
373
+ }
374
+ begin = iter;
375
+ }
376
+ return false ;
377
+ }
378
+
328
379
template <class Delegate ,class Callback >
329
380
void parse_body (Delegate& delegate_, Callback callback,size_t bytes) {
330
381
// TODO(dberris): we should really not use a string for the partial body
@@ -333,8 +384,12 @@ struct http_async_protocol_handler {
333
384
std::advance (it, bytes);
334
385
partial_parsed.append (part_begin, it);
335
386
part_begin = part.begin ();
336
- delegate_->read_some (
337
- boost::asio::mutable_buffers_1 (part.data (), part.size ()), callback);
387
+ if (check_parse_body_complete ()) {
388
+ callback (boost::asio::error::eof, bytes);
389
+ }else {
390
+ delegate_->read_some (
391
+ boost::asio::mutable_buffers_1 (part.data (), part.size ()), callback);
392
+ }
338
393
}
339
394
340
395
typedef response_parser<Tag> response_parser_type;
@@ -353,6 +408,9 @@ struct http_async_protocol_handler {
353
408
typename buffer_type::const_iterator part_begin;
354
409
string_type partial_parsed;
355
410
bool is_chunk_encoding;
411
+ bool is_chunk_end;
412
+ bool is_content_length;
413
+ std::size_t content_length;
356
414
};
357
415
358
416
}// namespace impl