From d00836dfe281a59af8dacbb6864fe0bcae2d39a0 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Tue, 30 Oct 2012 18:27:12 +0000 Subject: [PATCH 1/5] Take content length into account when reading body --- .../http/client/connection/async_normal.ipp | 55 +++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/include/network/protocol/http/client/connection/async_normal.ipp b/include/network/protocol/http/client/connection/async_normal.ipp index a99680632..5e30db45f 100644 --- a/include/network/protocol/http/client/connection/async_normal.ipp +++ b/include/network/protocol/http/client/connection/async_normal.ipp @@ -430,20 +430,53 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thispart.begin(); + buffer_type::const_iterator end = begin; + std::advance(end, bytes_transferred); + // check the content length header + //auto headers_future = headers_promise.get_future(); + auto it = headers_.find("Content-Length"); + if (it != headers_.end()) { + try { + unsigned content_length = stoi(it->second); + get_more = (end - begin) < content_length; + NETWORK_MESSAGE("Content-Length: " << content_length + << ", disconnect: " << !get_more); + } catch(...) { + } + } // Here we don't have a body callback. Let's // make sure that we deal with the remainder // from the headers part in case we do have data // that's still in the buffer. - this->parse_body(request_strand_.wrap( - boost::bind( - &this_type::handle_received_data, - this_type::shared_from_this(), - body, - get_body, - callback, - placeholders::error, - placeholders::bytes_transferred)), - bytes_transferred); + if (get_more) { + this->parse_body(request_strand_.wrap( + boost::bind( + &this_type::handle_received_data, + this_type::shared_from_this(), + body, + get_body, + callback, + placeholders::error, + placeholders::bytes_transferred)), + bytes_transferred); + } else { + std::string body_string; + std::swap(body_string, this->partial_parsed); + body_string.append( + this->part.begin() + , bytes_transferred + ); + this->body_promise.set_value(body_string); + // TODO set the destination value somewhere! + this->destination_promise.set_value(""); + this->source_promise.set_value(""); + this->part.assign('\0'); + this->response_parser_.reset(); + //NETWORK_MESSAGE("forcing socket disconnect on content length"); + //connection_delegate_->disconnect(); + } } } return; @@ -709,6 +742,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thisheaders_ = headers; headers_promise.set_value(headers); } @@ -790,6 +824,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this status_promise; boost::promise status_message_promise; boost::promise > headers_promise; + std::multimap headers_; boost::promise source_promise; boost::promise destination_promise; boost::promise body_promise; From 78afee4adb9f3f70372a3a118851485b582b3bc2 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Wed, 31 Oct 2012 12:42:57 +0000 Subject: [PATCH 2/5] Qualify stoi and only catch exceptions thrown by it. --- .../protocol/http/client/connection/async_normal.ipp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/network/protocol/http/client/connection/async_normal.ipp b/include/network/protocol/http/client/connection/async_normal.ipp index 5e30db45f..d0645e8f9 100644 --- a/include/network/protocol/http/client/connection/async_normal.ipp +++ b/include/network/protocol/http/client/connection/async_normal.ipp @@ -439,11 +439,11 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thissecond); + unsigned content_length = std::stoi(it->second); get_more = (end - begin) < content_length; - NETWORK_MESSAGE("Content-Length: " << content_length - << ", disconnect: " << !get_more); - } catch(...) { + NETWORK_MESSAGE("Content-Length: " << content_length); + } catch(const std::invalid_argument&) { + } catch(const std::out_of_range&) { } } // Here we don't have a body callback. Let's From a941fb1c05230bad3a8c4ca1d1e4cdfa28a9aa42 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Wed, 31 Oct 2012 13:38:48 +0000 Subject: [PATCH 3/5] Use optional member variable to keep track of content length. --- .../http/client/connection/async_normal.ipp | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/include/network/protocol/http/client/connection/async_normal.ipp b/include/network/protocol/http/client/connection/async_normal.ipp index d0645e8f9..0b8b4ef89 100644 --- a/include/network/protocol/http/client/connection/async_normal.ipp +++ b/include/network/protocol/http/client/connection/async_normal.ipp @@ -431,20 +431,13 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thispart.begin(); - buffer_type::const_iterator end = begin; - std::advance(end, bytes_transferred); - // check the content length header - //auto headers_future = headers_promise.get_future(); - auto it = headers_.find("Content-Length"); - if (it != headers_.end()) { - try { - unsigned content_length = std::stoi(it->second); - get_more = (end - begin) < content_length; - NETWORK_MESSAGE("Content-Length: " << content_length); - } catch(const std::invalid_argument&) { - } catch(const std::out_of_range&) { - } + if (content_length_) { + buffer_type::const_iterator begin = this->part.begin(); + buffer_type::const_iterator end = begin; + std::advance(end, bytes_transferred); + get_more = (end - begin) < *content_length_; + NETWORK_MESSAGE("content_length = " << * content_length_ + << ", bytes read = " << (end - begin) << ", read more = " << get_more); } // Here we don't have a body callback. Let's // make sure that we deal with the remainder @@ -474,8 +467,6 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thissource_promise.set_value(""); this->part.assign('\0'); this->response_parser_.reset(); - //NETWORK_MESSAGE("forcing socket disconnect on content length"); - //connection_delegate_->disconnect(); } } } @@ -742,7 +733,17 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thisheaders_ = headers; + // Set content length + content_length_ = boost::none; + auto it = headers.find("Content-Length"); + if (it != headers.end()) { + try { + content_length_ = std::stoi(it->second); + NETWORK_MESSAGE("Content-Length: " << *content_length_); + } catch(const std::invalid_argument&) { + } catch(const std::out_of_range&) { + } + } headers_promise.set_value(headers); } @@ -824,7 +825,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this status_promise; boost::promise status_message_promise; boost::promise > headers_promise; - std::multimap headers_; + boost::optional content_length_; boost::promise source_promise; boost::promise destination_promise; boost::promise body_promise; From 3079bdae66d116e61ff19c5d856cf6e05bf83db4 Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Wed, 31 Oct 2012 14:00:46 +0000 Subject: [PATCH 4/5] Use size_t to store content length. --- .../network/protocol/http/client/connection/async_normal.ipp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/network/protocol/http/client/connection/async_normal.ipp b/include/network/protocol/http/client/connection/async_normal.ipp index 0b8b4ef89..62506dfc5 100644 --- a/include/network/protocol/http/client/connection/async_normal.ipp +++ b/include/network/protocol/http/client/connection/async_normal.ipp @@ -738,7 +738,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thissecond); + content_length_ = std::stoul(it->second); NETWORK_MESSAGE("Content-Length: " << *content_length_); } catch(const std::invalid_argument&) { } catch(const std::out_of_range&) { @@ -825,7 +825,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this status_promise; boost::promise status_message_promise; boost::promise > headers_promise; - boost::optional content_length_; + boost::optional content_length_; boost::promise source_promise; boost::promise destination_promise; boost::promise body_promise; From 4054936d0b0d8e9b775759e9bdd7f27cf1a47dde Mon Sep 17 00:00:00 2001 From: Joel Reymont Date: Wed, 31 Oct 2012 14:04:22 +0000 Subject: [PATCH 5/5] Print a debug message if content length conversion to size_t fails. --- .../network/protocol/http/client/connection/async_normal.ipp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/network/protocol/http/client/connection/async_normal.ipp b/include/network/protocol/http/client/connection/async_normal.ipp index 62506dfc5..5366532df 100644 --- a/include/network/protocol/http/client/connection/async_normal.ipp +++ b/include/network/protocol/http/client/connection/async_normal.ipp @@ -741,7 +741,11 @@ struct http_async_connection_pimpl : boost::enable_shared_from_thissecond); NETWORK_MESSAGE("Content-Length: " << *content_length_); } catch(const std::invalid_argument&) { + NETWORK_MESSAGE("invalid argument exception while interpreting " + << it->second << " as content length"); } catch(const std::out_of_range&) { + NETWORK_MESSAGE("out of range exception while interpreting " + << it->second << " as content length"); } } headers_promise.set_value(headers);