10
10
#include < boost/network/protocol/http/detail/connection_helper.hpp>
11
11
#include < boost/network/traits/ostringstream.hpp>
12
12
#include < boost/network/traits/istringstream.hpp>
13
- #include < boost/asio/ssl.hpp>
14
13
#include < boost/asio/streambuf.hpp>
15
14
#include < boost/asio/read.hpp>
15
+ #include < boost/asio/write.hpp>
16
16
#include < boost/asio/read_until.hpp>
17
17
#include < boost/tuple/tuple.hpp>
18
18
19
+ #include < boost/network/protocol/http/impl/http_sync_connection.hpp>
20
+ #ifdef BOOST_NETWORK_ENABLE_HTTPS
21
+ #include < boost/network/protocol/http/impl/https_sync_connection.hpp>
22
+ #endif
23
+
19
24
namespace boost { namespace network { namespace http { namespace impl {
25
+
20
26
template <class Tag , unsigned version_major, unsigned version_minor>
21
- struct connection_base_impl {
27
+ struct sync_connection_base_impl {
22
28
protected:
23
29
typedef typename resolver_policy<Tag>::type resolver_base;
24
30
typedef typename resolver_base::resolver_type resolver_type;
@@ -119,7 +125,7 @@ namespace boost { namespace network { namespace http { namespace impl {
119
125
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
120
126
headers (response_)[" Transfer-Encoding" ];
121
127
if (empty (transfer_encoding_range)) throw std::runtime_error (" Missing Transfer-Encoding Header from response." );
122
- if (boost::iequals (begin (transfer_encoding_range)->second , " chunked" )) {
128
+ if (boost::iequals (boost:: begin (transfer_encoding_range)->second , " chunked" )) {
123
129
bool stopping = false ;
124
130
do {
125
131
std::size_t chunk_size_line = read_until (socket_, response_buffer, " \r\n " , error);
@@ -158,7 +164,7 @@ namespace boost { namespace network { namespace http { namespace impl {
158
164
} while (!stopping);
159
165
} else throw std::runtime_error (" Unsupported Transfer-Encoding." );
160
166
} else {
161
- size_t length = lexical_cast<size_t >(begin (content_length_range)->second );
167
+ size_t length = lexical_cast<size_t >(boost:: begin (content_length_range)->second );
162
168
size_t bytes_read = 0 ;
163
169
while ((bytes_read = boost::asio::read (socket_, response_buffer, boost::asio::transfer_at_least (1 ), error))) {
164
170
body_stream << &response_buffer;
@@ -190,139 +196,6 @@ namespace boost { namespace network { namespace http { namespace impl {
190
196
191
197
};
192
198
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 (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 (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
-
326
199
template <class Tag , unsigned version_major, unsigned version_minor>
327
200
struct sync_connection_base {
328
201
typedef typename resolver_policy<Tag>::type resolver_base;
@@ -332,7 +205,11 @@ namespace boost { namespace network { namespace http { namespace impl {
332
205
333
206
static sync_connection_base<Tag,version_major,version_minor> * new_connection (resolver_type & resolver, resolver_function_type resolve, bool https) {
334
207
if (https) {
208
+ #ifdef BOOST_NETWORK_ENABLE_HTTPS
335
209
return dynamic_cast <sync_connection_base<Tag,version_major,version_minor>*>(new https_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
210
+ #else
211
+ throw std::runtime_error (" HTTPS not supported." );
212
+ #endif
336
213
}
337
214
return dynamic_cast <sync_connection_base<Tag,version_major,version_minor>*>(new http_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
338
215
}
0 commit comments