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>
15+ #include < boost/asio/write.hpp>
1616#include < boost/asio/read_until.hpp>
1717#include < boost/tuple/tuple.hpp>
1818
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+
1924namespace boost {namespace network {namespace http {namespace impl {
25+
2026template <class Tag ,unsigned version_major,unsigned version_minor>
21- struct connection_base_impl {
27+ struct sync_connection_base_impl {
2228protected:
2329typedef typename resolver_policy<Tag>::type resolver_base;
2430typedef typename resolver_base::resolver_type resolver_type;
@@ -119,7 +125,7 @@ namespace boost { namespace network { namespace http { namespace impl {
119125typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
120126headers (response_)[" Transfer-Encoding" ];
121127if (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" )) {
123129bool stopping =false ;
124130do {
125131 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 {
158164 }while (!stopping);
159165 }else throw std::runtime_error (" Unsupported Transfer-Encoding." );
160166 }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 );
162168size_t bytes_read =0 ;
163169while ((bytes_read =boost::asio::read (socket_, response_buffer,boost::asio::transfer_at_least (1 ), error))) {
164170 body_stream << &response_buffer;
@@ -190,139 +196,6 @@ namespace boost { namespace network { namespace http { namespace impl {
190196
191197 };
192198
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_typeconst &, string_typeconst &)> 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_typeconst & hostname, string_typeconst & 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_typeconst & 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_typeconst &, string_typeconst &)> 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_typeconst & hostname, string_typeconst & port) {
278- connection_base::init_socket (socket_, resolver_, hostname, port, resolve_);
279- }
280-
281- void send_request_impl (string_typeconst & 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-
326199template <class Tag ,unsigned version_major,unsigned version_minor>
327200struct sync_connection_base {
328201typedef typename resolver_policy<Tag>::type resolver_base;
@@ -332,7 +205,11 @@ namespace boost { namespace network { namespace http { namespace impl {
332205
333206static sync_connection_base<Tag,version_major,version_minor> *new_connection (resolver_type & resolver, resolver_function_type resolve,bool https) {
334207if (https) {
208+ #ifdef BOOST_NETWORK_ENABLE_HTTPS
335209return 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
336213 }
337214return dynamic_cast <sync_connection_base<Tag,version_major,version_minor>*>(new http_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
338215 }