nghttpx: Implement cookie crumbling
This commit is contained in:
parent
0c669898a4
commit
e14baf134c
|
@ -179,6 +179,7 @@ size_t IGN_HDLEN = sizeof(IGN_HD)/sizeof(IGN_HD[0]);
|
||||||
namespace {
|
namespace {
|
||||||
const char *HTTP1_IGN_HD[] = {
|
const char *HTTP1_IGN_HD[] = {
|
||||||
"connection",
|
"connection",
|
||||||
|
"cookie",
|
||||||
"expect",
|
"expect",
|
||||||
"http2-settings",
|
"http2-settings",
|
||||||
"keep-alive",
|
"keep-alive",
|
||||||
|
|
|
@ -106,7 +106,7 @@ void copy_norm_headers_to_nv
|
||||||
|
|
||||||
// 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|. Certain headers, which requires special handling
|
||||||
// (i.e. via), are not appended.
|
// (i.e. via and cookie), are not appended.
|
||||||
void build_http1_headers_from_norm_headers
|
void build_http1_headers_from_norm_headers
|
||||||
(std::string& hdrs,
|
(std::string& hdrs,
|
||||||
const std::vector<std::pair<std::string, std::string>>& headers);
|
const std::vector<std::pair<std::string, std::string>>& headers);
|
||||||
|
|
|
@ -92,6 +92,10 @@ int main(int argc, char* argv[])
|
||||||
shrpx::test_downstream_get_norm_request_header) ||
|
shrpx::test_downstream_get_norm_request_header) ||
|
||||||
!CU_add_test(pSuite, "downstream_get_norm_response_header",
|
!CU_add_test(pSuite, "downstream_get_norm_response_header",
|
||||||
shrpx::test_downstream_get_norm_response_header) ||
|
shrpx::test_downstream_get_norm_response_header) ||
|
||||||
|
!CU_add_test(pSuite, "downstream_crumble_request_cookie",
|
||||||
|
shrpx::test_downstream_crumble_request_cookie) ||
|
||||||
|
!CU_add_test(pSuite, "downstream_assemble_request_cookie",
|
||||||
|
shrpx::test_downstream_assemble_request_cookie) ||
|
||||||
!CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) ||
|
!CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) ||
|
||||||
!CU_add_test(pSuite, "util_inp_strlower",
|
!CU_add_test(pSuite, "util_inp_strlower",
|
||||||
shrpx::test_util_inp_strlower) ||
|
shrpx::test_util_inp_strlower) ||
|
||||||
|
|
|
@ -178,6 +178,69 @@ const Headers& Downstream::get_request_headers() const
|
||||||
return request_headers_;
|
return request_headers_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(end == std::string::npos) {
|
||||||
|
cookie += kv.second;
|
||||||
|
} else {
|
||||||
|
cookie.append(std::begin(kv.second), std::begin(kv.second) + end + 1);
|
||||||
|
}
|
||||||
|
cookie += "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(cookie.size() >= 2) {
|
||||||
|
cookie.erase(cookie.size() - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
size_t num = 0;
|
||||||
|
std::string rep_cookie;
|
||||||
|
|
||||||
|
for(size_t j = 0; j < last;) {
|
||||||
|
j = kv.second.find_first_not_of("\t ;", j);
|
||||||
|
if(j == std::string::npos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto first = j;
|
||||||
|
|
||||||
|
j = kv.second.find(';', j);
|
||||||
|
if(j == std::string::npos) {
|
||||||
|
j = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(num == 0) {
|
||||||
|
rep_cookie = kv.second.substr(first, j - first);
|
||||||
|
} else {
|
||||||
|
cookie_hdrs.push_back
|
||||||
|
(std::make_pair("cookie", kv.second.substr(first, j - first)));
|
||||||
|
}
|
||||||
|
++num;
|
||||||
|
}
|
||||||
|
if(num > 0) {
|
||||||
|
kv.second = std::move(rep_cookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request_headers_.insert(std::end(request_headers_),
|
||||||
|
std::begin(cookie_hdrs), std::end(cookie_hdrs));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Downstream::get_assembled_request_cookie() const
|
||||||
|
{
|
||||||
|
return assembled_request_cookie_;
|
||||||
|
}
|
||||||
|
|
||||||
void Downstream::normalize_request_headers()
|
void Downstream::normalize_request_headers()
|
||||||
{
|
{
|
||||||
normalize_headers(request_headers_);
|
normalize_headers(request_headers_);
|
||||||
|
|
|
@ -82,6 +82,9 @@ public:
|
||||||
bool http2_upgrade_request() const;
|
bool http2_upgrade_request() const;
|
||||||
// downstream request API
|
// downstream request API
|
||||||
const Headers& get_request_headers() const;
|
const Headers& get_request_headers() const;
|
||||||
|
void crumble_request_cookie();
|
||||||
|
void assemble_request_cookie();
|
||||||
|
const std::string& get_assembled_request_cookie() const;
|
||||||
// Makes key lowercase and sort headers by name using <
|
// Makes key lowercase and sort headers by name using <
|
||||||
void normalize_request_headers();
|
void normalize_request_headers();
|
||||||
// Returns iterator pointing to the request header with the name
|
// Returns iterator pointing to the request header with the name
|
||||||
|
@ -197,6 +200,7 @@ private:
|
||||||
bool chunked_request_;
|
bool chunked_request_;
|
||||||
bool request_connection_close_;
|
bool request_connection_close_;
|
||||||
bool request_expect_100_continue_;
|
bool request_expect_100_continue_;
|
||||||
|
std::string assembled_request_cookie_;
|
||||||
Headers request_headers_;
|
Headers request_headers_;
|
||||||
bool request_header_key_prev_;
|
bool request_header_key_prev_;
|
||||||
// the length of request body
|
// the length of request body
|
||||||
|
|
|
@ -110,4 +110,40 @@ void test_downstream_get_norm_response_header(void)
|
||||||
CU_ASSERT(i == std::end(d.get_response_headers()));
|
CU_ASSERT(i == std::end(d.get_response_headers()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_downstream_crumble_request_cookie(void)
|
||||||
|
{
|
||||||
|
Downstream d(nullptr, 0, 0);
|
||||||
|
d.add_request_header(":method", "get");
|
||||||
|
d.add_request_header(":path", "/");
|
||||||
|
d.add_request_header("cookie", "alpha; bravo; ; ;; charlie;;");
|
||||||
|
d.add_request_header("cookie", ";delta");
|
||||||
|
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")
|
||||||
|
};
|
||||||
|
CU_ASSERT(ans == d.get_request_headers());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_downstream_assemble_request_cookie(void)
|
||||||
|
{
|
||||||
|
Downstream d(nullptr, 0, 0);
|
||||||
|
d.add_request_header(":method", "get");
|
||||||
|
d.add_request_header(":path", "/");
|
||||||
|
d.add_request_header("cookie", "alpha");
|
||||||
|
d.add_request_header("cookie", "bravo;");
|
||||||
|
d.add_request_header("cookie", "charlie; ");
|
||||||
|
d.add_request_header("cookie", "delta;;");
|
||||||
|
d.assemble_request_cookie();
|
||||||
|
CU_ASSERT("alpha; bravo; charlie; delta" ==
|
||||||
|
d.get_assembled_request_cookie());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -31,6 +31,8 @@ void test_downstream_normalize_request_headers(void);
|
||||||
void test_downstream_normalize_response_headers(void);
|
void test_downstream_normalize_response_headers(void);
|
||||||
void test_downstream_get_norm_request_header(void);
|
void test_downstream_get_norm_request_header(void);
|
||||||
void test_downstream_get_norm_response_header(void);
|
void test_downstream_get_norm_response_header(void);
|
||||||
|
void test_downstream_crumble_request_cookie(void);
|
||||||
|
void test_downstream_assemble_request_cookie(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,7 @@ int Http2DownstreamConnection::push_request_headers()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t nheader = downstream_->get_request_headers().size();
|
size_t nheader = downstream_->get_request_headers().size();
|
||||||
|
downstream_->crumble_request_cookie();
|
||||||
downstream_->normalize_request_headers();
|
downstream_->normalize_request_headers();
|
||||||
auto end_headers = std::end(downstream_->get_request_headers());
|
auto end_headers = std::end(downstream_->get_request_headers());
|
||||||
// 12 means:
|
// 12 means:
|
||||||
|
|
|
@ -116,6 +116,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream)
|
||||||
|
|
||||||
int HttpDownstreamConnection::push_request_headers()
|
int HttpDownstreamConnection::push_request_headers()
|
||||||
{
|
{
|
||||||
|
downstream_->assemble_request_cookie();
|
||||||
downstream_->normalize_request_headers();
|
downstream_->normalize_request_headers();
|
||||||
auto end_headers = std::end(downstream_->get_request_headers());
|
auto end_headers = std::end(downstream_->get_request_headers());
|
||||||
// Assume that method and request path do not contain \r\n.
|
// Assume that method and request path do not contain \r\n.
|
||||||
|
@ -152,6 +153,12 @@ int HttpDownstreamConnection::push_request_headers()
|
||||||
http2::build_http1_headers_from_norm_headers
|
http2::build_http1_headers_from_norm_headers
|
||||||
(hdrs, downstream_->get_request_headers());
|
(hdrs, downstream_->get_request_headers());
|
||||||
|
|
||||||
|
if(!downstream_->get_assembled_request_cookie().empty()) {
|
||||||
|
hdrs += "Cookie: ";
|
||||||
|
hdrs += downstream_->get_assembled_request_cookie();
|
||||||
|
hdrs += "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
if(downstream_->get_request_connection_close()) {
|
if(downstream_->get_request_connection_close()) {
|
||||||
hdrs += "Connection: close\r\n";
|
hdrs += "Connection: close\r\n";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue