Don't index name/value pair bearing NO_INDEX flag when forwarding it
This commit is contained in:
parent
c53c1dc669
commit
b1edb1f3ae
|
@ -1342,6 +1342,10 @@ typedef int (*nghttp2_on_begin_headers_callback)
|
|||
* The |value| of length |valuelen| is header value. The |flags| is
|
||||
* bitwise OR of one or more of :type:`nghttp2_nv_flag`.
|
||||
*
|
||||
* If :enum:`NGHTTP2_NV_FLAG_NO_INDEX` is set in |flags|, the receiver
|
||||
* must not index this name/value pair when forwarding it to the next
|
||||
* hop.
|
||||
*
|
||||
* When this callback is invoked, ``frame->hd.type`` is either
|
||||
* :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`. After all
|
||||
* header name/value pairs are processed with this callback, and no
|
||||
|
|
|
@ -805,7 +805,7 @@ int Http2Handler::submit_response
|
|||
http2::make_nv_ls("date", date_str)
|
||||
};
|
||||
for(size_t i = 0; i < headers.size(); ++i) {
|
||||
nva.push_back(http2::make_nv(headers[i].first, headers[i].second));
|
||||
nva.push_back(http2::make_nv(headers[i].first, headers[i].second, false));
|
||||
}
|
||||
int r = nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(),
|
||||
data_prd);
|
||||
|
@ -830,21 +830,21 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
|||
std::string authority;
|
||||
auto itr = std::lower_bound(std::begin(stream->headers),
|
||||
std::end(stream->headers),
|
||||
std::make_pair(std::string(":authority"),
|
||||
std::string("")));
|
||||
if(itr == std::end(stream->headers) || (*itr).first != ":authority") {
|
||||
Header(":authority", ""));
|
||||
|
||||
if(itr == std::end(stream->headers) || (*itr).name != ":authority") {
|
||||
itr = std::lower_bound(std::begin(stream->headers),
|
||||
std::end(stream->headers),
|
||||
std::make_pair(std::string("host"),
|
||||
std::string("")));
|
||||
Header("host", ""));
|
||||
}
|
||||
|
||||
auto nva = std::vector<nghttp2_nv>{
|
||||
http2::make_nv_ll(":method", "GET"),
|
||||
http2::make_nv_ls(":path", push_path),
|
||||
get_config()->no_tls ?
|
||||
http2::make_nv_ll(":scheme", "http") :
|
||||
http2::make_nv_ll(":scheme", "https"),
|
||||
http2::make_nv_ls(":authority", (*itr).second)
|
||||
http2::make_nv_ls(":authority", (*itr).value)
|
||||
};
|
||||
return nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_END_HEADERS,
|
||||
stream->stream_id, nva.data(), nva.size(),
|
||||
|
@ -1008,18 +1008,17 @@ void prepare_response(Stream *stream, Http2Handler *hd, bool allow_push = true)
|
|||
int rv;
|
||||
auto url = (*std::lower_bound(std::begin(stream->headers),
|
||||
std::end(stream->headers),
|
||||
std::make_pair(std::string(":path"),
|
||||
std::string()))).second;
|
||||
Header(":path", ""))).value;
|
||||
auto ims = std::lower_bound(std::begin(stream->headers),
|
||||
std::end(stream->headers),
|
||||
std::make_pair(std::string("if-modified-since"),
|
||||
std::string()));
|
||||
Header("if-modified-since", ""));
|
||||
|
||||
time_t last_mod = 0;
|
||||
bool last_mod_found = false;
|
||||
if(ims != std::end(stream->headers) &&
|
||||
(*ims).first == "if-modified-since") {
|
||||
(*ims).name == "if-modified-since") {
|
||||
last_mod_found = true;
|
||||
last_mod = util::parse_http_date((*ims).second);
|
||||
last_mod = util::parse_http_date((*ims).value);
|
||||
}
|
||||
auto query_pos = url.find("?");
|
||||
if(query_pos != std::string::npos) {
|
||||
|
@ -1078,7 +1077,8 @@ void append_nv(Stream *stream, const std::vector<nghttp2_nv>& nva)
|
|||
{
|
||||
for(auto& nv : nva) {
|
||||
http2::split_add_header(stream->headers,
|
||||
nv.name, nv.namelen, nv.value, nv.valuelen);
|
||||
nv.name, nv.namelen, nv.value, nv.valuelen,
|
||||
nv.flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
@ -1114,7 +1114,8 @@ int on_header_callback(nghttp2_session *session,
|
|||
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||
return 0;
|
||||
}
|
||||
http2::split_add_header(stream->headers, name, namelen, value, valuelen);
|
||||
http2::split_add_header(stream->headers, name, namelen, value, valuelen,
|
||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
|
|
@ -792,7 +792,7 @@ int main(int argc, char **argv)
|
|||
nva.push_back(http2::make_nv_ls(":path", req));
|
||||
|
||||
for(auto& nv : shared_nva) {
|
||||
nva.push_back(http2::make_nv(nv.first, nv.second));
|
||||
nva.push_back(http2::make_nv(nv.name, nv.value, false));
|
||||
}
|
||||
|
||||
config.nva.push_back(std::move(nva));
|
||||
|
@ -804,12 +804,12 @@ int main(int argc, char **argv)
|
|||
cva.push_back(req.c_str());
|
||||
|
||||
for(auto& nv : shared_nva) {
|
||||
if(nv.first == ":authority") {
|
||||
if(nv.name == ":authority") {
|
||||
cva.push_back(":host");
|
||||
} else {
|
||||
cva.push_back(nv.first.c_str());
|
||||
cva.push_back(nv.name.c_str());
|
||||
}
|
||||
cva.push_back(nv.second.c_str());
|
||||
cva.push_back(nv.value.c_str());
|
||||
}
|
||||
cva.push_back(":version");
|
||||
cva.push_back("HTTP/1.1");
|
||||
|
|
101
src/http2.cc
101
src/http2.cc
|
@ -206,14 +206,14 @@ auto nv_name_less = [](const nghttp2_nv& lhs, const nghttp2_nv& rhs)
|
|||
bool name_less(const Headers::value_type& lhs,
|
||||
const Headers::value_type& rhs)
|
||||
{
|
||||
return lhs.first < rhs.first;
|
||||
return lhs.name < rhs.name;
|
||||
}
|
||||
|
||||
bool check_http2_headers(const Headers& nva)
|
||||
{
|
||||
for(size_t i = 0; i < DISALLOWED_HDLEN; ++i) {
|
||||
if(std::binary_search(std::begin(nva), std::end(nva),
|
||||
std::make_pair(DISALLOWED_HD[i], ""), name_less)) {
|
||||
Header(DISALLOWED_HD[i], ""), name_less)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ bool check_http2_headers(const Headers& nva)
|
|||
void normalize_headers(Headers& nva)
|
||||
{
|
||||
for(auto& kv : nva) {
|
||||
util::inp_strlower(kv.first);
|
||||
util::inp_strlower(kv.name);
|
||||
}
|
||||
std::stable_sort(std::begin(nva), std::end(nva), name_less);
|
||||
}
|
||||
|
@ -260,20 +260,23 @@ std::vector<nghttp2_nv> sort_nva(const nghttp2_nv *nva, size_t nvlen)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return std::make_pair(std::string(reinterpret_cast<const char*>(name),
|
||||
namelen),
|
||||
std::string(reinterpret_cast<const char*>(value),
|
||||
valuelen));
|
||||
return Header(std::string(reinterpret_cast<const char*>(name),
|
||||
namelen),
|
||||
std::string(reinterpret_cast<const char*>(value),
|
||||
valuelen),
|
||||
no_index);
|
||||
}
|
||||
|
||||
void split_add_header(Headers& nva,
|
||||
const uint8_t *name, size_t namelen,
|
||||
const uint8_t *value, size_t valuelen)
|
||||
const uint8_t *value, size_t valuelen,
|
||||
bool no_index)
|
||||
{
|
||||
if(valuelen == 0) {
|
||||
nva.push_back(to_header(name, namelen, value, valuelen));
|
||||
nva.push_back(to_header(name, namelen, value, valuelen, no_index));
|
||||
return;
|
||||
}
|
||||
auto j = value;
|
||||
|
@ -289,7 +292,7 @@ void split_add_header(Headers& nva,
|
|||
break;
|
||||
}
|
||||
auto l = std::find(j, end, '\0');
|
||||
nva.push_back(to_header(name, namelen, j, l-j));
|
||||
nva.push_back(to_header(name, namelen, j, l-j, no_index));
|
||||
j = l;
|
||||
}
|
||||
}
|
||||
|
@ -299,9 +302,9 @@ const Headers::value_type* get_unique_header(const Headers& nva,
|
|||
{
|
||||
auto nv = Headers::value_type(name, "");
|
||||
auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less);
|
||||
if(i != std::end(nva) && (*i).first == nv.first) {
|
||||
if(i != std::end(nva) && (*i).name == nv.name) {
|
||||
auto j = i + 1;
|
||||
if(j == std::end(nva) || (*j).first != nv.first) {
|
||||
if(j == std::end(nva) || (*j).name != nv.name) {
|
||||
return &(*i);
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +315,7 @@ const Headers::value_type* get_header(const Headers& nva, const char *name)
|
|||
{
|
||||
auto nv = Headers::value_type(name, "");
|
||||
auto i = std::lower_bound(std::begin(nva), std::end(nva), nv, name_less);
|
||||
if(i != std::end(nva) && (*i).first == nv.first) {
|
||||
if(i != std::end(nva) && (*i).name == nv.name) {
|
||||
return &(*i);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -321,14 +324,14 @@ const Headers::value_type* get_header(const Headers& nva, const char *name)
|
|||
std::string value_to_str(const Headers::value_type *nv)
|
||||
{
|
||||
if(nv) {
|
||||
return nv->second;
|
||||
return nv->value;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool value_lws(const Headers::value_type *nv)
|
||||
{
|
||||
return (*nv).second.find_first_not_of("\t ") == std::string::npos;
|
||||
return (*nv).value.find_first_not_of("\t ") == std::string::npos;
|
||||
}
|
||||
|
||||
bool non_empty_value(const Headers::value_type *nv)
|
||||
|
@ -336,13 +339,18 @@ bool non_empty_value(const Headers::value_type *nv)
|
|||
return nv && !value_lws(nv);
|
||||
}
|
||||
|
||||
nghttp2_nv make_nv(const std::string& name, const std::string& value)
|
||||
nghttp2_nv make_nv(const std::string& name, const std::string& value,
|
||||
bool no_index)
|
||||
{
|
||||
uint8_t flags;
|
||||
|
||||
flags = no_index ? NGHTTP2_NV_FLAG_NO_INDEX : NGHTTP2_NV_FLAG_NONE;
|
||||
|
||||
return {
|
||||
(uint8_t*)name.c_str(),
|
||||
(uint8_t*)value.c_str(),
|
||||
(uint16_t)name.size(), (uint16_t)value.size(),
|
||||
NGHTTP2_NV_FLAG_NONE
|
||||
flags
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -351,12 +359,17 @@ Headers concat_norm_headers(Headers headers)
|
|||
auto res = Headers();
|
||||
res.reserve(headers.size());
|
||||
for(auto& kv : headers) {
|
||||
if(!res.empty() && res.back().first == kv.first &&
|
||||
kv.first != "cookie" && kv.first != "set-cookie") {
|
||||
if(!kv.second.empty()) {
|
||||
res.back().second.append(1, '\0');
|
||||
res.back().second += kv.second;
|
||||
if(!res.empty() && res.back().name == kv.name &&
|
||||
kv.name != "cookie" && kv.name != "set-cookie") {
|
||||
|
||||
auto& last = res.back();
|
||||
|
||||
if(!kv.value.empty()) {
|
||||
last.value.append(1, '\0');
|
||||
last.value += kv.value;
|
||||
}
|
||||
// We do ORing nv flags. This is done even if value is empty.
|
||||
last.no_index |= kv.no_index;
|
||||
} else {
|
||||
res.push_back(std::move(kv));
|
||||
}
|
||||
|
@ -369,10 +382,11 @@ void copy_norm_headers_to_nva
|
|||
{
|
||||
size_t i, j;
|
||||
for(i = 0, j = 0; i < headers.size() && j < IGN_HDLEN;) {
|
||||
int rv = strcmp(headers[i].first.c_str(), IGN_HD[j]);
|
||||
auto& kv = headers[i];
|
||||
int rv = strcmp(kv.name.c_str(), IGN_HD[j]);
|
||||
if(rv < 0) {
|
||||
if(!headers[i].first.empty() && headers[i].first.c_str()[0] != ':') {
|
||||
nva.push_back(make_nv(headers[i].first, headers[i].second));
|
||||
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
|
||||
nva.push_back(make_nv(kv.name, kv.value, kv.no_index));
|
||||
}
|
||||
++i;
|
||||
} else if(rv > 0) {
|
||||
|
@ -382,8 +396,9 @@ void copy_norm_headers_to_nva
|
|||
}
|
||||
}
|
||||
for(; i < headers.size(); ++i) {
|
||||
if(!headers[i].first.empty() && headers[i].first.c_str()[0] != ':') {
|
||||
nva.push_back(make_nv(headers[i].first, headers[i].second));
|
||||
auto& kv = headers[i];
|
||||
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
|
||||
nva.push_back(make_nv(kv.name, kv.value, kv.no_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -393,14 +408,16 @@ void build_http1_headers_from_norm_headers
|
|||
{
|
||||
size_t i, j;
|
||||
for(i = 0, j = 0; i < headers.size() && j < HTTP1_IGN_HDLEN;) {
|
||||
int rv = strcmp(headers[i].first.c_str(), HTTP1_IGN_HD[j]);
|
||||
auto& kv = headers[i];
|
||||
auto rv = strcmp(kv.name.c_str(), HTTP1_IGN_HD[j]);
|
||||
|
||||
if(rv < 0) {
|
||||
if(!headers[i].first.empty() && headers[i].first.c_str()[0] != ':') {
|
||||
hdrs += headers[i].first;
|
||||
capitalize(hdrs, hdrs.size()-headers[i].first.size());
|
||||
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
|
||||
hdrs += kv.name;
|
||||
capitalize(hdrs, hdrs.size() - kv.name.size());
|
||||
hdrs += ": ";
|
||||
hdrs += headers[i].second;
|
||||
sanitize_header_value(hdrs, hdrs.size() - headers[i].second.size());
|
||||
hdrs += kv.value;
|
||||
sanitize_header_value(hdrs, hdrs.size() - kv.value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
++i;
|
||||
|
@ -411,12 +428,14 @@ void build_http1_headers_from_norm_headers
|
|||
}
|
||||
}
|
||||
for(; i < headers.size(); ++i) {
|
||||
if(!headers[i].first.empty() && headers[i].first.c_str()[0] != ':') {
|
||||
hdrs += headers[i].first;
|
||||
capitalize(hdrs, hdrs.size()-headers[i].first.size());
|
||||
auto& kv = headers[i];
|
||||
|
||||
if(!kv.name.empty() && kv.name.c_str()[0] != ':') {
|
||||
hdrs += kv.name;
|
||||
capitalize(hdrs, hdrs.size() - kv.name.size());
|
||||
hdrs += ": ";
|
||||
hdrs += headers[i].second;
|
||||
sanitize_header_value(hdrs, hdrs.size() - headers[i].second.size());
|
||||
hdrs += kv.value;
|
||||
sanitize_header_value(hdrs, hdrs.size() - kv.value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
}
|
||||
|
@ -472,9 +491,9 @@ void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen)
|
|||
void dump_nv(FILE *out, const Headers& nva)
|
||||
{
|
||||
for(auto& nv : nva) {
|
||||
fwrite(nv.first.c_str(), nv.first.size(), 1, out);
|
||||
fwrite(nv.name.c_str(), nv.name.size(), 1, out);
|
||||
fwrite(": ", 2, 1, out);
|
||||
fwrite(nv.second.c_str(), nv.second.size(), 1, out);
|
||||
fwrite(nv.value.c_str(), nv.value.size(), 1, out);
|
||||
fwrite("\n", 1, 1, out);
|
||||
}
|
||||
fwrite("\n", 1, 1, out);
|
||||
|
|
43
src/http2.h
43
src/http2.h
|
@ -38,7 +38,33 @@
|
|||
|
||||
namespace nghttp2 {
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string>> Headers;
|
||||
struct Header {
|
||||
Header(std::string name, std::string value, bool no_index=false)
|
||||
: name(std::move(name)),
|
||||
value(std::move(value)),
|
||||
no_index(no_index)
|
||||
{}
|
||||
|
||||
Header()
|
||||
: no_index(false)
|
||||
{}
|
||||
|
||||
bool operator==(const Header& other) const
|
||||
{
|
||||
return name == other.name && value == other.value;
|
||||
}
|
||||
|
||||
bool operator<(const Header& rhs) const
|
||||
{
|
||||
return name < rhs.name || (name == rhs.name && value < rhs.value);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string value;
|
||||
bool no_index;
|
||||
};
|
||||
|
||||
typedef std::vector<Header> Headers;
|
||||
|
||||
namespace http2 {
|
||||
|
||||
|
@ -75,15 +101,18 @@ bool name_less(const Headers::value_type& lhs, const Headers::value_type& rhs);
|
|||
void normalize_headers(Headers& nva);
|
||||
|
||||
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);
|
||||
|
||||
// Add name/value pairs to |nva|. The name is given in the |name| with
|
||||
// |namelen| bytes. This function inspects the |value| and split it
|
||||
// using '\0' as delimiter. Each token is added to the |nva| with the
|
||||
// name |name|.
|
||||
// name |name|. If |no_index| is true, this name/value pair won't be
|
||||
// indexed when it is forwarded to the next hop.
|
||||
void split_add_header(Headers& nva,
|
||||
const uint8_t *name, size_t namelen,
|
||||
const uint8_t *value, size_t valuelen);
|
||||
const uint8_t *value, size_t valuelen,
|
||||
bool no_index);
|
||||
|
||||
// Returns sorted |nva| with |nvlen| elements. The headers are sorted
|
||||
// by name only and not necessarily stable. In addition to the
|
||||
|
@ -122,8 +151,10 @@ Headers concat_norm_headers(Headers headers);
|
|||
|
||||
// Creates nghttp2_nv using |name| and |value| and returns it. The
|
||||
// returned value only references the data pointer to name.c_str() and
|
||||
// value.c_str().
|
||||
nghttp2_nv make_nv(const std::string& name, const std::string& value);
|
||||
// value.c_str(). If |no_index| is true, nghttp2_nv flags member has
|
||||
// NGHTTP2_NV_FLAG_NO_INDEX flag set.
|
||||
nghttp2_nv make_nv(const std::string& name, const std::string& value,
|
||||
bool no_index);
|
||||
|
||||
// Create nghttp2_nv from string literal |name| and |value|.
|
||||
template<size_t N, size_t M>
|
||||
|
|
|
@ -44,13 +44,12 @@ using namespace nghttp2;
|
|||
namespace shrpx {
|
||||
|
||||
namespace {
|
||||
void check_nv(const std::pair<std::string, std::string>& a,
|
||||
const nghttp2_nv *b)
|
||||
void check_nv(const Header& a, const nghttp2_nv *b)
|
||||
{
|
||||
CU_ASSERT(a.first.size() == b->namelen);
|
||||
CU_ASSERT(a.second.size() == b->valuelen);
|
||||
CU_ASSERT(memcmp(a.first.c_str(), b->name, b->namelen) == 0);
|
||||
CU_ASSERT(memcmp(a.second.c_str(), b->value, b->valuelen) == 0);
|
||||
CU_ASSERT(a.name.size() == b->namelen);
|
||||
CU_ASSERT(a.value.size() == b->valuelen);
|
||||
CU_ASSERT(memcmp(a.name.c_str(), b->name, b->namelen) == 0);
|
||||
CU_ASSERT(memcmp(a.value.c_str(), b->value, b->valuelen) == 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -78,7 +77,7 @@ void test_http2_split_add_header(void)
|
|||
const uint8_t concatval[] = { '4', 0x00, 0x00, '6', 0x00, '5', '9', 0x00 };
|
||||
auto nva = Headers();
|
||||
http2::split_add_header(nva, (const uint8_t*)"delta", 5,
|
||||
concatval, sizeof(concatval));
|
||||
concatval, sizeof(concatval), false);
|
||||
CU_ASSERT(Headers::value_type("delta", "4") == nva[0]);
|
||||
CU_ASSERT(Headers::value_type("delta", "6") == nva[1]);
|
||||
CU_ASSERT(Headers::value_type("delta", "59") == nva[2]);
|
||||
|
@ -86,14 +85,16 @@ void test_http2_split_add_header(void)
|
|||
nva.clear();
|
||||
|
||||
http2::split_add_header(nva, (const uint8_t*)"alpha", 5,
|
||||
(const uint8_t*)"123", 3);
|
||||
(const uint8_t*)"123", 3, false);
|
||||
CU_ASSERT(Headers::value_type("alpha", "123") == nva[0]);
|
||||
CU_ASSERT(!nva[0].no_index);
|
||||
|
||||
nva.clear();
|
||||
|
||||
http2::split_add_header(nva, (const uint8_t*)"alpha", 5,
|
||||
(const uint8_t*)"", 0);
|
||||
(const uint8_t*)"", 0, true);
|
||||
CU_ASSERT(Headers::value_type("alpha", "") == nva[0]);
|
||||
CU_ASSERT(nva[0].no_index);
|
||||
}
|
||||
|
||||
void test_http2_check_http2_headers(void)
|
||||
|
@ -133,7 +134,7 @@ void test_http2_get_unique_header(void)
|
|||
const Headers::value_type *rv;
|
||||
rv = http2::get_unique_header(nva, "delta");
|
||||
CU_ASSERT(rv != nullptr);
|
||||
CU_ASSERT("delta" == rv->first);
|
||||
CU_ASSERT("delta" == rv->name);
|
||||
|
||||
rv = http2::get_unique_header(nva, "bravo");
|
||||
CU_ASSERT(rv == nullptr);
|
||||
|
@ -155,11 +156,11 @@ void test_http2_get_header(void)
|
|||
const Headers::value_type *rv;
|
||||
rv = http2::get_header(nva, "delta");
|
||||
CU_ASSERT(rv != nullptr);
|
||||
CU_ASSERT("delta" == rv->first);
|
||||
CU_ASSERT("delta" == rv->name);
|
||||
|
||||
rv = http2::get_header(nva, "bravo");
|
||||
CU_ASSERT(rv != nullptr);
|
||||
CU_ASSERT("bravo" == rv->first);
|
||||
CU_ASSERT("bravo" == rv->name);
|
||||
|
||||
rv = http2::get_header(nva, "foxtrot");
|
||||
CU_ASSERT(rv == nullptr);
|
||||
|
@ -182,8 +183,8 @@ void test_http2_value_lws(void)
|
|||
}
|
||||
|
||||
namespace {
|
||||
auto headers = std::vector<std::pair<std::string, std::string>>
|
||||
{{"alpha", "0"},
|
||||
auto headers = Headers
|
||||
{{"alpha", "0", true},
|
||||
{"bravo", "1"},
|
||||
{"connection", "2"},
|
||||
{"connection", "3"},
|
||||
|
@ -207,7 +208,7 @@ void test_http2_concat_norm_headers(void)
|
|||
hds.emplace_back("set-cookie", "buzz");
|
||||
auto res = http2::concat_norm_headers(hds);
|
||||
CU_ASSERT(14 == res.size());
|
||||
CU_ASSERT(std::string("2") + '\0' + std::string("3") == res[2].second);
|
||||
CU_ASSERT(std::string("2") + '\0' + std::string("3") == res[2].value);
|
||||
}
|
||||
|
||||
void test_http2_copy_norm_headers_to_nva(void)
|
||||
|
@ -218,6 +219,12 @@ void test_http2_copy_norm_headers_to_nva(void)
|
|||
auto ans = std::vector<int>{0, 1, 4, 6, 7, 12};
|
||||
for(size_t i = 0; i < ans.size(); ++i) {
|
||||
check_nv(headers[ans[i]], &nva[i]);
|
||||
|
||||
if(ans[i] == 0) {
|
||||
CU_ASSERT(nva[i].flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
} else {
|
||||
CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -921,7 +921,7 @@ int submit_request
|
|||
{
|
||||
auto path = req->make_reqpath();
|
||||
auto scheme = util::get_uri_field(req->uri.c_str(), req->u, UF_SCHEMA);
|
||||
auto build_headers = std::vector<std::pair<std::string, std::string>>
|
||||
auto build_headers = Headers
|
||||
{{":method", req->data_prd ? "POST" : "GET"},
|
||||
{":path", path},
|
||||
{":scheme", scheme},
|
||||
|
@ -942,27 +942,30 @@ int submit_request
|
|||
for(auto& kv : headers) {
|
||||
size_t i;
|
||||
for(i = 0; i < num_initial_headers; ++i) {
|
||||
if(util::strieq(kv.first, build_headers[i].first)) {
|
||||
build_headers[i].second = kv.second;
|
||||
if(util::strieq(kv.first, build_headers[i].name)) {
|
||||
build_headers[i].value = kv.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i < num_initial_headers) {
|
||||
continue;
|
||||
}
|
||||
build_headers.push_back(kv);
|
||||
build_headers.emplace_back(kv.first, kv.second);
|
||||
}
|
||||
std::stable_sort(std::begin(build_headers), std::end(build_headers),
|
||||
[](const std::pair<std::string, std::string>& lhs,
|
||||
const std::pair<std::string, std::string>& rhs)
|
||||
[](const Headers::value_type& lhs,
|
||||
const Headers::value_type& rhs)
|
||||
{
|
||||
return lhs.first < rhs.first;
|
||||
return lhs.name < rhs.name;
|
||||
});
|
||||
|
||||
build_headers = http2::concat_norm_headers(std::move(build_headers));
|
||||
|
||||
auto nva = std::vector<nghttp2_nv>();
|
||||
nva.reserve(build_headers.size());
|
||||
|
||||
for(auto& kv : build_headers) {
|
||||
nva.push_back(http2::make_nv(kv.first, kv.second));
|
||||
nva.push_back(http2::make_nv(kv.name, kv.value, false));
|
||||
}
|
||||
|
||||
auto rv = nghttp2_submit_request(client->session, &req->pri_spec,
|
||||
|
@ -1157,13 +1160,13 @@ void check_response_header(nghttp2_session *session, Request* req)
|
|||
{
|
||||
bool gzip = false;
|
||||
for(auto& nv : req->res_nva) {
|
||||
if("content-encoding" == nv.first) {
|
||||
gzip = util::strieq("gzip", nv.second) ||
|
||||
util::strieq("deflate", nv.second);
|
||||
if("content-encoding" == nv.name) {
|
||||
gzip = util::strieq("gzip", nv.value) ||
|
||||
util::strieq("deflate", nv.value);
|
||||
continue;
|
||||
}
|
||||
if(":status" == nv.first) {
|
||||
req->status.assign(nv.second);
|
||||
if(":status" == nv.name) {
|
||||
req->status.assign(nv.value);
|
||||
}
|
||||
}
|
||||
if(gzip) {
|
||||
|
@ -1228,7 +1231,8 @@ int on_header_callback(nghttp2_session *session,
|
|||
if(!req) {
|
||||
break;
|
||||
}
|
||||
http2::split_add_header(req->res_nva, name, namelen, value, valuelen);
|
||||
http2::split_add_header(req->res_nva, name, namelen, value, valuelen,
|
||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_PUSH_PROMISE: {
|
||||
|
@ -1237,7 +1241,8 @@ int on_header_callback(nghttp2_session *session,
|
|||
if(!req) {
|
||||
break;
|
||||
}
|
||||
http2::split_add_header(req->push_req_nva, name, namelen, value, valuelen);
|
||||
http2::split_add_header(req->push_req_nva, name, namelen, value, valuelen,
|
||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1284,20 +1289,20 @@ int on_frame_recv_callback2
|
|||
}
|
||||
std::string scheme, authority, method, path;
|
||||
for(auto& nv : req->push_req_nva) {
|
||||
if(nv.first == ":scheme") {
|
||||
scheme = nv.second;
|
||||
if(nv.name == ":scheme") {
|
||||
scheme = nv.value;
|
||||
continue;
|
||||
}
|
||||
if(nv.first == ":authority" || nv.first == "host") {
|
||||
authority = nv.second;
|
||||
if(nv.name == ":authority" || nv.name == "host") {
|
||||
authority = nv.value;
|
||||
continue;
|
||||
}
|
||||
if(nv.first == ":method") {
|
||||
method = nv.second;
|
||||
if(nv.name == ":method") {
|
||||
method = nv.value;
|
||||
continue;
|
||||
}
|
||||
if(nv.first == ":path") {
|
||||
path = nv.second;
|
||||
if(nv.name == ":path") {
|
||||
path = nv.value;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,8 +121,8 @@ namespace {
|
|||
void check_header_field(bool *result, const Headers::value_type &item,
|
||||
const char *name, const char *value)
|
||||
{
|
||||
if(util::strieq(item.first.c_str(), name)) {
|
||||
if(util::strifind(item.second.c_str(), value)) {
|
||||
if(util::strieq(item.name.c_str(), name)) {
|
||||
if(util::strifind(item.value.c_str(), value)) {
|
||||
*result = true;
|
||||
}
|
||||
}
|
||||
|
@ -150,8 +150,8 @@ Headers::const_iterator get_norm_header(const Headers& headers,
|
|||
const std::string& name)
|
||||
{
|
||||
auto i = std::lower_bound(std::begin(headers), std::end(headers),
|
||||
std::make_pair(name, ""), http2::name_less);
|
||||
if(i != std::end(headers) && (*i).first == name) {
|
||||
Header(name, ""), http2::name_less);
|
||||
if(i != std::end(headers) && (*i).name == name) {
|
||||
return i;
|
||||
}
|
||||
return std::end(headers);
|
||||
|
@ -162,8 +162,8 @@ namespace {
|
|||
Headers::iterator get_norm_header(Headers& headers, const std::string& name)
|
||||
{
|
||||
auto i = std::lower_bound(std::begin(headers), std::end(headers),
|
||||
std::make_pair(name, ""), http2::name_less);
|
||||
if(i != std::end(headers) && (*i).first == name) {
|
||||
Header(name, ""), http2::name_less);
|
||||
if(i != std::end(headers) && (*i).name == name) {
|
||||
return i;
|
||||
}
|
||||
return std::end(headers);
|
||||
|
@ -180,12 +180,12 @@ void Downstream::assemble_request_cookie()
|
|||
std::string& cookie = assembled_request_cookie_;
|
||||
cookie = "";
|
||||
for(auto& kv : request_headers_) {
|
||||
if(util::strieq("cookie", kv.first.c_str())) {
|
||||
auto end = kv.second.find_last_not_of(" ;");
|
||||
if(util::strieq("cookie", kv.name.c_str())) {
|
||||
auto end = kv.value.find_last_not_of(" ;");
|
||||
if(end == std::string::npos) {
|
||||
cookie += kv.second;
|
||||
cookie += kv.value;
|
||||
} else {
|
||||
cookie.append(std::begin(kv.second), std::begin(kv.second) + end + 1);
|
||||
cookie.append(std::begin(kv.value), std::begin(kv.value) + end + 1);
|
||||
}
|
||||
cookie += "; ";
|
||||
}
|
||||
|
@ -199,19 +199,19 @@ void Downstream::crumble_request_cookie()
|
|||
{
|
||||
Headers cookie_hdrs;
|
||||
for(auto& kv : request_headers_) {
|
||||
if(util::strieq("cookie", kv.first.c_str())) {
|
||||
size_t last = kv.second.size();
|
||||
if(util::strieq("cookie", kv.name.c_str())) {
|
||||
size_t last = kv.value.size();
|
||||
size_t num = 0;
|
||||
std::string rep_cookie;
|
||||
|
||||
for(size_t j = 0; j < last;) {
|
||||
j = kv.second.find_first_not_of("\t ;", j);
|
||||
j = kv.value.find_first_not_of("\t ;", j);
|
||||
if(j == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
auto first = j;
|
||||
|
||||
j = kv.second.find(';', j);
|
||||
j = kv.value.find(';', j);
|
||||
if(j == std::string::npos) {
|
||||
j = last;
|
||||
}
|
||||
|
@ -220,15 +220,16 @@ void Downstream::crumble_request_cookie()
|
|||
if(first == 0 && j == last) {
|
||||
break;
|
||||
}
|
||||
rep_cookie = kv.second.substr(first, j - first);
|
||||
rep_cookie = kv.value.substr(first, j - first);
|
||||
} else {
|
||||
cookie_hdrs.push_back
|
||||
(std::make_pair("cookie", kv.second.substr(first, j - first)));
|
||||
(Header("cookie", kv.value.substr(first, j - first),
|
||||
kv.no_index));
|
||||
}
|
||||
++num;
|
||||
}
|
||||
if(num > 0) {
|
||||
kv.second = std::move(rep_cookie);
|
||||
kv.value = std::move(rep_cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,17 +270,19 @@ void Downstream::set_last_request_header_value(std::string value)
|
|||
request_header_key_prev_ = false;
|
||||
request_headers_sum_ += value.size();
|
||||
Headers::value_type &item = request_headers_.back();
|
||||
item.second = std::move(value);
|
||||
item.value = std::move(value);
|
||||
check_transfer_encoding_chunked(&chunked_request_, item);
|
||||
check_expect_100_continue(&request_expect_100_continue_, item);
|
||||
}
|
||||
|
||||
void Downstream::split_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)
|
||||
{
|
||||
request_headers_sum_ += namelen + valuelen;
|
||||
http2::split_add_header(request_headers_, name, namelen, value, valuelen);
|
||||
http2::split_add_header(request_headers_, name, namelen, value, valuelen,
|
||||
no_index);
|
||||
}
|
||||
|
||||
bool Downstream::get_request_header_key_prev() const
|
||||
|
@ -292,7 +295,7 @@ void Downstream::append_last_request_header_key(const char *data, size_t len)
|
|||
assert(request_header_key_prev_);
|
||||
request_headers_sum_ += len;
|
||||
auto& item = request_headers_.back();
|
||||
item.first.append(data, len);
|
||||
item.name.append(data, len);
|
||||
}
|
||||
|
||||
void Downstream::append_last_request_header_value(const char *data, size_t len)
|
||||
|
@ -300,7 +303,7 @@ void Downstream::append_last_request_header_value(const char *data, size_t len)
|
|||
assert(!request_header_key_prev_);
|
||||
request_headers_sum_ += len;
|
||||
auto& item = request_headers_.back();
|
||||
item.second.append(data, len);
|
||||
item.value.append(data, len);
|
||||
}
|
||||
|
||||
size_t Downstream::get_request_headers_sum() const
|
||||
|
@ -498,14 +501,14 @@ void Downstream::rewrite_norm_location_response_header
|
|||
}
|
||||
http_parser_url u;
|
||||
memset(&u, 0, sizeof(u));
|
||||
int rv = http_parser_parse_url((*hd).second.c_str(), (*hd).second.size(),
|
||||
int rv = http_parser_parse_url((*hd).value.c_str(), (*hd).value.size(),
|
||||
0, &u);
|
||||
if(rv != 0) {
|
||||
return;
|
||||
}
|
||||
std::string new_uri;
|
||||
if(!request_http2_authority_.empty()) {
|
||||
new_uri = http2::rewrite_location_uri((*hd).second, u,
|
||||
new_uri = http2::rewrite_location_uri((*hd).value, u,
|
||||
request_http2_authority_,
|
||||
upstream_scheme, upstream_port);
|
||||
}
|
||||
|
@ -514,11 +517,11 @@ void Downstream::rewrite_norm_location_response_header
|
|||
if(host == std::end(request_headers_)) {
|
||||
return;
|
||||
}
|
||||
new_uri = http2::rewrite_location_uri((*hd).second, u, (*host).second,
|
||||
new_uri = http2::rewrite_location_uri((*hd).value, u, (*host).value,
|
||||
upstream_scheme, upstream_port);
|
||||
}
|
||||
if(!new_uri.empty()) {
|
||||
(*hd).second = std::move(new_uri);
|
||||
(*hd).value = std::move(new_uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,16 +539,18 @@ void Downstream::set_last_response_header_value(std::string value)
|
|||
response_header_key_prev_ = false;
|
||||
response_headers_sum_ += value.size();
|
||||
auto& item = response_headers_.back();
|
||||
item.second = std::move(value);
|
||||
item.value = std::move(value);
|
||||
check_transfer_encoding_chunked(&chunked_response_, item);
|
||||
}
|
||||
|
||||
void Downstream::split_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)
|
||||
{
|
||||
response_headers_sum_ += namelen + valuelen;
|
||||
http2::split_add_header(response_headers_, name, namelen, value, valuelen);
|
||||
http2::split_add_header(response_headers_, name, namelen, value, valuelen,
|
||||
no_index);
|
||||
}
|
||||
|
||||
bool Downstream::get_response_header_key_prev() const
|
||||
|
@ -558,7 +563,7 @@ void Downstream::append_last_response_header_key(const char *data, size_t len)
|
|||
assert(response_header_key_prev_);
|
||||
response_headers_sum_ += len;
|
||||
auto& item = response_headers_.back();
|
||||
item.first.append(data, len);
|
||||
item.name.append(data, len);
|
||||
}
|
||||
|
||||
void Downstream::append_last_response_header_value(const char *data,
|
||||
|
@ -567,7 +572,7 @@ void Downstream::append_last_response_header_value(const char *data,
|
|||
assert(!response_header_key_prev_);
|
||||
response_headers_sum_ += len;
|
||||
auto& item = response_headers_.back();
|
||||
item.second.append(data, len);
|
||||
item.value.append(data, len);
|
||||
}
|
||||
|
||||
size_t Downstream::get_response_headers_sum() const
|
||||
|
@ -692,7 +697,7 @@ void Downstream::check_upgrade_fulfilled()
|
|||
// TODO Do more strict checking for upgrade headers
|
||||
if(response_http_status_ == 101) {
|
||||
for(auto& hd : request_headers_) {
|
||||
if(util::strieq("upgrade", hd.first.c_str())) {
|
||||
if(util::strieq("upgrade", hd.name.c_str())) {
|
||||
upgraded_ = true;
|
||||
break;
|
||||
}
|
||||
|
@ -713,7 +718,7 @@ void Downstream::check_upgrade_request()
|
|||
} else {
|
||||
// TODO Do more strict checking for upgrade headers
|
||||
for(auto& hd : request_headers_) {
|
||||
if(util::strieq("upgrade", hd.first.c_str())) {
|
||||
if(util::strieq("upgrade", hd.name.c_str())) {
|
||||
upgrade_request_ = true;
|
||||
break;
|
||||
}
|
||||
|
@ -737,12 +742,12 @@ bool Downstream::http2_upgrade_request() const
|
|||
// For now just check NGHTTP2_CLEARTEXT_PROTO_VERSION_ID in
|
||||
// Upgrade header field and existence of HTTP2-Settings header
|
||||
// field.
|
||||
if(util::strieq(hd.first.c_str(), "upgrade")) {
|
||||
if(util::strieq(hd.second.c_str(),
|
||||
if(util::strieq(hd.name.c_str(), "upgrade")) {
|
||||
if(util::strieq(hd.value.c_str(),
|
||||
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID)) {
|
||||
upgrade_seen = true;
|
||||
}
|
||||
} else if(util::strieq(hd.first.c_str(), "http2-settings")) {
|
||||
} else if(util::strieq(hd.name.c_str(), "http2-settings")) {
|
||||
http2_settings_seen = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,8 @@ public:
|
|||
void set_last_request_header_value(std::string value);
|
||||
|
||||
void split_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);
|
||||
|
||||
bool get_request_header_key_prev() const;
|
||||
void append_last_request_header_key(const char *data, size_t len);
|
||||
|
@ -171,7 +172,8 @@ public:
|
|||
void set_last_response_header_value(std::string value);
|
||||
|
||||
void split_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);
|
||||
|
||||
bool get_response_header_key_prev() const;
|
||||
void append_last_response_header_key(const char *data, size_t len);
|
||||
|
|
|
@ -78,13 +78,13 @@ void test_downstream_get_norm_request_header(void)
|
|||
d.add_request_header("delta", "4");
|
||||
d.add_request_header("echo", "5");
|
||||
auto i = d.get_norm_request_header("alpha");
|
||||
CU_ASSERT(std::make_pair(std::string("alpha"), std::string("0")) == *i);
|
||||
CU_ASSERT(Header("alpha", "0") == *i);
|
||||
i = d.get_norm_request_header("bravo");
|
||||
CU_ASSERT(std::make_pair(std::string("bravo"), std::string("1")) == *i);
|
||||
CU_ASSERT(Header("bravo", "1") == *i);
|
||||
i = d.get_norm_request_header("delta");
|
||||
CU_ASSERT(std::make_pair(std::string("delta"), std::string("4")) == *i);
|
||||
CU_ASSERT(Header("delta", "4") == *i);
|
||||
i = d.get_norm_request_header("echo");
|
||||
CU_ASSERT(std::make_pair(std::string("echo"), std::string("5")) == *i);
|
||||
CU_ASSERT(Header("echo", "5") == *i);
|
||||
i = d.get_norm_request_header("foxtrot");
|
||||
CU_ASSERT(i == std::end(d.get_request_headers()));
|
||||
}
|
||||
|
@ -99,13 +99,13 @@ void test_downstream_get_norm_response_header(void)
|
|||
d.add_response_header("delta", "4");
|
||||
d.add_response_header("echo", "5");
|
||||
auto i = d.get_norm_response_header("alpha");
|
||||
CU_ASSERT(std::make_pair(std::string("alpha"), std::string("0")) == *i);
|
||||
CU_ASSERT(Header("alpha", "0") == *i);
|
||||
i = d.get_norm_response_header("bravo");
|
||||
CU_ASSERT(std::make_pair(std::string("bravo"), std::string("1")) == *i);
|
||||
CU_ASSERT(Header("bravo", "1") == *i);
|
||||
i = d.get_norm_response_header("delta");
|
||||
CU_ASSERT(std::make_pair(std::string("delta"), std::string("4")) == *i);
|
||||
CU_ASSERT(Header("delta", "4") == *i);
|
||||
i = d.get_norm_response_header("echo");
|
||||
CU_ASSERT(std::make_pair(std::string("echo"), std::string("5")) == *i);
|
||||
CU_ASSERT(Header("echo", "5") == *i);
|
||||
i = d.get_norm_response_header("foxtrot");
|
||||
CU_ASSERT(i == std::end(d.get_response_headers()));
|
||||
}
|
||||
|
@ -120,13 +120,13 @@ void test_downstream_crumble_request_cookie(void)
|
|||
d.add_request_header("cookie", "echo");
|
||||
d.crumble_request_cookie();
|
||||
Headers ans = {
|
||||
std::make_pair(":method", "get"),
|
||||
std::make_pair(":path", "/"),
|
||||
std::make_pair("cookie", "alpha"),
|
||||
std::make_pair("cookie", "delta"),
|
||||
std::make_pair("cookie", "echo"),
|
||||
std::make_pair("cookie", "bravo"),
|
||||
std::make_pair("cookie", "charlie")
|
||||
{":method", "get"},
|
||||
{":path", "/"},
|
||||
{"cookie", "alpha"},
|
||||
{"cookie", "delta"},
|
||||
{"cookie", "echo"},
|
||||
{"cookie", "bravo"},
|
||||
{"cookie", "charlie"}
|
||||
};
|
||||
CU_ASSERT(ans == d.get_request_headers());
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ void test_downstream_rewrite_norm_location_response_header(void)
|
|||
d.add_response_header("location", "http://localhost:3000/");
|
||||
d.rewrite_norm_location_response_header("https", 443);
|
||||
auto location = d.get_norm_response_header("location");
|
||||
CU_ASSERT("https://localhost/" == (*location).second);
|
||||
CU_ASSERT("https://localhost/" == (*location).value);
|
||||
}
|
||||
{
|
||||
Downstream d(nullptr, 0, 0);
|
||||
|
@ -162,7 +162,7 @@ void test_downstream_rewrite_norm_location_response_header(void)
|
|||
d.add_response_header("location", "http://localhost/");
|
||||
d.rewrite_norm_location_response_header("https", 443);
|
||||
auto location = d.get_norm_response_header("location");
|
||||
CU_ASSERT("https://localhost/" == (*location).second);
|
||||
CU_ASSERT("https://localhost/" == (*location).value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -356,21 +356,21 @@ int Http2DownstreamConnection::push_request_headers()
|
|||
auto transfer_encoding =
|
||||
downstream_->get_norm_request_header("transfer-encoding");
|
||||
if(transfer_encoding != end_headers &&
|
||||
util::strieq((*transfer_encoding).second.c_str(), "chunked")) {
|
||||
util::strieq((*transfer_encoding).value.c_str(), "chunked")) {
|
||||
chunked_encoding = true;
|
||||
}
|
||||
|
||||
auto xff = downstream_->get_norm_request_header("x-forwarded-for");
|
||||
if(get_config()->add_x_forwarded_for) {
|
||||
if(xff != end_headers) {
|
||||
xff_value = (*xff).second;
|
||||
xff_value = (*xff).value;
|
||||
xff_value += ", ";
|
||||
}
|
||||
xff_value += downstream_->get_upstream()->get_client_handler()->
|
||||
get_ipaddr();
|
||||
nva.push_back(http2::make_nv_ls("x-forwarded-for", xff_value));
|
||||
} else if(xff != end_headers) {
|
||||
nva.push_back(http2::make_nv_ls("x-forwarded-for", (*xff).second));
|
||||
nva.push_back(http2::make_nv_ls("x-forwarded-for", (*xff).value));
|
||||
}
|
||||
|
||||
if(downstream_->get_request_method() != "CONNECT") {
|
||||
|
@ -389,11 +389,11 @@ int Http2DownstreamConnection::push_request_headers()
|
|||
auto via = downstream_->get_norm_request_header("via");
|
||||
if(get_config()->no_via) {
|
||||
if(via != end_headers) {
|
||||
nva.push_back(http2::make_nv_ls("via", (*via).second));
|
||||
nva.push_back(http2::make_nv_ls("via", (*via).value));
|
||||
}
|
||||
} else {
|
||||
if(via != end_headers) {
|
||||
via_value = (*via).second;
|
||||
via_value = (*via).value;
|
||||
via_value += ", ";
|
||||
}
|
||||
via_value += http::create_via_header_value
|
||||
|
|
|
@ -814,7 +814,8 @@ int on_header_callback(nghttp2_session *session,
|
|||
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||
return 0;
|
||||
}
|
||||
downstream->split_add_response_header(name, namelen, value, valuelen);
|
||||
downstream->split_add_response_header(name, namelen, value, valuelen,
|
||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -886,7 +887,7 @@ int on_response_headers(Http2Session *http2session,
|
|||
call_downstream_readcb(http2session, downstream);
|
||||
return 0;
|
||||
}
|
||||
downstream->set_response_http_status(strtoul(status->second.c_str(),
|
||||
downstream->set_response_http_status(strtoul(status->value.c_str(),
|
||||
nullptr, 10));
|
||||
downstream->set_response_major(2);
|
||||
downstream->set_response_minor(0);
|
||||
|
@ -916,7 +917,7 @@ int on_response_headers(Http2Session *http2session,
|
|||
if(LOG_ENABLED(INFO)) {
|
||||
std::stringstream ss;
|
||||
for(auto& nv : nva) {
|
||||
ss << TTY_HTTP_HD << nv.first << TTY_RST << ": " << nv.second << "\n";
|
||||
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n";
|
||||
}
|
||||
SSLOG(INFO, http2session) << "HTTP response headers. stream_id="
|
||||
<< frame->hd.stream_id
|
||||
|
|
|
@ -101,8 +101,8 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
|
|||
std::string settings_payload;
|
||||
auto downstream = http->get_downstream();
|
||||
for(auto& hd : downstream->get_request_headers()) {
|
||||
if(util::strieq(hd.first.c_str(), "http2-settings")) {
|
||||
auto val = hd.second;
|
||||
if(util::strieq(hd.name.c_str(), "http2-settings")) {
|
||||
auto val = hd.value;
|
||||
util::to_base64(val);
|
||||
settings_payload = base64::decode(std::begin(val), std::end(val));
|
||||
break;
|
||||
|
@ -205,7 +205,8 @@ int on_header_callback(nghttp2_session *session,
|
|||
if(!http2::check_nv(name, namelen, value, valuelen)) {
|
||||
return 0;
|
||||
}
|
||||
downstream->split_add_request_header(name, namelen, value, valuelen);
|
||||
downstream->split_add_request_header(name, namelen, value, valuelen,
|
||||
flags & NGHTTP2_NV_FLAG_NO_INDEX);
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -259,7 +260,7 @@ int on_request_headers(Http2Upstream *upstream,
|
|||
if(LOG_ENABLED(INFO)) {
|
||||
std::stringstream ss;
|
||||
for(auto& nv : nva) {
|
||||
ss << TTY_HTTP_HD << nv.first << TTY_RST << ": " << nv.second << "\n";
|
||||
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n";
|
||||
}
|
||||
ULOG(INFO, upstream) << "HTTP request headers. stream_id="
|
||||
<< downstream->get_stream_id()
|
||||
|
@ -280,7 +281,7 @@ int on_request_headers(Http2Upstream *upstream,
|
|||
auto path = http2::get_unique_header(nva, ":path");
|
||||
auto method = http2::get_unique_header(nva, ":method");
|
||||
auto scheme = http2::get_unique_header(nva, ":scheme");
|
||||
bool is_connect = method && "CONNECT" == method->second;
|
||||
bool is_connect = method && "CONNECT" == method->value;
|
||||
bool having_host = http2::non_empty_value(host);
|
||||
bool having_authority = http2::non_empty_value(authority);
|
||||
|
||||
|
@ -1014,11 +1015,11 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream)
|
|||
auto via = downstream->get_norm_response_header("via");
|
||||
if(get_config()->no_via) {
|
||||
if(via != end_headers) {
|
||||
nva.push_back(http2::make_nv_ls("via", (*via).second));
|
||||
nva.push_back(http2::make_nv_ls("via", (*via).value));
|
||||
}
|
||||
} else {
|
||||
if(via != end_headers) {
|
||||
via_value = (*via).second;
|
||||
via_value = (*via).value;
|
||||
via_value += ", ";
|
||||
}
|
||||
via_value += http::create_via_header_value
|
||||
|
|
|
@ -171,16 +171,16 @@ int HttpDownstreamConnection::push_request_headers()
|
|||
if(get_config()->add_x_forwarded_for) {
|
||||
hdrs += "X-Forwarded-For: ";
|
||||
if(xff != end_headers) {
|
||||
hdrs += (*xff).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).second.size());
|
||||
hdrs += (*xff).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).value.size());
|
||||
hdrs += ", ";
|
||||
}
|
||||
hdrs += client_handler_->get_ipaddr();
|
||||
hdrs += "\r\n";
|
||||
} else if(xff != end_headers) {
|
||||
hdrs += "X-Forwarded-For: ";
|
||||
hdrs += (*xff).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).second.size());
|
||||
hdrs += (*xff).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*xff).value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
if(downstream_->get_request_method() != "CONNECT") {
|
||||
|
@ -196,25 +196,25 @@ int HttpDownstreamConnection::push_request_headers()
|
|||
}
|
||||
auto expect = downstream_->get_norm_request_header("expect");
|
||||
if(expect != end_headers &&
|
||||
!util::strifind((*expect).second.c_str(), "100-continue")) {
|
||||
!util::strifind((*expect).value.c_str(), "100-continue")) {
|
||||
hdrs += "Expect: ";
|
||||
hdrs += (*expect).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*expect).second.size());
|
||||
hdrs += (*expect).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*expect).value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
auto via = downstream_->get_norm_request_header("via");
|
||||
if(get_config()->no_via) {
|
||||
if(via != end_headers) {
|
||||
hdrs += "Via: ";
|
||||
hdrs += (*via).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).second.size());
|
||||
hdrs += (*via).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
} else {
|
||||
hdrs += "Via: ";
|
||||
if(via != end_headers) {
|
||||
hdrs += (*via).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).second.size());
|
||||
hdrs += (*via).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size());
|
||||
hdrs += ", ";
|
||||
}
|
||||
hdrs += http::create_via_header_value(downstream_->get_request_major(),
|
||||
|
|
|
@ -159,8 +159,8 @@ int htp_hdrs_completecb(http_parser *htp)
|
|||
<< downstream->get_request_minor() << "\n";
|
||||
const auto& headers = downstream->get_request_headers();
|
||||
for(size_t i = 0; i < headers.size(); ++i) {
|
||||
ss << TTY_HTTP_HD << headers[i].first << TTY_RST << ": "
|
||||
<< headers[i].second << "\n";
|
||||
ss << TTY_HTTP_HD << headers[i].name << TTY_RST << ": "
|
||||
<< headers[i].value << "\n";
|
||||
}
|
||||
ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str();
|
||||
}
|
||||
|
@ -682,15 +682,15 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
|||
if(get_config()->no_via) {
|
||||
if(via != end_headers) {
|
||||
hdrs += "Via: ";
|
||||
hdrs += (*via).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).second.size());
|
||||
hdrs += (*via).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size());
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
} else {
|
||||
hdrs += "Via: ";
|
||||
if(via != end_headers) {
|
||||
hdrs += (*via).second;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).second.size());
|
||||
hdrs += (*via).value;
|
||||
http2::sanitize_header_value(hdrs, hdrs.size() - (*via).value.size());
|
||||
hdrs += ", ";
|
||||
}
|
||||
hdrs += http::create_via_header_value
|
||||
|
|
|
@ -864,18 +864,18 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream)
|
|||
nv[hdidx++] = ":version";
|
||||
nv[hdidx++] = "HTTP/1.1";
|
||||
for(auto& hd : downstream->get_response_headers()) {
|
||||
if(hd.first.empty() || hd.first.c_str()[0] == ':' ||
|
||||
util::strieq(hd.first.c_str(), "transfer-encoding") ||
|
||||
util::strieq(hd.first.c_str(), "keep-alive") || // HTTP/1.0?
|
||||
util::strieq(hd.first.c_str(), "connection") ||
|
||||
util::strieq(hd.first.c_str(), "proxy-connection")) {
|
||||
if(hd.name.empty() || hd.name.c_str()[0] == ':' ||
|
||||
util::strieq(hd.name.c_str(), "transfer-encoding") ||
|
||||
util::strieq(hd.name.c_str(), "keep-alive") || // HTTP/1.0?
|
||||
util::strieq(hd.name.c_str(), "connection") ||
|
||||
util::strieq(hd.name.c_str(), "proxy-connection")) {
|
||||
// These are ignored
|
||||
} else if(!get_config()->no_via &&
|
||||
util::strieq(hd.first.c_str(), "via")) {
|
||||
via_value = hd.second;
|
||||
util::strieq(hd.name.c_str(), "via")) {
|
||||
via_value = hd.value;
|
||||
} else {
|
||||
nv[hdidx++] = hd.first.c_str();
|
||||
nv[hdidx++] = hd.second.c_str();
|
||||
nv[hdidx++] = hd.name.c_str();
|
||||
nv[hdidx++] = hd.value.c_str();
|
||||
}
|
||||
}
|
||||
if(!get_config()->no_via) {
|
||||
|
|
Loading…
Reference in New Issue