@@ -52,6 +52,8 @@ namespace network {
5252
5353~impl ()noexcept ;
5454
55+ std::future<response>do_request (std::shared_ptr<request_helper> helper);
56+
5557void connect (const boost::system::error_code &ec,
5658 tcp::resolver::iterator endpoint_iterator,
5759 std::shared_ptr<request_helper> helper);
@@ -78,8 +80,6 @@ namespace network {
7880 std::shared_ptr<request_helper> helper,
7981 std::shared_ptr<response> res);
8082
81- std::future<response>do_request (method method_, std::shared_ptr<request_helper> helper);
82-
8383client_options options_;
8484boost::asio::io_service io_service_;
8585std::unique_ptr<boost::asio::io_service::work> sentinel_;
@@ -103,6 +103,44 @@ namespace network {
103103lifetime_thread_.join ();
104104 }
105105
106+ std::future<client::response>client::impl::do_request (std::shared_ptr<request_helper> helper) {
107+ std::future<client::response> res = helper->response_promise_ .get_future ();
108+
109+ // TODO see linearize.hpp
110+ // TODO write User-Agent: cpp-netlib/NETLIB_VERSION (if no user-agent is supplied)
111+
112+ // HTTP 1.1
113+ auto it =std::find_if (std::begin (helper->request_ .headers ()),
114+ std::end (helper->request_ .headers ()),
115+ [] (const std::pair<uri::string_type, uri::string_type> &header) {
116+ return (boost::iequals (header.first ," host" ));
117+ });
118+ if (it ==std::end (helper->request_ .headers ())) {
119+ // set error
120+ helper->response_promise_ .set_value (response ());
121+ return res;
122+ }
123+
124+ uri_builder builder;
125+ builder
126+ .authority (it->second )
127+ ;
128+
129+ auto auth = builder.uri ();
130+ auto host = auth.host ()?
131+ uri::string_type (std::begin (*auth.host ()),std::end (*auth.host ())) :uri::string_type ();
132+ auto port = auth.port <std::uint16_t >()? *auth.port <std::uint16_t >() :80 ;
133+
134+ resolver_->async_resolve (host, port,
135+ strand_.wrap (
136+ [=](const boost::system::error_code &ec,
137+ tcp::resolver::iterator endpoint_iterator) {
138+ connect (ec, endpoint_iterator, helper);
139+ }));
140+
141+ return res;
142+ }
143+
106144void client::impl::connect (const boost::system::error_code &ec,
107145 tcp::resolver::iterator endpoint_iterator,
108146 std::shared_ptr<request_helper> helper) {
@@ -122,6 +160,15 @@ namespace network {
122160 helper->connection_ ->async_connect (endpoint,
123161 strand_.wrap (
124162 [=] (const boost::system::error_code &ec) {
163+ if (ec && endpoint_iterator !=tcp::resolver::iterator ()) {
164+ // copy iterator because it is const after the lambda
165+ // capture
166+ auto it = endpoint_iterator;
167+ boost::system::error_code ignore;
168+ connect (ignore, ++it, helper);
169+ return ;
170+ }
171+
125172write_request (ec, helper);
126173 }));
127174 }
@@ -134,6 +181,15 @@ namespace network {
134181return ;
135182 }
136183
184+ std::ostreamrequest_stream (&helper->request_buffer_ );
185+ request_stream << helper->request_ ;
186+ if (!request_stream) {
187+ helper->response_promise_ .set_exception (
188+ std::make_exception_ptr (client_exception (client_error::invalid_request)));
189+ }
190+
191+ // TODO write payload to request_buffer_
192+
137193 helper->connection_ ->async_write (helper->request_buffer_ ,
138194 strand_.wrap (
139195 [=] (const boost::system::error_code &ec,
@@ -265,52 +321,6 @@ namespace network {
265321 }));
266322 }
267323
268- std::future<client::response>client::impl::do_request (method met,
269- std::shared_ptr<request_helper> helper) {
270- std::future<client::response> res = helper->response_promise_ .get_future ();
271-
272- helper->request_ .method (met);
273- std::ostreamrequest_stream (&helper->request_buffer_ );
274- request_stream << helper->request_ ;
275- if (!request_stream) {
276- helper->response_promise_ .set_exception (
277- std::make_exception_ptr (client_exception (client_error::invalid_request)));
278- }
279-
280- // TODO write payload to request_buffer_
281-
282- // HTTP 1.1
283- auto it =std::find_if (std::begin (helper->request_ .headers ()),
284- std::end (helper->request_ .headers ()),
285- [] (const std::pair<uri::string_type, uri::string_type> &header) {
286- return (boost::iequals (header.first ," host" ));
287- });
288- if (it ==std::end (helper->request_ .headers ())) {
289- // set error
290- helper->response_promise_ .set_value (response ());
291- return res;
292- }
293-
294- uri_builder builder;
295- builder
296- .authority (it->second )
297- ;
298-
299- auto auth = builder.uri ();
300- auto host = auth.host ()?
301- uri::string_type (std::begin (*auth.host ()),std::end (*auth.host ())) :uri::string_type ();
302- auto port = auth.port <std::uint16_t >()? *auth.port <std::uint16_t >() :80 ;
303-
304- resolver_->async_resolve (host, port,
305- strand_.wrap (
306- [=](const boost::system::error_code &ec,
307- tcp::resolver::iterator endpoint_iterator) {
308- connect (ec, endpoint_iterator, helper);
309- }));
310-
311- return res;
312- }
313-
314324client::client (client_options options)
315325: pimpl_(new impl(options)) {
316326
@@ -321,33 +331,33 @@ namespace network {
321331 }
322332
323333 std::future<client::response>client::get (request req, request_options options) {
324- return pimpl_-> do_request (method::get,
325- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
334+ req. method (method::get);
335+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
326336 }
327337
328338 std::future<client::response>client::post (request req, request_options options) {
329- return pimpl_-> do_request (method::post ,
330- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
339+ req. method (method::post );
340+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
331341 }
332342
333343 std::future<client::response>client::put (request req, request_options options) {
334- return pimpl_-> do_request (method::put,
335- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
344+ req. method (method::put);
345+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
336346 }
337347
338348 std::future<client::response>client::delete_ (request req, request_options options) {
339- return pimpl_-> do_request (method::delete_,
340- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
349+ req. method (method::delete_);
350+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
341351 }
342352
343353 std::future<client::response>client::head (request req, request_options options) {
344- return pimpl_-> do_request (method::head,
345- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
354+ req. method (method::head);
355+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
346356 }
347357
348358 std::future<client::response>client::options (request req, request_options options) {
349- return pimpl_-> do_request (method::options,
350- std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
359+ req. method (method::options);
360+ return pimpl_-> do_request ( std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
351361 }
352362 }// namespace v2
353363 }// namespace http