Skip to content

Commit 6072032

Browse files
committed
Refactoring out the synchronous HTTP/HTTPS implementation, and adding a flag for BOOST_NETWORK_NO_HTTPS to disable linking against OpenSSL.
1 parent 37357c6 commit 6072032

File tree

3 files changed

+195
-135
lines changed

3 files changed

+195
-135
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100601
3+
4+
// Copyright 2010 (C) Dean Michael Berris
5+
// Copyright 2010 (C) Sinefunc, Inc.
6+
// Distributed under the Boost Software License, Version 1.0.
7+
// (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
10+
namespace boost { namespace network { namespace http { namespace impl {
11+
12+
template <class Tag, unsigned version_major, unsigned version_minor>
13+
struct sync_connection_base_impl;
14+
15+
template <class Tag, unsigned version_major, unsigned version_minor>
16+
struct sync_connection_base;
17+
18+
template <class Tag, unsigned version_major, unsigned version_minor>
19+
struct http_sync_connection : public virtual sync_connection_base<Tag, version_major, version_minor>, detail::connection_helper<Tag, version_major, version_minor>, connection_base_impl<Tag, version_major, version_minor> {
20+
typedef typename resolver_policy<Tag>::type resolver_base;
21+
typedef typename resolver_base::resolver_type resolver_type;
22+
typedef typename string<Tag>::type string_type;
23+
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
24+
typedef sync_connection_base_impl<Tag,version_major,version_minor> connection_base;
25+
26+
http_sync_connection(resolver_type & resolver, resolver_function_type resolve)
27+
: connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.io_service()) { }
28+
29+
void init_socket(string_type const & hostname, string_type const & port) {
30+
connection_base::init_socket(socket_, resolver_, hostname, port, resolve_);
31+
}
32+
33+
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
34+
boost::asio::streambuf request_buffer;
35+
create_request(request_buffer, method, request_);
36+
connection_base::send_request_impl(socket_, method, request_buffer);
37+
}
38+
39+
void read_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
40+
connection_base::read_status(socket_, response_, response_buffer);
41+
}
42+
43+
void read_headers(basic_response<Tag> & response, boost::asio::streambuf & response_buffer) {
44+
connection_base::read_headers(socket_, response, response_buffer);
45+
}
46+
47+
void read_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
48+
connection_base::read_body(socket_, response_, response_buffer);
49+
typename headers_range<basic_response<Tag> >::type connection_range =
50+
headers(response_)["Connection"];
51+
if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) {
52+
close_socket();
53+
} else if (version_major == 1 && version_minor == 0) {
54+
close_socket();
55+
}
56+
}
57+
58+
bool is_open() { return socket_.is_open(); }
59+
60+
void close_socket() {
61+
boost::system::error_code ignored;
62+
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored);
63+
socket_.close(ignored);
64+
}
65+
66+
~http_sync_connection() {
67+
close_socket();
68+
}
69+
70+
private:
71+
72+
resolver_type & resolver_;
73+
resolver_function_type resolve_;
74+
boost::asio::ip::tcp::socket socket_;
75+
76+
};
77+
78+
} // namespace impl
79+
80+
} // nmaespace http
81+
82+
} // namespace network
83+
84+
} // nmaespace boost
85+
86+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTP_SYNC_CONNECTION_20100
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601
2+
#define BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601
3+
4+
// Copyright 2010 (C) Dean Michael Berris
5+
// Copyright 2010 (C) Sinefunc, Inc.
6+
// Distributed under the Boost Software License, Version 1.0.
7+
// (See accompanying file LICENSE_1_0.txt or copy at
8+
// http://www.boost.org/LICENSE_1_0.txt)
9+
10+
#include <boost/asio/ssl.hpp>
11+
12+
namespace boost { namespace network { namespace http { namespace impl {
13+
14+
template <class Tag, unsigned version_major, unsigned version_minor>
15+
struct sync_connection_base_impl;
16+
17+
template <class Tag, unsigned version_major, unsigned version_minor>
18+
struct sync_connection_base;
19+
20+
template <class Tag, unsigned version_major, unsigned version_minor>
21+
struct https_sync_connection : public virtual sync_connection_base<Tag,version_major,version_minor>, detail::connection_helper<Tag, version_major, version_minor>, connection_base_impl<Tag, version_major, version_minor> {
22+
typedef typename resolver_policy<Tag>::type resolver_base;
23+
typedef typename resolver_base::resolver_type resolver_type;
24+
typedef typename string<Tag>::type string_type;
25+
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
26+
typedef sync_connection_base_impl<Tag,version_major,version_minor> connection_base;
27+
28+
https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional<string_type> const & certificate_filename = optional<string_type>())
29+
: connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.io_service(), context_) {
30+
if (certificate_filename) {
31+
context_.set_verify_mode(boost::asio::ssl::context::verify_peer);
32+
context_.load_verify_file(*certificate_filename);
33+
} else {
34+
context_.set_verify_mode(boost::asio::ssl::context::verify_none);
35+
}
36+
}
37+
38+
void init_socket(string_type const & hostname, string_type const & port) {
39+
connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_);
40+
socket_.handshake(boost::asio::ssl::stream_base::client);
41+
}
42+
43+
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
44+
boost::asio::streambuf request_buffer;
45+
create_request(request_buffer, method, request_);
46+
connection_base::send_request_impl(socket_, method, request_buffer);
47+
}
48+
49+
void read_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
50+
connection_base::read_status(socket_, response_, response_buffer);
51+
}
52+
53+
void read_headers(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
54+
connection_base::read_headers(socket_, response_, response_buffer);
55+
}
56+
57+
void read_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
58+
connection_base::read_body(socket_, response_, response_buffer);
59+
typename headers_range<basic_response<Tag> >::type connection_range =
60+
headers(response_)["Connection"];
61+
if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) {
62+
close_socket();
63+
} else if (version_major == 1 && version_minor == 0) {
64+
close_socket();
65+
}
66+
}
67+
68+
bool is_open() {
69+
return socket_.lowest_layer().is_open();
70+
}
71+
72+
void close_socket() {
73+
boost::system::error_code ignored;
74+
socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored);
75+
socket_.lowest_layer().close(ignored);
76+
}
77+
78+
~https_sync_connection() {
79+
close_socket();
80+
}
81+
82+
private:
83+
resolver_type & resolver_;
84+
resolver_function_type resolve_;
85+
boost::asio::ssl::context context_;
86+
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
87+
88+
};
89+
90+
} // namespace impl
91+
92+
} // namespace http
93+
94+
} // namespace network
95+
96+
} // namespace boost
97+
98+
#endif // BOOST_NETWORK_PROTOCOL_HTTP_IMPL_HTTPS_SYNC_CONNECTION_HTTP_20100601

