connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_, optional<string_type> const & certificate_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>()) { string_type index = (request_.host() + ':') + lexical_cast<string_type>(request_.port()); connection_ptr connection_; typename host_connection_map::iterator it = host_connections.find(index); if (it == host_connections.end()) { connection_.reset(new connection_impl( resolver , follow_redirect_ , request_.host() , lexical_cast<string_type>(request_.port()) , boost::bind( &pooled_connection_policy<Tag,version_major,version_minor>::resolve, this, _1, _2, _3 ) , boost::bind( &pooled_connection_policy<Tag,version_major,version_minor>::get_connection, this, _1, _2, _3, _4 ) , boost::iequals(request_.protocol(), string_type("https")) , certificate_filename , verify_path ) ); host_connections.insert(std::make_pair(index, connection_)); return connection_; } return it->second; }
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body) { basic_response<Tag> response_; do { pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port())); pimpl->send_request_impl(method, request_); response_ = basic_response<Tag>(); response_ << network::source(request_.host()); boost::asio::streambuf response_buffer; pimpl->read_status(response_, response_buffer); pimpl->read_headers(response_, response_buffer); if (get_body) pimpl->read_body(response_, response_buffer); if (follow_redirect_) { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range<http::basic_response<Tag> >::type location_range = headers(response_)["Location"]; typename range_iterator<typename headers_range<http::basic_request<Tag> >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); } else throw std::runtime_error("Location header not defined in redirect response."); } else break; } else break; } while(true); return response_; }
basic_response<Tag> send_request(string_type /*unused*/ const& method, basic_request<Tag> request_, bool get_body, body_callback_function_type callback, body_generator_function_type generator) { // TODO(dberris): review parameter necessity. (void)callback; basic_response<Tag> response_; do { pimpl->init_socket(request_.host(), std::to_string(request_.port())); pimpl->send_request_impl(method, request_, generator); response_ = basic_response<Tag>(); response_ << network::source(request_.host()); ::asio::streambuf response_buffer; pimpl->read_status(response_, response_buffer); pimpl->read_headers(response_, response_buffer); if (get_body) pimpl->read_body(response_, response_buffer); if (follow_redirect_) { std::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range<http::basic_response<Tag> >::type location_range = headers(response_)["Location"]; typename range_iterator< typename headers_range<http::basic_response<Tag> >::type>::type location_header = std::begin(location_range); if (location_header != std::end(location_range)) { request_.uri(location_header->second); } else throw std::runtime_error( "Location header not defined in redirect response."); } else { break; } } else { break; } } while (true); return response_; }
connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_) { connection_ptr connection_( new connection_impl( resolver , follow_redirect_ , request_.host() , lexical_cast<string_type>(request_.port()) , boost::bind( &simple_connection_policy<Tag,version_major,version_minor>::resolve, this, _1, _2, _3 ) , boost::iequals(request_.protocol(), string_type("https")) ) ); return connection_; }
connection_ptr get_connection( resolver_type& resolver, basic_request<Tag> const& request_, bool always_verify_peer, optional<string_type> /*unused*/ const& certificate_filename = optional<string_type>(), optional<string_type> const& verify_path = optional<string_type>(), optional<string_type> const& certificate_file = optional<string_type>(), optional<string_type> const& private_key_file = optional<string_type>(), optional<string_type> const& ciphers = optional<string_type>(), long ssl_options = 0) { namespace ph = std::placeholders; connection_ptr connection_(new connection_impl( resolver, follow_redirect_, always_verify_peer, request_.host(), std::to_string(request_.port()), [this](resolver_type& resolver, string_type const& host, std::uint16_t port, resolver_completion_function once_resolved) { this->resolve(resolver, host, port, once_resolved); }, boost::iequals(request_.protocol(), string_type("https")), timeout_, certificate_filename, verify_path, certificate_file, private_key_file, ciphers, ssl_options)); return connection_; }
basic_response<Tag> send_request_impl(string_type const & method, basic_request<Tag> request_, bool get_body) { boost::uint8_t count = 0; bool retry = false; do { if (count >= BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT) boost::throw_exception(std::runtime_error("Redirection exceeds maximum redirect count.")); basic_response<Tag> response_; // check if the socket is open first if (!pimpl->is_open()) { pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port())); } response_ = basic_response<Tag>(); response_ << ::boost::network::source(request_.host()); pimpl->send_request_impl(method, request_); boost::asio::streambuf response_buffer; try { pimpl->read_status(response_, response_buffer); } catch (boost::system::system_error & e) { if (!retry && e.code() == boost::asio::error::eof) { retry = true; pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port())); continue; } throw; // it's a retry, and there's something wrong. } pimpl->read_headers(response_, response_buffer); if ( get_body && response_.status() != 304 && (response_.status() != 204) && !(response_.status() >= 100 && response_.status() <= 199) ) { pimpl->read_body(response_, response_buffer); } typename headers_range<basic_response<Tag> >::type connection_range = headers(response_)["Connection"]; if (version_major == 1 && version_minor == 1 && !empty(connection_range) && boost::begin(connection_range)->second == string_type("close")) { pimpl->close_socket(); } else if (version_major == 1 && version_minor == 0) { pimpl->close_socket(); } if (connection_follow_redirect_) { boost::uint16_t status = response_.status(); if (status >= 300 && status <= 307) { typename headers_range<basic_response<Tag> >::type location_range = headers(response_)["Location"]; typename range_iterator<typename headers_range<basic_request<Tag> >::type>::type location_header = boost::begin(location_range); if (location_header != boost::end(location_range)) { request_.uri(location_header->second); connection_ptr connection_; connection_ = get_connection_(resolver_, request_, certificate_filename_, verify_path_); ++count; continue; } else boost::throw_exception(std::runtime_error("Location header not defined in redirect response.")); } } return response_; } while(true); }