@@ -24,11 +24,24 @@ namespace network {
24
24
25
25
struct request_helper {
26
26
27
+ std::unique_ptr<client_connection::async_connection> connection_;
28
+
27
29
client::request request_;
28
30
client::request_options options_;
29
31
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)
32
45
, options_(options) { }
33
46
34
47
};
@@ -69,24 +82,18 @@ namespace network {
69
82
70
83
client_options options_;
71
84
boost::asio::io_service io_service_;
85
+ std::unique_ptr<boost::asio::io_service::work> sentinel_;
72
86
boost::asio::io_service::strand strand_;
73
87
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_;
76
88
std::thread lifetime_thread_;
77
89
78
- std::promise<response> response_promise_;
79
- boost::asio::streambuf request_buffer_;
80
- boost::asio::streambuf response_buffer_;
81
-
82
90
};
83
91
84
92
client::impl::impl (client_options options)
85
93
: 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_))
89
94
, 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()))
90
97
, lifetime_thread_([=] () { io_service_.run (); }) {
91
98
92
99
}
@@ -101,18 +108,18 @@ namespace network {
101
108
std::shared_ptr<request_helper> helper) {
102
109
if (ec) {
103
110
if (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)));
106
113
return ;
107
114
}
108
115
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 ())));
111
118
return ;
112
119
}
113
120
114
121
tcp::endpoint endpoint (*endpoint_iterator);
115
- connection_->async_connect (endpoint,
122
+ helper-> connection_ ->async_connect (endpoint,
116
123
strand_.wrap (
117
124
[=] (const boost::system ::error_code &ec) {
118
125
write_request (ec, helper);
@@ -122,12 +129,12 @@ namespace network {
122
129
void client::impl::write_request (const boost::system::error_code &ec,
123
130
std::shared_ptr<request_helper> helper) {
124
131
if (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 ())));
127
134
return ;
128
135
}
129
136
130
- connection_->async_write (request_buffer_,
137
+ helper-> connection_ ->async_write (helper-> request_buffer_ ,
131
138
strand_.wrap (
132
139
[=] (const boost::system ::error_code &ec,
133
140
std::size_t bytes_written) {
@@ -138,13 +145,13 @@ namespace network {
138
145
void client::impl::read_response (const boost::system::error_code &ec, std::size_t ,
139
146
std::shared_ptr<request_helper> helper) {
140
147
if (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 ())));
143
150
return ;
144
151
}
145
152
146
153
std::shared_ptr<response> res (new response{});
147
- connection_->async_read_until (response_buffer_,
154
+ helper-> connection_ ->async_read_until (helper-> response_buffer_ ,
148
155
" \r\n " ,
149
156
strand_.wrap (
150
157
[=] (const boost::system ::error_code &ec,
@@ -158,12 +165,12 @@ namespace network {
158
165
std::shared_ptr<request_helper> helper,
159
166
std::shared_ptr<response> res) {
160
167
if (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 ())));
163
170
return ;
164
171
}
165
172
166
- std::istream is (&response_buffer_);
173
+ std::istream is (&helper-> response_buffer_ );
167
174
string_type version;
168
175
is >> version;
169
176
unsigned int status;
@@ -175,7 +182,7 @@ namespace network {
175
182
res->set_status (network::http::v2::status::code (status));
176
183
res->set_status_message (boost::trim_copy (message));
177
184
178
- connection_->async_read_until (response_buffer_,
185
+ helper-> connection_ ->async_read_until (helper-> response_buffer_ ,
179
186
" \r\n\r\n " ,
180
187
strand_.wrap (
181
188
[=] (const boost::system ::error_code &ec,
@@ -189,13 +196,13 @@ namespace network {
189
196
std::shared_ptr<request_helper> helper,
190
197
std::shared_ptr<response> res) {
191
198
if (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 ())));
194
201
return ;
195
202
}
196
203
197
204
// fill headers
198
- std::istream is (&response_buffer_);
205
+ std::istream is (&helper-> response_buffer_ );
199
206
string_type header;
200
207
while (std::getline (is, header) && (header != " \r " )) {
201
208
auto delim = boost::find_first_of (header, " :" );
@@ -205,7 +212,7 @@ namespace network {
205
212
res->add_header (key, value);
206
213
}
207
214
208
- connection_->async_read (response_buffer_,
215
+ helper-> connection_ ->async_read (helper-> response_buffer_ ,
209
216
strand_.wrap (
210
217
[=] (const boost::system ::error_code &ec,
211
218
std::size_t bytes_read) {
@@ -240,17 +247,17 @@ namespace network {
240
247
std::shared_ptr<request_helper> helper,
241
248
std::shared_ptr<response> res) {
242
249
if (bytes_read == 0 ) {
243
- response_promise_.set_value (*res);
250
+ helper-> response_promise_ .set_value (*res);
244
251
return ;
245
252
}
246
253
247
- std::istream is (&response_buffer_);
254
+ std::istream is (&helper-> response_buffer_ );
248
255
string_type line;
249
256
while (!getline_with_newline (is, line).eof ()) {
250
257
res->append_body (line);
251
258
}
252
259
253
- connection_->async_read (response_buffer_,
260
+ helper-> connection_ ->async_read (helper-> response_buffer_ ,
254
261
strand_.wrap (
255
262
[=] (const boost::system ::error_code &ec,
256
263
std::size_t bytes_read) {
@@ -260,16 +267,18 @@ namespace network {
260
267
261
268
std::future<client::response> client::impl::do_request (method met,
262
269
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 ();
264
271
265
272
helper->request_ .method (met);
266
- std::ostream request_stream (&request_buffer_);
273
+ std::ostream request_stream (&helper-> request_buffer_ );
267
274
request_stream << helper->request_ ;
268
275
if (!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)));
271
278
}
272
279
280
+ // TODO write payload to request_buffer_
281
+
273
282
// HTTP 1.1
274
283
auto it = std::find_if (std::begin (helper->request_ .headers ()),
275
284
std::end (helper->request_ .headers ()),
@@ -278,7 +287,7 @@ namespace network {
278
287
});
279
288
if (it == std::end (helper->request_ .headers ())) {
280
289
// set error
281
- response_promise_.set_value (response ());
290
+ helper-> response_promise_ .set_value (response ());
282
291
return res;
283
292
}
284
293
@@ -312,27 +321,33 @@ namespace network {
312
321
}
313
322
314
323
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));
316
326
}
317
327
318
328
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));
320
331
}
321
332
322
333
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));
324
336
}
325
337
326
338
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));
328
341
}
329
342
330
343
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));
332
346
}
333
347
334
348
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));
336
351
}
337
352
} // namespace v2
338
353
} // namespace http
0 commit comments