-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
websocket: http request header Connection may contains multiple values #2070
Changes from 3 commits
c45b1ad
d11de77
4ffbe41
4913e34
8d1b113
f922cb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,6 +102,28 @@ class HeaderString { | |
*/ | ||
bool find(const char* str) const { return strstr(c_str(), str); } | ||
|
||
/** | ||
* HeaderString is in token list form, each token separated by commas or whitespace, | ||
* see https://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.1 for more information, | ||
* header field value's case sensitivity depends on each header. | ||
* @return whether contains token in case insensitive manner. | ||
*/ | ||
bool caseInsensitiveContains(const char* token) const { | ||
const int n = strlen(token); | ||
if (n == 0) { | ||
return true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this should return false? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you are right. |
||
} | ||
const char* tokens = c_str(); | ||
const char* separators = " ,"; | ||
for (const char* p = tokens; (p = strcasestr(p, token)); p += n) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this logic is really hard to quickly read. Can you add a small comment on what it is doing? |
||
if ((p == tokens || strchr(separators, *(p - 1)) != NULL) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: s/NULL/nullptr in both places. |
||
(*(p + n) == '\0' || strchr(separators, *(p + n)) != NULL)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Set the value of the string by copying data into it. This overwrites any existing string. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,18 +22,31 @@ void ConnectionManagerUtility::mutateRequestHeaders( | |
Runtime::RandomGenerator& random, Runtime::Loader& runtime, | ||
const LocalInfo::LocalInfo& local_info) { | ||
// Clean proxy headers. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops sorry, one more nit: Can you please move this comment down with the rest of header removes? |
||
request_headers.removeEnvoyInternalRequest(); | ||
request_headers.removeKeepAlive(); | ||
request_headers.removeProxyConnection(); | ||
request_headers.removeTransferEncoding(); | ||
|
||
// If this is a WebSocket Upgrade request, do not remove the Connection and Upgrade headers, | ||
// as we forward them verbatim to the upstream hosts. | ||
if (protocol != Protocol::Http11 || !Utility::isWebSocketUpgradeRequest(request_headers)) { | ||
if (protocol == Protocol::Http11 && Utility::isWebSocketUpgradeRequest(request_headers)) { | ||
// Current WebSocket implementation re-use the HTTP1 codec to send upgrade headers to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Grammar nits, please just replace with (reflow as needed to 100 col):
|
||
// upstream host, which add "transfer-encoding: chunked" request header if stream not end | ||
// and content-length not exists. | ||
// In HTTP1.1, if transfer-encoding and content-length both not exists means no request body, | ||
// after transfer-encoding striped here, the upstream request become invalid: | ||
// chunked encoding with no request body. | ||
// We can fix it by explicitly add a "content-length: 0" request header here. | ||
bool no_body = (!request_headers.TransferEncoding() && !request_headers.ContentLength()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: |
||
if (no_body) { | ||
request_headers.insertContentLength().value(uint64_t(0)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a test case where we check for the existence of content-length: 0? We should be able to look for this in one of the conn_manager_impl websocket tests. |
||
} | ||
} else { | ||
request_headers.removeConnection(); | ||
request_headers.removeUpgrade(); | ||
} | ||
|
||
request_headers.removeEnvoyInternalRequest(); | ||
request_headers.removeKeepAlive(); | ||
request_headers.removeProxyConnection(); | ||
request_headers.removeTransferEncoding(); | ||
|
||
// If we are "using remote address" this means that we create/append to XFF with our immediate | ||
// peer. Cases where we don't "use remote address" include trusted double proxy where we expect | ||
// our peer to have already properly set XFF, etc. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a test case for this branch?