Skip to content

Commit bdf1b22

Browse files
committed
add client size close
1 parent 8554867 commit bdf1b22

File tree

2 files changed

+84
-5
lines changed

2 files changed

+84
-5
lines changed

boost/network/protocol/http/client/connection/async_normal.hpp

+68-5
Original file line numberDiff line numberDiff line change
@@ -363,14 +363,25 @@ struct http_async_connection
363363
// Here we handle the body data ourself and append to an
364364
// ever-growing string buffer.
365365
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(
367377
delegate_,
368378
request_strand_.wrap([=] (boost::system::error_code const &ec,
369379
std::size_t bytes_transferred) {
370380
self->handle_received_data(body, get_body, callback,
371381
ec, bytes_transferred);
372382
}),
373383
remainder);
384+
}
374385
}
375386
return;
376387
case body:
@@ -428,17 +439,25 @@ struct http_async_connection
428439
ec, bytes_transferred);
429440
}));
430441
} 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(
435453
delegate_,
436454
request_strand_.wrap([=] (boost::system::error_code const &ec,
437455
std::size_t bytes_transferred) {
438456
self->handle_received_data(body, get_body, callback,
439457
ec, bytes_transferred);
440458
}),
441459
bytes_transferred);
460+
}
442461
}
443462
}
444463
return;
@@ -476,6 +495,50 @@ struct http_async_connection
476495
}
477496
}
478497

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+
479542
string_type parse_chunk_encoding(string_type& body_string) {
480543
string_type body;
481544
string_type crlf = "\r\n";

boost/network/protocol/http/client/connection/async_protocol_handler.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ struct http_async_protocol_handler {
246246
response_parser_type::http_header_line_done);
247247
typename 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;
249253
while (!boost::empty(input_range)) {
250254
std::tie(parsed_ok, result_range) = headers_parser.parse_until(
251255
response_parser_type::http_header_colon, input_range);
@@ -266,6 +270,10 @@ struct http_async_protocol_handler {
266270
}
267271
trim(header_pair.second);
268272
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+
}
269277
}
270278
// determine if the body parser will need to handle chunked encoding
271279
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
@@ -325,6 +333,11 @@ struct http_async_protocol_handler {
325333
parsed_ok, std::distance(std::end(result_range), part_end));
326334
}
327335

336+
void append_body(size_t bytes) {
337+
partial_parsed.append(part_begin, part_begin + bytes);
338+
part_begin = part.begin();
339+
}
340+
328341
template <class Delegate, class Callback>
329342
void parse_body(Delegate& delegate_, Callback callback, size_t bytes) {
330343
// TODO(dberris): we should really not use a string for the partial body
@@ -351,6 +364,9 @@ struct http_async_protocol_handler {
351364
typename buffer_type::const_iterator part_begin;
352365
string_type partial_parsed;
353366
bool is_chunk_encoding;
367+
bool is_chunk_end;
368+
bool is_content_length;
369+
std::size_t content_length;
354370
};
355371

356372
} // namespace impl

0 commit comments

Comments
 (0)