asio: Introduce uri_ref

This commit is contained in:
Tatsuhiro Tsujikawa 2015-03-04 00:59:22 +09:00
parent b2196f215a
commit e15d302985
9 changed files with 87 additions and 15 deletions

View File

@ -63,6 +63,7 @@ noinst_PROGRAMS += asio-sv asio-sv2 asio-sv3 asio-cl
ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS}
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \ ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \ $(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
$(top_builddir)/third-party/libhttp-parser.la \
${BOOST_LDFLAGS} \ ${BOOST_LDFLAGS} \
${BOOST_ASIO_LIB} \ ${BOOST_ASIO_LIB} \
${BOOST_THREAD_LIB} \ ${BOOST_THREAD_LIB} \

View File

@ -49,9 +49,13 @@ void print_header(const response &res) {
} }
void print_header(const request &req) { void print_header(const request &req) {
std::cerr << req.method() << " " << req.scheme() << "://" << req.authority() auto &uri = req.uri();
<< req.path() << " " std::cerr << req.method() << " " << uri.scheme << "://" << uri.host
<< "HTTP/2\n"; << uri.path;
if (!uri.raw_query.empty()) {
std::cerr << "?" << uri.raw_query;
}
std::cerr << " HTTP/2\n";
print_header(req.header()); print_header(req.header());
} }

View File

@ -46,16 +46,10 @@ void request::on_push(request_cb cb) const { impl_->on_push(std::move(cb)); }
void request::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); } void request::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); }
const uri_ref &request::uri() const { return impl_->uri(); }
const std::string &request::method() const { return impl_->method(); } const std::string &request::method() const { return impl_->method(); }
const std::string &request::scheme() const { return impl_->scheme(); }
const std::string &request::path() const { return impl_->path(); }
const std::string &request::authority() const { return impl_->authority(); }
const std::string &request::host() const { return impl_->host(); }
const header_map &request::header() const { return impl_->header(); } const header_map &request::header() const { return impl_->header(); }
request_impl &request::impl() { return *impl_; } request_impl &request::impl() { return *impl_; }

View File

@ -76,6 +76,10 @@ const header_map &request_impl::header() const { return header_; }
void request_impl::stream(class stream *strm) { strm_ = strm; } void request_impl::stream(class stream *strm) { strm_ = strm; }
void request_impl::uri(uri_ref uri) { uri_ = std::move(uri); }
const uri_ref &request_impl::uri() const { return uri_; }
void request_impl::method(std::string s) { method_ = std::move(s); } void request_impl::method(std::string s) { method_ = std::move(s); }
const std::string &request_impl::method() const { return method_; } const std::string &request_impl::method() const { return method_; }

View File

@ -63,6 +63,9 @@ public:
void stream(class stream *strm); void stream(class stream *strm);
void uri(uri_ref uri);
const uri_ref &uri() const;
void method(std::string s); void method(std::string s);
const std::string &method() const; const std::string &method() const;
@ -85,6 +88,7 @@ private:
close_cb close_cb_; close_cb close_cb_;
read_cb read_cb_; read_cb read_cb_;
class stream *strm_; class stream *strm_;
uri_ref uri_;
std::string method_; std::string method_;
std::string scheme_; std::string scheme_;
std::string path_; std::string path_;

View File

@ -246,6 +246,11 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
return 0; return 0;
} }
auto &req = push_strm->request().impl();
req.uri(make_uri_ref(req.scheme(),
req.authority().empty() ? req.host() : req.authority(),
req.path()));
strm->request().impl().call_on_push(push_strm->request()); strm->request().impl().call_on_push(push_strm->request());
break; break;
@ -364,6 +369,19 @@ const request *session_impl::submit(boost::system::error_code &ec,
header_map h) { header_map h) {
ec.clear(); ec.clear();
http_parser_url u{};
// TODO Handle CONNECT method
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) {
ec = make_error_code(boost::system::errc::invalid_argument);
return nullptr;
}
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 nullptr;
}
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
nva.reserve(3 + h.size()); nva.reserve(3 + h.size());
nva.push_back(http2::make_nv_ls(":method", method)); nva.push_back(http2::make_nv_ls(":method", method));
@ -379,6 +397,17 @@ const request *session_impl::submit(boost::system::error_code &ec,
auto &req = strm->request().impl(); auto &req = strm->request().impl();
req.header(std::move(h)); req.header(std::move(h));
{
std::string scheme, host, raw_path, raw_query;
http2::copy_url_component(scheme, &u, UF_SCHEMA, uri.c_str());
http2::copy_url_component(host, &u, UF_HOST, uri.c_str());
http2::copy_url_component(raw_path, &u, UF_PATH, uri.c_str());
http2::copy_url_component(raw_query, &u, UF_QUERY, uri.c_str());
req.uri(make_uri_ref(std::move(scheme), std::move(host),
std::move(raw_path), std::move(raw_query)));
}
nghttp2_data_provider *prdptr = nullptr; nghttp2_data_provider *prdptr = nullptr;
nghttp2_data_provider prd; nghttp2_data_provider prd;

View File

@ -57,5 +57,28 @@ read_cb string_reader(std::string data) {
}; };
} }
uri_ref make_uri_ref(std::string scheme, std::string host, std::string raw_path,
std::string raw_query) {
return uri_ref{
std::move(scheme), std::move(host), percent_decode(raw_path),
std::move(raw_path),
};
}
uri_ref make_uri_ref(std::string scheme, std::string host,
const std::string &raw_path_query) {
auto path_end = raw_path_query.find('?');
std::size_t query_pos;
if (path_end == std::string::npos) {
query_pos = path_end = raw_path_query.size();
} else {
query_pos = path_end + 1;
}
return uri_ref{std::move(scheme), std::move(host),
util::percentDecode(std::begin(raw_path_query),
std::begin(raw_path_query) + path_end),
raw_path_query.substr(query_pos)};
}
} // namespace asio_http2 } // namespace asio_http2
} // namespace nghttp2 } // namespace nghttp2

View File

@ -38,6 +38,12 @@ read_cb string_reader(std::string data);
boost::system::error_code make_error_code(nghttp2_error ev); boost::system::error_code make_error_code(nghttp2_error ev);
uri_ref make_uri_ref(std::string scheme, std::string host, std::string raw_path,
std::string raw_query);
uri_ref make_uri_ref(std::string scheme, std::string host,
const std::string &raw_path_query);
} // namespace asio_http2 } // namespace asio_http2
} // namespace nghttp2 } // namespace nghttp2

View File

@ -74,6 +74,15 @@ using header_map = std::multimap<std::string, header_value>;
const boost::system::error_category &nghttp2_category() noexcept; const boost::system::error_category &nghttp2_category() noexcept;
struct uri_ref {
std::string scheme;
std::string host;
// percent-decoded form
std::string path;
std::string raw_query;
std::string fragment;
};
typedef std::function<void(const uint8_t *, std::size_t)> data_cb; typedef std::function<void(const uint8_t *, std::size_t)> data_cb;
typedef std::function<void(void)> void_cb; typedef std::function<void(void)> void_cb;
typedef std::function<void(const boost::system::error_code &ec)> error_cb; typedef std::function<void(const boost::system::error_code &ec)> error_cb;
@ -320,10 +329,8 @@ public:
void cancel() const; void cancel() const;
const std::string &method() const; const std::string &method() const;
const std::string &scheme() const;
const std::string &path() const; const uri_ref &uri() const;
const std::string &authority() const;
const std::string &host() const;
const header_map &header() const; const header_map &header() const;