Add http2::make_field family functions

http2::make_nv family functions are removed in favor of the new
function.
This commit is contained in:
Tatsuhiro Tsujikawa
2024-04-22 19:26:17 +09:00
parent dc969cc7f9
commit a7f588189f
7 changed files with 131 additions and 182 deletions

View File

@@ -924,29 +924,32 @@ int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
const std::string *content_type, const std::string *content_type,
nghttp2_data_provider2 *data_prd) { nghttp2_data_provider2 *data_prd) {
std::string last_modified_str; std::string last_modified_str;
auto nva = auto nva = std::to_array({
std::to_array({http2::make_nv_ls_nocopy(":status", status), http2::make_field(":status"_sr, status),
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), http2::make_field("server"_sr, NGHTTPD_SERVER),
http2::make_nv_ll("cache-control", "max-age=3600"), http2::make_field("cache-control"_sr, "max-age=3600"_sr),
http2::make_nv_ls("date", sessions_->get_cached_date()), http2::make_field_v("date"_sr, sessions_->get_cached_date()),
http2::make_nv_ll("", ""), http2::make_nv_ll("", ""), {},
http2::make_nv_ll("", ""), http2::make_nv_ll("", "")}); {},
{},
{},
});
size_t nvlen = 4; size_t nvlen = 4;
if (!get_config()->no_content_length) { if (!get_config()->no_content_length) {
nva[nvlen++] = http2::make_nv_ls_nocopy( nva[nvlen++] = http2::make_field(
"content-length", "content-length"_sr,
util::make_string_ref_uint(stream->balloc, file_length)); util::make_string_ref_uint(stream->balloc, file_length));
} }
if (last_modified != 0) { if (last_modified != 0) {
last_modified_str = util::http_date(last_modified); last_modified_str = util::http_date(last_modified);
nva[nvlen++] = http2::make_nv_ls("last-modified", last_modified_str); nva[nvlen++] = http2::make_field_v("last-modified"_sr, last_modified_str);
} }
if (content_type) { if (content_type) {
nva[nvlen++] = http2::make_nv_ls("content-type", *content_type); nva[nvlen++] = http2::make_field_v("content-type"_sr, *content_type);
} }
auto &trailer_names = get_config()->trailer_names; auto &trailer_names = get_config()->trailer_names;
if (!trailer_names.empty()) { if (!trailer_names.empty()) {
nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
} }
return nghttp2_submit_response2(session_, stream->stream_id, nva.data(), return nghttp2_submit_response2(session_, stream->stream_id, nva.data(),
nvlen, data_prd); nvlen, data_prd);
@@ -957,19 +960,20 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
nghttp2_data_provider2 *data_prd) { nghttp2_data_provider2 *data_prd) {
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
nva.reserve(4 + headers.size()); nva.reserve(4 + headers.size());
nva.push_back(http2::make_nv_ls_nocopy(":status", status)); nva.push_back(http2::make_field(":status"_sr, status));
nva.push_back(http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER)); nva.push_back(http2::make_field("server"_sr, NGHTTPD_SERVER));
nva.push_back(http2::make_nv_ls("date", sessions_->get_cached_date())); nva.push_back(http2::make_field_v("date"_sr, sessions_->get_cached_date()));
if (data_prd) { if (data_prd) {
auto &trailer_names = get_config()->trailer_names; auto &trailer_names = get_config()->trailer_names;
if (!trailer_names.empty()) { if (!trailer_names.empty()) {
nva.push_back(http2::make_nv_ls_nocopy("trailer", trailer_names)); nva.push_back(http2::make_field("trailer"_sr, trailer_names));
} }
} }
for (auto &nv : headers) { for (auto &nv : headers) {
nva.push_back(http2::make_nv_nocopy(nv.name, nv.value, nv.no_index)); nva.push_back(
http2::make_field(nv.name, nv.value, http2::no_index(nv.no_index)));
} }
int r = nghttp2_submit_response2(session_, stream_id, nva.data(), nva.size(), int r = nghttp2_submit_response2(session_, stream_id, nva.data(), nva.size(),
data_prd); data_prd);
@@ -978,17 +982,18 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id, int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
nghttp2_data_provider2 *data_prd) { nghttp2_data_provider2 *data_prd) {
auto nva = auto nva = std::to_array({
std::to_array({http2::make_nv_ls_nocopy(":status", status), http2::make_field(":status"_sr, status),
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER), http2::make_field("server"_sr, NGHTTPD_SERVER),
http2::make_nv_ls("date", sessions_->get_cached_date()), http2::make_field_v("date"_sr, sessions_->get_cached_date()),
http2::make_nv_ll("", "")}); {},
});
size_t nvlen = 3; size_t nvlen = 3;
if (data_prd) { if (data_prd) {
auto &trailer_names = get_config()->trailer_names; auto &trailer_names = get_config()->trailer_names;
if (!trailer_names.empty()) { if (!trailer_names.empty()) {
nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names); nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
} }
} }
@@ -998,7 +1003,7 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
int Http2Handler::submit_non_final_response(const std::string &status, int Http2Handler::submit_non_final_response(const std::string &status,
int32_t stream_id) { int32_t stream_id) {
auto nva = std::to_array({http2::make_nv_ls(":status", status)}); auto nva = std::to_array({http2::make_field_v(":status"_sr, status)});
return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr, return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr,
nva.data(), nva.size(), nullptr); nva.data(), nva.size(), nullptr);
} }
@@ -1013,10 +1018,10 @@ int Http2Handler::submit_push_promise(Stream *stream,
auto scheme = get_config()->no_tls ? "http"_sr : "https"_sr; auto scheme = get_config()->no_tls ? "http"_sr : "https"_sr;
auto nva = std::to_array({http2::make_nv_ll(":method", "GET"), auto nva = std::to_array({http2::make_field(":method"_sr, "GET"_sr),
http2::make_nv_ls_nocopy(":path", push_path), http2::make_field(":path"_sr, push_path),
http2::make_nv_ls_nocopy(":scheme", scheme), http2::make_field(":scheme"_sr, scheme),
http2::make_nv_ls_nocopy(":authority", authority)}); http2::make_field(":authority"_sr, authority)});
auto promised_stream_id = nghttp2_submit_push_promise( auto promised_stream_id = nghttp2_submit_push_promise(
session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(), session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(),
@@ -1103,7 +1108,8 @@ nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
std::vector<nghttp2_nv> nva; std::vector<nghttp2_nv> nva;
nva.reserve(config->trailer.size()); nva.reserve(config->trailer.size());
for (auto &kv : config->trailer) { for (auto &kv : config->trailer) {
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); nva.push_back(http2::make_field_nv(kv.name, kv.value,
http2::no_index(kv.no_index)));
} }
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
if (rv != 0) { if (rv != 0) {

View File

@@ -3068,15 +3068,15 @@ int main(int argc, char **argv) {
// 2 for :path, and possible content-length // 2 for :path, and possible content-length
nva.reserve(2 + shared_nva.size()); nva.reserve(2 + shared_nva.size());
nva.push_back(http2::make_nv_ls(":path", req)); nva.push_back(http2::make_field_v(":path"_sr, req));
for (auto &nv : shared_nva) { for (auto &nv : shared_nva) {
nva.push_back(http2::make_nv(nv.name, nv.value, false)); nva.push_back(http2::make_field_nv(nv.name, nv.value));
} }
if (!content_length_str.empty()) { if (!content_length_str.empty()) {
nva.push_back( nva.push_back(
http2::make_nv("content-length"_sr, StringRef{content_length_str})); http2::make_field_nv("content-length"_sr, content_length_str));
} }
config.nva.push_back(std::move(nva)); config.nva.push_back(std::move(nva));

View File

@@ -315,56 +315,6 @@ bool non_empty_value(const HeaderRefs::value_type *nv) {
return nv && !nv->value.empty(); return nv && !nv->value.empty();
} }
namespace {
nghttp2_nv make_nv_internal(const std::string &name, const std::string &value,
bool no_index, uint8_t nv_flags) {
uint8_t flags;
flags =
nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE);
return {(uint8_t *)name.c_str(), (uint8_t *)value.c_str(), name.size(),
value.size(), flags};
}
} // namespace
namespace {
nghttp2_nv make_nv_internal(const StringRef &name, const StringRef &value,
bool no_index, uint8_t nv_flags) {
uint8_t flags;
flags =
nv_flags | (no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE);
return {(uint8_t *)name.data(), (uint8_t *)value.data(), name.size(),
value.size(), flags};
}
} // namespace
nghttp2_nv make_nv(const std::string &name, const std::string &value,
bool no_index) {
return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE);
}
nghttp2_nv make_nv(const StringRef &name, const StringRef &value,
bool no_index) {
return make_nv_internal(name, value, no_index, NGHTTP2_NV_FLAG_NONE);
}
nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value,
bool no_index) {
return make_nv_internal(name, value, no_index,
NGHTTP2_NV_FLAG_NO_COPY_NAME |
NGHTTP2_NV_FLAG_NO_COPY_VALUE);
}
nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value,
bool no_index) {
return make_nv_internal(name, value, no_index,
NGHTTP2_NV_FLAG_NO_COPY_NAME |
NGHTTP2_NV_FLAG_NO_COPY_VALUE);
}
namespace { namespace {
void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva, void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers, uint8_t nv_flags, const HeaderRefs &headers, uint8_t nv_flags,
@@ -459,8 +409,8 @@ void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
it_via = it; it_via = it;
break; break;
} }
nva.push_back( nva.push_back(make_field_flags(kv->name, kv->value,
make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags)); nv_flags | http2::no_index(kv->no_index)));
} }
} }
} // namespace } // namespace

