src: Store token in Header object to avoid additional lookups
This commit is contained in:
parent
8dd8d68b83
commit
b14cfaf308
|
@ -85,7 +85,7 @@ template <typename Array> void append_nv(Stream *stream, const Array &nva) {
|
||||||
http2::index_header(stream->hdidx, token, i);
|
http2::index_header(stream->hdidx, token, i);
|
||||||
}
|
}
|
||||||
http2::add_header(stream->headers, nv.name, nv.namelen, nv.value,
|
http2::add_header(stream->headers, nv.name, nv.namelen, nv.value,
|
||||||
nv.valuelen, nv.flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
nv.valuelen, nv.flags & NGHTTP2_NV_FLAG_NO_INDEX, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -1061,7 +1061,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
|
|
||||||
http2::index_header(stream->hdidx, token, stream->headers.size());
|
http2::index_header(stream->hdidx, token, stream->headers.size());
|
||||||
http2::add_header(stream->headers, name, namelen, value, valuelen,
|
http2::add_header(stream->headers, name, namelen, value, valuelen,
|
||||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
flags & NGHTTP2_NV_FLAG_NO_INDEX, token);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
36
src/http2.cc
36
src/http2.cc
|
@ -165,14 +165,15 @@ void copy_url_component(std::string &dest, const http_parser_url *u, int field,
|
||||||
|
|
||||||
Headers::value_type to_header(const uint8_t *name, size_t namelen,
|
Headers::value_type to_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
bool no_index) {
|
bool no_index, int16_t token) {
|
||||||
return Header(std::string(reinterpret_cast<const char *>(name), namelen),
|
return Header(std::string(reinterpret_cast<const char *>(name), namelen),
|
||||||
std::string(reinterpret_cast<const char *>(value), valuelen),
|
std::string(reinterpret_cast<const char *>(value), valuelen),
|
||||||
no_index);
|
no_index, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
|
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen, bool no_index) {
|
const uint8_t *value, size_t valuelen, bool no_index,
|
||||||
|
int16_t token) {
|
||||||
if (valuelen > 0) {
|
if (valuelen > 0) {
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
for (i = 0; i < valuelen && (value[i] == ' ' || value[i] == '\t'); ++i)
|
for (i = 0; i < valuelen && (value[i] == ' ' || value[i] == '\t'); ++i)
|
||||||
|
@ -182,7 +183,7 @@ void add_header(Headers &nva, const uint8_t *name, size_t namelen,
|
||||||
value += i;
|
value += i;
|
||||||
valuelen -= i + (valuelen - j - 1);
|
valuelen -= i + (valuelen - j - 1);
|
||||||
}
|
}
|
||||||
nva.push_back(to_header(name, namelen, value, valuelen, no_index));
|
nva.push_back(to_header(name, namelen, value, valuelen, no_index, token));
|
||||||
}
|
}
|
||||||
|
|
||||||
const Headers::value_type *get_header(const Headers &nva, const char *name) {
|
const Headers::value_type *get_header(const Headers &nva, const char *name) {
|
||||||
|
@ -221,7 +222,7 @@ void copy_headers_to_nva(std::vector<nghttp2_nv> &nva, const Headers &headers) {
|
||||||
if (kv.name.empty() || kv.name[0] == ':') {
|
if (kv.name.empty() || kv.name[0] == ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (lookup_token(kv.name)) {
|
switch (kv.token) {
|
||||||
case HD_COOKIE:
|
case HD_COOKIE:
|
||||||
case HD_CONNECTION:
|
case HD_CONNECTION:
|
||||||
case HD_HOST:
|
case HD_HOST:
|
||||||
|
@ -247,7 +248,7 @@ void build_http1_headers_from_headers(std::string &hdrs,
|
||||||
if (kv.name.empty() || kv.name[0] == ':') {
|
if (kv.name.empty() || kv.name[0] == ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (lookup_token(kv.name)) {
|
switch (kv.token) {
|
||||||
case HD_CONNECTION:
|
case HD_CONNECTION:
|
||||||
case HD_COOKIE:
|
case HD_COOKIE:
|
||||||
case HD_HOST:
|
case HD_HOST:
|
||||||
|
@ -608,18 +609,7 @@ void init_hdidx(HeaderIndex &hdidx) {
|
||||||
std::fill(std::begin(hdidx), std::end(hdidx), -1);
|
std::fill(std::begin(hdidx), std::end(hdidx), -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void index_headers(HeaderIndex &hdidx, const Headers &headers) {
|
void index_header(HeaderIndex &hdidx, int16_t token, size_t idx) {
|
||||||
for (size_t i = 0; i < headers.size(); ++i) {
|
|
||||||
auto &kv = headers[i];
|
|
||||||
auto token = lookup_token(
|
|
||||||
reinterpret_cast<const uint8_t *>(kv.name.c_str()), kv.name.size());
|
|
||||||
if (token >= 0) {
|
|
||||||
http2::index_header(hdidx, token, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void index_header(HeaderIndex &hdidx, int token, size_t idx) {
|
|
||||||
if (token == -1) {
|
if (token == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -627,7 +617,8 @@ void index_header(HeaderIndex &hdidx, int token, size_t idx) {
|
||||||
hdidx[token] = idx;
|
hdidx[token] = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_http2_request_pseudo_header(const HeaderIndex &hdidx, int token) {
|
bool check_http2_request_pseudo_header(const HeaderIndex &hdidx,
|
||||||
|
int16_t token) {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case HD__AUTHORITY:
|
case HD__AUTHORITY:
|
||||||
case HD__METHOD:
|
case HD__METHOD:
|
||||||
|
@ -639,7 +630,8 @@ bool check_http2_request_pseudo_header(const HeaderIndex &hdidx, int token) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_http2_response_pseudo_header(const HeaderIndex &hdidx, int token) {
|
bool check_http2_response_pseudo_header(const HeaderIndex &hdidx,
|
||||||
|
int16_t token) {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case HD__STATUS:
|
case HD__STATUS:
|
||||||
return hdidx[token] == -1;
|
return hdidx[token] == -1;
|
||||||
|
@ -648,7 +640,7 @@ bool check_http2_response_pseudo_header(const HeaderIndex &hdidx, int token) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http2_header_allowed(int token) {
|
bool http2_header_allowed(int16_t token) {
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case HD_CONNECTION:
|
case HD_CONNECTION:
|
||||||
case HD_KEEP_ALIVE:
|
case HD_KEEP_ALIVE:
|
||||||
|
@ -670,7 +662,7 @@ bool http2_mandatory_request_headers_presence(const HeaderIndex &hdidx) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Headers::value_type *get_header(const HeaderIndex &hdidx, int token,
|
const Headers::value_type *get_header(const HeaderIndex &hdidx, int16_t token,
|
||||||
const Headers &nva) {
|
const Headers &nva) {
|
||||||
auto i = hdidx[token];
|
auto i = hdidx[token];
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
|
|
39
src/http2.h
39
src/http2.h
|
@ -40,10 +40,12 @@
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
struct Header {
|
struct Header {
|
||||||
Header(std::string name, std::string value, bool no_index = false)
|
Header(std::string name, std::string value, bool no_index = false,
|
||||||
: name(std::move(name)), value(std::move(value)), no_index(no_index) {}
|
int16_t token = -1)
|
||||||
|
: name(std::move(name)), value(std::move(value)), token(token),
|
||||||
|
no_index(no_index) {}
|
||||||
|
|
||||||
Header() : no_index(false) {}
|
Header() : token(-1), no_index(false) {}
|
||||||
|
|
||||||
bool operator==(const Header &other) const {
|
bool operator==(const Header &other) const {
|
||||||
return name == other.name && value == other.value;
|
return name == other.name && value == other.value;
|
||||||
|
@ -55,6 +57,7 @@ struct Header {
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
int16_t token;
|
||||||
bool no_index;
|
bool no_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,13 +80,14 @@ void copy_url_component(std::string &dest, const http_parser_url *u, int field,
|
||||||
|
|
||||||
Headers::value_type to_header(const uint8_t *name, size_t namelen,
|
Headers::value_type to_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
bool no_index);
|
bool no_index, int16_t token);
|
||||||
|
|
||||||
// Add name/value pairs to |nva|. If |no_index| is true, this
|
// Add name/value pairs to |nva|. If |no_index| is true, this
|
||||||
// name/value pair won't be indexed when it is forwarded to the next
|
// name/value pair won't be indexed when it is forwarded to the next
|
||||||
// hop. This function strips white spaces around |value|.
|
// hop. This function strips white spaces around |value|.
|
||||||
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
|
void add_header(Headers &nva, const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen, bool no_index);
|
const uint8_t *value, size_t valuelen, bool no_index,
|
||||||
|
int16_t token);
|
||||||
|
|
||||||
// Returns pointer to the entry in |nva| which has name |name|. If
|
// Returns pointer to the entry in |nva| which has name |name|. If
|
||||||
// more than one entries which have the name |name|, last occurrence
|
// more than one entries which have the name |name|, last occurrence
|
||||||
|
@ -125,14 +129,16 @@ nghttp2_nv make_nv_ls(const char (&name)[N], const std::string &value) {
|
||||||
NGHTTP2_NV_FLAG_NONE};
|
NGHTTP2_NV_FLAG_NONE};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends headers in |headers| to |nv|. Certain headers, including
|
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
||||||
// disallowed headers in HTTP/2 spec and headers which require
|
// before this call (its element's token field is assigned). Certain
|
||||||
// special handling (i.e. via), are not copied.
|
// headers, including disallowed headers in HTTP/2 spec and headers
|
||||||
|
// which require special handling (i.e. via), are not copied.
|
||||||
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva, const Headers &headers);
|
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva, const Headers &headers);
|
||||||
|
|
||||||
// Appends HTTP/1.1 style header lines to |hdrs| from headers in
|
// Appends HTTP/1.1 style header lines to |hdrs| from headers in
|
||||||
// |headers|. Certain headers, which requires special handling
|
// |headers|. |headers| must be indexed before this call (its
|
||||||
// (i.e. via and cookie), are not appended.
|
// element's token field is assigned). Certain headers, which
|
||||||
|
// requires special handling (i.e. via and cookie), are not appended.
|
||||||
void build_http1_headers_from_headers(std::string &hdrs,
|
void build_http1_headers_from_headers(std::string &hdrs,
|
||||||
const Headers &headers);
|
const Headers &headers);
|
||||||
|
|
||||||
|
@ -226,28 +232,27 @@ int lookup_token(const std::string &name);
|
||||||
// array containing at least HD_MAXIDX elements.
|
// array containing at least HD_MAXIDX elements.
|
||||||
void init_hdidx(HeaderIndex &hdidx);
|
void init_hdidx(HeaderIndex &hdidx);
|
||||||
// Indexes header |token| using index |idx|.
|
// Indexes header |token| using index |idx|.
|
||||||
void index_header(HeaderIndex &hdidx, int token, size_t idx);
|
void index_header(HeaderIndex &hdidx, int16_t token, size_t idx);
|
||||||
// Iterates |headers| and for each element, call index_header.
|
|
||||||
void index_headers(HeaderIndex &hdidx, const Headers &headers);
|
|
||||||
|
|
||||||
// Returns true if HTTP/2 request pseudo header |token| is not indexed
|
// Returns true if HTTP/2 request pseudo header |token| is not indexed
|
||||||
// yet and not -1.
|
// yet and not -1.
|
||||||
bool check_http2_request_pseudo_header(const HeaderIndex &hdidx, int token);
|
bool check_http2_request_pseudo_header(const HeaderIndex &hdidx, int16_t token);
|
||||||
|
|
||||||
// Returns true if HTTP/2 response pseudo header |token| is not
|
// Returns true if HTTP/2 response pseudo header |token| is not
|
||||||
// indexed yet and not -1.
|
// indexed yet and not -1.
|
||||||
bool check_http2_response_pseudo_header(const HeaderIndex &hdidx, int token);
|
bool check_http2_response_pseudo_header(const HeaderIndex &hdidx,
|
||||||
|
int16_t token);
|
||||||
|
|
||||||
// Returns true if header field denoted by |token| is allowed for
|
// Returns true if header field denoted by |token| is allowed for
|
||||||
// HTTP/2.
|
// HTTP/2.
|
||||||
bool http2_header_allowed(int token);
|
bool http2_header_allowed(int16_t token);
|
||||||
|
|
||||||
// Returns true that |hdidx| contains mandatory HTTP/2 request
|
// Returns true that |hdidx| contains mandatory HTTP/2 request
|
||||||
// headers.
|
// headers.
|
||||||
bool http2_mandatory_request_headers_presence(const HeaderIndex &hdidx);
|
bool http2_mandatory_request_headers_presence(const HeaderIndex &hdidx);
|
||||||
|
|
||||||
// Returns header denoted by |token| using index |hdidx|.
|
// Returns header denoted by |token| using index |hdidx|.
|
||||||
const Headers::value_type *get_header(const HeaderIndex &hdidx, int token,
|
const Headers::value_type *get_header(const HeaderIndex &hdidx, int16_t token,
|
||||||
const Headers &nva);
|
const Headers &nva);
|
||||||
|
|
||||||
struct LinkHeader {
|
struct LinkHeader {
|
||||||
|
|
|
@ -58,46 +58,52 @@ void test_http2_add_header(void) {
|
||||||
auto nva = Headers();
|
auto nva = Headers();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3,
|
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"123", 3,
|
||||||
false);
|
false, -1);
|
||||||
CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]);
|
CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]);
|
||||||
CU_ASSERT(!nva[0].no_index);
|
CU_ASSERT(!nva[0].no_index);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0,
|
http2::add_header(nva, (const uint8_t *)"alpha", 5, (const uint8_t *)"", 0,
|
||||||
true);
|
true, -1);
|
||||||
CU_ASSERT(Headers::value_type("alpha", "") == nva[0]);
|
CU_ASSERT(Headers::value_type("alpha", "") == nva[0]);
|
||||||
CU_ASSERT(nva[0].no_index);
|
CU_ASSERT(nva[0].no_index);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2,
|
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b", 2,
|
||||||
false);
|
false, -1);
|
||||||
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2,
|
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)"b ", 2,
|
||||||
false);
|
false, -1);
|
||||||
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b ", 5,
|
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" b ", 5,
|
||||||
false);
|
false, -1);
|
||||||
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
CU_ASSERT(Headers::value_type("a", "b") == nva[0]);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" bravo ",
|
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" bravo ",
|
||||||
9, false);
|
9, false, -1);
|
||||||
CU_ASSERT(Headers::value_type("a", "bravo") == nva[0]);
|
CU_ASSERT(Headers::value_type("a", "bravo") == nva[0]);
|
||||||
|
|
||||||
nva.clear();
|
nva.clear();
|
||||||
|
|
||||||
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" ", 4,
|
http2::add_header(nva, (const uint8_t *)"a", 1, (const uint8_t *)" ", 4,
|
||||||
false);
|
false, -1);
|
||||||
CU_ASSERT(Headers::value_type("a", "") == nva[0]);
|
CU_ASSERT(Headers::value_type("a", "") == nva[0]);
|
||||||
|
|
||||||
|
nva.clear();
|
||||||
|
|
||||||
|
http2::add_header(nva, (const uint8_t *)"te", 2, (const uint8_t *)"trailers",
|
||||||
|
8, false, http2::HD_TE);
|
||||||
|
CU_ASSERT(http2::HD_TE == nva[0].token);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_http2_get_header(void) {
|
void test_http2_get_header(void) {
|
||||||
|
@ -128,19 +134,20 @@ void test_http2_get_header(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
auto headers = Headers{{"alpha", "0", true},
|
auto headers =
|
||||||
{"bravo", "1"},
|
Headers{{"alpha", "0", true},
|
||||||
{"connection", "2"},
|
{"bravo", "1"},
|
||||||
{"connection", "3"},
|
{"connection", "2", false, http2::HD_CONNECTION},
|
||||||
{"delta", "4"},
|
{"connection", "3", false, http2::HD_CONNECTION},
|
||||||
{"expect", "5"},
|
{"delta", "4"},
|
||||||
{"foxtrot", "6"},
|
{"expect", "5"},
|
||||||
{"tango", "7"},
|
{"foxtrot", "6"},
|
||||||
{"te", "8"},
|
{"tango", "7"},
|
||||||
{"te", "9"},
|
{"te", "8", false, http2::HD_TE},
|
||||||
{"x-forwarded-proto", "10"},
|
{"te", "9", false, http2::HD_TE},
|
||||||
{"x-forwarded-proto", "11"},
|
{"x-forwarded-proto", "10", false, http2::HD_X_FORWARDED_FOR},
|
||||||
{"zulu", "12"}};
|
{"x-forwarded-proto", "11", false, http2::HD_X_FORWARDED_FOR},
|
||||||
|
{"zulu", "12"}};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void test_http2_copy_headers_to_nva(void) {
|
void test_http2_copy_headers_to_nva(void) {
|
||||||
|
|
|
@ -250,7 +250,7 @@ bool Request::is_ipv6_literal_addr() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Request::response_pseudo_header_allowed(int token) const {
|
bool Request::response_pseudo_header_allowed(int16_t token) const {
|
||||||
if (!res_nva.empty() && res_nva.back().name.c_str()[0] != ':') {
|
if (!res_nva.empty() && res_nva.back().name.c_str()[0] != ':') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ bool Request::response_pseudo_header_allowed(int token) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Request::push_request_pseudo_header_allowed(int token) const {
|
bool Request::push_request_pseudo_header_allowed(int16_t token) const {
|
||||||
if (!req_nva.empty() && req_nva.back().name.c_str()[0] != ':') {
|
if (!req_nva.empty() && req_nva.back().name.c_str()[0] != ':') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ bool Request::push_request_pseudo_header_allowed(int token) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Headers::value_type *Request::get_res_header(int token) {
|
Headers::value_type *Request::get_res_header(int16_t token) {
|
||||||
auto idx = res_hdidx[token];
|
auto idx = res_hdidx[token];
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -285,7 +285,7 @@ Headers::value_type *Request::get_res_header(int token) {
|
||||||
return &res_nva[idx];
|
return &res_nva[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
Headers::value_type *Request::get_req_header(int token) {
|
Headers::value_type *Request::get_req_header(int16_t token) {
|
||||||
auto idx = req_hdidx[token];
|
auto idx = req_hdidx[token];
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1688,7 +1688,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
|
|
||||||
http2::index_header(req->res_hdidx, token, req->res_nva.size());
|
http2::index_header(req->res_hdidx, token, req->res_nva.size());
|
||||||
http2::add_header(req->res_nva, name, namelen, value, valuelen,
|
http2::add_header(req->res_nva, name, namelen, value, valuelen,
|
||||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
flags & NGHTTP2_NV_FLAG_NO_INDEX, token);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NGHTTP2_PUSH_PROMISE: {
|
case NGHTTP2_PUSH_PROMISE: {
|
||||||
|
@ -1712,7 +1712,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
|
|
||||||
http2::index_header(req->req_hdidx, token, req->req_nva.size());
|
http2::index_header(req->req_hdidx, token, req->req_nva.size());
|
||||||
http2::add_header(req->req_nva, name, namelen, value, valuelen,
|
http2::add_header(req->req_nva, name, namelen, value, valuelen,
|
||||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
flags & NGHTTP2_NV_FLAG_NO_INDEX, token);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,11 +122,11 @@ struct Request {
|
||||||
|
|
||||||
bool is_ipv6_literal_addr() const;
|
bool is_ipv6_literal_addr() const;
|
||||||
|
|
||||||
bool response_pseudo_header_allowed(int token) const;
|
bool response_pseudo_header_allowed(int16_t token) const;
|
||||||
bool push_request_pseudo_header_allowed(int token) const;
|
bool push_request_pseudo_header_allowed(int16_t token) const;
|
||||||
|
|
||||||
Headers::value_type *get_res_header(int token);
|
Headers::value_type *get_res_header(int16_t token);
|
||||||
Headers::value_type *get_req_header(int token);
|
Headers::value_type *get_req_header(int16_t token);
|
||||||
|
|
||||||
void record_request_time();
|
void record_request_time();
|
||||||
void record_response_time();
|
void record_response_time();
|
||||||
|
|
|
@ -300,6 +300,7 @@ int index_headers(http2::HeaderIndex &hdidx, Headers &headers,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kv.token = token;
|
||||||
http2::index_header(hdidx, token, i);
|
http2::index_header(hdidx, token, i);
|
||||||
|
|
||||||
if (token == http2::HD_CONTENT_LENGTH) {
|
if (token == http2::HD_CONTENT_LENGTH) {
|
||||||
|
@ -322,7 +323,7 @@ int Downstream::index_request_headers() {
|
||||||
request_content_length_);
|
request_content_length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Headers::value_type *Downstream::get_request_header(int token) const {
|
const Headers::value_type *Downstream::get_request_header(int16_t token) const {
|
||||||
return http2::get_header(request_hdidx_, token, request_headers_);
|
return http2::get_header(request_hdidx_, token, request_headers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +347,11 @@ void Downstream::set_last_request_header_value(std::string value) {
|
||||||
|
|
||||||
void Downstream::add_request_header(const uint8_t *name, size_t namelen,
|
void Downstream::add_request_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
bool no_index, int token) {
|
bool no_index, int16_t token) {
|
||||||
http2::index_header(request_hdidx_, token, request_headers_.size());
|
http2::index_header(request_hdidx_, token, request_headers_.size());
|
||||||
request_headers_sum_ += namelen + valuelen;
|
request_headers_sum_ += namelen + valuelen;
|
||||||
http2::add_header(request_headers_, name, namelen, value, valuelen, no_index);
|
http2::add_header(request_headers_, name, namelen, value, valuelen, no_index,
|
||||||
|
token);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Downstream::get_request_header_key_prev() const {
|
bool Downstream::get_request_header_key_prev() const {
|
||||||
|
@ -525,7 +527,8 @@ int Downstream::index_response_headers() {
|
||||||
response_content_length_);
|
response_content_length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Headers::value_type *Downstream::get_response_header(int token) const {
|
const Headers::value_type *
|
||||||
|
Downstream::get_response_header(int16_t token) const {
|
||||||
return http2::get_header(response_hdidx_, token, response_headers_);
|
return http2::get_header(response_hdidx_, token, response_headers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,13 +580,21 @@ void Downstream::set_last_response_header_value(std::string value) {
|
||||||
item.value = std::move(value);
|
item.value = std::move(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downstream::add_response_header(std::string name, std::string value,
|
||||||
|
int16_t token) {
|
||||||
|
http2::index_header(response_hdidx_, token, response_headers_.size());
|
||||||
|
response_headers_sum_ += name.size() + value.size();
|
||||||
|
response_headers_.emplace_back(std::move(name), std::move(value), false,
|
||||||
|
token);
|
||||||
|
}
|
||||||
|
|
||||||
void Downstream::add_response_header(const uint8_t *name, size_t namelen,
|
void Downstream::add_response_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen,
|
const uint8_t *value, size_t valuelen,
|
||||||
bool no_index, int token) {
|
bool no_index, int16_t token) {
|
||||||
http2::index_header(response_hdidx_, token, response_headers_.size());
|
http2::index_header(response_hdidx_, token, response_headers_.size());
|
||||||
response_headers_sum_ += namelen + valuelen;
|
response_headers_sum_ += namelen + valuelen;
|
||||||
http2::add_header(response_headers_, name, namelen, value, valuelen,
|
http2::add_header(response_headers_, name, namelen, value, valuelen, no_index,
|
||||||
no_index);
|
token);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Downstream::get_response_header_key_prev() const {
|
bool Downstream::get_response_header_key_prev() const {
|
||||||
|
@ -893,14 +904,14 @@ bool pseudo_header_allowed(const Headers &headers) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool Downstream::request_pseudo_header_allowed(int token) const {
|
bool Downstream::request_pseudo_header_allowed(int16_t token) const {
|
||||||
if (!pseudo_header_allowed(request_headers_)) {
|
if (!pseudo_header_allowed(request_headers_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return http2::check_http2_request_pseudo_header(request_hdidx_, token);
|
return http2::check_http2_request_pseudo_header(request_hdidx_, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Downstream::response_pseudo_header_allowed(int token) const {
|
bool Downstream::response_pseudo_header_allowed(int16_t token) const {
|
||||||
if (!pseudo_header_allowed(response_headers_)) {
|
if (!pseudo_header_allowed(response_headers_)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
// multiple header have |name| as name, return last occurrence from
|
// multiple header have |name| as name, return last occurrence from
|
||||||
// the beginning. If no such header is found, returns nullptr.
|
// the beginning. If no such header is found, returns nullptr.
|
||||||
// This function must be called after headers are indexed
|
// This function must be called after headers are indexed
|
||||||
const Headers::value_type *get_request_header(int token) const;
|
const Headers::value_type *get_request_header(int16_t token) const;
|
||||||
// Returns pointer to the request header with the name |name|. If
|
// Returns pointer to the request header with the name |name|. If
|
||||||
// no such header is found, returns nullptr.
|
// no such header is found, returns nullptr.
|
||||||
const Headers::value_type *get_request_header(const std::string &name) const;
|
const Headers::value_type *get_request_header(const std::string &name) const;
|
||||||
|
@ -117,7 +117,7 @@ public:
|
||||||
|
|
||||||
void add_request_header(const uint8_t *name, size_t namelen,
|
void add_request_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen, bool no_index,
|
const uint8_t *value, size_t valuelen, bool no_index,
|
||||||
int token);
|
int16_t token);
|
||||||
|
|
||||||
bool get_request_header_key_prev() const;
|
bool get_request_header_key_prev() const;
|
||||||
void append_last_request_header_key(const char *data, size_t len);
|
void append_last_request_header_key(const char *data, size_t len);
|
||||||
|
@ -165,7 +165,7 @@ public:
|
||||||
bool validate_request_bodylen() const;
|
bool validate_request_bodylen() const;
|
||||||
int64_t get_request_content_length() const;
|
int64_t get_request_content_length() const;
|
||||||
void set_request_content_length(int64_t len);
|
void set_request_content_length(int64_t len);
|
||||||
bool request_pseudo_header_allowed(int token) const;
|
bool request_pseudo_header_allowed(int16_t token) const;
|
||||||
bool expect_response_body() const;
|
bool expect_response_body() const;
|
||||||
enum {
|
enum {
|
||||||
INITIAL,
|
INITIAL,
|
||||||
|
@ -192,16 +192,17 @@ public:
|
||||||
// multiple header have |name| as name, return last occurrence from
|
// multiple header have |name| as name, return last occurrence from
|
||||||
// the beginning. If no such header is found, returns nullptr.
|
// the beginning. If no such header is found, returns nullptr.
|
||||||
// This function must be called after response headers are indexed.
|
// This function must be called after response headers are indexed.
|
||||||
const Headers::value_type *get_response_header(int token) const;
|
const Headers::value_type *get_response_header(int16_t token) const;
|
||||||
// Rewrites the location response header field.
|
// Rewrites the location response header field.
|
||||||
void rewrite_location_response_header(const std::string &upstream_scheme,
|
void rewrite_location_response_header(const std::string &upstream_scheme,
|
||||||
uint16_t upstream_port);
|
uint16_t upstream_port);
|
||||||
void add_response_header(std::string name, std::string value);
|
void add_response_header(std::string name, std::string value);
|
||||||
void set_last_response_header_value(std::string value);
|
void set_last_response_header_value(std::string value);
|
||||||
|
|
||||||
|
void add_response_header(std::string name, std::string value, int16_t token);
|
||||||
void add_response_header(const uint8_t *name, size_t namelen,
|
void add_response_header(const uint8_t *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen, bool no_index,
|
const uint8_t *value, size_t valuelen, bool no_index,
|
||||||
int token);
|
int16_t token);
|
||||||
|
|
||||||
bool get_response_header_key_prev() const;
|
bool get_response_header_key_prev() const;
|
||||||
void append_last_response_header_key(const char *data, size_t len);
|
void append_last_response_header_key(const char *data, size_t len);
|
||||||
|
@ -248,7 +249,7 @@ public:
|
||||||
void dec_response_datalen(size_t len);
|
void dec_response_datalen(size_t len);
|
||||||
size_t get_response_datalen() const;
|
size_t get_response_datalen() const;
|
||||||
void reset_response_datalen();
|
void reset_response_datalen();
|
||||||
bool response_pseudo_header_allowed(int token) const;
|
bool response_pseudo_header_allowed(int16_t token) const;
|
||||||
|
|
||||||
// Call this method when there is incoming data in downstream
|
// Call this method when there is incoming data in downstream
|
||||||
// connection.
|
// connection.
|
||||||
|
|
|
@ -823,7 +823,8 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream,
|
||||||
// Otherwise, use chunked encoding to keep upstream connection
|
// Otherwise, use chunked encoding to keep upstream connection
|
||||||
// open. In HTTP2, we are supporsed not to receive
|
// open. In HTTP2, we are supporsed not to receive
|
||||||
// transfer-encoding.
|
// transfer-encoding.
|
||||||
downstream->add_response_header("transfer-encoding", "chunked");
|
downstream->add_response_header("transfer-encoding", "chunked",
|
||||||
|
http2::HD_TRANSFER_ENCODING);
|
||||||
downstream->set_chunked_response(true);
|
downstream->set_chunked_response(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1521,8 +1521,7 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
|
||||||
baselen = 1;
|
baselen = 1;
|
||||||
}
|
}
|
||||||
for (auto &kv : downstream->get_response_headers()) {
|
for (auto &kv : downstream->get_response_headers()) {
|
||||||
auto token = http2::lookup_token(kv.name);
|
if (kv.token != http2::HD_LINK) {
|
||||||
if (token != http2::HD_LINK) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (auto &link :
|
for (auto &link :
|
||||||
|
@ -1588,8 +1587,7 @@ int Http2Upstream::submit_push_promise(const std::string &path,
|
||||||
std::vector<nghttp2_nv> nva;
|
std::vector<nghttp2_nv> nva;
|
||||||
nva.reserve(downstream->get_request_headers().size());
|
nva.reserve(downstream->get_request_headers().size());
|
||||||
for (auto &kv : downstream->get_request_headers()) {
|
for (auto &kv : downstream->get_request_headers()) {
|
||||||
auto token = http2::lookup_token(kv.name);
|
switch (kv.token) {
|
||||||
switch (token) {
|
|
||||||
case http2::HD__METHOD:
|
case http2::HD__METHOD:
|
||||||
// juse use "GET" for now
|
// juse use "GET" for now
|
||||||
nva.push_back(http2::make_nv_lc(":method", "GET"));
|
nva.push_back(http2::make_nv_lc(":method", "GET"));
|
||||||
|
|
|
@ -860,8 +860,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
if (hd.name.empty() || hd.name.c_str()[0] == ':') {
|
if (hd.name.empty() || hd.name.c_str()[0] == ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto token = http2::lookup_token(hd.name);
|
switch (hd.token) {
|
||||||
switch (token) {
|
|
||||||
case http2::HD_CONNECTION:
|
case http2::HD_CONNECTION:
|
||||||
case http2::HD_KEEP_ALIVE:
|
case http2::HD_KEEP_ALIVE:
|
||||||
case http2::HD_PROXY_CONNECTION:
|
case http2::HD_PROXY_CONNECTION:
|
||||||
|
|
Loading…
Reference in New Issue