Skip to content

Commit 32d730c

Browse files
deanberrisglynos
authored andcommitted
Body generator for PUT/POST APIs
This commit does the following things: - Add overloads to the HTTP Client implementation that takes a generator callback to generate chunks of the POST or PUT requests. - Fixes cpp-netlib#245 which happens when a resolution error occurs, which leaks futures and potentially threads associated with futures. - Formats the files touched using clang-format in Google's style. Unfortunately the API cannot be tested without starting a POST/PUT capable server. A future commit should add an end-to-end test that uses the HTTP server implementation and the HTTP client implementation to verify end-to-end correctness.
1 parent a5feaa6 commit 32d730c

File tree

11 files changed

+1673
-1346
lines changed

11 files changed

+1673
-1346
lines changed

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

+63-67
Original file line numberDiff line numberDiff line change
@@ -15,82 +15,78 @@
1515
#include <boost/make_shared.hpp>
1616
#include <boost/bind.hpp>
1717

18-
namespace boost { namespace network { namespace http {
18+
namespace boost {
19+
namespace network {
20+
namespace http {
1921

20-
template <class Tag, unsigned version_major, unsigned version_minor>
21-
struct basic_client_impl;
22+
template <class Tag, unsigned version_major, unsigned version_minor>
23+
struct basic_client_impl;
2224

23-
namespace impl {
24-
template <class Tag, unsigned version_major, unsigned version_minor>
25-
struct async_client :
26-
connection_policy<Tag,version_major,version_minor>::type
27-
{
28-
typedef
29-
typename connection_policy<Tag,version_major,version_minor>::type
30-
connection_base;
31-
typedef
32-
typename resolver<Tag>::type
33-
resolver_type;
34-
typedef
35-
typename string<Tag>::type
36-
string_type;
25+
namespace impl {
26+
template <class Tag, unsigned version_major, unsigned version_minor>
27+
struct async_client
28+
: connection_policy<Tag, version_major, version_minor>::type {
29+
typedef typename connection_policy<Tag, version_major, version_minor>::type
30+
connection_base;
31+
typedef typename resolver<Tag>::type resolver_type;
32+
typedef typename string<Tag>::type string_type;
3733

38-
typedef
39-
function<void(boost::iterator_range<char const *> const &, system::error_code const &)>
40-
body_callback_function_type;
34+
typedef function<void(boost::iterator_range<char const*> const&,
35+
system::error_code const&)> body_callback_function_type;
4136

42-
async_client(bool cache_resolved, bool follow_redirect, boost::shared_ptr<boost::asio::io_service> service, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
43-
: connection_base(cache_resolved, follow_redirect),
44-
service_ptr(service.get() ? service : boost::make_shared<boost::asio::io_service>()),
37+
typedef function<bool(string_type&)> body_generator_function_type;
38+
39+
async_client(bool cache_resolved,
40+
bool follow_redirect,
41+
boost::shared_ptr<boost::asio::io_service> service,
42+
optional<string_type> const& certificate_filename,
43+
optional<string_type> const& verify_path)
44+
: connection_base(cache_resolved, follow_redirect),
45+
service_ptr(service.get()
46+
? service
47+
: boost::make_shared<boost::asio::io_service>()),
4548
service_(*service_ptr),
4649
resolver_(service_),
4750
sentinel_(new boost::asio::io_service::work(service_)),
4851
certificate_filename_(certificate_filename),
49-
verify_path_(verify_path)
50-
{
51-
connection_base::resolver_strand_.reset(new
52-
boost::asio::io_service::strand(service_));
53-
lifetime_thread_.reset(new boost::thread(
54-
boost::bind(
55-
&boost::asio::io_service::run,
56-
&service_
57-
)));
58-
}
59-
60-
~async_client() throw ()
61-
{
62-
sentinel_.reset();
63-
if (lifetime_thread_.get()) {
64-
lifetime_thread_->join();
65-
lifetime_thread_.reset();
66-
}
67-
}
68-
69-
basic_response<Tag> const request_skeleton(
70-
basic_request<Tag> const & request_,
71-
string_type const & method,
72-
bool get_body,
73-
body_callback_function_type callback
74-
)
75-
{
76-
typename connection_base::connection_ptr connection_;
77-
connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_);
78-
return connection_->send_request(method, request_, get_body, callback);
79-
}
80-
81-
boost::shared_ptr<boost::asio::io_service> service_ptr;
82-
boost::asio::io_service & service_;
83-
resolver_type resolver_;
84-
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
85-
boost::shared_ptr<boost::thread> lifetime_thread_;
86-
optional<string_type> certificate_filename_, verify_path_;
87-
};
88-
} // namespace impl
52+
verify_path_(verify_path) {
53+
connection_base::resolver_strand_.reset(
54+
new boost::asio::io_service::strand(service_));
55+
lifetime_thread_.reset(new boost::thread(
56+
boost::bind(&boost::asio::io_service::run, &service_)));
57+
}
8958

90-
} // namespace http
59+
~async_client() throw() {
60+
sentinel_.reset();
61+
if (lifetime_thread_.get()) {
62+
lifetime_thread_->join();
63+
lifetime_thread_.reset();
64+
}
65+
}
9166

92-
} // namespace network
67+
basic_response<Tag> const request_skeleton(
68+
basic_request<Tag> const& request_,
69+
string_type const& method,
70+
bool get_body,
71+
body_callback_function_type callback,
72+
body_generator_function_type generator) {
73+
typename connection_base::connection_ptr connection_;
74+
connection_ = connection_base::get_connection(
75+
resolver_, request_, certificate_filename_, verify_path_);
76+
return connection_->send_request(
77+
method, request_, get_body, callback, generator);
78+
}
9379

94-
} // namespace boost
80+
boost::shared_ptr<boost::asio::io_service> service_ptr;
81+
boost::asio::io_service& service_;
82+
resolver_type resolver_;
83+
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
84+
boost::shared_ptr<boost::thread> lifetime_thread_;
85+
optional<string_type> certificate_filename_, verify_path_;
86+
};
87+
} // namespace impl
88+
} // namespace http
89+
} // namespace network
90+
} // namespace boost
9591

96-
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623
92+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529
22
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_ASYNC_CONNECTION_BASE_20100529
33

4-
// Copyright 2010 (C) Dean Michael Berris
4+
// Copryight 2013 Google, Inc.
5+
// Copyright 2010 Dean Michael Berris <[email protected]>
56
// Copyright 2010 (C) Sinefunc, Inc.
67
// Distributed under the Boost Software License, Version 1.0.
78
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -26,6 +27,7 @@ namespace boost { namespace network { namespace http { namespace impl {
2627
typedef iterator_range<char const *> char_const_range;
2728
typedef function<void(char_const_range const &, system::error_code const &)>
2829
body_callback_function_type;
30+
typedef function<bool(string_type&)> body_generator_function_type;
2931
typedef shared_ptr<this_type> connection_ptr;
3032

3133
// This is the factory function which constructs the appropriate async
@@ -61,7 +63,8 @@ namespace boost { namespace network { namespace http { namespace impl {
6163
request const & request,
6264
string_type const & method,
6365
bool get_body,
64-
body_callback_function_type callback) = 0;
66+
body_callback_function_type callback,
67+
body_generator_function_type generator) = 0;
6568

6669
virtual ~async_connection_base() {}
6770

0 commit comments

Comments
 (0)