diff --git a/examples/asio-sv2.cc b/examples/asio-sv2.cc index 0cbefc6a..07be841b 100644 --- a/examples/asio-sv2.cc +++ b/examples/asio-sv2.cc @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) { server.listen("*", port, [&docroot](const request &req, const response &res) { - auto path = percent_decode(req.path()); + auto path = percent_decode(req.uri().path); if (!check_path(path)) { res.write_head(404); res.end(); diff --git a/src/asio_http2_handler.cc b/src/asio_http2_handler.cc index 7e0ce166..6854bc4d 100644 --- a/src/asio_http2_handler.cc +++ b/src/asio_http2_handler.cc @@ -45,13 +45,7 @@ const header_map &request::header() const { return impl_->header(); } const std::string &request::method() const { return impl_->method(); } -const std::string &request::scheme() const { return impl_->scheme(); } - -const std::string &request::authority() const { return impl_->authority(); } - -const std::string &request::host() const { return impl_->host(); } - -const std::string &request::path() const { return impl_->path(); } +const uri_ref &request::uri() const { return impl_->uri(); } bool request::push(std::string method, std::string path, header_map h) const { return impl_->push(std::move(method), std::move(path), std::move(h)); @@ -91,13 +85,9 @@ const header_map &request_impl::header() const { return header_; } const std::string &request_impl::method() const { return method_; } -const std::string &request_impl::scheme() const { return scheme_; } +const uri_ref &request_impl::uri() const { return uri_; } -const std::string &request_impl::authority() const { return authority_; } - -const std::string &request_impl::host() const { return host_; } - -const std::string &request_impl::path() const { return path_; } +uri_ref &request_impl::uri() { return uri_; } void request_impl::header(header_map h) { header_ = std::move(h); } @@ -105,14 +95,6 @@ header_map &request_impl::header() { return header_; } void request_impl::method(std::string arg) { method_ = std::move(arg); } -void request_impl::scheme(std::string arg) { scheme_ = std::move(arg); } - -void request_impl::authority(std::string arg) { authority_ = std::move(arg); } - -void request_impl::host(std::string arg) { host_ = std::move(arg); } - -void request_impl::path(std::string arg) { path_ = std::move(arg); } - bool request_impl::push(std::string method, std::string path, header_map h) { auto handler = stream_->handler(); auto rv = handler->push_promise(*stream_, std::move(method), std::move(path), @@ -261,22 +243,25 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame, } auto &req = stream->request().impl(); + auto &uref = req.uri(); switch (nghttp2::http2::lookup_token(name, namelen)) { case nghttp2::http2::HD__METHOD: req.method(std::string(value, value + valuelen)); break; case nghttp2::http2::HD__SCHEME: - req.scheme(std::string(value, value + valuelen)); + uref.scheme.assign(value, value + valuelen); break; case nghttp2::http2::HD__AUTHORITY: - req.authority(std::string(value, value + valuelen)); + uref.host.assign(value, value + valuelen); break; case nghttp2::http2::HD__PATH: - req.path(std::string(value, value + valuelen)); + split_path(uref, value, value + valuelen); break; case nghttp2::http2::HD_HOST: - req.host(std::string(value, value + valuelen)); + if (uref.host.empty()) { + uref.host.assign(value, value + valuelen); + } // fall through default: req.header().emplace(std::string(name, name + namelen), @@ -310,12 +295,6 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame, break; } - auto &req = stream->request().impl(); - - if (req.host().empty()) { - req.host(req.authority()); - } - handler->call_on_request(*stream); if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { @@ -549,22 +528,17 @@ void http2_handler::resume(http2_stream &stream) { } int http2_handler::push_promise(http2_stream &stream, std::string method, - std::string path, header_map h) { + std::string raw_path_query, header_map h) { int rv; auto &req = stream.request().impl(); auto nva = std::vector(); - nva.reserve(5 + h.size()); + nva.reserve(4 + h.size()); nva.push_back(nghttp2::http2::make_nv_ls(":method", method)); - nva.push_back(nghttp2::http2::make_nv_ls(":scheme", req.scheme())); - if (!req.authority().empty()) { - nva.push_back(nghttp2::http2::make_nv_ls(":authority", req.authority())); - } - nva.push_back(nghttp2::http2::make_nv_ls(":path", path)); - if (!req.host().empty()) { - nva.push_back(nghttp2::http2::make_nv_ls("host", req.host())); - } + nva.push_back(nghttp2::http2::make_nv_ls(":scheme", req.uri().scheme)); + nva.push_back(nghttp2::http2::make_nv_ls(":authority", req.uri().host)); + nva.push_back(nghttp2::http2::make_nv_ls(":path", raw_path_query)); for (auto &hd : h) { nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, @@ -582,15 +556,12 @@ int http2_handler::push_promise(http2_stream &stream, std::string method, auto promised_stream = create_stream(rv); auto &promised_req = promised_stream->request().impl(); promised_req.pushed(true); - promised_req.method(std::move(method)); - promised_req.scheme(req.scheme()); - promised_req.authority(req.authority()); - promised_req.path(std::move(path)); - promised_req.host(req.host()); promised_req.header(std::move(h)); - if (!req.host().empty()) { - promised_req.header().emplace("host", header_value(req.host())); - } + promised_req.method(std::move(method)); + auto &uref = promised_req.uri(); + uref.scheme = req.uri().scheme; + uref.host = req.uri().host; + split_path(uref, std::begin(raw_path_query), std::end(raw_path_query)); return 0; } diff --git a/src/asio_http2_handler.h b/src/asio_http2_handler.h index e2825d4e..055fbac6 100644 --- a/src/asio_http2_handler.h +++ b/src/asio_http2_handler.h @@ -47,27 +47,23 @@ class request_impl { public: request_impl(); + void header(header_map h); const header_map &header() const; - const std::string &method() const; - const std::string &scheme() const; - const std::string &authority() const; - const std::string &host() const; - const std::string &path() const; + header_map &header(); - bool push(std::string method, std::string path, header_map h = {}); + void method(std::string method); + const std::string &method() const; + + const uri_ref &uri() const; + uri_ref &uri(); + + bool push(std::string method, std::string raw_path_query, header_map h = {}); bool pushed() const; void on_data(data_cb cb); void on_end(void_cb cb); - void header(header_map h); - header_map &header(); - void method(std::string method); - void scheme(std::string scheme); - void authority(std::string authority); - void host(std::string host); - void path(std::string path); void pushed(bool f); void stream(http2_stream *s); void call_on_data(const uint8_t *data, std::size_t len); @@ -77,10 +73,7 @@ private: http2_stream *stream_; header_map header_; std::string method_; - std::string scheme_; - std::string authority_; - std::string host_; - std::string path_; + uri_ref uri_; data_cb on_data_cb_; void_cb on_end_cb_; bool pushed_; @@ -162,8 +155,8 @@ public: void resume(http2_stream &stream); - int push_promise(http2_stream &stream, std::string method, std::string path, - header_map h); + int push_promise(http2_stream &stream, std::string method, + std::string raw_path_query, header_map h); boost::asio::io_service &io_service(); diff --git a/src/includes/nghttp2/asio_http2_server.h b/src/includes/nghttp2/asio_http2_server.h index 3a023b48..caf1238d 100644 --- a/src/includes/nghttp2/asio_http2_server.h +++ b/src/includes/nghttp2/asio_http2_server.h @@ -48,20 +48,8 @@ public: // Returns method (e.g., GET). const std::string &method() const; - // Returns scheme (e.g., https). - const std::string &scheme() const; - - // Returns authority (e.g., example.org). This could be empty - // string. In this case, check host(). - - const std::string &authority() const; - - // Returns host (e.g., example.org). If host header field is not - // present, this value is copied from authority(). - const std::string &host() const; - - // Returns path (e.g., /index.html). - const std::string &path() const; + // Returns request URI, split into components. + const uri_ref &uri() const; // Sets callback when chunk of request body is received. void on_data(data_cb cb) const; @@ -73,7 +61,8 @@ public: // headers can be given in |h|. request_cb will be called for // pushed resource later on. This function returns true if it // succeeds, or false. - bool push(std::string method, std::string path, header_map h = {}) const; + bool push(std::string method, std::string raw_path_query, + header_map h = {}) const; // Returns true if this is pushed request. bool pushed() const;