-
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
[WIP] new listener filter for terminating HTTP/1 CONNECT(#19077) #19346
Conversation
Hi @liverbirdkte, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
CC @envoyproxy/api-shepherds: Your approval is needed for changes made to |
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.
Nice! I added a few comments.
Also this PR needs docs and tests.
}; | ||
|
||
thread_local uint8_t Filter::buf_[Config::MAX_INSPECT_SIZE]; | ||
static absl::string_view response_body = " 200 Connection Established\r\n\r\n"; |
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.
Per https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
static absl::string_view response_body = " 200 Connection Established\r\n\r\n"; | |
static constexpr absl::string_view response_body = " 200 Connection Established\r\n\r\n"; |
And instead of static
we prefer anonymous namespaces.
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.
got it, will use anonymous namespace instead.
Event::PlatformDefaultTriggerType, Event::FileReadyType::Read); | ||
return Network::FilterStatus::StopIteration; | ||
} | ||
NOT_REACHED_GCOVR_EXCL_LINE; |
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.
The switch
above is meant to be fully exhaustive. We'd better detect a missing case in it if we extend ParseState
. Better replace NOT_REACHED_GCOVR_EXCL_LINE
with ENVOY_BUG()
.
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 you mean adding a default for switch to handle missing cases or to extend ParseState by adding a new status?
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.
No need to add default
as some compilers can generate a warning at compile time about non-exhaustive switch'es.
If ParseState
is ever extended with a new value then this switch
will become non-exhaustive. So, it'll be possible to reach NOT_REACHED_GCOVR_EXCL_LINE
. And that would be a bug most probably. Unfortunately reaching NOT_REACHED_GCOVR_EXCL_LINE
doesn't trigger a bug nor prints a warning. Thus it's better to replace it with ENVOY_BUG()
.
if (result.return_value_ == 0) { | ||
return ParseState::Error; | ||
} | ||
return parseConnect(absl::string_view(reinterpret_cast<const char*>(buf_))); |
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.
nit: no need to instantiate a string_view here.
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.
got it
/wait |
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.
Thanks for working on this, left an API comment.
option (udpa.annotations.versioning).previous_message_type = | ||
"envoy.config.filter.listener.http_inspector.v2.ConnectHandler"; |
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.
I don't think such a type exists.
If there is no v2 predecessor, you should remove the annotation.
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.
sure, will remove this.
Sorry for the late response, thanks for the comments, I'll submit a new version soon. The patch is for issue #19077. |
start working on tests and docs, will update when code is ready |
/wait |
Add unittest, looking at how to write fuzz tests.. |
Add a new listener filter to handle CONNECT request, only HTTP/1.x is supported. 1. inspect if incoming request is HTTP CONNECT 2. drain CONNECT request queue 3. terminate HTTP CONNECT by writing a response to the client 4. set server names using request url in CONNECT request Signed-off-by: leizhang <[email protected]>
Signed-off-by: leizhang <[email protected]>
Signed-off-by: leizhang <[email protected]>
Signed-off-by: leizhang <[email protected]>
7ae9503
to
04203ad
Compare
Please never use git force-push. If the PR is not ready for review you can turn it into a Draft. |
OK, I was fixing some CI failures, saw the DOC issue, so I added sign-off and force push as the instruction on the page told me to. Also didn't mean to modify unrelated jwt_authn proto, but git hook format checker won't get passed unless I apply these changes. |
Thanks, I will convert it back when it's ready. |
Signed-off-by: leizhang <[email protected]>
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.
/lgtm api
left a minor comment.
CODEOWNERS
Outdated
# connect handler | ||
/*/extensions/filters/listener/connect_handler @rojkov @alyssawilk |
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.
Please move up to the extensions part.
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.
done
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.
Thank you! Looks good. I added a few questions.
static constexpr absl::string_view HTTP1_CONNECT_PREFACE = "CONNECT"; | ||
Buffer::OwnedImpl resp_buf_{}; | ||
absl::string_view protocol_; | ||
absl::string_view request_url_; |
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.
Is it used?
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.
Removed
return ParseState::Error; | ||
} | ||
// terminate CONNECT request | ||
resp_buf_.add(protocol_); |
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.
It seems there's no need to make protocol_
a member of the class.
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.
done
http_parser_settings Filter::settings_{ | ||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, | ||
}; |
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.
Can it be just a compilation unit-wide constexpr?
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.
done
thread_local uint8_t Filter::buf_[Config::MAX_INSPECT_SIZE]; | ||
|
||
namespace { | ||
constexpr absl::string_view response_body = " 200 Connection Established\r\n\r\n"; |
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.
According to STYLE.md this should be
constexpr absl::string_view response_body = " 200 Connection Established\r\n\r\n"; | |
constexpr absl::string_view ResponseBody = " 200 Connection Established\r\n\r\n"; |
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.
Done
if (result.return_value_ == 0) { | ||
return ParseState::Error; | ||
} | ||
return parseConnect(absl::string_view(reinterpret_cast<const char*>(buf_), result.return_value_)); |
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.
No need to instantiate a temp string_view here.
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.
done
return ParseState::Done; | ||
} | ||
|
||
std::vector<absl::string_view> fields = absl::StrSplit(data, absl::ByAnyChar(" :")); |
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.
Would it be more efficient to use StringUtil::cropLeft()
and StringUtil::cropRight()
for server name extraction?
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.
done
@@ -756,6 +756,7 @@ interpretable | |||
intra | |||
ints | |||
invariance | |||
iov |
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.
This is probably not needed.
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.
I added this because my local checker could not get passed, removing this to see if CI job works well.
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.
Indeed the check fails. This is weird as I used iov in my PRs and everything was ok. And it's all over the code base. Looks like the code is treated as a comment by the spellchecker. @phlax could you please have a look?
/wait |
Signed-off-by: leizhang <[email protected]>
constexpr http_parser_settings Settings{ | ||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, | ||
}; | ||
} |
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.
nit:
} | |
} // namespace |
#TODO(davinci26): The test passes on Windows *but* http inspector | ||
# *used* to rely on Event::FileTriggerType::Edge and we got away with it |
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.
Is this comment relevant to connect_handler?
envoy_cc_fuzz_test( | ||
name = "connect_handler_fuzz_test", | ||
srcs = ["connect_handler_fuzz_test.cc"], | ||
corpus = "connect_handler_corpus", | ||
deps = [ | ||
"//source/extensions/filters/listener/connect_handler:connect_handler_lib", | ||
"//test/extensions/filters/listener/common/fuzz:listener_filter_fuzzer_lib", | ||
], | ||
) |
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.
This target seems to be missing in the PR.
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.
Thanks!
Left a small comment on the doc.
/lgtm api
I suggest adding an integration test.
Connect Handler | ||
=============== | ||
|
||
Connect Handler listener filter allows detecting whether the incoming request appears to be HTTP/1.x CONNECT, and if it is CONNECT, it removes the CONNECT by reading data from socket and responding with a 200 status code to indicate a connection to remote server is established. It also extracts remote server url from the CONNECT. This can be used to select a |
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.
Connect Handler listener filter allows detecting whether the incoming request appears to be HTTP/1.x CONNECT, and if it is CONNECT, it removes the CONNECT by reading data from socket and responding with a 200 status code to indicate a connection to remote server is established. It also extracts remote server url from the CONNECT. This can be used to select a | |
Connect Handler listener filter allows detecting whether the incoming request appears to be HTTP/1.x CONNECT, and if it is CONNECT, it removes the CONNECT by reading data from the socket and responding with a 200 status code to indicate a connection to the remote server is established. It also extracts the remote server url from the CONNECT. This can be used to select a |
/wait |
This pull request has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 37 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
Add a new listener filter to handle CONNECT request, only HTTP/1.x is supported.
inspect if incoming request is HTTP CONNECT
drain CONNECT request data out of queue
terminate HTTP CONNECT by writing a response to the client
set server names using request url in CONNECT request
It seems the behavior of draining CONNECT data and writing response may have an impact on other listener filters in the loop. Is there any way to exit the listener filter iteration? Or I should put this listener filter as the last one in the config.
Commit Message:
Additional Description:
Risk Level:
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Fixes commit #PR or SHA]
[Optional Deprecated:]
[Optional API Considerations:]