diff --git a/src/asio_client_request.cc b/src/asio_client_request.cc index bf4ce0d6..1fa93ca2 100644 --- a/src/asio_client_request.cc +++ b/src/asio_client_request.cc @@ -38,6 +38,10 @@ request::request() : impl_(make_unique()) {} request::~request() {} +void request::write_trailer(header_map h) const { + impl_->write_trailer(std::move(h)); +} + void request::cancel(uint32_t error_code) const { impl_->cancel(error_code); } void request::on_response(response_cb cb) const { diff --git a/src/asio_client_request_impl.cc b/src/asio_client_request_impl.cc index 584a1396..5512c967 100644 --- a/src/asio_client_request_impl.cc +++ b/src/asio_client_request_impl.cc @@ -34,6 +34,11 @@ namespace client { request_impl::request_impl() : strm_(nullptr) {} +void request_impl::write_trailer(header_map h) { + auto sess = strm_->session(); + sess->write_trailer(*strm_, std::move(h)); +} + void request_impl::cancel(uint32_t error_code) { auto sess = strm_->session(); sess->cancel(*strm_, error_code); diff --git a/src/asio_client_request_impl.h b/src/asio_client_request_impl.h index f5d5249b..802a83d1 100644 --- a/src/asio_client_request_impl.h +++ b/src/asio_client_request_impl.h @@ -43,6 +43,8 @@ public: request_impl(const request_impl &) = delete; request_impl &operator=(const request_impl &) = delete; + void write_trailer(header_map h); + void cancel(uint32_t error_code); void on_response(response_cb cb); diff --git a/src/asio_client_session_impl.cc b/src/asio_client_session_impl.cc index e7a0197e..844b1957 100644 --- a/src/asio_client_session_impl.cc +++ b/src/asio_client_session_impl.cc @@ -330,6 +330,27 @@ bool session_impl::setup_session() { return true; } +int session_impl::write_trailer(stream &strm, header_map h) { + int rv; + auto nva = std::vector(); + nva.reserve(h.size()); + for (auto &hd : h) { + nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value, + hd.second.sensitive)); + } + + rv = nghttp2_submit_trailer(session_, strm.stream_id(), nva.data(), + nva.size()); + + if (rv != 0) { + return -1; + } + + signal_write(); + + return 0; +} + void session_impl::cancel(stream &strm, uint32_t error_code) { nghttp2_submit_rst_stream(session_, NGHTTP2_FLAG_NONE, strm.stream_id(), error_code); diff --git a/src/asio_client_session_impl.h b/src/asio_client_session_impl.h index c5c0e9ac..be77365b 100644 --- a/src/asio_client_session_impl.h +++ b/src/asio_client_session_impl.h @@ -55,6 +55,8 @@ public: const connect_cb &on_connect() const; const error_cb &on_error() const; + int write_trailer(stream &strm, header_map h); + void cancel(stream &strm, uint32_t error_code); void resume(stream &strm); diff --git a/src/includes/nghttp2/asio_http2_client.h b/src/includes/nghttp2/asio_http2_client.h index 5d5b2c2a..0f86af98 100644 --- a/src/includes/nghttp2/asio_http2_client.h +++ b/src/includes/nghttp2/asio_http2_client.h @@ -89,6 +89,12 @@ public: // must not access request and response object. void on_close(close_cb cb) const; + // Write trailer part. This must be called after setting both + // NGHTTP2_DATA_FLAG_EOF and NGHTTP2_DATA_FLAG_NO_END_STREAM set in + // *data_flag parameter in generator_cb passed to session::submit() + // function. + void write_trailer(header_map h) const; + // Cancels this request and response with given error code. void cancel(uint32_t error_code = NGHTTP2_INTERNAL_ERROR) const;