Skip to content

Commit 49d3b20

Browse files
committed
Merge pull request cpp-netlib#164 from wagerlabs/master
Fix indefinite wait on body responses where content-length has already been provided.
2 parents e1aad6e + 4054936 commit 49d3b20

File tree

1 file changed

+50
-10
lines changed

1 file changed

+50
-10
lines changed

include/network/protocol/http/client/connection/async_normal.ipp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -430,20 +430,44 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
430430
placeholders::bytes_transferred)));
431431
} else {
432432
NETWORK_MESSAGE("no callback provided, appending to body...");
433+
bool get_more = true;
434+
if (content_length_) {
435+
buffer_type::const_iterator begin = this->part.begin();
436+
buffer_type::const_iterator end = begin;
437+
std::advance(end, bytes_transferred);
438+
get_more = (end - begin) < *content_length_;
439+
NETWORK_MESSAGE("content_length = " << * content_length_
440+
<< ", bytes read = " << (end - begin) << ", read more = " << get_more);
441+
}
433442
// Here we don't have a body callback. Let's
434443
// make sure that we deal with the remainder
435444
// from the headers part in case we do have data
436445
// that's still in the buffer.
437-
this->parse_body(request_strand_.wrap(
438-
boost::bind(
439-
&this_type::handle_received_data,
440-
this_type::shared_from_this(),
441-
body,
442-
get_body,
443-
callback,
444-
placeholders::error,
445-
placeholders::bytes_transferred)),
446-
bytes_transferred);
446+
if (get_more) {
447+
this->parse_body(request_strand_.wrap(
448+
boost::bind(
449+
&this_type::handle_received_data,
450+
this_type::shared_from_this(),
451+
body,
452+
get_body,
453+
callback,
454+
placeholders::error,
455+
placeholders::bytes_transferred)),
456+
bytes_transferred);
457+
} else {
458+
std::string body_string;
459+
std::swap(body_string, this->partial_parsed);
460+
body_string.append(
461+
this->part.begin()
462+
, bytes_transferred
463+
);
464+
this->body_promise.set_value(body_string);
465+
// TODO set the destination value somewhere!
466+
this->destination_promise.set_value("");
467+
this->source_promise.set_value("");
468+
this->part.assign('\0');
469+
this->response_parser_.reset();
470+
}
447471
}
448472
}
449473
return;
@@ -709,6 +733,21 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
709733
boost::trim(header_pair.second);
710734
headers.insert(header_pair);
711735
}
736+
// Set content length
737+
content_length_ = boost::none;
738+
auto it = headers.find("Content-Length");
739+
if (it != headers.end()) {
740+
try {
741+
content_length_ = std::stoul(it->second);
742+
NETWORK_MESSAGE("Content-Length: " << *content_length_);
743+
} catch(const std::invalid_argument&) {
744+
NETWORK_MESSAGE("invalid argument exception while interpreting "
745+
<< it->second << " as content length");
746+
} catch(const std::out_of_range&) {
747+
NETWORK_MESSAGE("out of range exception while interpreting "
748+
<< it->second << " as content length");
749+
}
750+
}
712751
headers_promise.set_value(headers);
713752
}
714753

@@ -790,6 +829,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
790829
boost::promise<boost::uint16_t> status_promise;
791830
boost::promise<std::string> status_message_promise;
792831
boost::promise<std::multimap<std::string, std::string> > headers_promise;
832+
boost::optional<size_t> content_length_;
793833
boost::promise<std::string> source_promise;
794834
boost::promise<std::string> destination_promise;
795835
boost::promise<std::string> body_promise;

0 commit comments

Comments
 (0)