-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Removed exception in getResponseStatus() #13314
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
Changes from 2 commits
6c1b18e
5d54f1e
b4564b2
1d723cf
0900801
582a966
dcfddd3
5f345b3
f34ac08
5d49ae6
0e260cd
ebd0f1a
8f2e640
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 |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| #include "absl/strings/str_cat.h" | ||
| #include "absl/strings/str_split.h" | ||
| #include "absl/strings/string_view.h" | ||
| #include "absl/types/optional.h" | ||
| #include "nghttp2/nghttp2.h" | ||
|
|
||
| namespace Envoy { | ||
|
|
@@ -369,10 +370,17 @@ std::string Utility::makeSetCookieValue(const std::string& key, const std::strin | |
| } | ||
|
|
||
| uint64_t Utility::getResponseStatus(const ResponseHeaderMap& headers) { | ||
| absl::StatusOr<uint64_t> response_status_or_absl_status = getResponseStatusOr(headers); | ||
|
Contributor
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. Is there a case where this function can fail parsing the Status header now that there are tests that verify that invalid Status header is rejected by both H/1 and H/2 codecs?
Contributor
Author
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. No, but you don't think it's worth removing exceptions (removing meaning converting to error earlier instead of in try catch block) for any future iterations, considering if we keep the exception then it'll still be there in the long run, even though currently not triggerable?
Contributor
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. I think it is totally worth removing this exception. We have proven with the test that the code does the right thing and does not accept responses with invalid Status header. Given this I think we should just assert that the parsing of the status number was successful. I think we could use ENVOY_BUG or event RELEASE_ASSERT here, given that we have solid test.
Contributor
Author
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. Hey Yan, I've been thinking about this some, and I think that the problem is that getResponseStatus() is called all around the codebase, and the problem is that if we make it an assert rather than an exception for other parts of the codebase, it would introduce a point of failure out of nothing? Let me know what you're thinking :) |
||
| RELEASE_ASSERT(response_status_or_absl_status.ok(), | ||
| ":status must be specified and a valid unsigned long"); | ||
|
zasweq marked this conversation as resolved.
Outdated
|
||
| return response_status_or_absl_status.value(); | ||
| } | ||
|
|
||
| absl::StatusOr<uint64_t> Utility::getResponseStatusOr(const ResponseHeaderMap& headers) { | ||
|
Contributor
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. When this method is only called from the
Contributor
Author
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. Interesting. I liked how this got rid of exceptions, but your suggestion is a much cleaner way to remove the exceptions. Take the two things in the if and move one thing (simpleAtoi() call) to an assert and another (status presence) to codebase. However, I do believe the codecs already account for missing status headers similarly to overflowing status, so why even add a check there? @asraa what are your thoughts
Contributor
Author
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. Quickly glanced around codebase, couldn't seem to find a missing status integration test? If not there (perhaps ctrl f in GitHub missed it :)) I can add one!
Contributor
Author
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. Out of my own interest I wrote an http2 frame method for header frames without statuses breaking the HTTP/2 requirement and wrote an integration test for it. I got "[2020-10-22 05:28:34.375][31][trace][http2] [source/common/http/http2/codec_impl.cc:715] [C2] about to recv frame type=1, flags=5
Contributor
Author
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. Hey Yan, I discussed this with Asra in our standup. Asra wants to keep it consistent, and is indifferent to whether we ASSERT or have a check, however wants to keep it consistent, and not an assert on atoi and a check for headers, because that would be unneeded complexity by splitting them.
Contributor
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. Ok, I understand. I think given that we also verify that missing status from the response headers is rejected, I think we could either ENVOY_BUG or RELEASE_ASSERT that status header is present.
Contributor
Author
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. So release assert on both conditions in the utility function?
Contributor
Author
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. "Both" meaning missing status and overflowed status
Contributor
Author
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. Hey - so just to make sure - what you want is to keep the function as is, but instead of throwing up an exception with the if clause, wrap those two booleans (headers present, atoi call okay) in a RELASE_ASSERT. Basically, since we have validated that across both codecs the codecs handle it, we can move it.
Contributor
Author
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. "Keep the function as is" meaning what is currently checked into master for getResponseStatus? Both utility function and not having my error handling in codecs. |
||
| const HeaderEntry* header = headers.Status(); | ||
| uint64_t response_code; | ||
| if (!header || !absl::SimpleAtoi(headers.getStatusValue(), &response_code)) { | ||
| throw CodecClientException(":status must be specified and a valid unsigned long"); | ||
| return absl::InvalidArgumentError(":status must be specified and a valid unsigned long"); | ||
| } | ||
| return response_code; | ||
| } | ||
|
|
||
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 think it is possible that it could throw exception and exception and not crash when processing upstream response. The exception would have been caught by the dispatch() method of the client connection. Do we have an integration test where upstream responds with a garbage status?