Skip to content

Commit 3e33f13

Browse files
committed
Continued refactoring, improved read_headers and simple_wget examples.
1 parent 1238f44 commit 3e33f13

File tree

7 files changed

+87
-64
lines changed

7 files changed

+87
-64
lines changed

contrib/http_examples/read_headers.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ main(int argc, char *argv[]) {
2020
try {
2121
http::client client;
2222
http::client::request request{network::uri{std::string{argv[1]}}};
23+
request.version("1.0");
2324
request.append_header("Connection", "close");
25+
request.append_header("User-Agent", "cpp-netlib read_headers example");
2426
auto future_response = client.head(request);
2527
auto response = future_response.get();
2628

@@ -37,6 +39,5 @@ main(int argc, char *argv[]) {
3739
return 1;
3840
}
3941

40-
4142
return 0;
4243
}

contrib/http_examples/simple_wget.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ int main(int argc, char* argv[]) {
3838
try {
3939
http::client client;
4040
http::client::request request{network::uri{std::string{argv[1]}}};
41+
request.version("1.0");
4142
request.append_header("Connection", "close");
43+
request.append_header("User-Agent", "cpp-netlib simple_wget example");
4244
auto future_response = client.get(request);
4345
auto response = future_response.get();
4446

@@ -54,4 +56,3 @@ int main(int argc, char* argv[]) {
5456

5557
return 0;
5658
}
57-
//]

http/src/http/v2/client/client.cpp

Lines changed: 70 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ namespace network {
5252

5353
~impl() noexcept;
5454

55+
std::future<response> do_request(std::shared_ptr<request_helper> helper);
56+
5557
void 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-
8383
client_options options_;
8484
boost::asio::io_service io_service_;
8585
std::unique_ptr<boost::asio::io_service::work> sentinel_;
@@ -103,6 +103,44 @@ namespace network {
103103
lifetime_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+
106144
void 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+
125172
write_request(ec, helper);
126173
}));
127174
}
@@ -134,6 +181,15 @@ namespace network {
134181
return;
135182
}
136183

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+
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::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-
314324
client::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

http/src/network/http/client.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
namespace network {
1616
namespace http {
1717
using v2::client;
18+
using v2::client_options;
19+
using v2::method;
20+
namespace status = v2::status;
1821
using v2::client_error;
1922
using v2::invalid_url;
2023
using v2::client_exception;

http/src/network/http/v2/client/request.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ namespace network {
249249

250250
is_https_ = boost::equal(*scheme, boost::as_literal("https"));
251251
path_.assign(std::begin(*url.path()), std::end(*url.path()));
252+
// TODO append query and fragment to path_
252253

253254
std::ostringstream oss;
254255
std::copy(std::begin(*url.host()), std::end(*url.host()),

http/src/network/http/v2/client/response.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,12 +161,19 @@ namespace network {
161161
return status_message_;
162162
}
163163

164+
/**
165+
* \brief Adds a header to the HTTP response.
166+
* \param name The header name.
167+
* \param value The header value.
168+
*/
164169
void add_header(const string_type &name, const string_type &value) {
165170
headers_.push_back(std::make_pair(name, value));
166171
}
167172

168173
/**
169-
* \brief
174+
* \brief Returns the full range of headers.
175+
* \returns An iterator range covering the HTTP response
176+
* headers.
170177
*/
171178
boost::iterator_range<const_headers_iterator> headers() const {
172179
return boost::make_iterator_range(std::begin(headers_), std::end(headers_));

http/src/network/version.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright Dean Michael Berris 2009.
2-
// Copyright Glyn Matthews 2010.
2+
// Copyright Glyn Matthews 2010, 2013.
33
// Copyright 2012 Google, Inc.
44
// Distributed under the Boost Software License, Version 1.0.
55
// (See accompanying file LICENSE_1_0.txt or copy at

0 commit comments

Comments
 (0)