19
19
#include < boost/logic/tribool.hpp>
20
20
#include < boost/network/protocol/http/parser/incremental.hpp>
21
21
#include < boost/network/protocol/http/message/wrappers/uri.hpp>
22
+ #include < boost/array.hpp>
22
23
#include < iterator>
23
24
24
25
namespace boost { namespace network { namespace http { namespace impl {
@@ -55,11 +56,13 @@ namespace boost { namespace network { namespace http { namespace impl {
55
56
template <class U >
56
57
string_type const operator () (U const & pair) const {
57
58
typedef typename ostringstream<Tag>::type ostringstream_type;
59
+ typedef constants<Tag> constants;
58
60
ostringstream_type header_line;
59
61
header_line << pair.first
60
- << constants<Tag>::colon ()
62
+ << constants::colon ()
63
+ << constants::space ()
61
64
<< pair.second
62
- << constants<Tag> ::crlf ();
65
+ << constants::crlf ();
63
66
return header_line.str ();
64
67
}
65
68
};
@@ -84,12 +87,12 @@ namespace boost { namespace network { namespace http { namespace impl {
84
87
if (!get_body) body_promise.set_value (string_type ());
85
88
86
89
typename ostringstream<Tag>::type command_stream;
87
- string_type uri_str ;
88
- uri_str = boost::network::http::uri (request);
90
+ string_type path_str ;
91
+ path_str = path (request);
89
92
typedef constants<Tag> constants;
90
93
command_stream
91
94
<< method << constants::space ()
92
- << uri_str << constants::space ()
95
+ << path_str << constants::space ()
93
96
<< constants::http_slash () << version_major
94
97
<< constants::dot () << version_minor
95
98
<< constants::crlf ();
@@ -122,18 +125,19 @@ namespace boost { namespace network { namespace http { namespace impl {
122
125
<< constants::user_agent () << constants::colon () << constants::space () << constants::cpp_netlib_slash () << BOOST_NETLIB_VERSION << constants::crlf ();
123
126
}
124
127
128
+ command_stream << constants::crlf ();
129
+
125
130
command_string_ = command_stream.str ();
126
131
127
132
this ->method = method;
128
-
129
- resolve_ (resolver_, host (request),
133
+
134
+ resolve_ (resolver_, host (request), port (request),
130
135
request_strand_->wrap (
131
136
boost::bind (
132
137
&http_async_connection<Tag,version_major,version_minor>::handle_resolved,
133
138
http_async_connection<Tag,version_major,version_minor>::shared_from_this (),
134
139
port (request),
135
140
_1, _2)));
136
-
137
141
return temp;
138
142
}
139
143
@@ -217,7 +221,7 @@ namespace boost { namespace network { namespace http { namespace impl {
217
221
if (!ec) {
218
222
boost::asio::async_read (
219
223
*socket_,
220
- response_buffer_ ,
224
+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
221
225
request_strand_->wrap (
222
226
boost::bind (
223
227
&http_async_connection<Tag,version_major,version_minor>::handle_received_version,
@@ -238,8 +242,10 @@ namespace boost { namespace network { namespace http { namespace impl {
238
242
}
239
243
240
244
void parse_version () {
245
+ std::cerr << ' \n ' ;
246
+
241
247
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;
243
249
fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
244
250
response_parser_type::http_version_done,
245
251
part);
@@ -249,8 +255,8 @@ namespace boost { namespace network { namespace http { namespace impl {
249
255
version.append (boost::begin (result_range), boost::end (result_range));
250
256
algorithm::trim (version);
251
257
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 () );
254
260
this ->parse_status ();
255
261
} else if (parsed_ok == false ) {
256
262
std::runtime_error error (" Invalid Version Part." );
@@ -266,10 +272,9 @@ namespace boost { namespace network { namespace http { namespace impl {
266
272
part.begin (),
267
273
part.end ()
268
274
);
269
- string_type ().swap (part);
270
275
boost::asio::async_read (
271
276
*socket_,
272
- response_buffer_ ,
277
+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
273
278
request_strand_->wrap (
274
279
boost::bind (
275
280
&http_async_connection<Tag,version_major,version_minor>::handle_received_version,
@@ -279,12 +284,8 @@ namespace boost { namespace network { namespace http { namespace impl {
279
284
}
280
285
281
286
void handle_received_version (boost::system::error_code const & ec, std::size_t bytes_transferred) {
282
- if (!ec) {
283
- typename istream<Tag>::type input_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 ();
288
289
} else {
289
290
boost::system::system_error error (ec);
290
291
version_promise.set_exception (boost::copy_exception (error));
@@ -299,7 +300,7 @@ namespace boost { namespace network { namespace http { namespace impl {
299
300
300
301
void parse_status () {
301
302
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;
303
304
fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
304
305
response_parser_type::http_status_done,
305
306
part);
@@ -310,8 +311,8 @@ namespace boost { namespace network { namespace http { namespace impl {
310
311
trim (status);
311
312
boost::uint16_t status_int = lexical_cast<boost::uint16_t >(status);
312
313
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 () );
315
316
this ->parse_status_message ();
316
317
} else if (parsed_ok == false ) {
317
318
std::runtime_error error (" Invalid status part." );
@@ -323,8 +324,8 @@ namespace boost { namespace network { namespace http { namespace impl {
323
324
body_promise.set_exception (boost::copy_exception (error));
324
325
} else {
325
326
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 ()) ,
328
329
request_strand_->wrap (
329
330
boost::bind (
330
331
&http_async_connection<Tag,version_major,version_minor>::handle_received_status,
@@ -335,11 +336,6 @@ namespace boost { namespace network { namespace http { namespace impl {
335
336
336
337
void handle_received_status (boost::system::error_code const & ec, size_t bytes_transferred) {
337
338
if (!ec) {
338
- typename istream<Tag>::type input_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
- );
343
339
this ->parse_status ();
344
340
} else {
345
341
boost::system::system_error error (ec);
@@ -354,7 +350,7 @@ namespace boost { namespace network { namespace http { namespace impl {
354
350
355
351
void parse_status_message () {
356
352
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;
358
354
fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
359
355
response_parser_type::http_status_message_done,
360
356
part);
@@ -364,8 +360,8 @@ namespace boost { namespace network { namespace http { namespace impl {
364
360
status_message.append (boost::begin (result_range), boost::end (result_range));
365
361
algorithm::trim (status_message);
366
362
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 () );
369
365
this ->parse_headers ();
370
366
} else if (parsed_ok == false ) {
371
367
std::runtime_error error (" Invalid status message part." );
@@ -376,10 +372,9 @@ namespace boost { namespace network { namespace http { namespace impl {
376
372
body_promise.set_exception (boost::copy_exception (error));
377
373
} else {
378
374
partial_parsed.append (part.begin (), part.end ());
379
- string_type ().swap (part);
380
375
boost::asio::async_read (
381
376
*socket_,
382
- response_buffer_ ,
377
+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
383
378
request_strand_->wrap (
384
379
boost::bind (
385
380
&http_async_connection<Tag,version_major,version_minor>::handle_received_status_message,
@@ -390,11 +385,6 @@ namespace boost { namespace network { namespace http { namespace impl {
390
385
391
386
void handle_received_status_message (boost::system::error_code const & ec, size_t bytes_transferred) {
392
387
if (!ec) {
393
- typename istream<Tag>::type input_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
- );
398
388
this ->parse_status_message ();
399
389
} else {
400
390
boost::system::system_error error (ec);
@@ -408,26 +398,24 @@ namespace boost { namespace network { namespace http { namespace impl {
408
398
409
399
void parse_headers () {
410
400
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;
412
402
fusion::tie (parsed_ok, result_range) = response_parser_.parse_until (
413
403
response_parser_type::http_headers_done,
414
404
part);
415
405
if (parsed_ok == true ) {
416
406
string_type headers_string;
417
407
std::swap (headers_string, partial_parsed);
418
408
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));
423
412
} else if (parsed_ok == false ) {
424
413
std::runtime_error error (" Invalid header part." );
425
414
} else {
426
415
partial_parsed.append (part.begin (), part.end ());
427
- string_type ().swap (part);
428
416
boost::asio::async_read (
429
417
*socket_,
430
- response_buffer_ ,
418
+ boost::asio::mutable_buffers_1 (part. c_array (), part. size ()) ,
431
419
request_strand_->wrap (
432
420
boost::bind (
433
421
&http_async_connection<Tag,version_major,version_minor>::handle_received_headers,
@@ -438,11 +426,6 @@ namespace boost { namespace network { namespace http { namespace impl {
438
426
439
427
void handle_received_headers (boost::system::error_code const & ec, size_t bytes_transferred) {
440
428
if (!ec) {
441
- typename istream<Tag>::type input_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
- );
446
429
this ->parse_headers ();
447
430
} else {
448
431
boost::system::system_error error (ec);
@@ -453,13 +436,12 @@ namespace boost { namespace network { namespace http { namespace impl {
453
436
}
454
437
}
455
438
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 ()),
460
442
request_strand_->wrap (
461
443
boost::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 ,
463
445
http_async_connection<Tag,version_major,version_minor>::shared_from_this (),
464
446
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
465
447
}
@@ -468,17 +450,18 @@ namespace boost { namespace network { namespace http { namespace impl {
468
450
if (ec == boost::asio::error::eof) {
469
451
string_type body;
470
452
std::swap (body, partial_parsed);
471
- typename istream<Tag>::type input_stream (&response_buffer_);
472
453
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
475
456
);
476
457
body_promise.set_value (body);
477
458
// TODO set the destination value somewhere!
478
459
destination_promise.set_value (" " );
479
460
source_promise.set_value (" " );
480
- string_type (). swap (part );
461
+ part. assign ( ' \0 ' );
481
462
response_parser_.reset ();
463
+ } else if (!ec) {
464
+ this ->parse_body (bytes_transferred);
482
465
} else {
483
466
boost::system::system_error error (ec);
484
467
source_promise.set_exception (boost::copy_exception (error));
@@ -488,6 +471,7 @@ namespace boost { namespace network { namespace http { namespace impl {
488
471
}
489
472
490
473
typedef response_parser<Tag> response_parser_type;
474
+ typedef boost::array<typename char_<Tag>::type, 1024 > buffer_type;
491
475
492
476
boost::shared_ptr<resolver_type> resolver_;
493
477
resolve_function resolve_;
@@ -502,9 +486,8 @@ namespace boost { namespace network { namespace http { namespace impl {
502
486
boost::promise<string_type> destination_promise;
503
487
boost::promise<string_type> body_promise;
504
488
string_type command_string_;
505
- boost::asio::streambuf response_buffer_;
506
489
response_parser_type response_parser_;
507
- string_type part;
490
+ buffer_type part;
508
491
string_type partial_parsed;
509
492
string_type method;
510
493
};
0 commit comments