1919#include < boost/logic/tribool.hpp>
2020#include < boost/network/protocol/http/parser/incremental.hpp>
2121#include < boost/network/protocol/http/message/wrappers/uri.hpp>
22+ #include < boost/array.hpp>
2223#include < iterator>
2324
2425namespace boost {namespace network {namespace http {namespace impl {
@@ -55,11 +56,13 @@ namespace boost { namespace network { namespace http { namespace impl {
5556template <class U >
5657 string_typeconst operator () (Uconst & pair)const {
5758typedef typename ostringstream<Tag>::type ostringstream_type;
59+ typedef constants<Tag> constants;
5860 ostringstream_type header_line;
5961 header_line << pair.first
60- << constants<Tag>::colon ()
62+ <<constants::colon ()
63+ <<constants::space ()
6164 << pair.second
62- << constants<Tag> ::crlf ();
65+ <<constants::crlf ();
6366return header_line.str ();
6467 }
6568 };
@@ -84,12 +87,12 @@ namespace boost { namespace network { namespace http { namespace impl {
8487if (!get_body) body_promise.set_value (string_type ());
8588
8689typename ostringstream<Tag>::type command_stream;
87- string_typeuri_str ;
88- uri_str =boost::network::http::uri (request);
90+ string_typepath_str ;
91+ path_str =path (request);
8992typedef constants<Tag> constants;
9093 command_stream
9194 << method <<constants::space ()
92- <<uri_str <<constants::space ()
95+ <<path_str <<constants::space ()
9396 <<constants::http_slash () << version_major
9497 <<constants::dot () << version_minor
9598 <<constants::crlf ();
@@ -122,18 +125,19 @@ namespace boost { namespace network { namespace http { namespace impl {
122125 <<constants::user_agent () <<constants::colon () <<constants::space () <<constants::cpp_netlib_slash () << BOOST_NETLIB_VERSION <<constants::crlf ();
123126 }
124127
128+ command_stream <<constants::crlf ();
129+
125130 command_string_ = command_stream.str ();
126131
127132this ->method = method;
128-
129- resolve_ (resolver_,host (request),
133+
134+ resolve_ (resolver_,host (request),port (request),
130135 request_strand_->wrap (
131136boost::bind (
132137 &http_async_connection<Tag,version_major,version_minor>::handle_resolved,
133138 http_async_connection<Tag,version_major,version_minor>::shared_from_this (),
134139port (request),
135140 _1, _2)));
136-
137141return temp;
138142 }
139143
@@ -217,7 +221,7 @@ namespace boost { namespace network { namespace http { namespace impl {
217221if (!ec) {
218222boost::asio::async_read (
219223 *socket_,
220- response_buffer_ ,
224+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
221225 request_strand_->wrap (
222226boost::bind (
223227 &http_async_connection<Tag,version_major,version_minor>::handle_received_version,
@@ -238,8 +242,10 @@ namespace boost { namespace network { namespace http { namespace impl {
238242 }
239243
240244void parse_version () {
245+ std::cerr <<' \n ' ;
246+
241247 logic::tribool parsed_ok;
242- typename response_parser_type::range_type result_range;
248+ typename boost::iterator_range< typename buffer_type::const_iterator> result_range;
243249fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
244250 response_parser_type::http_version_done,
245251 part);
@@ -249,8 +255,8 @@ namespace boost { namespace network { namespace http { namespace impl {
249255 version.append (boost::begin (result_range),boost::end (result_range));
250256algorithm::trim (version);
251257 version_promise.set_value (version);
252- typename string_type ::const_iterator end = part.end ();
253- part. assign (boost::end (result_range), end);
258+ typename buffer_type ::const_iterator end = part.end ();
259+ std::copy (boost::end (result_range), end, part. begin () );
254260this ->parse_status ();
255261 }else if (parsed_ok ==false ) {
256262 std::runtime_errorerror (" Invalid Version Part." );
@@ -266,10 +272,9 @@ namespace boost { namespace network { namespace http { namespace impl {
266272 part.begin (),
267273 part.end ()
268274 );
269- string_type ().swap (part);
270275boost::asio::async_read (
271276 *socket_,
272- response_buffer_ ,
277+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
273278 request_strand_->wrap (
274279boost::bind (
275280 &http_async_connection<Tag,version_major,version_minor>::handle_received_version,
@@ -279,12 +284,8 @@ namespace boost { namespace network { namespace http { namespace impl {
279284 }
280285
281286void handle_received_version (boost::system::error_codeconst & ec, std::size_t bytes_transferred) {
282- if (!ec) {
283- typename istream<Tag>::typeinput_stream (&response_buffer_);
284- part.append (
285- std::istream_iterator<typename char_<Tag>::type>(input_stream)
286- , std::istream_iterator<typename char_<Tag>::type>()
287- );
287+ if (!ec || ec == boost::asio::error::eof) {
288+ this ->parse_version ();
288289 }else {
289290 boost::system::system_errorerror (ec);
290291 version_promise.set_exception (boost::copy_exception (error));
@@ -299,7 +300,7 @@ namespace boost { namespace network { namespace http { namespace impl {
299300
300301void parse_status () {
301302 logic::tribool parsed_ok;
302- typename response_parser_type::range_type result_range;
303+ typename boost::iterator_range< typename buffer_type::const_iterator> result_range;
303304fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
304305 response_parser_type::http_status_done,
305306 part);
@@ -310,8 +311,8 @@ namespace boost { namespace network { namespace http { namespace impl {
310311trim (status);
311312 boost::uint16_t status_int = lexical_cast<boost::uint16_t >(status);
312313 status_promise.set_value (status_int);
313- typename string_type::iterator end = part.end ();
314- part. assign (boost::end (result_range), end);
314+ typename buffer_type::const_iterator end = part.end ();
315+ std::copy (boost::end (result_range), end, part. begin () );
315316this ->parse_status_message ();
316317 }else if (parsed_ok ==false ) {
317318 std::runtime_errorerror (" Invalid status part." );
@@ -323,8 +324,8 @@ namespace boost { namespace network { namespace http { namespace impl {
323324 body_promise.set_exception (boost::copy_exception (error));
324325 }else {
325326 partial_parsed.append (part.begin (), part.end ());
326- string_type (). swap (part);
327- boost::asio::async_read (*socket_, response_buffer_ ,
327+ boost::asio::async_read (*socket_,
328+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
328329 request_strand_->wrap (
329330boost::bind (
330331 &http_async_connection<Tag,version_major,version_minor>::handle_received_status,
@@ -335,11 +336,6 @@ namespace boost { namespace network { namespace http { namespace impl {
335336
336337void handle_received_status (boost::system::error_codeconst & ec,size_t bytes_transferred) {
337338if (!ec) {
338- typename istream<Tag>::typeinput_stream (&response_buffer_);
339- part.append (
340- std::istream_iterator<typename char_<Tag>::type>(input_stream)
341- , std::istream_iterator<typename char_<Tag>::type>()
342- );
343339this ->parse_status ();
344340 }else {
345341 boost::system::system_errorerror (ec);
@@ -354,7 +350,7 @@ namespace boost { namespace network { namespace http { namespace impl {
354350
355351void parse_status_message () {
356352 logic::tribool parsed_ok;
357- typename response_parser_type::range_type result_range;
353+ typename boost::iterator_range< typename buffer_type::const_iterator> result_range;
358354fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
359355 response_parser_type::http_status_message_done,
360356 part);
@@ -364,8 +360,8 @@ namespace boost { namespace network { namespace http { namespace impl {
364360 status_message.append (boost::begin (result_range),boost::end (result_range));
365361algorithm::trim (status_message);
366362 status_message_promise.set_value (status_message);
367- typename string_type::iterator end = part.end ();
368- part. assign (boost::end (result_range), end);
363+ typename buffer_type::const_iterator end = part.end ();
364+ std::copy (boost::end (result_range), end, part. c_array () );
369365this ->parse_headers ();
370366 }else if (parsed_ok ==false ) {
371367 std::runtime_errorerror (" Invalid status message part." );
@@ -376,10 +372,9 @@ namespace boost { namespace network { namespace http { namespace impl {
376372 body_promise.set_exception (boost::copy_exception (error));
377373 }else {
378374 partial_parsed.append (part.begin (), part.end ());
379- string_type ().swap (part);
380375boost::asio::async_read (
381376 *socket_,
382- response_buffer_ ,
377+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
383378 request_strand_->wrap (
384379boost::bind (
385380 &http_async_connection<Tag,version_major,version_minor>::handle_received_status_message,
@@ -390,11 +385,6 @@ namespace boost { namespace network { namespace http { namespace impl {
390385
391386void handle_received_status_message (boost::system::error_codeconst & ec,size_t bytes_transferred) {
392387if (!ec) {
393- typename istream<Tag>::typeinput_stream (&response_buffer_);
394- part.append (
395- std::istream_iterator<typename char_<Tag>::type>(input_stream)
396- , std::istream_iterator<typename char_<Tag>::type>()
397- );
398388this ->parse_status_message ();
399389 }else {
400390 boost::system::system_errorerror (ec);
@@ -408,26 +398,24 @@ namespace boost { namespace network { namespace http { namespace impl {
408398
409399void parse_headers () {
410400 logic::tribool parsed_ok;
411- typename response_parser_type::range_type result_range;
401+ typename boost::iterator_range< typename buffer_type::const_iterator> result_range;
412402fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
413403 response_parser_type::http_headers_done,
414404 part);
415405if (parsed_ok ==true ) {
416406 string_type headers_string;
417407std::swap (headers_string, partial_parsed);
418408 headers_string.append (boost::begin (result_range),boost::end (result_range));
419- typename string_type::const_iterator end = part.end ();
420- part.assign (boost::end (result_range), end);
421- // TODO implement the header line parsing here.
422- this ->parse_body ();
409+ typename buffer_type::const_iterator end = part.end ();
410+ std::copy (boost::end (result_range), end, part.begin ());
411+ this ->parse_body (std::distance (boost::end (result_range), end));
423412 }else if (parsed_ok ==false ) {
424413 std::runtime_errorerror (" Invalid header part." );
425414 }else {
426415 partial_parsed.append (part.begin (), part.end ());
427- string_type ().swap (part);
428416boost::asio::async_read (
429417 *socket_,
430- response_buffer_ ,
418+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
431419 request_strand_->wrap (
432420boost::bind (
433421 &http_async_connection<Tag,version_major,version_minor>::handle_received_headers,
@@ -438,11 +426,6 @@ namespace boost { namespace network { namespace http { namespace impl {
438426
439427void handle_received_headers (boost::system::error_codeconst & ec,size_t bytes_transferred) {
440428if (!ec) {
441- typename istream<Tag>::typeinput_stream (&response_buffer_);
442- part.append (
443- std::istream_iterator<typename char_<Tag>::type>(input_stream)
444- , std::istream_iterator<typename char_<Tag>::type>()
445- );
446429this ->parse_headers ();
447430 }else {
448431 boost::system::system_errorerror (ec);
@@ -453,13 +436,12 @@ namespace boost { namespace network { namespace http { namespace impl {
453436 }
454437 }
455438
456- void parse_body () {
457- partial_parsed.append (part.begin (), part.end ());
458- string_type ().swap (part);
459- boost::asio::async_read (*socket_, response_buffer_,
439+ void parse_body (size_t bytes) {
440+ partial_parsed.append (part.begin (), bytes);
441+ boost::asio::async_read (*socket_,boost::asio::mutable_buffers_1 (part.c_array (), part.size ()),
460442 request_strand_->wrap (
461443boost::bind (
462- &http_async_connection<Tag,version_major,version_minor>::handle_received_body ,
444+ &http_async_connection<Tag,version_major,version_minor>::handle_recieved_body ,
463445 http_async_connection<Tag,version_major,version_minor>::shared_from_this (),
464446 boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
465447 }
@@ -468,17 +450,18 @@ namespace boost { namespace network { namespace http { namespace impl {
468450if (ec == boost::asio::error::eof) {
469451 string_type body;
470452std::swap (body, partial_parsed);
471- typename istream<Tag>::typeinput_stream (&response_buffer_);
472453 body.append (
473- std::istream_iterator< typename char_<Tag>::type>(input_stream )
474- ,std::istream_iterator< typename char_<Tag>::type>()
454+ part. begin ( )
455+ ,bytes_transferred
475456 );
476457 body_promise.set_value (body);
477458// TODO set the destination value somewhere!
478459 destination_promise.set_value (" " );
479460 source_promise.set_value (" " );
480- string_type (). swap (part );
461+ part. assign ( ' \0 ' );
481462 response_parser_.reset ();
463+ }else if (!ec) {
464+ this ->parse_body (bytes_transferred);
482465 }else {
483466 boost::system::system_errorerror (ec);
484467 source_promise.set_exception (boost::copy_exception (error));
@@ -488,6 +471,7 @@ namespace boost { namespace network { namespace http { namespace impl {
488471 }
489472
490473typedef response_parser<Tag> response_parser_type;
474+ typedef boost::array<typename char_<Tag>::type,1024 > buffer_type;
491475
492476 boost::shared_ptr<resolver_type> resolver_;
493477 resolve_function resolve_;
@@ -502,9 +486,8 @@ namespace boost { namespace network { namespace http { namespace impl {
502486 boost::promise<string_type> destination_promise;
503487 boost::promise<string_type> body_promise;
504488 string_type command_string_;
505- boost::asio::streambuf response_buffer_;
506489 response_parser_type response_parser_;
507- string_type part;
490+ buffer_type part;
508491 string_type partial_parsed;
509492 string_type method;
510493 };