View File

@@ -132,60 +132,48 @@ const Headers::value_type *get_header(const Headers &nva, const char *name);
// Returns true if the value of |nv| is not empty. // Returns true if the value of |nv| is not empty.
bool non_empty_value(const HeaderRefs::value_type *nv); bool non_empty_value(const HeaderRefs::value_type *nv);
// Creates nghttp2_nv using |name| and |value| and returns it. The // Create nghttp2_nv from |name|, |value| and |flags|.
// returned value only references the data pointer to name.c_str() and inline nghttp2_nv make_field_flags(const StringRef &name,
// value.c_str(). If |no_index| is true, nghttp2_nv flags member has const StringRef &value,
// NGHTTP2_NV_FLAG_NO_INDEX flag set. uint8_t flags = NGHTTP2_NV_FLAG_NONE) {
nghttp2_nv make_nv(const std::string &name, const std::string &value, auto ns = as_uint8_span(std::span{name});
bool no_index = false); auto vs = as_uint8_span(std::span{value});
nghttp2_nv make_nv(const StringRef &name, const StringRef &value, return {const_cast<uint8_t *>(ns.data()), const_cast<uint8_t *>(vs.data()),
bool no_index = false); ns.size(), vs.size(), flags};
nghttp2_nv make_nv_nocopy(const std::string &name, const std::string &value,
bool no_index = false);
nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value,
bool no_index = false);
// Create nghttp2_nv from string literal |name| and |value|.
template <size_t N, size_t M>
constexpr nghttp2_nv make_nv_ll(const char (&name)[N], const char (&value)[M]) {
return {(uint8_t *)name, (uint8_t *)value, N - 1, M - 1,
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
} }
// Create nghttp2_nv from string literal |name| and c-string |value|. // Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2
template <size_t N> // library does not copy them.
nghttp2_nv make_nv_lc(const char (&name)[N], const char *value) { inline nghttp2_nv make_field(const StringRef &name, const StringRef &value,
return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), uint8_t flags = NGHTTP2_NV_FLAG_NONE) {
NGHTTP2_NV_FLAG_NO_COPY_NAME}; return make_field_flags(name, value,
static_cast<uint8_t>(NGHTTP2_NV_FLAG_NO_COPY_NAME |
NGHTTP2_NV_FLAG_NO_COPY_VALUE |
flags));
} }
template <size_t N> // Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2
nghttp2_nv make_nv_lc_nocopy(const char (&name)[N], const char *value) { // library copies |value| unless |flags| includes
return {(uint8_t *)name, (uint8_t *)value, N - 1, strlen(value), // NGHTTP2_NV_FLAG_NO_COPY_VALUE.
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; inline nghttp2_nv make_field_v(const StringRef &name, const StringRef &value,
uint8_t flags = NGHTTP2_NV_FLAG_NONE) {
return make_field_flags(
name, value, static_cast<uint8_t>(NGHTTP2_NV_FLAG_NO_COPY_NAME | flags));
} }
// Create nghttp2_nv from string literal |name| and std::string // Creates nghttp2_nv from |name|, |value| and |flags|. nghttp2
// |value|. // library copies |name| and |value| unless |flags| includes
template <size_t N> // NGHTTP2_NV_FLAG_NO_COPY_NAME or NGHTTP2_NV_FLAG_NO_COPY_VALUE.
nghttp2_nv make_nv_ls(const char (&name)[N], const std::string &value) { inline nghttp2_nv make_field_nv(const StringRef &name, const StringRef &value,
return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), uint8_t flags = NGHTTP2_NV_FLAG_NONE) {
NGHTTP2_NV_FLAG_NO_COPY_NAME}; return make_field_flags(name, value, flags);
} }
template <size_t N> // Returns NGHTTP2_NV_FLAG_NO_INDEX if |no_index| is true, otherwise
nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const std::string &value) { // NGHTTP2_NV_FLAG_NONE.
return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(), inline uint8_t no_index(bool no_index) {
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE}; return no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE;
}
template <size_t N>
nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const StringRef &value) {
return {(uint8_t *)name, (uint8_t *)value.data(), N - 1, value.size(),
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
} }
enum HeaderBuildOp { enum HeaderBuildOp {

View File

@@ -500,7 +500,8 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
nva.reserve(build_headers.size()); nva.reserve(build_headers.size());
for (auto &kv : build_headers) { for (auto &kv : build_headers) {
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); nva.push_back(
http2::make_field_nv(kv.name, kv.value, http2::no_index(kv.no_index)));
} }
auto method = http2::get_header(build_headers, ":method"); auto method = http2::get_header(build_headers, ":method");
@@ -515,7 +516,7 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
trailer_names += ", "; trailer_names += ", ";
trailer_names += config.trailer[i].name; trailer_names += config.trailer[i].name;
} }
nva.push_back(http2::make_nv_ls("trailer", trailer_names)); nva.push_back(http2::make_field_v("trailer"_sr, trailer_names));
} }
int32_t stream_id; int32_t stream_id;
@@ -2437,7 +2438,8 @@ nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
std::vector<nghttp2_nv> nva; std::vector<nghttp2_nv> nva;
nva.reserve(config.trailer.size()); nva.reserve(config.trailer.size());
for (auto &kv : config.trailer) { for (auto &kv : config.trailer) {
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); nva.push_back(http2::make_field_nv(kv.name, kv.value,
http2::no_index(kv.no_index)));
} }
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size()); rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
if (rv != 0) { if (rv != 0) {

View File

@@ -295,11 +295,11 @@ int Http2DownstreamConnection::push_request_headers() {
httpconf.add_request_headers.size()); httpconf.add_request_headers.size());
if (req.connect_proto == ConnectProto::WEBSOCKET) { if (req.connect_proto == ConnectProto::WEBSOCKET) {
nva.push_back(http2::make_nv_ll(":method", "CONNECT")); nva.push_back(http2::make_field(":method"_sr, "CONNECT"_sr));
nva.push_back(http2::make_nv_ll(":protocol", "websocket")); nva.push_back(http2::make_field(":protocol"_sr, "websocket"_sr));
} else { } else {
nva.push_back(http2::make_nv_ls_nocopy( nva.push_back(
":method", http2::to_method_string(req.method))); http2::make_field(":method"_sr, http2::to_method_string(req.method)));
} }
if (!req.regular_connect_method()) { if (!req.regular_connect_method()) {
@@ -309,24 +309,24 @@ int Http2DownstreamConnection::push_request_headers() {
assert(addr); assert(addr);
// We will handle more protocol scheme upgrade in the future. // We will handle more protocol scheme upgrade in the future.
if (addr->tls && addr->upgrade_scheme && req.scheme == "http") { if (addr->tls && addr->upgrade_scheme && req.scheme == "http") {
nva.push_back(http2::make_nv_ll(":scheme", "https")); nva.push_back(http2::make_field(":scheme"_sr, "https"_sr));
} else { } else {
nva.push_back(http2::make_nv_ls_nocopy(":scheme", req.scheme)); nva.push_back(http2::make_field(":scheme"_sr, req.scheme));
} }
if (req.method == HTTP_OPTIONS && req.path.empty()) { if (req.method == HTTP_OPTIONS && req.path.empty()) {
nva.push_back(http2::make_nv_ll(":path", "*")); nva.push_back(http2::make_field(":path"_sr, "*"_sr));
} else { } else {
nva.push_back(http2::make_nv_ls_nocopy(":path", req.path)); nva.push_back(http2::make_field(":path"_sr, req.path));
} }
if (!req.no_authority || req.connect_proto != ConnectProto::NONE) { if (!req.no_authority || req.connect_proto != ConnectProto::NONE) {
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); nva.push_back(http2::make_field(":authority"_sr, authority));
} else { } else {
nva.push_back(http2::make_nv_ls_nocopy("host", authority)); nva.push_back(http2::make_field("host"_sr, authority));
} }
} else { } else {
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); nva.push_back(http2::make_field(":authority"_sr, authority));
} }
auto &fwdconf = httpconf.forwarded; auto &fwdconf = httpconf.forwarded;
@@ -354,7 +354,7 @@ int Http2DownstreamConnection::push_request_headers() {
auto conn = handler->get_connection(); auto conn = handler->get_connection();
if (conn->tls.ssl && !SSL_is_init_finished(conn->tls.ssl)) { if (conn->tls.ssl && !SSL_is_init_finished(conn->tls.ssl)) {
nva.push_back(http2::make_nv_ll("early-data", "1")); nva.push_back(http2::make_field("early-data"_sr, "1"_sr));
} }
#endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL #endif // NGHTTP2_GENUINE_OPENSSL || NGHTTP2_OPENSSL_IS_BORINGSSL
@@ -381,10 +381,10 @@ int Http2DownstreamConnection::push_request_headers() {
} }
} }
nva.push_back(http2::make_nv_ls_nocopy("forwarded", value)); nva.push_back(http2::make_field("forwarded"_sr, value));
} }
} else if (fwd) { } else if (fwd) {
nva.push_back(http2::make_nv_ls_nocopy("forwarded", fwd->value)); nva.push_back(http2::make_field("forwarded"_sr, fwd->value));
} }
auto xff = xffconf.strip_incoming ? nullptr auto xff = xffconf.strip_incoming ? nullptr
@@ -398,9 +398,9 @@ int Http2DownstreamConnection::push_request_headers() {
} else { } else {
xff_value = addr; xff_value = addr;
} }
nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff_value)); nva.push_back(http2::make_field("x-forwarded-for"_sr, xff_value));
} else if (xff) { } else if (xff) {
nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-for", xff->value)); nva.push_back(http2::make_field("x-forwarded-for"_sr, xff->value));
} }
if (!config->http2_proxy && !req.regular_connect_method()) { if (!config->http2_proxy && !req.regular_connect_method()) {
@@ -416,16 +416,16 @@ int Http2DownstreamConnection::push_request_headers() {
} else { } else {
xfp_value = req.scheme; xfp_value = req.scheme;
} }
nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-proto", xfp_value)); nva.push_back(http2::make_field("x-forwarded-proto"_sr, xfp_value));
} else if (xfp) { } else if (xfp) {
nva.push_back(http2::make_nv_ls_nocopy("x-forwarded-proto", xfp->value)); nva.push_back(http2::make_field("x-forwarded-proto"_sr, xfp->value));
} }
} }
auto via = req.fs.header(http2::HD_VIA); auto via = req.fs.header(http2::HD_VIA);
if (httpconf.no_via) { if (httpconf.no_via) {
if (via) { if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); nva.push_back(http2::make_field("via"_sr, (*via).value));
} }
} else { } else {
size_t vialen = 16; size_t vialen = 16;
@@ -443,8 +443,8 @@ int Http2DownstreamConnection::push_request_headers() {
p = http::create_via_header_value(p, req.http_major, req.http_minor); p = http::create_via_header_value(p, req.http_major, req.http_minor);
*p = '\0'; *p = '\0';
nva.push_back(http2::make_nv_ls_nocopy( nva.push_back(
"via", StringRef{std::span{std::begin(iov), p}})); http2::make_field("via"_sr, StringRef{std::span{std::begin(iov), p}}));
} }
auto te = req.fs.header(http2::HD_TE); auto te = req.fs.header(http2::HD_TE);
@@ -452,11 +452,11 @@ int Http2DownstreamConnection::push_request_headers() {
// "trailers". We just forward "trailers". // "trailers". We just forward "trailers".
// TODO more strict handling required here. // TODO more strict handling required here.
if (te && http2::contains_trailers(te->value)) { if (te && http2::contains_trailers(te->value)) {
nva.push_back(http2::make_nv_ll("te", "trailers")); nva.push_back(http2::make_field("te"_sr, "trailers"_sr));
} }
for (auto &p : httpconf.add_request_headers) { for (auto &p : httpconf.add_request_headers) {
nva.push_back(http2::make_nv_nocopy(p.name, p.value)); nva.push_back(http2::make_field(p.name, p.value));
} }
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {

View File

@@ -1535,7 +1535,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
auto response_status = http2::stringify_status(balloc, resp.http_status); auto response_status = http2::stringify_status(balloc, resp.http_status);
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); nva.push_back(http2::make_field(":status"_sr, response_status));
for (auto &kv : headers) { for (auto &kv : headers) {
if (kv.name.empty() || kv.name[0] == ':') { if (kv.name.empty() || kv.name[0] == ':') {
@@ -1550,15 +1550,16 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
case http2::HD_UPGRADE: case http2::HD_UPGRADE:
continue; continue;
} }
nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); nva.push_back(
http2::make_field(kv.name, kv.value, http2::no_index(kv.no_index)));
} }
if (!resp.fs.header(http2::HD_SERVER)) { if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back(http2::make_nv_ls_nocopy("server", config->http.server_name)); nva.push_back(http2::make_field("server"_sr, config->http.server_name));
} }
for (auto &p : httpconf.add_response_headers) { for (auto &p : httpconf.add_response_headers) {
nva.push_back(http2::make_nv_nocopy(p.name, p.value)); nva.push_back(http2::make_field(p.name, p.value));
} }
rv = nghttp2_submit_response2(session_, downstream->get_stream_id(), rv = nghttp2_submit_response2(session_, downstream->get_stream_id(),
@@ -1612,11 +1613,11 @@ int Http2Upstream::error_reply(Downstream *downstream,
auto date = make_string_ref(balloc, lgconf->tstamp->time_http); auto date = make_string_ref(balloc, lgconf->tstamp->time_http);
auto nva = std::to_array( auto nva = std::to_array(
{http2::make_nv_ls_nocopy(":status", response_status), {http2::make_field(":status"_sr, response_status),
http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), http2::make_field("content-type"_sr, "text/html; charset=UTF-8"_sr),
http2::make_nv_ls_nocopy("server", get_config()->http.server_name), http2::make_field("server"_sr, get_config()->http.server_name),
http2::make_nv_ls_nocopy("content-length", content_length), http2::make_field("content-length"_sr, content_length),
http2::make_nv_ls_nocopy("date", date)}); http2::make_field("date"_sr, date)});
rv = nghttp2_submit_response2(session_, downstream->get_stream_id(), rv = nghttp2_submit_response2(session_, downstream->get_stream_id(),
nva.data(), nva.size(), data_prd_ptr); nva.data(), nva.size(), data_prd_ptr);
@@ -1758,7 +1759,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
if (downstream->get_non_final_response()) { if (downstream->get_non_final_response()) {
auto response_status = http2::stringify_status(balloc, resp.http_status); auto response_status = http2::stringify_status(balloc, resp.http_status);
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); nva.push_back(http2::make_field(":status"_sr, response_status));
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(),
http2::HDOP_STRIP_ALL); http2::HDOP_STRIP_ALL);
@@ -1791,16 +1792,16 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
response_status = http2::stringify_status(balloc, resp.http_status); response_status = http2::stringify_status(balloc, resp.http_status);
} }
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status)); nva.push_back(http2::make_field(":status"_sr, response_status));
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), striphd_flags); http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers(), striphd_flags);
if (!config->http2_proxy && !httpconf.no_server_rewrite) { if (!config->http2_proxy && !httpconf.no_server_rewrite) {
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name)); nva.push_back(http2::make_field("server"_sr, httpconf.server_name));
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
if (server) { if (server) {
nva.push_back(http2::make_nv_ls_nocopy("server", (*server).value)); nva.push_back(http2::make_field("server"_sr, (*server).value));
} }
} }
@@ -1816,22 +1817,22 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
http::require_cookie_secure_attribute(cookieconf.secure, req.scheme); http::require_cookie_secure_attribute(cookieconf.secure, req.scheme);
auto cookie_str = http::create_affinity_cookie( auto cookie_str = http::create_affinity_cookie(
balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure); balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure);
nva.push_back(http2::make_nv_ls_nocopy("set-cookie", cookie_str)); nva.push_back(http2::make_field("set-cookie"_sr, cookie_str));
} }
} }
if (!resp.fs.header(http2::HD_ALT_SVC)) { if (!resp.fs.header(http2::HD_ALT_SVC)) {
// We won't change or alter alt-svc from backend for now // We won't change or alter alt-svc from backend for now
if (!httpconf.http2_altsvc_header_value.empty()) { if (!httpconf.http2_altsvc_header_value.empty()) {
nva.push_back(http2::make_nv_ls_nocopy( nva.push_back(
"alt-svc", httpconf.http2_altsvc_header_value)); http2::make_field("alt-svc"_sr, httpconf.http2_altsvc_header_value));
} }
} }
auto via = resp.fs.header(http2::HD_VIA); auto via = resp.fs.header(http2::HD_VIA);
if (httpconf.no_via) { if (httpconf.no_via) {
if (via) { if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value)); nva.push_back(http2::make_field("via"_sr, (*via).value));
} }
} else { } else {
// we don't create more than 16 bytes in // we don't create more than 16 bytes in
@@ -1850,18 +1851,18 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
p = http::create_via_header_value(p, resp.http_major, resp.http_minor); p = http::create_via_header_value(p, resp.http_major, resp.http_minor);
*p = '\0'; *p = '\0';
nva.push_back(http2::make_nv_ls_nocopy( nva.push_back(
"via", StringRef{std::span{std::begin(iov), p}})); http2::make_field("via"_sr, StringRef{std::span{std::begin(iov), p}}));
} }
for (auto &p : httpconf.add_response_headers) { for (auto &p : httpconf.add_response_headers) {
nva.push_back(http2::make_nv_nocopy(p.name, p.value)); nva.push_back(http2::make_field(p.name, p.value));
} }
if (downstream->get_stream_id() % 2 == 0) { if (downstream->get_stream_id() % 2 == 0) {
// This header field is basically for human on client side to // This header field is basically for human on client side to
// figure out that the resource is pushed. // figure out that the resource is pushed.
nva.push_back(http2::make_nv_ll("x-http2-push", "1")); nva.push_back(http2::make_field("x-http2-push"_sr, "1"_sr));
} }
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@@ -2225,10 +2226,10 @@ int Http2Upstream::submit_push_promise(const StringRef &scheme,
nva.reserve(4 + req.fs.headers().size()); nva.reserve(4 + req.fs.headers().size());
// just use "GET" for now // just use "GET" for now
nva.push_back(http2::make_nv_ll(":method", "GET")); nva.push_back(http2::make_field(":method"_sr, "GET"_sr));
nva.push_back(http2::make_nv_ls_nocopy(":scheme", scheme)); nva.push_back(http2::make_field(":scheme"_sr, scheme));
nva.push_back(http2::make_nv_ls_nocopy(":path", path)); nva.push_back(http2::make_field(":path"_sr, path));
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority)); nva.push_back(http2::make_field(":authority"_sr, authority));
for (auto &kv : req.fs.headers()) { for (auto &kv : req.fs.headers()) {
switch (kv.token) { switch (kv.token) {
@@ -2243,7 +2244,8 @@ int Http2Upstream::submit_push_promise(const StringRef &scheme,
case http2::HD_CACHE_CONTROL: case http2::HD_CACHE_CONTROL:
case http2::HD_HOST: case http2::HD_HOST:
case http2::HD_USER_AGENT: case http2::HD_USER_AGENT:
nva.push_back(http2::make_nv_nocopy(kv.name, kv.value, kv.no_index)); nva.push_back(
http2::make_field(kv.name, kv.value, http2::no_index(kv.no_index)));
break; break;
} }
} }
@@ -2387,7 +2389,8 @@ int Http2Upstream::on_downstream_push_promise_complete(
nva.reserve(headers.size()); nva.reserve(headers.size());
for (auto &kv : headers) { for (auto &kv : headers) {
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); nva.push_back(
http2::make_field_nv(kv.name, kv.value, http2::no_index(kv.no_index)));
} }
auto promised_stream_id = nghttp2_submit_push_promise( auto promised_stream_id = nghttp2_submit_push_promise(