-
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
http: stream error on invalid HTTP messaging for HTTP/1 #11884
Changes from 17 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.
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
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? 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 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; | ||
}; | ||
|
||
/** | ||
|
@@ -388,6 +394,8 @@ struct Http1Settings { | |
|
||
// How header keys should be formatted when serializing HTTP/1.1 headers. | ||
HeaderKeyFormat header_key_format_{HeaderKeyFormat::Default}; | ||
|
||
absl::optional<bool> stream_error_on_invalid_http_message_{}; | ||
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. comment, please! 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: {} not needed |
||
}; | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
#include "common/http/conn_manager_impl.h" | ||
|
||
#include <cstdint> | ||
#include <functional> | ||
#include <list> | ||
|
@@ -27,6 +25,7 @@ | |
#include "common/common/scope_tracker.h" | ||
#include "common/common/utility.h" | ||
#include "common/http/codes.h" | ||
#include "common/http/conn_manager_impl.h" | ||
#include "common/http/conn_manager_utility.h" | ||
#include "common/http/exception.h" | ||
#include "common/http/header_map_impl.h" | ||
|
@@ -1524,8 +1523,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 && | ||
!Utility::streamErrorOnInvalidHttpMessage( | ||
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. If this function is only used in one place, I'd be mildly inclined to make this utility in an unnamed namespace in the cc file, and unit test the HCM by setting explicit configs. WDYT? 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. ping? |
||
connection_manager_.config_.streamErrorOnInvalidHttpMessaging(), | ||
response_encoder_->streamErrorOnInvalidHttpMessage())) { | ||
state_.saw_connection_close_ = true; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -123,8 +123,11 @@ class StreamEncoderImpl : public virtual StreamEncoder, | |
*/ | ||
class ResponseEncoderImpl : public StreamEncoderImpl, public ResponseEncoder { | ||
public: | ||
ResponseEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter) | ||
: StreamEncoderImpl(connection, header_key_formatter) {} | ||
ResponseEncoderImpl(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter, | ||
absl::optional<bool>& stream_error_on_invalid_http_message) | ||
: StreamEncoderImpl(connection, header_key_formatter) { | ||
stream_error_on_invalid_http_message_ = stream_error_on_invalid_http_message; | ||
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: initialize in initializer list, make constant member. Same below. |
||
} | ||
|
||
bool startedResponse() { return started_response_; } | ||
|
||
|
@@ -133,8 +136,13 @@ class ResponseEncoderImpl : public StreamEncoderImpl, public ResponseEncoder { | |
void encodeHeaders(const ResponseHeaderMap& headers, bool end_stream) override; | ||
void encodeTrailers(const ResponseTrailerMap& trailers) override { encodeTrailersBase(trailers); } | ||
|
||
absl::optional<bool> streamErrorOnInvalidHttpMessage() const override { | ||
return stream_error_on_invalid_http_message_; | ||
} | ||
|
||
private: | ||
bool started_response_{}; | ||
absl::optional<bool> stream_error_on_invalid_http_message_; | ||
}; | ||
|
||
/** | ||
|
@@ -432,8 +440,9 @@ class ServerConnectionImpl : public ServerConnection, public ConnectionImpl { | |
* An active HTTP/1.1 request. | ||
*/ | ||
struct ActiveRequest { | ||
ActiveRequest(ConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter) | ||
: response_encoder_(connection, header_key_formatter) {} | ||
ActiveRequest(ServerConnectionImpl& connection, HeaderKeyFormatter* header_key_formatter) | ||
: response_encoder_(connection, header_key_formatter, | ||
connection.codec_settings_.stream_error_on_invalid_http_message_) {} | ||
|
||
HeaderString request_url_; | ||
RequestDecoder* request_decoder_{}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -349,7 +349,9 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable<Log | |
*/ | ||
struct ServerStreamImpl : public StreamImpl, public ResponseEncoder { | ||
ServerStreamImpl(ConnectionImpl& parent, uint32_t buffer_limit) | ||
: StreamImpl(parent, buffer_limit), headers_or_trailers_(RequestHeaderMapImpl::create()) {} | ||
: StreamImpl(parent, buffer_limit), headers_or_trailers_(RequestHeaderMapImpl::create()) { | ||
stream_error_on_invalid_http_message_ = parent.stream_error_on_invalid_http_messaging_; | ||
alyssawilk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// StreamImpl | ||
void submitHeaders(const std::vector<nghttp2_nv>& final_headers, | ||
|
@@ -381,6 +383,11 @@ class ConnectionImpl : public virtual Connection, protected Logger::Loggable<Log | |
|
||
RequestDecoder* request_decoder_{}; | ||
absl::variant<RequestHeaderMapPtr, RequestTrailerMapPtr> headers_or_trailers_; | ||
absl::optional<bool> stream_error_on_invalid_http_message_; | ||
|
||
absl::optional<bool> streamErrorOnInvalidHttpMessage() const override { | ||
return stream_error_on_invalid_http_message_; | ||
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 latch this, or can we just return parent_.stream_error_on_invalid_http_messaging_ here? Also let's make sure this and the HTTP/1.1 function have unit tests, even if they're pretty trivial. |
||
} | ||
}; | ||
|
||
using ServerStreamImplPtr = std::unique_ptr<ServerStreamImpl>; | ||
|
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.
Hm, when this option is disabled, Envoy will terminate the connection, but I think you should remove reference to default behavior, since the default behavior is actually to ignore this field and use the HCM value.