@@ -24,11 +24,24 @@ namespace network {
2424
2525struct request_helper {
2626
27+ std::unique_ptr<client_connection::async_connection> connection_;
28+
2729 client::request request_;
2830 client::request_options options_;
2931
30- request_helper (client::request request, client::request_options options)
31- : request_(request)
32+ std::promise<client::response> response_promise_;
33+
34+ boost::asio::streambuf request_buffer_;
35+ boost::asio::streambuf response_buffer_;
36+
37+ // TODO configure deadline timer for timeouts
38+
39+ request_helper (boost::asio::io_service &io_service,
40+ client::request request,
41+ client::request_options options)
42+ // TODO factory based on HTTP or HTTPS
43+ : connection_(new client_connection::normal_connection(io_service))
44+ , request_(request)
3245 , options_(options) { }
3346
3447 };
@@ -69,24 +82,18 @@ namespace network {
6982
7083client_options options_;
7184boost::asio::io_service io_service_;
85+ std::unique_ptr<boost::asio::io_service::work> sentinel_;
7286 boost::asio::io_service::strand strand_;
7387 std::unique_ptr<client_connection::async_resolver> resolver_;
74- std::unique_ptr<client_connection::async_connection> connection_;
75- std::unique_ptr<boost::asio::io_service::work> sentinel_;
7688std::thread lifetime_thread_;
7789
78- std::promise<response> response_promise_;
79- boost::asio::streambuf request_buffer_;
80- boost::asio::streambuf response_buffer_;
81-
8290 };
8391
8492client::impl::impl (client_options options)
8593: options_(options)
86- , strand_(io_service_)
87- , resolver_(new client_connection::tcp_resolver(io_service_, options.cache_resolved()))
88- , connection_(new client_connection::normal_connection(io_service_))
8994, sentinel_(new boost::asio::io_service::work(io_service_))
95+ , strand_(io_service_)
96+ , resolver_(new client_connection::tcp_resolver(io_service_, options_.cache_resolved()))
9097, lifetime_thread_([=] () { io_service_.run (); }) {
9198
9299 }
@@ -101,18 +108,18 @@ namespace network {
101108 std::shared_ptr<request_helper> helper) {
102109if (ec) {
103110if (endpoint_iterator ==tcp::resolver::iterator ()) {
104- response_promise_.set_exception ( std::make_exception_ptr (
105- client_exception (client_error::host_not_found)));
111+ helper-> response_promise_ .set_exception (
112+ std::make_exception_ptr ( client_exception (client_error::host_not_found)));
106113return ;
107114 }
108115
109- response_promise_.set_exception ( std::make_exception_ptr (
110- std::system_error (ec.value (),std::system_category ())));
116+ helper-> response_promise_ .set_exception (
117+ std::make_exception_ptr ( std::system_error (ec.value (),std::system_category ())));
111118return ;
112119 }
113120
114121 tcp::endpointendpoint (*endpoint_iterator);
115- connection_->async_connect (endpoint,
122+ helper-> connection_ ->async_connect (endpoint,
116123 strand_.wrap (
117124 [=] (const boost::system::error_code &ec) {
118125write_request (ec, helper);
@@ -122,12 +129,12 @@ namespace network {
122129void client::impl::write_request (const boost::system::error_code &ec,
123130 std::shared_ptr<request_helper> helper) {
124131if (ec) {
125- response_promise_.set_exception ( std::make_exception_ptr (
126- std::system_error (ec.value (),std::system_category ())));
132+ helper-> response_promise_ .set_exception (
133+ std::make_exception_ptr ( std::system_error (ec.value (),std::system_category ())));
127134return ;
128135 }
129136
130- connection_->async_write (request_buffer_,
137+ helper-> connection_ ->async_write (helper-> request_buffer_ ,
131138 strand_.wrap (
132139 [=] (const boost::system::error_code &ec,
133140 std::size_t bytes_written) {
@@ -138,13 +145,13 @@ namespace network {
138145void client::impl::read_response (const boost::system::error_code &ec, std::size_t ,
139146 std::shared_ptr<request_helper> helper) {
140147if (ec) {
141- response_promise_.set_exception ( std::make_exception_ptr (
142- std::system_error (ec.value (),std::system_category ())));
148+ helper-> response_promise_ .set_exception (
149+ std::make_exception_ptr ( std::system_error (ec.value (),std::system_category ())));
143150return ;
144151 }
145152
146153 std::shared_ptr<response>res (new response{});
147- connection_->async_read_until (response_buffer_,
154+ helper-> connection_ ->async_read_until (helper-> response_buffer_ ,
148155" \r\n " ,
149156 strand_.wrap (
150157 [=] (const boost::system::error_code &ec,
@@ -158,12 +165,12 @@ namespace network {
158165 std::shared_ptr<request_helper> helper,
159166 std::shared_ptr<response> res) {
160167if (ec) {
161- response_promise_.set_exception ( std::make_exception_ptr (
162- std::system_error (ec.value (),std::system_category ())));
168+ helper-> response_promise_ .set_exception (
169+ std::make_exception_ptr ( std::system_error (ec.value (),std::system_category ())));
163170return ;
164171 }
165172
166- std::istreamis (&response_buffer_);
173+ std::istreamis (&helper-> response_buffer_ );
167174 string_type version;
168175 is >> version;
169176unsigned int status;
@@ -175,7 +182,7 @@ namespace network {
175182 res->set_status (network::http::v2::status::code (status));
176183 res->set_status_message (boost::trim_copy (message));
177184
178- connection_->async_read_until (response_buffer_,
185+ helper-> connection_ ->async_read_until (helper-> response_buffer_ ,
179186" \r\n\r\n " ,
180187 strand_.wrap (
181188 [=] (const boost::system::error_code &ec,
@@ -189,13 +196,13 @@ namespace network {
189196 std::shared_ptr<request_helper> helper,
190197 std::shared_ptr<response> res) {
191198if (ec) {
192- response_promise_.set_exception ( std::make_exception_ptr (
193- std::system_error (ec.value (),std::system_category ())));
199+ helper-> response_promise_ .set_exception (
200+ std::make_exception_ptr ( std::system_error (ec.value (),std::system_category ())));
194201return ;
195202 }
196203
197204// fill headers
198- std::istreamis (&response_buffer_);
205+ std::istreamis (&helper-> response_buffer_ );
199206 string_type header;
200207while (std::getline (is, header) && (header !=" \r " )) {
201208auto delim =boost::find_first_of (header," :" );
@@ -205,7 +212,7 @@ namespace network {
205212 res->add_header (key, value);
206213 }
207214
208- connection_->async_read (response_buffer_,
215+ helper-> connection_ ->async_read (helper-> response_buffer_ ,
209216 strand_.wrap (
210217 [=] (const boost::system::error_code &ec,
211218 std::size_t bytes_read) {
@@ -240,17 +247,17 @@ namespace network {
240247 std::shared_ptr<request_helper> helper,
241248 std::shared_ptr<response> res) {
242249if (bytes_read ==0 ) {
243- response_promise_.set_value (*res);
250+ helper-> response_promise_ .set_value (*res);
244251return ;
245252 }
246253
247- std::istreamis (&response_buffer_);
254+ std::istreamis (&helper-> response_buffer_ );
248255 string_type line;
249256while (!getline_with_newline (is, line).eof ()) {
250257 res->append_body (line);
251258 }
252259
253- connection_->async_read (response_buffer_,
260+ helper-> connection_ ->async_read (helper-> response_buffer_ ,
254261 strand_.wrap (
255262 [=] (const boost::system::error_code &ec,
256263 std::size_t bytes_read) {
@@ -260,16 +267,18 @@ namespace network {
260267
261268 std::future<client::response>client::impl::do_request (method met,
262269 std::shared_ptr<request_helper> helper) {
263- std::future<client::response> res = response_promise_.get_future ();
270+ std::future<client::response> res =helper-> response_promise_ .get_future ();
264271
265272helper->request_ .method (met);
266- std::ostreamrequest_stream (&request_buffer_);
273+ std::ostreamrequest_stream (&helper-> request_buffer_ );
267274 request_stream << helper->request_ ;
268275if (!request_stream) {
269- response_promise_.set_exception ( std::make_exception_ptr (
270- client_exception (client_error::invalid_request)));
276+ helper-> response_promise_ .set_exception (
277+ std::make_exception_ptr ( client_exception (client_error::invalid_request)));
271278 }
272279
280+ // TODO write payload to request_buffer_
281+
273282// HTTP 1.1
274283auto it =std::find_if (std::begin (helper->request_ .headers ()),
275284std::end (helper->request_ .headers ()),
@@ -278,7 +287,7 @@ namespace network {
278287 });
279288if (it ==std::end (helper->request_ .headers ())) {
280289// set error
281- response_promise_.set_value (response ());
290+ helper-> response_promise_ .set_value (response ());
282291return res;
283292 }
284293
@@ -312,27 +321,33 @@ namespace network {
312321 }
313322
314323 std::future<client::response>client::get (request req, request_options options) {
315- return pimpl_->do_request (method::GET, std::make_shared<request_helper>(req, options));
324+ return pimpl_->do_request (method::get,
325+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
316326 }
317327
318328 std::future<client::response>client::post (request req, request_options options) {
319- return pimpl_->do_request (method::POST, std::make_shared<request_helper>(req, options));
329+ return pimpl_->do_request (method::post ,
330+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
320331 }
321332
322333 std::future<client::response>client::put (request req, request_options options) {
323- return pimpl_->do_request (method::PUT, std::make_shared<request_helper>(req, options));
334+ return pimpl_->do_request (method::put,
335+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
324336 }
325337
326338 std::future<client::response>client::delete_ (request req, request_options options) {
327- return pimpl_->do_request (method::DELETE, std::make_shared<request_helper>(req, options));
339+ return pimpl_->do_request (method::delete_,
340+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
328341 }
329342
330343 std::future<client::response>client::head (request req, request_options options) {
331- return pimpl_->do_request (method::HEAD, std::make_shared<request_helper>(req, options));
344+ return pimpl_->do_request (method::head,
345+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
332346 }
333347
334348 std::future<client::response>client::options (request req, request_options options) {
335- return pimpl_->do_request (method::OPTIONS, std::make_shared<request_helper>(req, options));
349+ return pimpl_->do_request (method::options,
350+ std::make_shared<request_helper>(pimpl_->io_service_ , req, options));
336351 }
337352 }// namespace v2
338353 }// namespace http