diff --git a/examples/asio-cl.cc b/examples/asio-cl.cc index 7285d688..a4dc2e72 100644 --- a/examples/asio-cl.cc +++ b/examples/asio-cl.cc @@ -34,19 +34,33 @@ using namespace nghttp2::asio_http2::client; int main(int argc, char *argv[]) { try { + if (argc < 2) { + std::cerr << "Usage: asio-cl URI" << std::endl; + return 1; + } boost::system::error_code ec; boost::asio::io_service io_service; + std::string uri = argv[1]; + std::string scheme, host, service; + + if (host_service_from_uri(ec, scheme, host, service, uri)) { + std::cerr << "error: bad URI: " << ec.message() << std::endl; + return 1; + } + boost::asio::ssl::context tls_ctx(boost::asio::ssl::context::sslv23); tls_ctx.set_default_verify_paths(); // disabled to make development easier... // tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer); configure_tls_context(ec, tls_ctx); - session sess(io_service, tls_ctx, "localhost", "3000"); - sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) { + auto sess = scheme == "https" ? session(io_service, tls_ctx, host, service) + : session(io_service, host, service); + + sess.on_connect([&sess, &uri](tcp::resolver::iterator endpoint_it) { boost::system::error_code ec; - auto req = sess.submit(ec, "GET", "https://localhost:3000/"); + auto req = sess.submit(ec, "GET", uri); if (ec) { std::cerr << "error: " << ec.message() << std::endl; diff --git a/src/asio_client_session.cc b/src/asio_client_session.cc index 2e03f51e..bc6a46aa 100644 --- a/src/asio_client_session.cc +++ b/src/asio_client_session.cc @@ -49,6 +49,17 @@ session::session(boost::asio::io_service &io_service, session::~session() {} +session::session(session &&other) : impl_(std::move(other.impl_)) {} + +session &session::operator=(session &&other) { + if (this == &other) { + return *this; + } + + impl_ = std::move(other.impl_); + return *this; +} + void session::on_connect(connect_cb cb) const { impl_->on_connect(std::move(cb)); } diff --git a/src/asio_common.cc b/src/asio_common.cc index 3025c493..c3f98e7c 100644 --- a/src/asio_common.cc +++ b/src/asio_common.cc @@ -28,6 +28,7 @@ #include "util.h" #include "template.h" +#include "http2.h" namespace nghttp2 { namespace asio_http2 { @@ -112,5 +113,36 @@ std::string percent_decode(const std::string &s) { std::string http_date(int64_t t) { return util::http_date(t); } +boost::system::error_code host_service_from_uri(boost::system::error_code &ec, + std::string &scheme, + std::string &host, + std::string &service, + const std::string &uri) { + ec.clear(); + + http_parser_url u{}; + if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) { + ec = make_error_code(boost::system::errc::invalid_argument); + return ec; + } + + if ((u.field_set & (1 << UF_SCHEMA)) == 0 || + (u.field_set & (1 << UF_HOST)) == 0) { + ec = make_error_code(boost::system::errc::invalid_argument); + return ec; + } + + http2::copy_url_component(scheme, &u, UF_SCHEMA, uri.c_str()); + http2::copy_url_component(host, &u, UF_HOST, uri.c_str()); + + if (u.field_set & (1 << UF_PORT)) { + http2::copy_url_component(service, &u, UF_PORT, uri.c_str()); + } else { + service = scheme; + } + + return ec; +} + } // namespace asio_http2 } // namespace nghttp2 diff --git a/src/includes/nghttp2/asio_http2.h b/src/includes/nghttp2/asio_http2.h index 670952f1..a54a9e8e 100644 --- a/src/includes/nghttp2/asio_http2.h +++ b/src/includes/nghttp2/asio_http2.h @@ -123,6 +123,15 @@ std::string percent_decode(const std::string &s); // Returns HTTP date representation of current posix time |t|. std::string http_date(int64_t t); +// Parses |uri| and extract scheme, host and service. The service is +// port component of URI (e.g., "8443") if available, otherwise it is +// scheme (e.g., "https"). +boost::system::error_code host_service_from_uri(boost::system::error_code &ec, + std::string &scheme, + std::string &host, + std::string &service, + const std::string &uri); + } // namespace asio_http2 } // namespace nghttp2 diff --git a/src/includes/nghttp2/asio_http2_client.h b/src/includes/nghttp2/asio_http2_client.h index 03aacadc..0693a70a 100644 --- a/src/includes/nghttp2/asio_http2_client.h +++ b/src/includes/nghttp2/asio_http2_client.h @@ -128,6 +128,9 @@ public: const std::string &service); ~session(); + session(session &&other); + session &operator=(session &&other); + // Sets callback which is invoked after connection is established. void on_connect(connect_cb cb) const;