Skip to content

Commit c78ca0d

Browse files
committed
Adding support for Asynchronous Body Handling. Fixes cpp-netlib#53 cpp-netlib#27 cpp-netlib#3
1 parent 7f02e43 commit c78ca0d

15 files changed

+187
-65
lines changed

boost/network/protocol/http/client.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include <boost/network/protocol/http/client/facade.hpp>
2727
#include <boost/network/protocol/http/client/parameters.hpp>
28+
#include <boost/network/protocol/http/client/macros.hpp>
2829

2930
namespace boost { namespace network { namespace http {
3031

boost/network/protocol/http/client/async_impl.hpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ namespace boost { namespace network { namespace http {
3131
typename string<Tag>::type
3232
string_type;
3333

34+
typedef
35+
function<void(boost::iterator_range<char const *> const &, system::error_code const &)>
36+
body_callback_function_type;
37+
3438
async_client(bool cache_resolved, bool follow_redirect, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
3539
: connection_base(cache_resolved, follow_redirect),
3640
service_ptr(new boost::asio::io_service),
@@ -73,12 +77,13 @@ namespace boost { namespace network { namespace http {
7377
basic_response<Tag> const request_skeleton(
7478
basic_request<Tag> const & request_,
7579
string_type const & method,
76-
bool get_body
80+
bool get_body,
81+
body_callback_function_type callback
7782
)
7883
{
7984
typename connection_base::connection_ptr connection_;
8085
connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_);
81-
return connection_->send_request(method, request_, get_body);
86+
return connection_->send_request(method, request_, get_body, callback);
8287
}
8388

8489
boost::asio::io_service * service_ptr;

boost/network/protocol/http/client/connection/async_base.hpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace boost { namespace network { namespace http { namespace impl {
2323
typedef typename string<Tag>::type string_type;
2424
typedef basic_request<Tag> request;
2525
typedef basic_response<Tag> response;
26+
typedef
27+
function<void(iterator_range<char const *> const &, system::error_code const &)>
28+
body_callback_function_type;
2629

2730
static boost::shared_ptr<async_connection_base<Tag,version_major,version_minor> > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional<string_type> certificate_filename=optional<string_type>(), optional<string_type> const & verify_path=optional<string_type>()) {
2831
boost::shared_ptr<async_connection_base<Tag,version_major,version_minor> > temp;
@@ -39,7 +42,9 @@ namespace boost { namespace network { namespace http { namespace impl {
3942
return temp;
4043
}
4144

42-
virtual response start(request const & request, string_type const & method, bool get_body) = 0;
45+
virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) = 0;
46+
47+
virtual ~async_connection_base() {}
4348

4449
};
4550

boost/network/protocol/http/client/connection/async_normal.hpp

+72-40
Large diffs are not rendered by default.

boost/network/protocol/http/client/connection/async_protocol_handler.hpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ namespace boost { namespace network { namespace http { namespace impl {
7979
boost::end(result_range)
8080
);
8181
part_begin = part.begin();
82-
boost::asio::async_read(
83-
socket_,
82+
socket_.async_read_some(
8483
boost::asio::mutable_buffers_1(part.c_array(), part.size()),
8584
callback
8685
);
@@ -119,7 +118,7 @@ namespace boost { namespace network { namespace http { namespace impl {
119118
boost::end(result_range)
120119
);
121120
part_begin = part.begin();
122-
boost::asio::async_read(socket_,
121+
socket_.async_read_some(
123122
boost::asio::mutable_buffers_1(part.c_array(), part.size()),
124123
callback
125124
);
@@ -155,8 +154,7 @@ namespace boost { namespace network { namespace http { namespace impl {
155154
boost::begin(result_range),
156155
boost::end(result_range));
157156
part_begin = part.begin();
158-
boost::asio::async_read(
159-
socket_,
157+
socket_.async_read_some(
160158
boost::asio::mutable_buffers_1(part.c_array(), part.size()),
161159
callback
162160
);
@@ -225,8 +223,7 @@ namespace boost { namespace network { namespace http { namespace impl {
225223
} else {
226224
partial_parsed.append(boost::begin(result_range), boost::end(result_range));
227225
part_begin = part.begin();
228-
boost::asio::async_read(
229-
socket_,
226+
socket_.async_read_some(
230227
boost::asio::mutable_buffers_1(part.c_array(), part.size()),
231228
callback
232229
);
@@ -244,8 +241,7 @@ namespace boost { namespace network { namespace http { namespace impl {
244241
void parse_body(Socket & socket_, Callback callback, size_t bytes) {
245242
partial_parsed.append(part_begin, bytes);
246243
part_begin = part.begin();
247-
boost::asio::async_read(
248-
socket_,
244+
socket_.async_read_some(
249245
boost::asio::mutable_buffers_1(part.c_array(), part.size()),
250246
callback
251247
);

boost/network/protocol/http/client/connection/async_ssl.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ namespace boost { namespace network { namespace http { namespace impl {
3232
typedef typename base::string_type string_type;
3333
typedef typename base::request request;
3434
typedef typename base::resolver_base::resolve_function resolve_function;
35+
typedef typename base::body_callback_function_type body_callback_function_type;
3536

3637
https_async_connection(
3738
resolver_type & resolver,
@@ -49,7 +50,7 @@ namespace boost { namespace network { namespace http { namespace impl {
4950
{}
5051

5152

52-
virtual response start(request const & request, string_type const & method, bool get_body) {
53+
virtual response start(request const & request, string_type const & method, bool get_body, body_callback_function_type callback) {
5354
response response_;
5455
this->init_response(response_, get_body);
5556
linearize(request, method, version_major, version_minor,

boost/network/protocol/http/client/facade.hpp

+19-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace boost { namespace network { namespace http {
2626
typedef basic_request<Tag> request;
2727
typedef basic_response<Tag> response;
2828
typedef basic_client_impl<Tag,version_major,version_minor> pimpl_type;
29+
typedef function<void(iterator_range<char const *> const &,system::error_code const &)> body_callback_function_type;
2930

3031
template <class ArgPack>
3132
basic_client_facade(ArgPack const & args)
@@ -42,11 +43,18 @@ namespace boost { namespace network { namespace http {
4243
}
4344

4445
BOOST_PARAMETER_MEMBER_FUNCTION((response const), head, tag, (required (request,(request const &)))) {
45-
return pimpl->request_skeleton(request, "HEAD", false);
46+
return pimpl->request_skeleton(request, "HEAD", false, body_callback_function_type());
4647
}
4748

48-
BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag, (required (request,(request const &)))) {
49-
return pimpl->request_skeleton(request, "GET", true);
49+
BOOST_PARAMETER_MEMBER_FUNCTION((response const), get , tag,
50+
(required
51+
(request,(request const &))
52+
)
53+
(optional
54+
(body_handler,(body_callback_function_type),body_callback_function_type())
55+
)
56+
) {
57+
return pimpl->request_skeleton(request, "GET", true, body_handler);
5058
}
5159

5260
BOOST_PARAMETER_MEMBER_FUNCTION((response const), post, tag,
@@ -56,6 +64,7 @@ namespace boost { namespace network { namespace http {
5664
(optional
5765
(body,(string_type const &),string_type())
5866
(content_type,(string_type const &),string_type())
67+
(body_handler,(body_callback_function_type),body_callback_function_type())
5968
)
6069
) {
6170
if (body != string_type()) {
@@ -76,7 +85,7 @@ namespace boost { namespace network { namespace http {
7685
request << header("Content-Type", content_type);
7786
}
7887
}
79-
return pimpl->request_skeleton(request, "POST", true);
88+
return pimpl->request_skeleton(request, "POST", true, body_handler);
8089
}
8190

8291
BOOST_PARAMETER_MEMBER_FUNCTION((response const), put , tag,
@@ -86,6 +95,7 @@ namespace boost { namespace network { namespace http {
8695
(optional
8796
(body,(string_type const &),string_type())
8897
(content_type,(string_type const &),string_type())
98+
(body_handler,(body_callback_function_type),body_callback_function_type())
8999
)
90100
) {
91101
if (body != string_type()) {
@@ -106,15 +116,18 @@ namespace boost { namespace network { namespace http {
106116
request << header("Content-Type", content_type);
107117
}
108118
}
109-
return pimpl->request_skeleton(request, "PUT", true);
119+
return pimpl->request_skeleton(request, "PUT", true, body_handler);
110120
}
111121

112122
BOOST_PARAMETER_MEMBER_FUNCTION((response const), delete_, tag,
113123
(required
114124
(request,(request const &))
115125
)
126+
(optional
127+
(body_handler,(body_callback_function_type),body_callback_function_type())
128+
)
116129
) {
117-
return pimpl->request_skeleton(request, "DELETE", true);
130+
return pimpl->request_skeleton(request, "DELETE", true, body_handler);
118131
}
119132

120133
void clear_resolved_cache() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430
3+
4+
// Copyright 2011 Dean Michael Berris <[email protected]>.
5+
// Distributed under the Boost Software License, Version 1.0.
6+
// (See accompanying file LICENSE_1_0.txt or copy at
7+
// http://www.boost.org/LICENSE_1_0.txt)
8+
9+
#include <boost/range/iterator_range.hpp>
10+
#include <boost/system/error_code.hpp>
11+
12+
#ifndef BOOST_NETWORK_HTTP_BODY_CALLBACK
13+
#define BOOST_NETWORK_HTTP_BODY_CALLBACK(function_name, range_name, error_name) \
14+
void function_name (boost::iterator_range<char*> const & range_name, boost::system::error_code const & error_name)
15+
#endif
16+
17+
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_MACROS_HPP_20110430 */
18+

boost/network/protocol/http/client/parameters.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace boost { namespace network { namespace http {
1818
BOOST_PARAMETER_NAME(request)
1919
BOOST_PARAMETER_NAME(body)
2020
BOOST_PARAMETER_NAME(content_type)
21+
BOOST_PARAMETER_NAME(body_handler)
2122

2223
} /* http */
2324

boost/network/protocol/http/client/sync_impl.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace boost { namespace network { namespace http {
1919
typedef typename string<Tag>::type string_type;
2020
typedef typename connection_policy<Tag,version_major,version_minor>::type connection_base;
2121
typedef typename resolver<Tag>::type resolver_type;
22+
typedef function<void(iterator_range<char const *> const &, system::error_code const &)> body_callback_function_type;
2223
friend struct basic_client_impl<Tag,version_major,version_minor>;
2324

2425
boost::asio::io_service * service_ptr;
@@ -55,10 +56,10 @@ namespace boost { namespace network { namespace http {
5556
delete service_ptr;
5657
}
5758

58-
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body) {
59+
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body, body_callback_function_type callback) {
5960
typename connection_base::connection_ptr connection_;
6061
connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path);
61-
return connection_->send_request(method, request_, get_body);
62+
return connection_->send_request(method, request_, get_body, callback);
6263
}
6364

6465
};

boost/network/protocol/http/policies/async_connection.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace boost { namespace network { namespace http {
2828
typedef typename resolver_policy<Tag>::type resolver_base;
2929
typedef typename resolver_base::resolver_type resolver_type;
3030
typedef typename resolver_base::resolve_function resolve_function;
31+
typedef function<void(iterator_range<char const *> const &, system::error_code const &)> body_callback_function_type;
3132

3233
struct connection_impl {
3334
connection_impl(
@@ -42,8 +43,8 @@ namespace boost { namespace network { namespace http {
4243
pimpl = impl::async_connection_base<Tag,version_major,version_minor>::new_connection(resolve, resolver, follow_redirect, https, certificate_filename, verify_path);
4344
}
4445

45-
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> const & request_, bool get_body) {
46-
return pimpl->start(request_, method, get_body);
46+
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> const & request_, bool get_body, body_callback_function_type callback) {
47+
return pimpl->start(request_, method, get_body, callback);
4748
}
4849

4950
private:

boost/network/protocol/http/policies/pooled_connection.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace boost { namespace network { namespace http {
2929
typedef typename resolver_policy<Tag>::type resolver_base;
3030
typedef typename resolver_base::resolver_type resolver_type;
3131
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type &, string_type const &, string_type const &)> resolver_function_type;
32+
typedef function<void(iterator_range<char const *> const &, system::error_code const &)> body_callback_function_type;
3233

3334
void cleanup() {
3435
host_connection_map().swap(host_connections);
@@ -46,7 +47,7 @@ namespace boost { namespace network { namespace http {
4647
, verify_path_(verify_path)
4748
{}
4849

49-
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body) {
50+
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body, body_callback_function_type callback) {
5051
return send_request_impl(method, request_, get_body);
5152
}
5253

boost/network/protocol/http/policies/simple_connection.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ namespace boost { namespace network { namespace http {
2727
typedef typename resolver_policy<Tag>::type resolver_base;
2828
typedef typename resolver_base::resolver_type resolver_type;
2929
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type &, string_type const &, string_type const &)> resolver_function_type;
30+
typedef function<void(iterator_range<char const *> const &, system::error_code const &)> body_callback_function_type;
3031

3132
struct connection_impl {
3233
connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & hostname, string_type const & port, resolver_function_type resolve, bool https, optional<string_type> const & certificate_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>())
@@ -36,7 +37,7 @@ namespace boost { namespace network { namespace http {
3637
pimpl.reset(impl::sync_connection_base<Tag,version_major,version_minor>::new_connection(resolver, resolve, https, certificate_filename, verify_path));
3738
}
3839

39-
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body) {
40+
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body, body_callback_function_type callback) {
4041
basic_response<Tag> response_;
4142
do {
4243
pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port()));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2011 Dean Michael Berris &lt;[email protected]&gt;.
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// (See accompanying file LICENSE_1_0.txt or copy at
4+
// http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#define BOOST_TEST_MODULE HTTP 1.1 Get Streaming Test
7+
#include <boost/network/include/http/client.hpp>
8+
#include <boost/test/unit_test.hpp>
9+
#include "client_types.hpp"
10+
11+
namespace net = boost::network;
12+
namespace http = boost::network::http;
13+
14+
struct body_handler {
15+
16+
explicit body_handler(std::string & body)
17+
: body(body) {}
18+
19+
BOOST_NETWORK_HTTP_BODY_CALLBACK(operator(), range, error) {
20+
std::cout << "Length: " << std::distance(boost::begin(range), boost::end(range)) << std::endl;
21+
body.append(boost::begin(range), boost::end(range));
22+
}
23+
24+
std::string & body;
25+
26+
};
27+
28+
29+
BOOST_AUTO_TEST_CASE_TEMPLATE(http_client_get_streaming_test, client, client_types) {
30+
typename client::request request("http://www.boost.org");
31+
client client_;
32+
typename client::response response;
33+
typename client::string_type body_string;
34+
body_handler handler_instance(body_string);
35+
BOOST_CHECK_NO_THROW( response = client_.get(request, http::_body_handler=handler_instance) );
36+
typename net::headers_range<typename client::response>::type range = headers(response)["Content-Type"];
37+
BOOST_CHECK ( !boost::empty(range) );
38+
BOOST_CHECK ( body(response).size() != 0 );
39+
BOOST_CHECK_EQUAL ( response.version().substr(0, 7), std::string("HTTP/1.") );
40+
BOOST_CHECK_EQUAL ( response.status(), 200u );
41+
BOOST_CHECK_EQUAL ( response.status_message(), std::string("OK") );
42+
typename client::string_type dummy_body = body(response);
43+
BOOST_CHECK_EQUAL ( dummy_body, typename client::string_type() );
44+
}
45+

libs/network/test/http/server_async_less_copy.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <boost/network/include/http/server.hpp>
1313
#include <boost/network/utils/thread_pool.hpp>
1414
#include <boost/range/algorithm/find_if.hpp>
15+
#include <iostream>
1516

1617
namespace net = boost::network;
1718
namespace http = boost::network::http;

0 commit comments

Comments
 (0)