asio: Add server::response::write_trailer()
This commit is contained in:
parent
5b5034f19c
commit
c976a0fcd1
|
@ -101,6 +101,30 @@ int main(int argc, char *argv[]) {
|
||||||
res.end("finally!\n");
|
res.end("finally!\n");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
server.handle("/trailer", [](const request &req, const response &res) {
|
||||||
|
// send trailer part.
|
||||||
|
res.write_head(200, {{"trailers", {"digest"}}});
|
||||||
|
|
||||||
|
std::string body = "nghttp2 FTW!\n";
|
||||||
|
auto left = std::make_shared<size_t>(body.size());
|
||||||
|
|
||||||
|
res.end([&res, body, left](uint8_t *dst, std::size_t len,
|
||||||
|
uint32_t *data_flags) {
|
||||||
|
auto n = std::min(len, *left);
|
||||||
|
std::copy_n(body.c_str() + (body.size() - *left), n, dst);
|
||||||
|
*left -= n;
|
||||||
|
if (*left == 0) {
|
||||||
|
*data_flags |=
|
||||||
|
NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
|
||||||
|
// RFC 3230 Instance Digests in HTTP. The digest value is
|
||||||
|
// SHA-256 message digest of body.
|
||||||
|
res.write_trailer(
|
||||||
|
{{"digest",
|
||||||
|
{"SHA-256=qqXqskW7F3ueBSvmZRCiSwl2ym4HRO0M/pvQCBlSDis="}}});
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
if (argc >= 6) {
|
if (argc >= 6) {
|
||||||
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
|
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
|
||||||
|
|
|
@ -359,6 +359,27 @@ int http2_handler::start_response(stream &strm) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int http2_handler::submit_trailer(stream &strm, header_map h) {
|
||||||
|
int rv;
|
||||||
|
auto nva = std::vector<nghttp2_nv>();
|
||||||
|
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.get_stream_id(), nva.data(),
|
||||||
|
nva.size());
|
||||||
|
|
||||||
|
if (rv != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
signal_write();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void http2_handler::enter_callback() {
|
void http2_handler::enter_callback() {
|
||||||
assert(!inside_callback_);
|
assert(!inside_callback_);
|
||||||
inside_callback_ = true;
|
inside_callback_ = true;
|
||||||
|
|
|
@ -70,6 +70,8 @@ public:
|
||||||
|
|
||||||
int start_response(stream &s);
|
int start_response(stream &s);
|
||||||
|
|
||||||
|
int submit_trailer(stream &s, header_map h);
|
||||||
|
|
||||||
void stream_error(int32_t stream_id, uint32_t error_code);
|
void stream_error(int32_t stream_id, uint32_t error_code);
|
||||||
|
|
||||||
void initiate_write();
|
void initiate_write();
|
||||||
|
|
|
@ -46,6 +46,10 @@ void response::end(std::string data) const { impl_->end(std::move(data)); }
|
||||||
|
|
||||||
void response::end(generator_cb cb) const { impl_->end(std::move(cb)); }
|
void response::end(generator_cb cb) const { impl_->end(std::move(cb)); }
|
||||||
|
|
||||||
|
void response::write_trailer(header_map h) const {
|
||||||
|
impl_->write_trailer(std::move(h));
|
||||||
|
}
|
||||||
|
|
||||||
void response::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); }
|
void response::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); }
|
||||||
|
|
||||||
void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); }
|
void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); }
|
||||||
|
|
|
@ -81,6 +81,11 @@ void response_impl::end(generator_cb cb) {
|
||||||
state_ = response_state::BODY_STARTED;
|
state_ = response_state::BODY_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void response_impl::write_trailer(header_map h) {
|
||||||
|
auto handler = strm_->handler();
|
||||||
|
handler->submit_trailer(*strm_, std::move(h));
|
||||||
|
}
|
||||||
|
|
||||||
void response_impl::start_response() {
|
void response_impl::start_response() {
|
||||||
auto handler = strm_->handler();
|
auto handler = strm_->handler();
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
void write_head(unsigned int status_code, header_map h = {});
|
void write_head(unsigned int status_code, header_map h = {});
|
||||||
void end(std::string data = "");
|
void end(std::string data = "");
|
||||||
void end(generator_cb cb);
|
void end(generator_cb cb);
|
||||||
|
void write_trailer(header_map h);
|
||||||
void on_close(close_cb cb);
|
void on_close(close_cb cb);
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,11 @@ public:
|
||||||
// call of end() is allowed.
|
// call of end() is allowed.
|
||||||
void end(generator_cb cb) const;
|
void end(generator_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 end() function.
|
||||||
|
void write_trailer(header_map h) const;
|
||||||
|
|
||||||
// Sets callback which is invoked when this request and response are
|
// Sets callback which is invoked when this request and response are
|
||||||
// finished. After the invocation of this callback, the application
|
// finished. After the invocation of this callback, the application
|
||||||
// must not access request and response object.
|
// must not access request and response object.
|
||||||
|
|
|
@ -76,6 +76,10 @@ template <typename F, typename... T> Defer<F, T...> defer(F &&f, T &&... t) {
|
||||||
return Defer<F, T...>(std::forward<F>(f), std::forward<T>(t)...);
|
return Defer<F, T...>(std::forward<F>(f), std::forward<T>(t)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, typename F> bool test_flags(T t, F flags) {
|
||||||
|
return (t & flags) == flags;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
||||||
#endif // TEMPLATE_H
|
#endif // TEMPLATE_H
|
||||||
|
|
Loading…
Reference in New Issue