@@ -52,6 +52,8 @@ namespace network {
52
52
53
53
~impl () noexcept ;
54
54
55
+ std::future<response> do_request (std::shared_ptr<request_helper> helper);
56
+
55
57
void connect (const boost::system::error_code &ec,
56
58
tcp::resolver::iterator endpoint_iterator,
57
59
std::shared_ptr<request_helper> helper);
@@ -78,8 +80,6 @@ namespace network {
78
80
std::shared_ptr<request_helper> helper,
79
81
std::shared_ptr<response> res);
80
82
81
- std::future<response> do_request (method method_, std::shared_ptr<request_helper> helper);
82
-
83
83
client_options options_;
84
84
boost::asio::io_service io_service_;
85
85
std::unique_ptr<boost::asio::io_service::work> sentinel_;
@@ -103,6 +103,44 @@ namespace network {
103
103
lifetime_thread_.join ();
104
104
}
105
105
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
+
106
144
void client::impl::connect (const boost::system::error_code &ec,
107
145
tcp::resolver::iterator endpoint_iterator,
108
146
std::shared_ptr<request_helper> helper) {
@@ -122,6 +160,15 @@ namespace network {
122
160
helper->connection_ ->async_connect (endpoint,
123
161
strand_.wrap (
124
162
[=] (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
+
125
172
write_request (ec, helper);
126
173
}));
127
174
}
@@ -134,6 +181,15 @@ namespace network {
134
181
return ;
135
182
}
136
183
184
+ std::ostream request_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
+
137
193
helper->connection_ ->async_write (helper->request_buffer_ ,
138
194
strand_.wrap (
139
195
[=] (const boost::system::error_code &ec,
@@ -265,52 +321,6 @@ namespace network {
265
321
}));
266
322
}
267
323
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::ostream request_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
-
314
324
client::client (client_options options)
315
325
: pimpl_(new impl(options)) {
316
326
@@ -321,33 +331,33 @@ namespace network {
321
331
}
322
332
323
333
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));
326
336
}
327
337
328
338
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));
331
341
}
332
342
333
343
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));
336
346
}
337
347
338
348
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));
341
351
}
342
352
343
353
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));
346
356
}
347
357
348
358
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));
351
361
}
352
362
} // namespace v2
353
363
} // namespace http
0 commit comments