diff --git a/boost/network/protocol/http/client/async_impl.hpp b/boost/network/protocol/http/client/async_impl.hpp index 1c0eb1fe7..4b5505cc5 100644 --- a/boost/network/protocol/http/client/async_impl.hpp +++ b/boost/network/protocol/http/client/async_impl.hpp @@ -37,14 +37,19 @@ struct async_client typedef function body_generator_function_type; async_client(bool cache_resolved, bool follow_redirect, - bool always_verify_peer, int timeout, + bool always_verify_peer, int timeout, bool remove_chunk_markers, + optional const& proxy_host, + optional const& proxy_port, + optional const& proxy_username, + optional const& proxy_password, boost::shared_ptr service, optional const& certificate_filename, optional const& verify_path, optional const& certificate_file, optional const& private_key_file, optional const& ciphers, long ssl_options) - : connection_base(cache_resolved, follow_redirect, timeout), + : connection_base(cache_resolved, follow_redirect, timeout, remove_chunk_markers, + proxy_host, proxy_port, proxy_username, proxy_password), service_ptr(service.get() ? service : boost::make_shared()), diff --git a/boost/network/protocol/http/client/connection/async_base.hpp b/boost/network/protocol/http/client/connection/async_base.hpp index ada856a22..390b4c963 100644 --- a/boost/network/protocol/http/client/connection/async_base.hpp +++ b/boost/network/protocol/http/client/connection/async_base.hpp @@ -39,7 +39,11 @@ struct async_connection_base { // tag. static connection_ptr new_connection( resolve_function resolve, resolver_type &resolver, bool follow_redirect, - bool always_verify_peer, bool https, int timeout, + bool always_verify_peer, bool https, int timeout, bool remove_chunk_markers, + optional proxy_host = optional(), + optional proxy_port = optional(), + optional proxy_username = optional(), + optional proxy_password = optional(), optional certificate_filename = optional(), optional const &verify_path = optional(), optional certificate_file = optional(), @@ -51,7 +55,8 @@ struct async_connection_base { typedef typename delegate_factory::type delegate_factory_type; connection_ptr temp; temp.reset(new async_connection( - resolver, resolve, follow_redirect, timeout, + resolver, resolve, follow_redirect, timeout, remove_chunk_markers, + proxy_host, proxy_port, proxy_username, proxy_password, delegate_factory_type::new_connection_delegate( resolver.get_io_service(), https, always_verify_peer, certificate_filename, verify_path, certificate_file, diff --git a/boost/network/protocol/http/client/connection/async_normal.hpp b/boost/network/protocol/http/client/connection/async_normal.hpp index f5590d7fc..0a0084f52 100644 --- a/boost/network/protocol/http/client/connection/async_normal.hpp +++ b/boost/network/protocol/http/client/connection/async_normal.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -68,11 +69,20 @@ struct http_async_connection connection_delegate_ptr; http_async_connection(resolver_type& resolver, resolve_function resolve, - bool follow_redirect, int timeout, + bool follow_redirect, int timeout, bool remove_chunk_markers, + optional proxy_host, + optional proxy_port, + optional proxy_username, + optional proxy_password, connection_delegate_ptr delegate) : timeout_(timeout), timer_(resolver.get_io_service()), is_timedout_(false), + remove_chunk_markers_(remove_chunk_markers), + proxy_host_(proxy_host), + proxy_port_(proxy_port), + proxy_username_(proxy_username), + proxy_password_(proxy_password), follow_redirect_(follow_redirect), resolver_(resolver), resolve_(resolve), @@ -89,15 +99,24 @@ struct http_async_connection body_generator_function_type generator) { response response_; this->init_response(response_, get_body); + + boost::uint16_t port_ = port(request); + string_type host_ = host(request); + boost::uint16_t source_port = request.source_port(); + + string_type tcp_host = host_; + + if (connect_via_proxy()) + { + tcp_host = *proxy_host_; + } + linearize(request, method, version_major, version_minor, std::ostreambuf_iterator::type>( &command_streambuf)); this->method = method; - boost::uint16_t port_ = port(request); - string_type host_ = host(request); - boost::uint16_t source_port = request.source_port(); - resolve_(resolver_, host_, port_, + resolve_(resolver_, tcp_host, port_, request_strand_.wrap(boost::bind( &this_type::handle_resolved, this_type::shared_from_this(), host_, port_, source_port, get_body, callback, @@ -140,15 +159,23 @@ struct http_async_connection // Here we deal with the case that there was an error encountered // and // that there's still more endpoints to try connecting to. + + boost::uint16_t tcp_port = port; + + if (connect_via_proxy()) { + tcp_port = boost::lexical_cast(*proxy_port_); + } + resolver_iterator iter = boost::begin(endpoint_range); - asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); + asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), tcp_port); delegate_->connect( - endpoint, host, source_port, + endpoint, host, port, source_port, request_strand_.wrap(boost::bind( &this_type::handle_connected, this_type::shared_from_this(), host, port, source_port, get_body, callback, generator, std::make_pair(++iter, resolver_iterator()), - placeholders::error))); + placeholders::error)), + connect_via_proxy(), proxy_username_, proxy_password_); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); boost::iterator_range range; @@ -176,12 +203,13 @@ struct http_async_connection resolver_iterator iter = boost::begin(endpoint_range); asio::ip::tcp::endpoint endpoint(iter->endpoint().address(), port); delegate_->connect( - endpoint, host, source_port, + endpoint, host, port, source_port, request_strand_.wrap(boost::bind( &this_type::handle_connected, this_type::shared_from_this(), host, port, source_port, get_body, callback, generator, std::make_pair(++iter, resolver_iterator()), - placeholders::error))); + placeholders::error)), + connect_via_proxy(), proxy_username_, proxy_password_); } else { set_errors(ec ? ec : boost::asio::error::host_not_found); boost::iterator_range range; @@ -322,10 +350,24 @@ struct http_async_connection // has already been parsed appropriately and we're // looking to treat everything that remains in the // buffer. - typename protocol_base::buffer_type::const_iterator begin = - this->part_begin; - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, remainder); + + this->partial_parsed.append(this->part_begin, remainder); + this->part_begin = this->part.begin(); + string_type body_string; + + if (remove_chunk_markers_ && this->is_chunk_encoding) + { + body_string = parse_chunk_encoding(this->partial_parsed, true); + } + else + { + body_string.swap(this->partial_parsed); + } + + typename protocol_base::buffer_type::const_iterator + begin = body_string.c_str(), + end = begin; + std::advance(end, body_string.size()); // We're setting the body promise here to an empty string // because @@ -346,7 +388,7 @@ struct http_async_connection &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred))); - } else { + } else { // Here we handle the body data ourself and append to an // ever-growing string buffer. this->parse_body( @@ -367,10 +409,24 @@ struct http_async_connection // the end // of the body processing chain. if (callback) { + + this->partial_parsed.append(this->part_begin, bytes_transferred); + this->part_begin = this->part.begin(); + string_type body_string; + + if (remove_chunk_markers_ && this->is_chunk_encoding) + { + body_string = parse_chunk_encoding(this->partial_parsed, true); + } + else + { + body_string.swap(this->partial_parsed); + } + typename protocol_base::buffer_type::const_iterator - begin = this->part.begin(), + begin = body_string.c_str(), end = begin; - std::advance(end, bytes_transferred); + std::advance(end, body_string.size()); // We call the callback function synchronously passing the // error @@ -383,9 +439,9 @@ struct http_async_connection std::swap(body_string, this->partial_parsed); body_string.append(this->part.begin(), bytes_transferred); if (this->is_chunk_encoding) - this->body_promise.set_value(parse_chunk_encoding(body_string)); - else - this->body_promise.set_value(body_string); + body_string = parse_chunk_encoding(body_string); + + this->body_promise.set_value(body_string); } // TODO set the destination value somewhere! this->destination_promise.set_value(""); @@ -403,10 +459,25 @@ struct http_async_connection // callback from here and make sure we're getting more // data // right after. - typename protocol_base::buffer_type::const_iterator begin = - this->part.begin(); - typename protocol_base::buffer_type::const_iterator end = begin; - std::advance(end, bytes_transferred); + + this->partial_parsed.append(this->part_begin, bytes_transferred); + this->part_begin = this->part.begin(); + string_type body_string; + + if (remove_chunk_markers_ && this->is_chunk_encoding) + { + body_string = parse_chunk_encoding(this->partial_parsed, true); + } + else + { + body_string.swap(this->partial_parsed); + } + + typename protocol_base::buffer_type::const_iterator + begin = body_string.c_str(), + end = begin; + std::advance(end, body_string.size()); + callback(make_iterator_range(begin, end), ec); delegate_->read_some( boost::asio::mutable_buffers_1(this->part.c_array(), @@ -415,7 +486,7 @@ struct http_async_connection &this_type::handle_received_data, this_type::shared_from_this(), body, get_body, callback, placeholders::error, placeholders::bytes_transferred))); - } else { + } else { // Here we don't have a body callback. Let's // make sure that we deal with the remainder // from the headers part in case we do have data @@ -462,7 +533,7 @@ struct http_async_connection } } - string_type parse_chunk_encoding(string_type& body_string) { + string_type parse_chunk_encoding(string_type& body_string, bool update = false) { string_type body; string_type crlf = "\r\n"; @@ -482,16 +553,34 @@ struct http_async_connection if (len <= body_string.end() - iter) { body.insert(body.end(), iter, iter + len); std::advance(iter, len + 2); + begin = iter; + } + else + { + break; } - begin = iter; } + if (update) + { + body_string.erase(body_string.begin(), begin); + } return body; } + bool connect_via_proxy() const + { + return (proxy_host_ && proxy_port_); + } + int timeout_; boost::asio::deadline_timer timer_; bool is_timedout_; + bool remove_chunk_markers_; + optional proxy_host_; + optional proxy_port_; + optional proxy_username_; + optional proxy_password_; bool follow_redirect_; resolver_type& resolver_; resolve_function resolve_; diff --git a/boost/network/protocol/http/client/connection/connection_delegate.hpp b/boost/network/protocol/http/client/connection/connection_delegate.hpp index 79fa1ca4d..82c2949ea 100644 --- a/boost/network/protocol/http/client/connection/connection_delegate.hpp +++ b/boost/network/protocol/http/client/connection/connection_delegate.hpp @@ -13,8 +13,12 @@ namespace http { namespace impl { struct connection_delegate { - virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, - function handler) = 0; + virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, + boost::uint16_t port, boost::uint16_t source_port, + function handler, + bool connect_via_proxy, + optional proxy_username, + optional proxy_password) = 0; virtual void write( asio::streambuf &command_streambuf, function handler) = 0; diff --git a/boost/network/protocol/http/client/connection/normal_delegate.hpp b/boost/network/protocol/http/client/connection/normal_delegate.hpp index ae6ace333..6dc24b798 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.hpp +++ b/boost/network/protocol/http/client/connection/normal_delegate.hpp @@ -7,20 +7,27 @@ // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +#include #include #include #include +#include namespace boost { namespace network { namespace http { namespace impl { -struct normal_delegate : connection_delegate { +struct normal_delegate : connection_delegate, + enable_shared_from_this { normal_delegate(asio::io_service &service); - virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, - function handler); + virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, + boost::uint16_t port, boost::uint16_t source_port, + function handler, + bool connect_via_proxy, + optional proxy_username, + optional proxy_password); virtual void write( asio::streambuf &command_streambuf, function handler); @@ -33,9 +40,26 @@ struct normal_delegate : connection_delegate { private: asio::io_service &service_; scoped_ptr socket_; + asio::streambuf response_buffer_; normal_delegate(normal_delegate const &); // = delete normal_delegate &operator=(normal_delegate); // = delete + + void handle_connected(system::error_code const &ec, + function handler, + bool connect_via_proxy, + std::string const &host, + boost::uint16_t port, + optional proxy_username, + optional proxy_password); + + void handle_proxy_sent_request(function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred); + + void handle_proxy_received_data(function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred); }; } /* impl */ diff --git a/boost/network/protocol/http/client/connection/normal_delegate.ipp b/boost/network/protocol/http/client/connection/normal_delegate.ipp index ae52fd870..4edbbd90d 100644 --- a/boost/network/protocol/http/client/connection/normal_delegate.ipp +++ b/boost/network/protocol/http/client/connection/normal_delegate.ipp @@ -9,24 +9,78 @@ #include #include +#include #include #include #include #include +#include +#include +#include boost::network::http::impl::normal_delegate::normal_delegate( asio::io_service &service) : service_(service) {} void boost::network::http::impl::normal_delegate::connect( - asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, - function handler) { - + asio::ip::tcp::endpoint &endpoint, std::string host, + boost::uint16_t port, boost::uint16_t source_port, + function handler, + bool connect_via_proxy, + optional proxy_username, + optional proxy_password) { // TODO(dberris): review parameter necessity. (void)host; - + socket_.reset(new asio::ip::tcp::socket(service_, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), source_port))); - socket_->async_connect(endpoint, handler); + socket_->async_connect( + endpoint, + service_.wrap(::boost::bind( + &boost::network::http::impl::normal_delegate::handle_connected, + boost::network::http::impl::normal_delegate::shared_from_this(), + asio::placeholders::error, handler, + connect_via_proxy, host, port, proxy_username, proxy_password))); +} + +void boost::network::http::impl::normal_delegate::handle_connected( + system::error_code const &ec, + function handler, + bool connect_via_proxy, + std::string const &host, + boost::uint16_t port, + optional proxy_username, + optional proxy_password) { + if ((!ec) && connect_via_proxy) { + // If PROXY establish connection via Proxy --> send CONNECT request + asio::streambuf command_streambuf; + // FIXME fill connect_streambuf with CONNECT request ... + + { + std::ostream request_stream(&command_streambuf); + + request_stream << "CONNECT " << host << ":" << port << " HTTP/1.1\r\n"; + request_stream << "Host: " << host << ":" << port << "\r\n"; + + if (proxy_username && proxy_password) { + std::string user_pass = *proxy_username + ":" + *proxy_password; + std::string encoded_user_pass; + + message::base64_encode(user_pass, encoded_user_pass); + request_stream << "Proxy-Authorization: Basic " << encoded_user_pass << "\r\n"; + } + + request_stream << "\r\n"; + } + + write(command_streambuf, + service_.wrap(::boost::bind( + &boost::network::http::impl::normal_delegate::handle_proxy_sent_request, + boost::network::http::impl::normal_delegate::shared_from_this(), + handler, asio::placeholders::error, asio::placeholders::bytes_transferred))); + } + else { + handler(ec); + } } void boost::network::http::impl::normal_delegate::write( @@ -53,5 +107,41 @@ void boost::network::http::impl::normal_delegate::disconnect() { boost::network::http::impl::normal_delegate::~normal_delegate() {} +void boost::network::http::impl::normal_delegate::handle_proxy_sent_request( + function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred) { + + boost::asio::async_read_until( + *socket_, response_buffer_, "\r\n\r\n", + service_.wrap(::boost::bind( + &boost::network::http::impl::normal_delegate::handle_proxy_received_data, + boost::network::http::impl::normal_delegate::shared_from_this(), + handler, asio::placeholders::error, asio::placeholders::bytes_transferred))); +} + +void boost::network::http::impl::normal_delegate::handle_proxy_received_data( + function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred) { + std::istream response_stream(&response_buffer_); + std::string http_tag; + boost::uint16_t http_status_code = 0; + + response_stream >> http_tag; + + if (http_tag.substr(0, 4) == "HTTP") { + response_stream >> http_status_code; + } + + if (http_status_code != 200) { + // FIXME set error code to something meaningful + boost::system::error_code ignored; + socket_->lowest_layer().close(ignored); + } + + handler(ec); +} + #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_NORMAL_DELEGATE_IPP_20110819 \ */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.hpp b/boost/network/protocol/http/client/connection/ssl_delegate.hpp index 712fc5173..d7f0f131b 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.hpp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.hpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include #include #include @@ -29,8 +29,13 @@ struct ssl_delegate : connection_delegate, optional private_key_file, optional ciphers, long ssl_options); - virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, - function handler); + virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host, + boost::uint16_t port, boost::uint16_t source_port, + function handler, + bool connect_via_proxy, + optional proxy_username, + optional proxy_password); + virtual void write( asio::streambuf &command_streambuf, function handler); @@ -52,12 +57,26 @@ struct ssl_delegate : connection_delegate, scoped_ptr tcp_socket_; scoped_ptr > socket_; bool always_verify_peer_; + asio::streambuf response_buffer_; ssl_delegate(ssl_delegate const &); // = delete ssl_delegate &operator=(ssl_delegate); // = delete void handle_connected(system::error_code const &ec, - function handler); + function handler, + bool connect_via_proxy, + std::string const &host, + boost::uint16_t port, + optional proxy_username, + optional proxy_password); + + void handle_proxy_sent_request(function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred); + + void handle_proxy_received_data(function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred); }; } /* impl */ diff --git a/boost/network/protocol/http/client/connection/ssl_delegate.ipp b/boost/network/protocol/http/client/connection/ssl_delegate.ipp index 71161ba46..b9faa2bb2 100644 --- a/boost/network/protocol/http/client/connection/ssl_delegate.ipp +++ b/boost/network/protocol/http/client/connection/ssl_delegate.ipp @@ -9,6 +9,7 @@ #include #include +#include #include boost::network::http::impl::ssl_delegate::ssl_delegate( @@ -29,8 +30,12 @@ boost::network::http::impl::ssl_delegate::ssl_delegate( always_verify_peer_(always_verify_peer) {} void boost::network::http::impl::ssl_delegate::connect( - asio::ip::tcp::endpoint &endpoint, std::string host, boost::uint16_t source_port, - function handler) { + asio::ip::tcp::endpoint &endpoint, std::string host, + boost::uint16_t port, boost::uint16_t source_port, + function handler, + bool connect_via_proxy, + optional proxy_username, + optional proxy_password) { context_.reset( new asio::ssl::context(service_, asio::ssl::context::sslv23_client)); if (ciphers_) { @@ -68,17 +73,54 @@ void boost::network::http::impl::ssl_delegate::connect( socket_->set_verify_callback(boost::asio::ssl::rfc2818_verification(host)); socket_->lowest_layer().async_connect( endpoint, - ::boost::bind( + service_.wrap(::boost::bind( &boost::network::http::impl::ssl_delegate::handle_connected, boost::network::http::impl::ssl_delegate::shared_from_this(), - asio::placeholders::error, handler)); + asio::placeholders::error, handler, + connect_via_proxy, host, port, proxy_username, proxy_password))); } void boost::network::http::impl::ssl_delegate::handle_connected( system::error_code const &ec, - function handler) { + function handler, + bool connect_via_proxy, + std::string const &host, + boost::uint16_t port, + optional proxy_username, + optional proxy_password) { if (!ec) { - socket_->async_handshake(asio::ssl::stream_base::client, handler); + if (connect_via_proxy) { + // If PROXY establish connection via Proxy --> send CONNECT request + asio::streambuf command_streambuf; + // FIXME fill connect_streambuf with CONNECT request ... + + { + std::ostream request_stream(&command_streambuf); + + request_stream << "CONNECT " << host << ":" << port << " HTTP/1.1\r\n"; + request_stream << "Host: " << host << ":" << port << "\r\n"; + + if (proxy_username && proxy_password) { + std::string user_pass = *proxy_username + ":" + *proxy_password; + std::string encoded_user_pass; + + message::base64_encode(user_pass, encoded_user_pass); + request_stream << "Proxy-Authorization: Basic " << encoded_user_pass << "\r\n"; + } + + request_stream << "\r\n"; + } + + asio::async_write(socket_->next_layer(), + command_streambuf, + service_.wrap(::boost::bind( + &boost::network::http::impl::ssl_delegate::handle_proxy_sent_request, + boost::network::http::impl::ssl_delegate::shared_from_this(), + handler, asio::placeholders::error, asio::placeholders::bytes_transferred))); + } + else { + socket_->async_handshake(asio::ssl::stream_base::client, handler); + } } else { handler(ec); } @@ -109,5 +151,43 @@ void boost::network::http::impl::ssl_delegate::disconnect() { boost::network::http::impl::ssl_delegate::~ssl_delegate() {} +void boost::network::http::impl::ssl_delegate::handle_proxy_sent_request( + function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred) { + boost::asio::async_read_until( + socket_->next_layer(), response_buffer_, "\r\n\r\n", + service_.wrap(::boost::bind( + &boost::network::http::impl::ssl_delegate::handle_proxy_received_data, + boost::network::http::impl::ssl_delegate::shared_from_this(), + handler, asio::placeholders::error, asio::placeholders::bytes_transferred))); +} + +void boost::network::http::impl::ssl_delegate::handle_proxy_received_data( + function handler, + boost::system::error_code const& ec, + std::size_t bytes_transferred) { + std::istream response_stream(&response_buffer_); + std::string http_tag; + boost::uint16_t http_status_code = 0; + + response_stream >> http_tag; + + if (http_tag.substr(0, 4) == "HTTP") { + response_stream >> http_status_code; + } + + if (http_status_code == 200) { + socket_->async_handshake(asio::ssl::stream_base::client, handler); + } + else { + // FIXME set error code to something meaningful + boost::system::error_code ignored; + socket_->lowest_layer().close(ignored); + + handler(ec); + } +} + #endif /* BOOST_NETWORK_PROTOCOL_HTTP_CLIENT_CONNECTION_SSL_DELEGATE_IPP_20110819 \ */ diff --git a/boost/network/protocol/http/client/facade.hpp b/boost/network/protocol/http/client/facade.hpp index 68c02ce18..21cc0e54e 100644 --- a/boost/network/protocol/http/client/facade.hpp +++ b/boost/network/protocol/http/client/facade.hpp @@ -163,7 +163,9 @@ struct basic_client_facade { options.always_verify_peer(), options.openssl_certificate(), options.openssl_verify_path(), options.openssl_certificate_file(), options.openssl_private_key_file(), options.openssl_ciphers(), - options.openssl_options(), options.io_service(), options.timeout())); + options.openssl_options(), options.io_service(), options.timeout(), + options.remove_chunk_markers(), options.proxy_host(), options.proxy_port(), + options.proxy_username(), options.proxy_password())); } }; diff --git a/boost/network/protocol/http/client/options.hpp b/boost/network/protocol/http/client/options.hpp index 8207dcaa7..e61d8892d 100644 --- a/boost/network/protocol/http/client/options.hpp +++ b/boost/network/protocol/http/client/options.hpp @@ -31,7 +31,13 @@ struct client_options { openssl_options_(0), io_service_(), always_verify_peer_(false), - timeout_(0) {} + timeout_(0), + remove_chunk_markers_(false), + proxy_host_(), + proxy_port_(), + proxy_username_(), + proxy_password_() + {} client_options(client_options const& other) : cache_resolved_(other.cache_resolved_), @@ -44,7 +50,12 @@ struct client_options { openssl_options_(other.openssl_options_), io_service_(other.io_service_), always_verify_peer_(other.always_verify_peer_), - timeout_(other.timeout_) {} + timeout_(other.timeout_), + remove_chunk_markers_(other.remove_chunk_markers_), + proxy_host_(other.proxy_host_), + proxy_port_(other.proxy_port_), + proxy_username_(other.proxy_username_), + proxy_password_(other.proxy_poassword_) {} client_options& operator=(client_options other) { other.swap(*this); @@ -64,6 +75,11 @@ struct client_options { swap(io_service_, other.io_service_); swap(always_verify_peer_, other.always_verify_peer_); swap(timeout_, other.timeout_); + swap(remove_chunk_markers_, other.remove_chunk_markers_); + swap(proxy_host_, other.proxy_host_); + swap(proxy_port_, other.proxy_port_); + swap(proxy_username_, other.proxy_username_); + swap(proxy_password_, other.proxy_poassword_); } client_options& cache_resolved(bool v) { @@ -121,6 +137,31 @@ struct client_options { return *this; } + client_options& remove_chunk_markers(bool v) { + remove_chunk_markers_ = v; + return *this; + } + + client_options& proxy_host(string_type const& v) { + proxy_host_ = v; + return *this; + } + + client_options& proxy_port(string_type const& v) { + proxy_port_ = v; + return *this; + } + + client_options& proxy_username(string_type const& v) { + proxy_username_ = v; + return *this; + } + + client_options& proxy_password(string_type const& v) { + proxy_password_ = v; + return *this; + } + bool cache_resolved() const { return cache_resolved_; } bool follow_redirects() const { return follow_redirects_; } @@ -155,6 +196,24 @@ struct client_options { int timeout() const { return timeout_; } + bool remove_chunk_markers() const { return remove_chunk_markers_; } + + boost::optional proxy_host() const { + return proxy_host_; + } + + boost::optional proxy_port() const { + return proxy_port_; + } + + boost::optional proxy_username() const { + return proxy_username_; + } + + boost::optional proxy_password() const { + return proxy_password_; + } + private: bool cache_resolved_; bool follow_redirects_; @@ -167,6 +226,11 @@ struct client_options { boost::shared_ptr io_service_; bool always_verify_peer_; int timeout_; + bool remove_chunk_markers_; + boost::optional proxy_host_; + boost::optional proxy_port_; + boost::optional proxy_username_; + boost::optional proxy_password_; }; template diff --git a/boost/network/protocol/http/client/pimpl.hpp b/boost/network/protocol/http/client/pimpl.hpp index d66aa3874..170983438 100644 --- a/boost/network/protocol/http/client/pimpl.hpp +++ b/boost/network/protocol/http/client/pimpl.hpp @@ -73,10 +73,16 @@ struct basic_client_impl optional const& private_key_file, optional const& ciphers, long ssl_options, boost::shared_ptr service, - int timeout) + int timeout, + bool remove_chunk_markers, + optional const& proxy_host, + optional const& proxy_port, + optional const& proxy_username, + optional const& proxy_password) : base_type(cache_resolved, follow_redirect, always_verify_peer, timeout, - service, certificate_filename, verify_path, certificate_file, - private_key_file, ciphers, ssl_options) {} + remove_chunk_markers, proxy_host, proxy_port, proxy_username, + proxy_password, service, certificate_filename, verify_path, + certificate_file, private_key_file, ciphers, ssl_options) {} ~basic_client_impl() {} }; diff --git a/boost/network/protocol/http/policies/async_connection.hpp b/boost/network/protocol/http/policies/async_connection.hpp index 667712b39..a4d337334 100644 --- a/boost/network/protocol/http/policies/async_connection.hpp +++ b/boost/network/protocol/http/policies/async_connection.hpp @@ -38,7 +38,11 @@ struct async_connection_policy : resolver_policy::type { struct connection_impl { connection_impl(bool follow_redirect, bool always_verify_peer, resolve_function resolve, resolver_type& resolver, - bool https, int timeout, + bool https, int timeout, bool remove_chunk_markers, + optional const& proxy_host, + optional const& proxy_port, + optional const& proxy_username, + optional const& proxy_password, optional const& certificate_filename, optional const& verify_path, optional const& certificate_file, @@ -48,8 +52,10 @@ struct async_connection_policy : resolver_policy::type { Tag, version_major, version_minor>::new_connection(resolve, resolver, follow_redirect, always_verify_peer, https, timeout, - certificate_filename, verify_path, - certificate_file, private_key_file, + remove_chunk_markers, proxy_host, + proxy_port, proxy_username, + proxy_password, certificate_filename, + verify_path, certificate_file, private_key_file, ciphers, ssl_options); } @@ -85,21 +91,36 @@ struct async_connection_policy : resolver_policy::type { this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>(), boost::arg<4>()), resolver, boost::iequals(protocol_, string_type("https")), timeout_, - certificate_filename, verify_path, certificate_file, private_key_file, - ciphers, ssl_options)); + remove_chunk_markers_, proxy_host_, proxy_port_, proxy_username_, proxy_password_, + certificate_filename, verify_path, certificate_file, + private_key_file, ciphers, ssl_options)); return connection_; } void cleanup() {} async_connection_policy(bool cache_resolved, bool follow_redirect, - int timeout) + int timeout, bool remove_chunk_markers, + optional const& proxy_host, + optional const& proxy_port, + optional const& proxy_username, + optional const& proxy_password) : resolver_base(cache_resolved), follow_redirect_(follow_redirect), - timeout_(timeout) {} + timeout_(timeout), + remove_chunk_markers_(remove_chunk_markers), + proxy_host_(proxy_host), + proxy_port_(proxy_port), + proxy_username_(proxy_username), + proxy_password_(proxy_password) {} bool follow_redirect_; int timeout_; + bool remove_chunk_markers_; + optional proxy_host_; + optional proxy_port_; + optional proxy_username_; + optional proxy_password_; }; } // namespace http