-
Notifications
You must be signed in to change notification settings - Fork 5.5k
http: stream error on invalid HTTP messaging for HTTP/1 #11884
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 36 commits
ee7cb0d
b04b98e
46768be
d1bf85d
2d7e93d
86031f0
397e369
c139ff1
2d6cac8
d30e854
aa421fd
9718246
cc33ccf
cab6751
00814d2
7f61bdf
908bdfc
e5239e8
4b2f72a
922bb6f
9dec35a
5fb9be3
83cbadf
c9c55bc
a31323f
354c08b
07c3ee5
5e1b95e
eec3bb2
f1787af
2fe6fbc
447b719
c1d456a
025dbc4
30154d7
f99724d
a35bada
b037f64
16414a0
4bb2a86
1410972
5e63612
85e57c4
3dd2c3d
464a5c7
e663b45
d92640d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,7 @@ Minor Behavior Changes | |
| * compressor: always insert `Vary` headers for compressible resources even if it's decided not to compress a response due to incompatible `Accept-Encoding` value. The `Vary` header needs to be inserted to let a caching proxy in front of Envoy know that the requested resource still can be served with compression applied. | ||
| * decompressor: headers-only requests were incorrectly not advertising accept-encoding when configured to do so. This is now fixed. | ||
| * http: added :ref:`headers_to_add <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.ResponseMapper.headers_to_add>` to :ref:`local reply mapper <config_http_conn_man_local_reply>` to allow its users to add/append/override response HTTP headers to local replies. | ||
| * http: added HCM level configuration of :ref:`error handling on invalid messaging <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.stream_error_on_invalid_http_message>` which substantially changes Envoy's behavior when encountering invalid HTTP/1.1 defaulting to closing the connection instead of allowing reuse. This can temporarily be reverted by setting `envoy.reloadable_features.hcm_stream_error_on_invalid_message` to false, or permanently reverted by setting the :ref:`HCM option <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.stream_error_on_invalid_http_message>` to true to restore prior HTTP/1.1 beavior and setting the *new* HTTP/2 configuration :ref:`override_stream_error_on_invalid_http_message <envoy_v3_api_field_config.core.v3.Http2ProtocolOptions.override_stream_error_on_invalid_http_message>` to false to retain prior HTTP/2 behavior. | ||
| * http: added HCM level configuration of :ref:`error handling on invalid messaging <envoy_v3_api_field_extensions.filters.network.http_connection_manager.v3.HttpConnectionManager.stream_error_on_invalid_http_message>` which substantially changes Envoy's behavior when encountering invalid HTTP/1.1 defaulting to closing the connection instead of allowing reuse. This can temporarily be reverted by setting `envoy.reloadable_features.hcm_stream_error_on_invalid_message` to false, or permanently reverted by setting the HTTP/1 configuration :ref:`override_stream_error_on_invalid_http_message <envoy_v3_api_field_config.core.v3.Http1ProtocolOptions.override_stream_error_on_invalid_http_message>` to true to restore prior HTTP/1.1 behavior. | ||
|
Member
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. Did you mean to delete the HTTP/2 text from here? I think we just want to unify the release note? |
||
| * http: changed Envoy to send error headers and body when possible. This behavior may be temporarily reverted by setting `envoy.reloadable_features.allow_response_for_timeout` to false. | ||
| * http: changed empty trailers encoding behavior by sending empty data with ``end_stream`` true (instead of sending empty trailers) for HTTP/2. This behavior can be reverted temporarily by setting runtime feature ``envoy.reloadable_features.http2_skip_encoding_empty_trailers`` to false. | ||
| * http: clarified and enforced 1xx handling. Multiple 100-continue headers are coalesced when proxying. 1xx headers other than {100, 101} are dropped. | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -142,6 +142,12 @@ class ResponseEncoder : public virtual StreamEncoder { | |
| * @param trailers supplies the trailers to encode. | ||
| */ | ||
| virtual void encodeTrailers(const ResponseTrailerMap& trailers) PURE; | ||
|
|
||
| /** | ||
| * Indicates whether invalid HTTP messaging should be handled with a stream error or a connection | ||
| * error. | ||
|
Comment on lines
+147
to
+148
Member
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. What does nullopt mean in this context?
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. It would mean that the new HTTP/1.1 config
Member
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 makes sense can you clarify the comment? Also what does this mean in the case of upstream since there is no HCM? |
||
| */ | ||
| virtual absl::optional<bool> streamErrorOnInvalidHttpMessage() const PURE; | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -386,6 +392,12 @@ struct Http1Settings { | |
|
|
||
| // How header keys should be formatted when serializing HTTP/1.1 headers. | ||
| HeaderKeyFormat header_key_format_{HeaderKeyFormat::Default}; | ||
|
|
||
| // Behaviour on invalid HTTP messaging: | ||
| // - if set and true, the HTTP/1.1 connection is left open (where possible) | ||
| // - if set and false, the HTTP/1.1 connection is terminated | ||
| // - if not set, fall back to the HCM behaviour on invalid HTTP messaging | ||
|
Member
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. Similar comment here about HCM. This is generic for upstream and downstream. Where does the upstream default come from?
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. The new HTTP/1.1 config introduced here works in tandem with the newly introduced
Member
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. Yeah I think it would be good to call this out more in the comments and the proto documentation. The proto is a generic message that is used for both upstream and downstream, so I think it would be good to clarify that it only applies right now for downstream? |
||
| absl::optional<bool> stream_error_on_invalid_http_message_; | ||
| }; | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,6 +80,16 @@ void recordLatestDataFilter(const typename FilterList<T>::iterator current_filte | |
| } | ||
| } | ||
|
|
||
| bool streamErrorOnInvalidHttpMessage( | ||
| bool hcm_stream_error_on_invalid_http_message, | ||
| const absl::optional<bool> override_stream_error_on_invalid_http_message) { | ||
| if (override_stream_error_on_invalid_http_message.has_value()) { | ||
| return override_stream_error_on_invalid_http_message.value(); | ||
| } else { | ||
| return hcm_stream_error_on_invalid_http_message; | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| ConnectionManagerStats ConnectionManagerImpl::generateStats(const std::string& prefix, | ||
|
|
@@ -1578,8 +1588,10 @@ void ConnectionManagerImpl::ActiveStream::sendLocalReply( | |
| // The BadRequest error code indicates there has been a messaging error. | ||
| if (Runtime::runtimeFeatureEnabled( | ||
| "envoy.reloadable_features.hcm_stream_error_on_invalid_message") && | ||
| !connection_manager_.config_.streamErrorOnInvalidHttpMessaging() && | ||
| code == Http::Code::BadRequest && connection_manager_.codec_->protocol() < Protocol::Http2) { | ||
| code == Http::Code::BadRequest && connection_manager_.codec_->protocol() < Protocol::Http2 && | ||
| !streamErrorOnInvalidHttpMessage( | ||
|
Member
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 need to runtime guard this twice? Can we remove the first if condition? Also, I haven't been tracking all of these changes, and you probably already discussed this with Alyssa, but is this the only place this needs to be checked? I would have naively assumed there are more places this is needed but maybe not?
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. The runtime guard here is needed because it affects HTTP/1.1 specifically, and the other place where it's checked affects HTTP/2 instead. As far as I understand, prior to #11714, we were sending errors in two places (codec and HCM), however after that change we now send errors only in the HCM. Not sure if we should check in the other code path as well (see #11884 (comment)). |
||
| connection_manager_.config_.streamErrorOnInvalidHttpMessaging(), | ||
| response_encoder_->streamErrorOnInvalidHttpMessage())) { | ||
| state_.saw_connection_close_ = true; | ||
| } | ||
|
|
||
|
|
||
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 you can leave out the "if not set" because the sentence above makes it clear that otherwise the HCM value is used.