Skip to content

Commit 286eb28

Browse files
committed
Work in progress, nearing solidification of asynchronous/synchronous plumbing re-gutting.
1 parent def75cf commit 286eb28

File tree

12 files changed

+465
-97
lines changed

12 files changed

+465
-97
lines changed

boost/network/protocol/http/client.hpp

Lines changed: 24 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#include <boost/network/protocol/http/message.hpp>
1212
#include <boost/network/protocol/http/response.hpp>
1313
#include <boost/network/protocol/http/request.hpp>
14-
#include <boost/network/protocol/http/traits/connection_policy.hpp>
14+
1515
#include <boost/asio/io_service.hpp>
1616
#include <boost/lexical_cast.hpp>
1717
#include <boost/algorithm/string/classification.hpp>
@@ -23,14 +23,19 @@
2323
#include <stdexcept>
2424
#include <map>
2525

26+
#include <boost/network/protocol/http/client/facade.hpp>
27+
#include <boost/network/protocol/http/client/pimpl.hpp>
28+
2629
namespace boost { namespace network { namespace http {
2730

2831
template <class Tag, unsigned version_major, unsigned version_minor>
29-
struct basic_client : connection_policy<Tag, version_major, version_minor>::type {
30-
private:
31-
typedef typename string<Tag>::type string_type;
32+
struct basic_client
33+
: basic_client_facade<basic_client<Tag,version_major,version_minor> >
34+
{
35+
private:
36+
typedef typename basic_client_impl<Tag,version_major,version_minor> pimpl_type;
3237

33-
public:
38+
public:
3439
typedef basic_request<Tag> request;
3540
typedef basic_response<Tag> response;
3641

@@ -53,84 +58,37 @@ namespace boost { namespace network { namespace http {
5358
// Constructors
5459
// =================================================================
5560
basic_client()
56-
: connection_base(false, false), service_(), resolver_(service_)
61+
: pimpl(new pimpl_type(false, false))
5762
{}
5863

5964
explicit basic_client(cache_resolved_type (*)())
60-
: connection_base(true, false), service_(), resolver_(service_)
65+
: pimpl(new pimmpl_type(true, false))
6166
{}
6267

6368
explicit basic_client(follow_redirect_type (*)())
64-
: connection_base(false, true), service_(), resolver_(service_)
69+
: pimpl(new pimpl_type(false, true))
6570
{}
6671

6772
basic_client(cache_resolved_type (*)(), follow_redirect_type (*)())
68-
: connection_base(true, true), service_(), resolver_(service_)
73+
: pimpl(new pimpl_type(true, true))
6974
{}
7075

7176
//
7277
// =================================================================
7378

74-
~basic_client() {
75-
connection_base::cleanup();
76-
}
77-
78-
void clear_resolved_cache() {
79-
connection_base::endpoint_cache_.clear();
80-
}
81-
82-
response const head (request const & request_) {
83-
return request_skeleton(request_, "HEAD", false);
84-
};
85-
86-
response const get (request const & request_) {
87-
return request_skeleton(request_, "GET", true);
88-
};
89-
90-
response const post (request const & request_) {
91-
return request_skeleton(request_, "POST", true);
92-
};
93-
94-
response const post (request request_, string_type const & content_type, string_type const & body_) {
95-
request_ << body(body_)
96-
<< header("Content-Type", content_type)
97-
<< header("Content-Length", boost::lexical_cast<string_type>(body_.size()));
98-
return post(request_);
99-
};
100-
101-
response const post (request const & request_, string_type const & body_) {
102-
return post(request_, "x-application/octet-stream", body_);
103-
};
104-
105-
response const put (request const & request_) {
106-
return request_skeleton(request_, "PUT", true);
107-
};
108-
109-
response const put (request const & request_, string_type const & body_) {
110-
return put(request_, "x-application/octet-stream", body_);
111-
};
112-
113-
response const put (request request_, string_type const & content_type, string_type const & body_) {
114-
request_ << body(body_)
115-
<< header("Content-Type", content_type)
116-
<< header("Content-Length", boost::lexical_cast<string_type>(body_.size()));
117-
return put(request_);
118-
};
119-
120-
response const delete_ (request const & request_) {
121-
return request_skeleton(request_, "DELETE", true);
122-
};
123-
124-
private:
79+
~basic_client()
80+
{}
12581

126-
typedef typename connection_policy<Tag, version_major, version_minor>::type connection_base;
127-
boost::asio::io_service service_;
128-
typename connection_base::resolver_type resolver_;
82+
private:
83+
84+
boost::shared_ptr<pimpl_type> pimpl;
12985

13086
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body) {
131-
typename connection_base::connection_ptr connection_;
132-
connection_ = connection_base::get_connection(resolver_, request_);
133-
return connection_->send_request(method, request_, get_body);
87+
return pimpl->request_skeleton(request_, method, get_body);
88+
}
89+
90+
void clear_resolved_cache() {
91+
pimpl->clear_resolved_cache();
13492
}
13593

13694
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623
3+
4+
// Copyright Dean Michael Berris 2010.
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/asio/io_service.hpp>
10+
#include <boost/thread/thread.hpp>
11+
#include <boost/bind.hpp>
12+
13+
namespace boost { namespace network { namespace http {
14+
15+
template <class Tag, unsigned version_major, unsigned version_minor>
16+
struct basic_client_impl;
17+
18+
namespace impl {
19+
template <class Tag, unsigned version_major, unsigned version_minor>
20+
struct async_client :
21+
connection_policy<Tag,version_major,version_minor>::type
22+
{
23+
protected:
24+
typedef
25+
typename connection_policy<Tag,version_major,version_minor>::type
26+
connection_base;
27+
typedef
28+
typename resolver<Tag>::type
29+
resolver_type;
30+
31+
async_client(bool cache_resolved, bool follow_redirect)
32+
: connection_base(cache_resolved, follow_redirect),
33+
service_(new boost::asio::io_service),
34+
resolver_(new resolver_type(*service_)),
35+
sentinel_(new boost::asio::io_service::work(*service_))
36+
{
37+
lifetime_thread_.reset(new boost::thread(
38+
boost::bind(
39+
&boost::asio::io_service::run,
40+
service_
41+
)));
42+
}
43+
44+
~async_client()
45+
{
46+
sentinel_.reset();
47+
lifetime_thread_->join();
48+
lifetime_thread_.reset();
49+
}
50+
51+
friend struct basic_client_impl<Tag,version_major,version_minor>;
52+
53+
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body) {
54+
typename connection_base::connection_ptr connection_;
55+
connection_ = connection_base::get_connection(service_, resolver_, request_);
56+
return connection_->send_request(method, request_, get_body);
57+
}
58+
59+
boost::shared_ptr<boost::asio::io_service> service_;
60+
boost::shared_ptr<resolver_type> resolver_;
61+
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
62+
boost::shared_ptr<boost::thread> lifetime_thread_;
63+
};
64+
} // namespace impl
65+
66+
} // namespace http
67+
68+
} // namespace network
69+
70+
} // namespace boost
71+
72+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_ASYNC_IMPL_HPP_20100623
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
3+
4+
// Copyright Dean Michael Berris 2010.
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+
namespace boost { namespace network { namespace http {
10+
11+
template <class Tag>
12+
class basic_request;
13+
14+
template <class Tag>
15+
struct basic_response;
16+
17+
template <class Derived>
18+
struct basic_client_facade {
19+
typedef basic_request<typename Derived::tag> request;
20+
typedef basic_response<typename Derived::tag> response;
21+
typedef typename string<typename Derived::tag>::type string_type;
22+
23+
response const head (request const & request_) {
24+
return static_cast<Derived*>(this)->request_skeleton(request_, "HEAD", false);
25+
}
26+
27+
response const get (request const & request_) {
28+
return static_cast<Derived*>(this)->request_skeleton(request_, "GET", true);
29+
}
30+
31+
response const post (request const & request_) {
32+
return static_cast<Derived*>(this)->request_skeleton(request_, "POST", true);
33+
}
34+
35+
response const post (request request_, string_type const & content_type, string_type const & body_) {
36+
request_ << body(body_)
37+
<< header("Content-Type", content_type)
38+
<< header("Content-Length", boost::lexical_cast<string_type>(body_.size()));
39+
return post(request_);
40+
}
41+
42+
response const post (request const & request_, string_type const & body_) {
43+
return post(request_, "x-application/octet-stream", body_);
44+
}
45+
46+
response const put (request const & request_) {
47+
return static_cast<Derived*>(this)->request_skeleton(request_, "PUT", true);
48+
}
49+
50+
response const put (request const & request_, string_type const & body_) {
51+
return put(request_, "x-application/octet-stream", body_);
52+
}
53+
54+
response const put (request request_, string_type const & content_type, string_type const & body_) {
55+
request_ << body(body_)
56+
<< header("Content-Type", content_type)
57+
<< header("Content-Length", boost::lexical_cast<string_type>(body_.size()));
58+
return put(request_);
59+
}
60+
61+
response const delete_ (request const & request_) {
62+
return static_cast<Derived*>(this)->request_skeleton(request_, "DELETE", true);
63+
}
64+
65+
void clear_resolved_cache() {
66+
static_cast<Derived*>(this)->clear_resolved_cache();
67+
}
68+
69+
};
70+
71+
} // namespace http
72+
73+
} // namespace network
74+
75+
} // namespace boost
76+
77+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_FACADE_HPP_20100623
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623
3+
4+
// Copyright Dean Michael Berris 2010.
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/network/support/is_async.hpp>
10+
#include <boost/network/support/is_sync.hpp>
11+
#include <boost/mpl/not.hpp>
12+
#include <boost/mpl/and.hpp>
13+
#include <boost/mpl/if.hpp>
14+
#include <boost/static_assert.hpp>
15+
16+
#include <boost/network/protocol/http/traits/connection_policy.hpp>
17+
18+
namespace boost { namespace network { namespace http {
19+
20+
template <class Tag, unsigned version_major, unsigned version_minor>
21+
struct basic_client_impl;
22+
23+
namespace impl {
24+
25+
template <class Tag, unsigned version_major, unsigned version_minor>
26+
struct async_client;
27+
28+
template <class Tag, unsigned version_major, unsigned version_minor>
29+
struct sync_client
30+
{
31+
protected:
32+
friend struct basic_client_impl<Tag,version_major,version_minor>;
33+
34+
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body) {
35+
typename connection_base::connection_ptr connection_;
36+
connection_ = connection_base::get_connection(resolver_, request_);
37+
return connection_->send_request(method, request_, get_body);
38+
}
39+
40+
};
41+
42+
template <class Tag, unsigned version_major, unsigned version_minor>
43+
struct client_base
44+
: mpl::if_<
45+
is_async<Tag>,
46+
async_client<Tag,version_major,version_minor>,
47+
sync_client<Tag,version_major,version_minor>
48+
>
49+
{};
50+
51+
} // namespace impl
52+
53+
template <class Tag, unsigned version_major, unsigned version_minor>
54+
struct basic_client;
55+
56+
template <class Tag, unsigned version_major, unsigned version_minor>
57+
struct basic_client_impl
58+
: impl::client_base<Tag,version_major,version_minor>::type
59+
{
60+
BOOST_STATIC_ASSERT((
61+
mpl::not_<
62+
mpl::and_<
63+
is_async<Tag>,
64+
is_sync<Tag>
65+
>
66+
>::value
67+
));
68+
69+
private:
70+
typedef typename impl::client_base<Tag,version_major,version_minor>::type base_type;
71+
basic_client_impl(bool cache_resolved, bool follow_redirect)
72+
: base_type(cache_resolved, follow_redirect)
73+
{}
74+
75+
~basic_client_impl()
76+
{}
77+
};
78+
79+
80+
};
81+
82+
} // namespace http
83+
84+
} // namespace network
85+
86+
} // namespace boost
87+
88+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_PIMPL_HPP_20100623

0 commit comments

Comments
 (0)