From 4c55a2340ba454b8d0565d14abf2ede7399fb731 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 7 Mar 2015 17:39:31 +0900 Subject: [PATCH] nghttp: Add --trailer optiont to send trailer header fields with -d option --- src/nghttp.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ src/nghttp.h | 1 + 2 files changed, 44 insertions(+) diff --git a/src/nghttp.cc b/src/nghttp.cc index cff6a84e..faa9c649 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -2110,6 +2110,7 @@ namespace { ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { + int rv; auto req = static_cast( nghttp2_session_get_stream_user_data(session, stream_id)); assert(req); @@ -2126,6 +2127,18 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id, if (nread == 0) { *data_flags |= NGHTTP2_DATA_FLAG_EOF; + if (!config.trailer.empty()) { + *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM; + std::vector nva; + nva.reserve(config.trailer.size()); + for (auto &kv : config.trailer) { + nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); + } + rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); + if (rv != 0) { + *data_flags &= ~NGHTTP2_DATA_FLAG_NO_END_STREAM; + } + } } else { req->data_offset += nread; } @@ -2347,6 +2360,11 @@ Options: -s, --stat Print statistics. -H, --header=
Add a header to the requests. Example: -H':method: PUT' + --trailer=
+ Add a trailer header to the requests.
must not + include pseudo header field (header field name starting + with ':'). To send trailer, one must use -d option to + send request body. Example: --trailer 'foo: bar'. --cert= Use the specified client certificate file. The file must be in PEM format. @@ -2425,6 +2443,7 @@ int main(int argc, char **argv) { {"no-content-length", no_argument, &flag, 6}, {"no-dep", no_argument, &flag, 7}, {"dep-idle", no_argument, &flag, 8}, + {"trailer", required_argument, &flag, 9}, {nullptr, 0, nullptr, 0}}; int option_index = 0; int c = getopt_long(argc, argv, "M:Oab:c:d:gm:np:r:hH:vst:uw:W:", @@ -2587,6 +2606,30 @@ int main(int argc, char **argv) { // dep-idle option config.dep_idle = true; break; + case 9: { + // trailer option + auto header = optarg; + auto value = strchr(optarg, ':'); + if (!value) { + std::cerr << "--trailer: invalid header: " << optarg << std::endl; + exit(EXIT_FAILURE); + } + *value = 0; + value++; + while (isspace(*value)) { + value++; + } + if (*value == 0) { + // This could also be a valid case for suppressing a header + // similar to curl + std::cerr << "--trailer: invalid header - value missing: " << optarg + << std::endl; + exit(EXIT_FAILURE); + } + config.trailer.emplace_back(header, value, false); + util::inp_strlower(config.trailer.back().name); + break; + } } break; default: diff --git a/src/nghttp.h b/src/nghttp.h index 3c8f8649..a4d85ef5 100644 --- a/src/nghttp.h +++ b/src/nghttp.h @@ -58,6 +58,7 @@ struct Config { ~Config(); Headers headers; + Headers trailer; std::string certfile; std::string keyfile; std::string datafile;