boost/network/protocol/http/impl/sync_connection_base.hpp

Lines changed: 11 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,20 @@
1010
#include <boost/network/protocol/http/detail/connection_helper.hpp>
1111
#include <boost/network/traits/ostringstream.hpp>
1212
#include <boost/network/traits/istringstream.hpp>
13-
#include <boost/asio/ssl.hpp>
1413
#include <boost/asio/streambuf.hpp>
1514
#include <boost/asio/read.hpp>
1615
#include <boost/asio/read_until.hpp>
1716
#include <boost/tuple/tuple.hpp>
1817

18+
#include <boost/network/protocol/http/impl/http_sync_connection.hpp>
19+
#ifndef BOOST_NETWORK_NO_HTTPS
20+
#include <boost/network/protocol/http/impl/https_sync_connection.hpp>
21+
#endif
22+
1923
namespace boost { namespace network { namespace http { namespace impl {
24+
2025
template <class Tag, unsigned version_major, unsigned version_minor>
21-
struct connection_base_impl {
26+
struct sync_connection_base_impl {
2227
protected:
2328
typedef typename resolver_policy<Tag>::type resolver_base;
2429
typedef typename resolver_base::resolver_type resolver_type;
@@ -190,139 +195,6 @@ namespace boost { namespace network { namespace http { namespace impl {
190195

191196
};
192197

193-
template <class Tag, unsigned version_major, unsigned version_minor>
194-
struct sync_connection_base;
195-
196-
template <class Tag, unsigned version_major, unsigned version_minor>
197-
struct https_sync_connection : public virtual sync_connection_base<Tag,version_major,version_minor>, detail::connection_helper<Tag, version_major, version_minor>, connection_base_impl<Tag, version_major, version_minor> {
198-
typedef typename resolver_policy<Tag>::type resolver_base;
199-
typedef typename resolver_base::resolver_type resolver_type;
200-
typedef typename string<Tag>::type string_type;
201-
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
202-
typedef connection_base_impl<Tag,version_major,version_minor> connection_base;
203-
204-
https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional<string_type> const & certificate_filename = optional<string_type>())
205-
: connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.io_service(), context_) {
206-
if (certificate_filename) {
207-
context_.set_verify_mode(boost::asio::ssl::context::verify_peer);
208-
context_.load_verify_file(*certificate_filename);
209-
} else {
210-
context_.set_verify_mode(boost::asio::ssl::context::verify_none);
211-
}
212-
}
213-
214-
void init_socket(string_type const & hostname, string_type const & port) {
215-
connection_base::init_socket(socket_.lowest_layer(), resolver_, hostname, port, resolve_);
216-
socket_.handshake(boost::asio::ssl::stream_base::client);
217-
}
218-
219-
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
220-
boost::asio::streambuf request_buffer;
221-
create_request(request_buffer, method, request_);
222-
connection_base::send_request_impl(socket_, method, request_buffer);
223-
}
224-
225-
void read_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
226-
connection_base::read_status(socket_, response_, response_buffer);
227-
}
228-
229-
void read_headers(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
230-
connection_base::read_headers(socket_, response_, response_buffer);
231-
}
232-
233-
void read_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
234-
connection_base::read_body(socket_, response_, response_buffer);
235-
typename headers_range<basic_response<Tag> >::type connection_range =
236-
headers(response_)["Connection"];
237-
if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) {
238-
close_socket();
239-
} else if (version_major == 1 && version_minor == 0) {
240-
close_socket();
241-
}
242-
}
243-
244-
bool is_open() {
245-
return socket_.lowest_layer().is_open();
246-
}
247-
248-
void close_socket() {
249-
boost::system::error_code ignored;
250-
socket_.lowest_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored);
251-
socket_.lowest_layer().close(ignored);
252-
}
253-
254-
~https_sync_connection() {
255-
close_socket();
256-
}
257-
258-
private:
259-
resolver_type & resolver_;
260-
resolver_function_type resolve_;
261-
boost::asio::ssl::context context_;
262-
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
263-
264-
};
265-
266-
template <class Tag, unsigned version_major, unsigned version_minor>
267-
struct http_sync_connection : public virtual sync_connection_base<Tag, version_major, version_minor>, detail::connection_helper<Tag, version_major, version_minor>, connection_base_impl<Tag, version_major, version_minor> {
268-
typedef typename resolver_policy<Tag>::type resolver_base;
269-
typedef typename resolver_base::resolver_type resolver_type;
270-
typedef typename string<Tag>::type string_type;
271-
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
272-
typedef connection_base_impl<Tag,version_major,version_minor> connection_base;
273-
274-
http_sync_connection(resolver_type & resolver, resolver_function_type resolve)
275-
: connection_base(), resolver_(resolver), resolve_(resolve), socket_(resolver.io_service()) { }
276-
277-
void init_socket(string_type const & hostname, string_type const & port) {
278-
connection_base::init_socket(socket_, resolver_, hostname, port, resolve_);
279-
}
280-
281-
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
282-
boost::asio::streambuf request_buffer;
283-
create_request(request_buffer, method, request_);
284-
connection_base::send_request_impl(socket_, method, request_buffer);
285-
}
286-
287-
void read_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
288-
connection_base::read_status(socket_, response_, response_buffer);
289-
}
290-
291-
void read_headers(basic_response<Tag> & response, boost::asio::streambuf & response_buffer) {
292-
connection_base::read_headers(socket_, response, response_buffer);
293-
}
294-
295-
void read_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
296-
connection_base::read_body(socket_, response_, response_buffer);
297-
typename headers_range<basic_response<Tag> >::type connection_range =
298-
headers(response_)["Connection"];
299-
if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::iequals(boost::begin(connection_range)->second, "close")) {
300-
close_socket();
301-
} else if (version_major == 1 && version_minor == 0) {
302-
close_socket();
303-
}
304-
}
305-
306-
bool is_open() { return socket_.is_open(); }
307-
308-
void close_socket() {
309-
boost::system::error_code ignored;
310-
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored);
311-
socket_.close(ignored);
312-
}
313-
314-
~http_sync_connection() {
315-
close_socket();
316-
}
317-
318-
private:
319-
320-
resolver_type & resolver_;
321-
resolver_function_type resolve_;
322-
boost::asio::ip::tcp::socket socket_;
323-
324-
};
325-
326198
template <class Tag, unsigned version_major, unsigned version_minor>
327199
struct sync_connection_base {
328200
typedef typename resolver_policy<Tag>::type resolver_base;
@@ -332,7 +204,11 @@ namespace boost { namespace network { namespace http { namespace impl {
332204

333205
static sync_connection_base<Tag,version_major,version_minor> * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https) {
334206
if (https) {
207+
#ifndef BOOST_NETWORK_NO_HTTPS
335208
return dynamic_cast<sync_connection_base<Tag,version_major,version_minor>*>(new https_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
209+
#else
210+
throw std::runtime_error("HTTPS not supported.");
211+
#endif
336212
}
337213
return dynamic_cast<sync_connection_base<Tag,version_major,version_minor>*>(new http_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
338214
}

0 commit comments

Comments
 (0)