From c6c1607b36849398ae040da4bb03bb95047c9ed3 Mon Sep 17 00:00:00 2001 From: Chase Geigle Date: Wed, 27 Feb 2013 02:14:39 -0600 Subject: [PATCH 1/2] Fix issue #110 and issue #168. --- .../protocol/http/message/async_message.hpp | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 39b16fd27..1e31800ce 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -118,7 +118,34 @@ namespace boost { namespace network { namespace http { } string_type const body() const { - return body_.get(); + string_type body; + string_type partial_parsed = body_.get(); + + typename headers_range >::type transfer_encoding_range = headers().equal_range("Transfer-Encoding"); + if (!empty(transfer_encoding_range) && boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { + typename string_type::iterator begin = partial_parsed.begin(); + string_type crlf = "\r\n"; + for (typename string_type::iterator iter = std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end()); + iter != partial_parsed.end(); + iter = std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end())) { + string_type line(begin, iter); + if (line.empty()) break; + std::stringstream stream(line); + int len; + stream >> std::hex >> len; + iter += 2; + if (!len) break; + if (len <= partial_parsed.end() - iter) { + body.insert(body.end(), iter, iter + len); + iter += len; + } + begin = iter; + } + } else { + std::swap(body, partial_parsed); + } + + return body; } void body(boost::shared_future const & future) const { From 30be91da242368ff1c7eff89b1c4d011269c3f35 Mon Sep 17 00:00:00 2001 From: Chase Geigle Date: Wed, 27 Feb 2013 12:22:55 -0600 Subject: [PATCH 2/2] Refactor chunked encoding body parsing. --- .../http/client/connection/async_normal.hpp | 33 ++++++++++++++++++- .../connection/async_protocol_handler.hpp | 6 ++++ .../protocol/http/message/async_message.hpp | 29 +--------------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index d2fb59e0b..98e2b5b0c 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -354,7 +354,10 @@ namespace boost { namespace network { namespace http { namespace impl { this->part.begin() , bytes_transferred ); - this->body_promise.set_value(body_string); + if (this->is_chunk_encoding) + this->body_promise.set_value(parse_chunk_encoding(body_string)); + else + this->body_promise.set_value(body_string); } // TODO set the destination value somewhere! this->destination_promise.set_value(""); @@ -428,6 +431,34 @@ namespace boost { namespace network { namespace http { namespace impl { } } } + + string_type parse_chunk_encoding( string_type & body_string ) { + string_type body; + string_type crlf = "\r\n"; + + typename string_type::iterator begin = body_string.begin(); + for (typename string_type::iterator iter = + std::search(begin, body_string.end(), crlf.begin(), crlf.end()); + iter != body_string.end(); + iter = std::search(begin, body_string.end(), crlf.begin(), crlf.end())) { + string_type line(begin, iter); + if (line.empty()) + break; + std::stringstream stream(line); + int len; + stream >> std::hex >> len; + std::advance(iter, 2); + if (!len) + break; + if (len <= body_string.end() - iter) { + body.insert(body.end(), iter, iter + len); + std::advance(iter, len); + } + begin = iter; + } + + return body; + } bool follow_redirect_; resolver_type & resolver_; diff --git a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp index f0368c0e1..9921f7b8c 100644 --- a/boost/network/protocol/http/client/connection/async_protocol_handler.hpp +++ b/boost/network/protocol/http/client/connection/async_protocol_handler.hpp @@ -286,6 +286,11 @@ namespace boost { namespace network { namespace http { namespace impl { trim(header_pair.second); headers.insert(header_pair); } + // determine if the body parser will need to handle chunked encoding + typename headers_range >::type transfer_encoding_range = + headers.equal_range("Transfer-Encoding"); + is_chunk_encoding = !empty(transfer_encoding_range) + && boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked"); headers_promise.set_value(headers); } @@ -373,6 +378,7 @@ namespace boost { namespace network { namespace http { namespace impl { buffer_type part; typename buffer_type::const_iterator part_begin; string_type partial_parsed; + bool is_chunk_encoding; }; diff --git a/boost/network/protocol/http/message/async_message.hpp b/boost/network/protocol/http/message/async_message.hpp index 1e31800ce..39b16fd27 100644 --- a/boost/network/protocol/http/message/async_message.hpp +++ b/boost/network/protocol/http/message/async_message.hpp @@ -118,34 +118,7 @@ namespace boost { namespace network { namespace http { } string_type const body() const { - string_type body; - string_type partial_parsed = body_.get(); - - typename headers_range >::type transfer_encoding_range = headers().equal_range("Transfer-Encoding"); - if (!empty(transfer_encoding_range) && boost::iequals(boost::begin(transfer_encoding_range)->second, "chunked")) { - typename string_type::iterator begin = partial_parsed.begin(); - string_type crlf = "\r\n"; - for (typename string_type::iterator iter = std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end()); - iter != partial_parsed.end(); - iter = std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end())) { - string_type line(begin, iter); - if (line.empty()) break; - std::stringstream stream(line); - int len; - stream >> std::hex >> len; - iter += 2; - if (!len) break; - if (len <= partial_parsed.end() - iter) { - body.insert(body.end(), iter, iter + len); - iter += len; - } - begin = iter; - } - } else { - std::swap(body, partial_parsed); - } - - return body; + return body_.get(); } void body(boost::shared_future const & future) const {