diff --git a/include/envoy/stream_info/stream_info.h b/include/envoy/stream_info/stream_info.h index 96d6a5e9d2404..bd7ff887b20db 100644 --- a/include/envoy/stream_info/stream_info.h +++ b/include/envoy/stream_info/stream_info.h @@ -18,6 +18,7 @@ #include "common/singleton/const_singleton.h" #include "absl/types/optional.h" +#include "absl/types/span.h" namespace Envoy { @@ -148,6 +149,18 @@ struct ResponseCodeDetailValues { using ResponseCodeDetails = ConstSingleton; +struct ProtocolStringValues { + const std::string TcpString{"TCP"}; + const std::string UdpString{"UDP"}; + const std::string HttpString{"HTTP"}; + const std::string Http10String{"HTTP/1.0"}; + const std::string Http11String{"HTTP/1.1"}; + const std::string Http2String{"HTTP/2"}; + const std::string Http3String{"HTTP/3"}; +}; + +using ProtocolStrings = ConstSingleton; + struct UpstreamTiming { /** * Sets the time when the first byte of the request was sent upstream. @@ -238,14 +251,14 @@ class StreamInfo { virtual uint64_t bytesReceived() const PURE; /** - * @return the protocol of the request. + * @return the set of protocols detected for a stream. */ - virtual absl::optional protocol() const PURE; + virtual absl::Span protocols() const PURE; /** - * @param protocol the request's protocol. + * @param protocol the request's protocol */ - virtual void protocol(Http::Protocol protocol) PURE; + virtual void addProtocol(absl::string_view protocol) PURE; /** * @return the response code. @@ -486,6 +499,7 @@ class StreamInfo { * filters (append only). Both object types can be consumed by multiple filters. * @return the filter state associated with this request. */ + virtual FilterStateSharedPtr& mutableFilterState() PURE; virtual const FilterStateSharedPtr& filterState() PURE; virtual const FilterState& filterState() const PURE; diff --git a/source/common/access_log/access_log_formatter.cc b/source/common/access_log/access_log_formatter.cc index 66b9d353158cf..50faa742cf9a1 100644 --- a/source/common/access_log/access_log_formatter.cc +++ b/source/common/access_log/access_log_formatter.cc @@ -61,12 +61,15 @@ FormatterPtr AccessLogFormatUtils::defaultAccessLogFormatter() { return FormatterPtr{new FormatterImpl(DEFAULT_FORMAT)}; } -const std::string& -AccessLogFormatUtils::protocolToString(const absl::optional& protocol) { - if (protocol) { +const std::string AccessLogFormatUtils::protocolToString(absl::Span protocols) { + auto protocol = Http::Utility::getProtocol(protocols); + if (protocol.has_value()) { return Http::Utility::getProtocolString(protocol.value()); } - return UnspecifiedValueString; + if (protocols.empty()) { + return UnspecifiedValueString; + } + return absl::StrJoin(protocols, ","); } const std::string AccessLogFormatUtils::getHostname() { @@ -558,7 +561,7 @@ StreamInfoFormatter::StreamInfoFormatter(const std::string& field_name) { } else if (field_name == "PROTOCOL") { field_extractor_ = std::make_unique( [](const StreamInfo::StreamInfo& stream_info) { - return AccessLogFormatUtils::protocolToString(stream_info.protocol()); + return AccessLogFormatUtils::protocolToString(stream_info.protocols()); }); } else if (field_name == "RESPONSE_CODE") { field_extractor_ = std::make_unique( diff --git a/source/common/access_log/access_log_formatter.h b/source/common/access_log/access_log_formatter.h index 86405ec2c3f1b..d4987085c4720 100644 --- a/source/common/access_log/access_log_formatter.h +++ b/source/common/access_log/access_log_formatter.h @@ -73,7 +73,7 @@ class AccessLogFormatParser { class AccessLogFormatUtils { public: static FormatterPtr defaultAccessLogFormatter(); - static const std::string& protocolToString(const absl::optional& protocol); + static const std::string protocolToString(absl::Span protocols); static const std::string getHostname(); private: diff --git a/source/common/http/conn_manager_impl.cc b/source/common/http/conn_manager_impl.cc index 80ba2147736b0..003e00d3ace10 100644 --- a/source/common/http/conn_manager_impl.cc +++ b/source/common/http/conn_manager_impl.cc @@ -357,7 +357,9 @@ Network::FilterStatus ConnectionManagerImpl::onData(Buffer::Instance& data, bool } Network::FilterStatus ConnectionManagerImpl::onNewConnection() { - if (!read_callbacks_->connection().streamInfo().protocol()) { + read_callbacks_->connection().streamInfo().addProtocol( + StreamInfo::ProtocolStrings::get().HttpString); + if (!Http::Utility::getProtocol(read_callbacks_->connection().streamInfo().protocols())) { // For Non-QUIC traffic, continue passing data to filters. return Network::FilterStatus::Continue; } @@ -539,7 +541,7 @@ ConnectionManagerImpl::ActiveStream::ActiveStream(ConnectionManagerImpl& connect request_response_timespan_(new Stats::HistogramCompletableTimespanImpl( connection_manager_.stats_.named_.downstream_rq_time_, connection_manager_.timeSource())), stream_info_(connection_manager_.codec_->protocol(), connection_manager_.timeSource(), - connection_manager.filterState()), + connection_manager_.read_callbacks_->connection().streamInfo()), upstream_options_(std::make_shared()) { ASSERT(!connection_manager.config_.isRoutable() || ((connection_manager.config_.routeConfigProvider() == nullptr && @@ -814,7 +816,9 @@ void ConnectionManagerImpl::ActiveStream::decodeHeaders(RequestHeaderMapPtr&& he // HTTP/1.1. // // The protocol may have shifted in the HTTP/1.0 case so reset it. - stream_info_.protocol(protocol); + if (Http::Utility::getProtocol(stream_info_.protocols()) != protocol) { + stream_info_.addProtocol(Http::Utility::getProtocolString(protocol)); + } if (!connection_manager_.config_.http1Settings().accept_http_10_) { // Send "Upgrade Required" if HTTP/1.0 support is not explicitly configured on. sendLocalReply(false, Code::UpgradeRequired, "", nullptr, state_.is_head_request_, diff --git a/source/common/http/conn_manager_impl.h b/source/common/http/conn_manager_impl.h index 426bb60a57fb6..3f880adea56d1 100644 --- a/source/common/http/conn_manager_impl.h +++ b/source/common/http/conn_manager_impl.h @@ -102,9 +102,6 @@ class ConnectionManagerImpl : Logger::Loggable, TimeSource& timeSource() { return time_source_; } - // Return a reference to the shared_ptr so that it can be lazy created on demand. - std::shared_ptr& filterState() { return filter_state_; } - private: struct ActiveStream; @@ -787,7 +784,6 @@ class ConnectionManagerImpl : Logger::Loggable, const Server::OverloadActionState& overload_stop_accepting_requests_ref_; const Server::OverloadActionState& overload_disable_keepalive_ref_; TimeSource& time_source_; - std::shared_ptr filter_state_; }; } // namespace Http diff --git a/source/common/http/headers.h b/source/common/http/headers.h index 2698501edff8b..7785a9b4a9f3b 100644 --- a/source/common/http/headers.h +++ b/source/common/http/headers.h @@ -271,13 +271,6 @@ class HeaderValues { const std::string True{"true"}; } CORSValues; - struct { - const std::string Http10String{"HTTP/1.0"}; - const std::string Http11String{"HTTP/1.1"}; - const std::string Http2String{"HTTP/2"}; - const std::string Http3String{"HTTP/3"}; - } ProtocolStrings; - struct { const std::string Gzip{"gzip"}; const std::string Identity{"identity"}; diff --git a/source/common/http/utility.cc b/source/common/http/utility.cc index ea4aa41cd4e80..0628fded36710 100644 --- a/source/common/http/utility.cc +++ b/source/common/http/utility.cc @@ -636,18 +636,34 @@ bool Utility::sanitizeConnectionHeader(Http::RequestHeaderMap& headers) { const std::string& Utility::getProtocolString(const Protocol protocol) { switch (protocol) { case Protocol::Http10: - return Headers::get().ProtocolStrings.Http10String; + return StreamInfo::ProtocolStrings::get().Http10String; case Protocol::Http11: - return Headers::get().ProtocolStrings.Http11String; + return StreamInfo::ProtocolStrings::get().Http11String; case Protocol::Http2: - return Headers::get().ProtocolStrings.Http2String; + return StreamInfo::ProtocolStrings::get().Http2String; case Protocol::Http3: - return Headers::get().ProtocolStrings.Http3String; + return StreamInfo::ProtocolStrings::get().Http3String; } NOT_REACHED_GCOVR_EXCL_LINE; } +absl::optional Utility::getProtocol(absl::Span protocols) { + for (auto it = protocols.rbegin(); it != protocols.rend(); it++) { + if (*it == StreamInfo::ProtocolStrings::get().Http10String) { + return Protocol::Http10; + } else if (*it == StreamInfo::ProtocolStrings::get().Http11String) { + return Protocol::Http11; + } else if (*it == StreamInfo::ProtocolStrings::get().Http2String) { + return Protocol::Http2; + } else if (*it == StreamInfo::ProtocolStrings::get().Http3String) { + return Protocol::Http3; + } + } + + return {}; +} + void Utility::extractHostPathFromUri(const absl::string_view& uri, absl::string_view& host, absl::string_view& path) { /** diff --git a/source/common/http/utility.h b/source/common/http/utility.h index 2daa237894d17..e3861029990bb 100644 --- a/source/common/http/utility.h +++ b/source/common/http/utility.h @@ -314,6 +314,13 @@ bool sanitizeConnectionHeader(Http::RequestHeaderMap& headers); */ const std::string& getProtocolString(const Protocol p); +/** + * Get the http protocol from the given protocol list. + * @param protocol list from the stream info. + * @return the last (most-specific) http protocol in the list. + */ +absl::optional getProtocol(absl::Span protocols); + /** * Extract host and path from a URI. The host may contain port. * This function doesn't validate if the URI is valid. It only parses the URI with following diff --git a/source/common/router/header_formatter.cc b/source/common/router/header_formatter.cc index fd84519f722dd..0451fbbb8869a 100644 --- a/source/common/router/header_formatter.cc +++ b/source/common/router/header_formatter.cc @@ -222,7 +222,7 @@ StreamInfoHeaderFormatter::StreamInfoHeaderFormatter(absl::string_view field_nam : append_(append) { if (field_name == "PROTOCOL") { field_extractor_ = [](const Envoy::StreamInfo::StreamInfo& stream_info) { - return Envoy::AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocol()); + return Envoy::AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocols()); }; } else if (field_name == "DOWNSTREAM_REMOTE_ADDRESS") { field_extractor_ = [](const StreamInfo::StreamInfo& stream_info) { diff --git a/source/common/router/router.cc b/source/common/router/router.cc index 3719b887a061c..78fdbbfafc1db 100644 --- a/source/common/router/router.cc +++ b/source/common/router/router.cc @@ -645,7 +645,8 @@ Http::FilterHeadersStatus Filter::decodeHeaders(Http::RequestHeaderMap& headers, Http::ConnectionPool::Instance* Filter::getConnPool() { // Choose protocol based on cluster configuration and downstream connection // Note: Cluster may downgrade HTTP2 to HTTP1 based on runtime configuration. - Http::Protocol protocol = cluster_->upstreamHttpProtocol(callbacks_->streamInfo().protocol()); + Http::Protocol protocol = cluster_->upstreamHttpProtocol( + Http::Utility::getProtocol(callbacks_->streamInfo().protocols())); transport_socket_options_ = Network::TransportSocketOptionsUtility::fromFilterState( *callbacks_->streamInfo().filterState()); diff --git a/source/common/stream_info/BUILD b/source/common/stream_info/BUILD index e2c04653a5561..8d4db7b15d421 100644 --- a/source/common/stream_info/BUILD +++ b/source/common/stream_info/BUILD @@ -16,6 +16,7 @@ envoy_cc_library( "//include/envoy/stream_info:stream_info_interface", "//source/common/common:assert_lib", "//source/common/common:dump_state_utils", + "//source/common/http:utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", ], ) diff --git a/source/common/stream_info/filter_state_impl.cc b/source/common/stream_info/filter_state_impl.cc index 6097f02e04286..d873587abfcf8 100644 --- a/source/common/stream_info/filter_state_impl.cc +++ b/source/common/stream_info/filter_state_impl.cc @@ -97,8 +97,8 @@ void FilterStateImpl::maybeCreateParent(ParentAccessMode parent_access_mode) { if (life_span_ >= FilterState::LifeSpan::TopSpan) { return; } - if (absl::holds_alternative>(ancestor_)) { - std::shared_ptr ancestor = absl::get>(ancestor_); + if (absl::holds_alternative(ancestor_)) { + FilterStateSharedPtr ancestor = absl::get(ancestor_); if (ancestor == nullptr || ancestor->lifeSpan() != life_span_ + 1) { parent_ = std::make_shared(ancestor, FilterState::LifeSpan(life_span_ + 1)); } else { diff --git a/source/common/stream_info/filter_state_impl.h b/source/common/stream_info/filter_state_impl.h index 6bf8fb9ad517b..793938e29eadc 100644 --- a/source/common/stream_info/filter_state_impl.h +++ b/source/common/stream_info/filter_state_impl.h @@ -22,12 +22,12 @@ class FilterStateImpl : public FilterState { * @param ancestor a std::shared_ptr storing an already created ancestor. * @param life_span the life span this is handling. */ - FilterStateImpl(std::shared_ptr ancestor, FilterState::LifeSpan life_span) + FilterStateImpl(FilterStateSharedPtr ancestor, FilterState::LifeSpan life_span) : ancestor_(ancestor), life_span_(life_span) { maybeCreateParent(ParentAccessMode::ReadOnly); } - using LazyCreateAncestor = std::pair&, FilterState::LifeSpan>; + using LazyCreateAncestor = std::pair; /** * @param ancestor a std::pair storing an ancestor, that can be passed in as a way to lazy * initialize a FilterState that's owned by an object with bigger scope than this. This is to @@ -49,7 +49,7 @@ class FilterStateImpl : public FilterState { bool hasDataAtOrAboveLifeSpan(FilterState::LifeSpan life_span) const override; FilterState::LifeSpan lifeSpan() const override { return life_span_; } - std::shared_ptr parent() const override { return parent_; } + FilterStateSharedPtr parent() const override { return parent_; } private: // This only checks the local data_storage_ for data_name existence. @@ -62,8 +62,8 @@ class FilterStateImpl : public FilterState { FilterState::StateType state_type_; }; - absl::variant, LazyCreateAncestor> ancestor_; - std::shared_ptr parent_; + absl::variant ancestor_; + FilterStateSharedPtr parent_; const FilterState::LifeSpan life_span_; absl::flat_hash_map> data_storage_; }; diff --git a/source/common/stream_info/stream_info_impl.h b/source/common/stream_info/stream_info_impl.h index 85f3296cb9482..0259c6828e13a 100644 --- a/source/common/stream_info/stream_info_impl.h +++ b/source/common/stream_info/stream_info_impl.h @@ -10,6 +10,7 @@ #include "common/common/assert.h" #include "common/common/dump_state_utils.h" +#include "common/http/utility.h" #include "common/stream_info/filter_state_impl.h" namespace Envoy { @@ -23,17 +24,22 @@ struct StreamInfoImpl : public StreamInfo { StreamInfoImpl(Http::Protocol protocol, TimeSource& time_source) : time_source_(time_source), start_time_(time_source.systemTime()), - start_time_monotonic_(time_source.monotonicTime()), protocol_(protocol), + start_time_monotonic_(time_source.monotonicTime()), + protocols_({Http::Utility::getProtocolString(protocol)}), filter_state_(std::make_shared(FilterState::LifeSpan::FilterChain)) {} - StreamInfoImpl(Http::Protocol protocol, TimeSource& time_source, - std::shared_ptr& parent_filter_state) + StreamInfoImpl(Http::Protocol protocol, TimeSource& time_source, StreamInfo& parent) : time_source_(time_source), start_time_(time_source.systemTime()), - start_time_monotonic_(time_source.monotonicTime()), protocol_(protocol), + start_time_monotonic_(time_source.monotonicTime()), filter_state_(std::make_shared( - FilterStateImpl::LazyCreateAncestor(parent_filter_state, + FilterStateImpl::LazyCreateAncestor(parent.mutableFilterState(), FilterState::LifeSpan::DownstreamConnection), - FilterState::LifeSpan::FilterChain)) {} + FilterState::LifeSpan::FilterChain)) { + for (const auto& protocol : parent.protocols()) { + protocols_.push_back(protocol); + } + protocols_.push_back(Http::Utility::getProtocolString(protocol)); + } SystemTime startTime() const override { return start_time_; } @@ -108,9 +114,11 @@ struct StreamInfoImpl : public StreamInfo { uint64_t bytesReceived() const override { return bytes_received_; } - absl::optional protocol() const override { return protocol_; } + absl::Span protocols() const override { return protocols_; } - void protocol(Http::Protocol protocol) override { protocol_ = protocol; } + void addProtocol(absl::string_view protocol) override { + protocols_.push_back(std::string(protocol)); + } absl::optional responseCode() const override { return response_code_; } @@ -216,6 +224,7 @@ struct StreamInfoImpl : public StreamInfo { (*metadata_.mutable_filter_metadata())[name].MergeFrom(value); }; + FilterStateSharedPtr& mutableFilterState() override { return filter_state_; } const FilterStateSharedPtr& filterState() override { return filter_state_; } const FilterState& filterState() const override { return *filter_state_; } @@ -248,7 +257,8 @@ struct StreamInfoImpl : public StreamInfo { void dumpState(std::ostream& os, int indent_level = 0) const { const char* spaces = spacesForLevel(indent_level); - os << spaces << "StreamInfoImpl " << this << DUMP_OPTIONAL_MEMBER(protocol_) + os << spaces << "StreamInfoImpl " << this + << DUMP_OPTIONAL_MEMBER(Http::Utility::getProtocol(protocols_)) << DUMP_OPTIONAL_MEMBER(response_code_) << DUMP_OPTIONAL_MEMBER(response_code_details_) << DUMP_MEMBER(health_check_request_) << DUMP_MEMBER(route_name_) << "\n"; } @@ -271,7 +281,7 @@ struct StreamInfoImpl : public StreamInfo { absl::optional last_downstream_tx_byte_sent_; absl::optional final_time_; - absl::optional protocol_; + std::vector protocols_; absl::optional response_code_; absl::optional response_code_details_; uint64_t response_flags_{}; diff --git a/source/common/tracing/http_tracer_impl.cc b/source/common/tracing/http_tracer_impl.cc index d9fe662ec69d7..172da9cdeb874 100644 --- a/source/common/tracing/http_tracer_impl.cc +++ b/source/common/tracing/http_tracer_impl.cc @@ -173,7 +173,7 @@ void HttpTracerUtility::finalizeDownstreamSpan(Span& span, valueOrDefault(request_headers->EnvoyDownstreamServiceCluster(), "-")); span.setTag(Tracing::Tags::get().UserAgent, valueOrDefault(request_headers->UserAgent(), "-")); span.setTag(Tracing::Tags::get().HttpProtocol, - AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocol())); + AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocols())); const auto& remote_address = stream_info.downstreamDirectRemoteAddress(); @@ -215,7 +215,7 @@ void HttpTracerUtility::finalizeUpstreamSpan(Span& span, const StreamInfo::StreamInfo& stream_info, const Config& tracing_config) { span.setTag(Tracing::Tags::get().HttpProtocol, - AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocol())); + AccessLog::AccessLogFormatUtils::protocolToString(stream_info.protocols())); if (stream_info.upstreamHost()) { span.setTag(Tracing::Tags::get().UpstreamAddress, diff --git a/source/extensions/access_loggers/grpc/BUILD b/source/extensions/access_loggers/grpc/BUILD index f487c0d3688ad..6f20d2988a560 100644 --- a/source/extensions/access_loggers/grpc/BUILD +++ b/source/extensions/access_loggers/grpc/BUILD @@ -64,6 +64,7 @@ envoy_cc_library( deps = [ ":grpc_access_log_lib", ":grpc_access_log_utils", + "//source/common/http:utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/data/accesslog/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/access_loggers/grpc/v3:pkg_cc_proto", diff --git a/source/extensions/access_loggers/grpc/http_grpc_access_log_impl.cc b/source/extensions/access_loggers/grpc/http_grpc_access_log_impl.cc index 6f07a77a44ecb..f9a8f1a538576 100644 --- a/source/extensions/access_loggers/grpc/http_grpc_access_log_impl.cc +++ b/source/extensions/access_loggers/grpc/http_grpc_access_log_impl.cc @@ -5,6 +5,7 @@ #include "envoy/extensions/access_loggers/grpc/v3/als.pb.h" #include "common/common/assert.h" +#include "common/http/utility.h" #include "common/network/utility.h" #include "common/stream_info/utility.h" @@ -53,8 +54,9 @@ void HttpGrpcAccessLog::emitLog(const Http::RequestHeaderMap& request_headers, GrpcCommon::Utility::extractCommonAccessLogProperties(*log_entry.mutable_common_properties(), stream_info, config_.common_config()); - if (stream_info.protocol()) { - switch (stream_info.protocol().value()) { + auto protocol = Http::Utility::getProtocol(stream_info.protocols()); + if (protocol.has_value()) { + switch (protocol.value()) { case Http::Protocol::Http10: log_entry.set_protocol_version(envoy::data::accesslog::v3::HTTPAccessLogEntry::HTTP10); break; diff --git a/source/extensions/filters/common/expr/context.cc b/source/extensions/filters/common/expr/context.cc index 19373693901a3..ac9a87ca057cc 100644 --- a/source/extensions/filters/common/expr/context.cc +++ b/source/extensions/filters/common/expr/context.cc @@ -82,8 +82,9 @@ absl::optional RequestWrapper::operator[](CelValue key) const { return CelValue::CreateDuration(absl::FromChrono(duration.value())); } } else if (value == Protocol) { - if (info_.protocol().has_value()) { - return CelValue::CreateString(&Http::Utility::getProtocolString(info_.protocol().value())); + auto protocol = Http::Utility::getProtocol(info_.protocols()); + if (protocol.has_value()) { + return CelValue::CreateString(&Http::Utility::getProtocolString(protocol.value())); } else { return {}; } diff --git a/source/extensions/filters/common/ext_authz/check_request_utils.cc b/source/extensions/filters/common/ext_authz/check_request_utils.cc index 7906ad3607f6a..cd991412455eb 100644 --- a/source/extensions/filters/common/ext_authz/check_request_utils.cc +++ b/source/extensions/filters/common/ext_authz/check_request_utils.cc @@ -110,8 +110,9 @@ void CheckRequestUtils::setHttpRequest( httpreq.set_scheme(getHeaderStr(headers.Scheme())); httpreq.set_size(stream_info.bytesReceived()); - if (stream_info.protocol()) { - httpreq.set_protocol(Envoy::Http::Utility::getProtocolString(stream_info.protocol().value())); + auto protocol = Envoy::Http::Utility::getProtocol(stream_info.protocols()); + if (protocol.has_value()) { + httpreq.set_protocol(Envoy::Http::Utility::getProtocolString(protocol.value())); } // Fill in the headers. diff --git a/source/extensions/filters/http/grpc_http1_bridge/BUILD b/source/extensions/filters/http/grpc_http1_bridge/BUILD index 379e0d75f1b63..aa68119003701 100644 --- a/source/extensions/filters/http/grpc_http1_bridge/BUILD +++ b/source/extensions/filters/http/grpc_http1_bridge/BUILD @@ -25,6 +25,7 @@ envoy_cc_library( "//source/common/grpc:common_lib", "//source/common/grpc:context_lib", "//source/common/http:headers_lib", + "//source/common/http:utility_lib", "//source/common/http/http1:codec_lib", ], ) diff --git a/source/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter.cc b/source/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter.cc index b6c77fd5422d0..cb0c2fba99716 100644 --- a/source/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter.cc +++ b/source/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter.cc @@ -12,6 +12,7 @@ #include "common/grpc/context_impl.h" #include "common/http/headers.h" #include "common/http/http1/codec_impl.h" +#include "common/http/utility.h" namespace Envoy { namespace Extensions { @@ -29,7 +30,8 @@ Http::FilterHeadersStatus Http1BridgeFilter::decodeHeaders(Http::RequestHeaderMa setupStatTracking(headers); } - const absl::optional& protocol = decoder_callbacks_->streamInfo().protocol(); + const absl::optional& protocol = + Http::Utility::getProtocol(decoder_callbacks_->streamInfo().protocols()); ASSERT(protocol); if (protocol.value() < Http::Protocol::Http2 && grpc_request) { do_bridging_ = true; diff --git a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc index f194bb66ca60e..dcf8a77f70a9f 100644 --- a/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc +++ b/source/extensions/filters/http/grpc_json_transcoder/json_transcoder_filter.cc @@ -588,7 +588,8 @@ void JsonTranscoderFilter::doTrailers(Http::ResponseHeaderOrTrailerMap& headers_ } // remove Trailer headers if the client connection was http/1 - if (encoder_callbacks_->streamInfo().protocol() < Http::Protocol::Http2) { + if (Http::Utility::getProtocol(encoder_callbacks_->streamInfo().protocols()) < + Http::Protocol::Http2) { response_headers_->remove(trailerHeader()); } @@ -724,7 +725,8 @@ bool JsonTranscoderFilter::maybeConvertGrpcStatus(Grpc::Status::GrpcStatus grpc_ } // remove Trailer headers if the client connection was http/1 - if (encoder_callbacks_->streamInfo().protocol() < Http::Protocol::Http2) { + if (Http::Utility::getProtocol(encoder_callbacks_->streamInfo().protocols()) < + Http::Protocol::Http2) { response_headers_->remove(trailerHeader()); } diff --git a/source/extensions/filters/http/lua/wrappers.cc b/source/extensions/filters/http/lua/wrappers.cc index a772f3c1edfe1..775a155e49b82 100644 --- a/source/extensions/filters/http/lua/wrappers.cc +++ b/source/extensions/filters/http/lua/wrappers.cc @@ -103,8 +103,12 @@ void HeaderMapWrapper::checkModifiable(lua_State* state) { } int StreamInfoWrapper::luaProtocol(lua_State* state) { - lua_pushstring(state, Http::Utility::getProtocolString(stream_info_.protocol().value()).c_str()); - return 1; + auto protocol = Http::Utility::getProtocol(stream_info_.protocols()); + if (protocol.has_value()) { + lua_pushstring(state, Http::Utility::getProtocolString(protocol.value()).c_str()); + return 1; + } + return 0; } int StreamInfoWrapper::luaDynamicMetadata(lua_State* state) { diff --git a/source/extensions/filters/listener/http_inspector/http_inspector.cc b/source/extensions/filters/listener/http_inspector/http_inspector.cc index bb039f8cfe5d8..ef0f9a3b2ad1a 100644 --- a/source/extensions/filters/listener/http_inspector/http_inspector.cc +++ b/source/extensions/filters/listener/http_inspector/http_inspector.cc @@ -153,10 +153,10 @@ ParseState Filter::parseHttpHeader(absl::string_view data) { } if (parser_.http_major == 1 && parser_.http_minor == 1) { - protocol_ = Http::Headers::get().ProtocolStrings.Http11String; + protocol_ = StreamInfo::ProtocolStrings::get().Http11String; } else { // Set other HTTP protocols to HTTP/1.0 - protocol_ = Http::Headers::get().ProtocolStrings.Http10String; + protocol_ = StreamInfo::ProtocolStrings::get().Http10String; } return ParseState::Done; } else { @@ -179,10 +179,10 @@ void Filter::done(bool success) { if (success) { absl::string_view protocol; - if (protocol_ == Http::Headers::get().ProtocolStrings.Http10String) { + if (protocol_ == StreamInfo::ProtocolStrings::get().Http10String) { config_->stats().http10_found_.inc(); protocol = "http/1.0"; - } else if (protocol_ == Http::Headers::get().ProtocolStrings.Http11String) { + } else if (protocol_ == StreamInfo::ProtocolStrings::get().Http11String) { config_->stats().http11_found_.inc(); protocol = "http/1.1"; } else { diff --git a/source/extensions/quic_listeners/quiche/quic_filter_manager_connection_impl.cc b/source/extensions/quic_listeners/quiche/quic_filter_manager_connection_impl.cc index 270c7eec91fff..cee719af85ce9 100644 --- a/source/extensions/quic_listeners/quiche/quic_filter_manager_connection_impl.cc +++ b/source/extensions/quic_listeners/quiche/quic_filter_manager_connection_impl.cc @@ -15,7 +15,7 @@ QuicFilterManagerConnectionImpl::QuicFilterManagerConnectionImpl(EnvoyQuicConnec write_buffer_watermark_simulation_( send_buffer_limit / 2, send_buffer_limit, [this]() { onSendBufferLowWatermark(); }, [this]() { onSendBufferHighWatermark(); }, ENVOY_LOGGER()) { - stream_info_.protocol(Http::Protocol::Http3); + stream_info_.addProtocol(Http::Utility::getProtocolString(Http::Protocol::Http3)); } void QuicFilterManagerConnectionImpl::addWriteFilter(Network::WriteFilterSharedPtr filter) { diff --git a/source/extensions/stat_sinks/hystrix/BUILD b/source/extensions/stat_sinks/hystrix/BUILD index 8437dff366b0d..291cf6119ced7 100644 --- a/source/extensions/stat_sinks/hystrix/BUILD +++ b/source/extensions/stat_sinks/hystrix/BUILD @@ -39,6 +39,7 @@ envoy_cc_library( "//source/common/common:logger_lib", "//source/common/config:well_known_names", "//source/common/http:headers_lib", + "//source/common/http:utility_lib", "//source/common/stats:symbol_table_lib", "//source/common/stats:utility_lib", ], diff --git a/source/extensions/stat_sinks/hystrix/hystrix.cc b/source/extensions/stat_sinks/hystrix/hystrix.cc index e04fa22ae0d1e..162fbb806d6b2 100644 --- a/source/extensions/stat_sinks/hystrix/hystrix.cc +++ b/source/extensions/stat_sinks/hystrix/hystrix.cc @@ -11,6 +11,7 @@ #include "common/common/logger.h" #include "common/config/well_known_names.h" #include "common/http/headers.h" +#include "common/http/utility.h" #include "common/stats/utility.h" #include "absl/strings/str_cat.h" @@ -299,7 +300,10 @@ Http::Code HystrixSink::handlerHystrixEventStream(absl::string_view, admin_stream.getDecoderFilterCallbacks(); // Disable chunk-encoding in HTTP/1.x. - if (stream_decoder_filter_callbacks.streamInfo().protocol() < Http::Protocol::Http2) { + // TODO: This request should be propagated to codecs via API, instead of using a pseudo-header. + // See: https://github.com/envoyproxy/envoy/issues/9749 + if (Http::Utility::getProtocol(stream_decoder_filter_callbacks.streamInfo().protocols()) < + Http::Protocol::Http2) { admin_stream.http1StreamEncoderOptions().value().get().disableChunkEncoding(); } diff --git a/source/server/connection_handler_impl.cc b/source/server/connection_handler_impl.cc index a08069bbbd880..c413890b033f6 100644 --- a/source/server/connection_handler_impl.cc +++ b/source/server/connection_handler_impl.cc @@ -334,6 +334,7 @@ void emitLogs(Network::ListenerConfig& config, StreamInfo::StreamInfo& stream_in void ConnectionHandlerImpl::ActiveTcpListener::newConnection( Network::ConnectionSocketPtr&& socket) { auto stream_info = std::make_unique(parent_.dispatcher_.timeSource()); + stream_info->addProtocol(StreamInfo::ProtocolStrings::get().TcpString); stream_info->setDownstreamLocalAddress(socket->localAddress()); stream_info->setDownstreamRemoteAddress(socket->remoteAddress()); stream_info->setDownstreamDirectRemoteAddress(socket->directRemoteAddress()); diff --git a/test/common/access_log/access_log_formatter_test.cc b/test/common/access_log/access_log_formatter_test.cc index d0903f07ccdeb..16fc50e814e2e 100644 --- a/test/common/access_log/access_log_formatter_test.cc +++ b/test/common/access_log/access_log_formatter_test.cc @@ -76,9 +76,15 @@ class TestSerializedStructFilterState : public StreamInfo::FilterState::Object { }; TEST(AccessLogFormatUtilsTest, protocolToString) { - EXPECT_EQ("HTTP/1.0", AccessLogFormatUtils::protocolToString(Http::Protocol::Http10)); - EXPECT_EQ("HTTP/1.1", AccessLogFormatUtils::protocolToString(Http::Protocol::Http11)); - EXPECT_EQ("HTTP/2", AccessLogFormatUtils::protocolToString(Http::Protocol::Http2)); + EXPECT_EQ("HTTP/1.0", AccessLogFormatUtils::protocolToString( + {StreamInfo::ProtocolStrings::get().Http10String})); + EXPECT_EQ("HTTP/1.1", AccessLogFormatUtils::protocolToString( + {StreamInfo::ProtocolStrings::get().Http11String})); + EXPECT_EQ("HTTP/2", AccessLogFormatUtils::protocolToString( + {StreamInfo::ProtocolStrings::get().Http2String})); + EXPECT_EQ("TCP,HTTP", AccessLogFormatUtils::protocolToString( + {StreamInfo::ProtocolStrings::get().TcpString, + StreamInfo::ProtocolStrings::get().HttpString})); EXPECT_EQ("-", AccessLogFormatUtils::protocolToString({})); } @@ -190,8 +196,8 @@ TEST(AccessLogFormatterTest, streamInfoFormatter) { { StreamInfoFormatter protocol_format("PROTOCOL"); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_EQ("HTTP/1.1", protocol_format.format(request_headers, response_headers, response_trailers, stream_info)); EXPECT_THAT(protocol_format.formatValue(request_headers, response_headers, response_trailers, @@ -1368,8 +1374,8 @@ TEST(AccessLogFormatterTest, JsonFormatterPlainStringTest) { envoy::config::core::v3::Metadata metadata; populateMetadataTestData(metadata); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); std::unordered_map expected_json_map = { {"plain_string", "plain_string_value"}}; @@ -1390,8 +1396,8 @@ TEST(AccessLogFormatterTest, JsonFormatterSingleOperatorTest) { envoy::config::core::v3::Metadata metadata; populateMetadataTestData(metadata); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); std::unordered_map expected_json_map = {{"protocol", "HTTP/1.1"}}; @@ -1421,8 +1427,8 @@ TEST(AccessLogFormatterTest, JsonFormatterNonExistentHeaderTest) { {"some_response_header", "%RESP(some_response_header)%"}}; JsonFormatterImpl formatter(key_mapping, false); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); verifyJsonOutput(formatter.format(request_header, response_header, response_trailer, stream_info), expected_json_map); @@ -1453,8 +1459,8 @@ TEST(AccessLogFormatterTest, JsonFormatterAlternateHeaderTest) { "%RESP(response_present_header?response_absent_header)%"}}; JsonFormatterImpl formatter(key_mapping, false); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); verifyJsonOutput(formatter.format(request_header, response_header, response_trailer, stream_info), expected_json_map); @@ -1619,8 +1625,8 @@ TEST(AccessLogFormatterTest, JsonFormatterMultiTokenTest) { for (const bool preserve_types : {false, true}) { JsonFormatterImpl formatter(key_mapping, preserve_types); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); const auto parsed = Json::Factory::loadFromString( formatter.format(request_header, response_header, response_trailer, stream_info)); @@ -1685,8 +1691,8 @@ TEST(AccessLogFormatterTest, CompositeFormatterSuccess) { "\t@%TRAILER(THIRD)%@\t%TRAILER(TEST?TEST-2)%[]"; FormatterImpl formatter(format); - absl::optional protocol = Http::Protocol::Http11; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(Return(protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_EQ("{{HTTP/1.1}} -++test GET PUT\t@POST@\ttest-2[]", formatter.format(request_header, response_header, response_trailer, stream_info)); diff --git a/test/common/http/async_client_impl_test.cc b/test/common/http/async_client_impl_test.cc index fc46f8a5ef43a..df8c442d08f99 100644 --- a/test/common/http/async_client_impl_test.cc +++ b/test/common/http/async_client_impl_test.cc @@ -1354,7 +1354,7 @@ TEST_F(AsyncClientImplTest, DumpState) { std::stringstream out; filter_callbacks->scope().dumpState(out); std::string state = out.str(); - EXPECT_THAT(state, testing::HasSubstr("protocol_: 1")); + EXPECT_THAT(state, testing::HasSubstr("protocols_): 1")); EXPECT_CALL(stream_callbacks_, onReset()); } diff --git a/test/common/http/conn_manager_impl_test.cc b/test/common/http/conn_manager_impl_test.cc index 2ed0052dd73cf..d2711cb513c5f 100644 --- a/test/common/http/conn_manager_impl_test.cc +++ b/test/common/http/conn_manager_impl_test.cc @@ -5065,7 +5065,7 @@ TEST_F(HttpConnectionManagerImplTest, TestSessionTrace) { object->dumpState(out); std::string state = out.str(); EXPECT_THAT(state, testing::HasSubstr("request_headers_: null")); - EXPECT_THAT(state, testing::HasSubstr("protocol_: 1")); + EXPECT_THAT(state, testing::HasSubstr("protocols_): 1")); return nullptr; })) .WillRepeatedly(Return(nullptr)); @@ -5088,7 +5088,7 @@ TEST_F(HttpConnectionManagerImplTest, TestSessionTrace) { std::string state = out.str(); EXPECT_THAT(state, testing::HasSubstr("request_headers_: \n")); EXPECT_THAT(state, testing::HasSubstr("':authority', 'host'\n")); - EXPECT_THAT(state, testing::HasSubstr("protocol_: 1")); + EXPECT_THAT(state, testing::HasSubstr("protocols_): 1")); return nullptr; })) .WillRepeatedly(Return(nullptr)); @@ -5278,15 +5278,16 @@ TEST_F(HttpConnectionManagerImplTest, TestSrdsRouteFound) { TEST_F(HttpConnectionManagerImplTest, NewConnection) { setup(false, "", true, true); - filter_callbacks_.connection_.stream_info_.protocol_ = absl::nullopt; - EXPECT_CALL(filter_callbacks_.connection_.stream_info_, protocol()); + filter_callbacks_.connection_.stream_info_.protocols_.clear(); + EXPECT_CALL(filter_callbacks_.connection_.stream_info_, protocols()); EXPECT_EQ(Network::FilterStatus::Continue, conn_manager_->onNewConnection()); EXPECT_EQ(0U, stats_.named_.downstream_cx_http3_total_.value()); EXPECT_EQ(0U, stats_.named_.downstream_cx_http3_active_.value()); - filter_callbacks_.connection_.stream_info_.protocol_ = Envoy::Http::Protocol::Http3; + filter_callbacks_.connection_.stream_info_.protocols_ = + std::vector({StreamInfo::ProtocolStrings::get().Http3String}); codec_->protocol_ = Http::Protocol::Http3; - EXPECT_CALL(filter_callbacks_.connection_.stream_info_, protocol()); + EXPECT_CALL(filter_callbacks_.connection_.stream_info_, protocols()); EXPECT_CALL(*codec_, protocol()).Times(AtLeast(1)); EXPECT_EQ(Network::FilterStatus::StopIteration, conn_manager_->onNewConnection()); EXPECT_EQ(1U, stats_.named_.downstream_cx_http3_total_.value()); @@ -5296,7 +5297,8 @@ TEST_F(HttpConnectionManagerImplTest, NewConnection) { TEST_F(HttpConnectionManagerImplTest, HeaderOnlyRequestAndResponseUsingHttp3) { setup(false, "envoy-custom-server", false); - filter_callbacks_.connection_.stream_info_.protocol_ = Envoy::Http::Protocol::Http3; + filter_callbacks_.connection_.stream_info_.protocols_ = + std::vector({StreamInfo::ProtocolStrings::get().Http3String}); codec_->protocol_ = Http::Protocol::Http3; EXPECT_EQ(Network::FilterStatus::StopIteration, conn_manager_->onNewConnection()); diff --git a/test/common/router/header_formatter_test.cc b/test/common/router/header_formatter_test.cc index 81044fddb558b..7d06f500e99a0 100644 --- a/test/common/router/header_formatter_test.cc +++ b/test/common/router/header_formatter_test.cc @@ -131,8 +131,8 @@ TEST_F(StreamInfoHeaderFormatterTest, TestformatWithHostnameVariable) { TEST_F(StreamInfoHeaderFormatterTest, TestFormatWithProtocolVariable) { NiceMock stream_info; - absl::optional protocol = Envoy::Http::Protocol::Http11; - ON_CALL(stream_info, protocol()).WillByDefault(ReturnPointee(&protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + ON_CALL(stream_info, protocols()).WillByDefault(Return(protocols)); testFormatting(stream_info, "PROTOCOL", "HTTP/1.1"); } @@ -839,8 +839,8 @@ TEST(HeaderParserTest, TestParseInternal) { }; NiceMock stream_info; - absl::optional protocol = Envoy::Http::Protocol::Http11; - ON_CALL(stream_info, protocol()).WillByDefault(ReturnPointee(&protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + ON_CALL(stream_info, protocols()).WillByDefault(Return(protocols)); std::shared_ptr> host( new NiceMock()); @@ -1020,8 +1020,8 @@ request_headers_to_remove: ["x-nope"] HeaderParser::configure(route.request_headers_to_add(), route.request_headers_to_remove()); Http::TestHeaderMapImpl header_map{{":method", "POST"}, {"x-safe", "safe"}, {"x-nope", "nope"}}; NiceMock stream_info; - absl::optional protocol = Envoy::Http::Protocol::Http11; - ON_CALL(stream_info, protocol()).WillByDefault(ReturnPointee(&protocol)); + std::vector protocols = {StreamInfo::ProtocolStrings::get().Http11String}; + ON_CALL(stream_info, protocols()).WillByDefault(Return(protocols)); std::shared_ptr> host( new NiceMock()); diff --git a/test/common/stream_info/BUILD b/test/common/stream_info/BUILD index 9c60f05c1c2b1..2d94cc71a4cfb 100644 --- a/test/common/stream_info/BUILD +++ b/test/common/stream_info/BUILD @@ -25,6 +25,7 @@ envoy_cc_test( ":test_int_accessor_lib", "//include/envoy/http:protocol_interface", "//include/envoy/upstream:host_description_interface", + "//source/common/http:utility_lib", "//source/common/stream_info:stream_info_lib", "//test/mocks/router:router_mocks", "//test/mocks/upstream:upstream_mocks", diff --git a/test/common/stream_info/stream_info_impl_test.cc b/test/common/stream_info/stream_info_impl_test.cc index e519473522829..a2153cd6d13d6 100644 --- a/test/common/stream_info/stream_info_impl_test.cc +++ b/test/common/stream_info/stream_info_impl_test.cc @@ -6,6 +6,7 @@ #include "envoy/upstream/host_description.h" #include "common/common/fmt.h" +#include "common/http/utility.h" #include "common/protobuf/utility.h" #include "common/stream_info/stream_info_impl.h" @@ -134,10 +135,10 @@ TEST_F(StreamInfoImplTest, MiscSettersAndGetters) { { StreamInfoImpl stream_info(Http::Protocol::Http2, test_time_.timeSystem()); - EXPECT_EQ(Http::Protocol::Http2, stream_info.protocol().value()); + EXPECT_EQ(Http::Protocol::Http2, Http::Utility::getProtocol(stream_info.protocols()).value()); - stream_info.protocol(Http::Protocol::Http10); - EXPECT_EQ(Http::Protocol::Http10, stream_info.protocol().value()); + stream_info.addProtocol(Http::Utility::getProtocolString(Http::Protocol::Http10)); + EXPECT_EQ(Http::Protocol::Http10, Http::Utility::getProtocol(stream_info.protocols()).value()); EXPECT_FALSE(stream_info.responseCode()); stream_info.response_code_ = 200; @@ -223,7 +224,7 @@ TEST_F(StreamInfoImplTest, DumpStateTest) { stream_info.dumpState(out, i); std::string state = out.str(); EXPECT_TRUE(absl::StartsWith(state, prefix)); - EXPECT_THAT(state, testing::HasSubstr("protocol_: 2")); + EXPECT_THAT(state, testing::HasSubstr("protocols_): 2")); prefix = prefix + " "; } } diff --git a/test/common/stream_info/test_util.h b/test/common/stream_info/test_util.h index 086f31666152e..b51b44231574b 100644 --- a/test/common/stream_info/test_util.h +++ b/test/common/stream_info/test_util.h @@ -29,8 +29,10 @@ class TestStreamInfo : public StreamInfo::StreamInfo { void addBytesReceived(uint64_t) override { NOT_IMPLEMENTED_GCOVR_EXCL_LINE; } uint64_t bytesReceived() const override { return 1; } - absl::optional protocol() const override { return protocol_; } - void protocol(Http::Protocol protocol) override { protocol_ = protocol; } + absl::Span protocols() const override { return protocols_; } + void addProtocol(absl::string_view protocol) override { + protocols_.push_back(std::string(protocol)); + } absl::optional responseCode() const override { return response_code_; } const absl::optional& responseCodeDetails() const override { return response_code_details_; @@ -176,6 +178,7 @@ class TestStreamInfo : public StreamInfo::StreamInfo { (*metadata_.mutable_filter_metadata())[name].MergeFrom(value); }; + Envoy::StreamInfo::FilterStateSharedPtr& mutableFilterState() override { return filter_state_; } const Envoy::StreamInfo::FilterStateSharedPtr& filterState() override { return filter_state_; } const Envoy::StreamInfo::FilterState& filterState() const override { return *filter_state_; } @@ -229,7 +232,7 @@ class TestStreamInfo : public StreamInfo::StreamInfo { absl::optional last_downstream_tx_byte_sent_; absl::optional end_time_; - absl::optional protocol_{Http::Protocol::Http11}; + std::vector protocols_{Envoy::StreamInfo::ProtocolStrings::get().Http11String}; absl::optional response_code_; absl::optional response_code_details_; uint64_t response_flags_{}; diff --git a/test/common/tracing/http_tracer_impl_test.cc b/test/common/tracing/http_tracer_impl_test.cc index 9b100e21f8732..7156417f4b44f 100644 --- a/test/common/tracing/http_tracer_impl_test.cc +++ b/test/common/tracing/http_tracer_impl_test.cc @@ -158,10 +158,10 @@ TEST_F(HttpConnManFinalizerImplTest, OriginalAndLongPath) { Http::TestResponseHeaderMapImpl response_headers; Http::TestResponseTrailerMapImpl response_trailers; - absl::optional protocol = Http::Protocol::Http2; EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(11)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); absl::optional response_code; EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) @@ -190,10 +190,10 @@ TEST_F(HttpConnManFinalizerImplTest, NoGeneratedId) { Http::TestResponseHeaderMapImpl response_headers; Http::TestResponseTrailerMapImpl response_trailers; - absl::optional protocol = Http::Protocol::Http2; EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(11)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); absl::optional response_code; EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) @@ -316,9 +316,9 @@ TEST_F(HttpConnManFinalizerImplTest, SpanOptionalHeaders) { const auto remote_address = Network::Address::InstanceConstSharedPtr{new Network::Address::Ipv4Instance(expected_ip, 0)}; - absl::optional protocol = Http::Protocol::Http10; EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http10String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) .WillRepeatedly(ReturnPointee(&remote_address)); @@ -401,9 +401,9 @@ TEST_F(HttpConnManFinalizerImplTest, SpanCustomTags) { (*stream_info.host_->cluster_.metadata_.mutable_filter_metadata())["m.cluster"].MergeFrom( fake_struct); - absl::optional protocol = Http::Protocol::Http10; EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http10String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); absl::optional response_code; EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(100)); @@ -506,8 +506,8 @@ TEST_F(HttpConnManFinalizerImplTest, SpanPopulatedFailureResponse) { request_headers.setEnvoyDownstreamServiceCluster("downstream_cluster"); request_headers.setClientTraceId("client_trace_id"); - absl::optional protocol = Http::Protocol::Http10; - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http10String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) .WillRepeatedly(ReturnPointee(&remote_address)); @@ -563,12 +563,12 @@ TEST_F(HttpConnManFinalizerImplTest, GrpcOkStatus) { {"content-type", "application/grpc"}}; Http::TestResponseTrailerMapImpl response_trailers{{"grpc-status", "0"}, {"grpc-message", ""}}; - absl::optional protocol = Http::Protocol::Http2; absl::optional response_code(200); EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(11)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) .WillRepeatedly(ReturnPointee(&remote_address)); @@ -615,12 +615,12 @@ TEST_F(HttpConnManFinalizerImplTest, GrpcErrorTag) { Http::TestResponseTrailerMapImpl response_trailers{{"grpc-status", "7"}, {"grpc-message", "permission denied"}}; - absl::optional protocol = Http::Protocol::Http2; absl::optional response_code(200); EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(11)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) .WillRepeatedly(ReturnPointee(&remote_address)); @@ -661,12 +661,12 @@ TEST_F(HttpConnManFinalizerImplTest, GrpcTrailersOnly) { {"grpc-message", "permission denied"}}; Http::TestResponseTrailerMapImpl response_trailers; - absl::optional protocol = Http::Protocol::Http2; absl::optional response_code(200); EXPECT_CALL(stream_info, responseCode()).WillRepeatedly(ReturnPointee(&response_code)); EXPECT_CALL(stream_info, bytesReceived()).WillOnce(Return(10)); EXPECT_CALL(stream_info, bytesSent()).WillOnce(Return(11)); - EXPECT_CALL(stream_info, protocol()).WillRepeatedly(ReturnPointee(&protocol)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(stream_info, protocols()).WillRepeatedly(Return(protocols)); EXPECT_CALL(stream_info, downstreamDirectRemoteAddress()) .WillRepeatedly(ReturnPointee(&remote_address)); diff --git a/test/extensions/access_loggers/grpc/http_grpc_access_log_impl_test.cc b/test/extensions/access_loggers/grpc/http_grpc_access_log_impl_test.cc index 13e0b1641cf0c..d015241ddce90 100644 --- a/test/extensions/access_loggers/grpc/http_grpc_access_log_impl_test.cc +++ b/test/extensions/access_loggers/grpc/http_grpc_access_log_impl_test.cc @@ -231,7 +231,7 @@ response: {} stream_info.setUpstreamLocalAddress( std::make_shared("10.0.0.2")); - stream_info.protocol_ = Http::Protocol::Http10; + stream_info.protocols_ = {StreamInfo::ProtocolStrings::get().Http10String}; stream_info.addBytesReceived(10); stream_info.addBytesSent(20); stream_info.response_code_ = 200; diff --git a/test/extensions/filters/common/expr/context_test.cc b/test/extensions/filters/common/expr/context_test.cc index 9ce4c6fcc756e..5831ca53c4b14 100644 --- a/test/extensions/filters/common/expr/context_test.cc +++ b/test/extensions/filters/common/expr/context_test.cc @@ -47,7 +47,8 @@ TEST(Context, RequestAttributes) { EXPECT_CALL(info, startTime()).WillRepeatedly(Return(start_time)); absl::optional dur = std::chrono::nanoseconds(15000000); EXPECT_CALL(info, requestComplete()).WillRepeatedly(Return(dur)); - EXPECT_CALL(info, protocol()).WillRepeatedly(Return(Http::Protocol::Http2)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http2String}); + EXPECT_CALL(info, protocols()).WillRepeatedly(Return(protocols)); // stub methods EXPECT_EQ(0, request.size()); diff --git a/test/extensions/filters/common/ext_authz/check_request_utils_test.cc b/test/extensions/filters/common/ext_authz/check_request_utils_test.cc index 8252defad35fa..02e393aabccef 100644 --- a/test/extensions/filters/common/ext_authz/check_request_utils_test.cc +++ b/test/extensions/filters/common/ext_authz/check_request_utils_test.cc @@ -29,7 +29,7 @@ class CheckRequestUtilsTest : public testing::Test { public: CheckRequestUtilsTest() { addr_ = std::make_shared("1.2.3.4", 1111); - protocol_ = Envoy::Http::Protocol::Http10; + protocol_ = {StreamInfo::ProtocolStrings::get().Http10String}; buffer_ = CheckRequestUtilsTest::newTestBuffer(8192); ssl_ = std::make_shared>(); }; @@ -42,7 +42,7 @@ class CheckRequestUtilsTest : public testing::Test { EXPECT_CALL(callbacks_, streamId()).Times(1).WillOnce(Return(0)); EXPECT_CALL(callbacks_, decodingBuffer()).WillOnce(Return(buffer_.get())); EXPECT_CALL(callbacks_, streamInfo()).Times(1).WillOnce(ReturnRef(req_info_)); - EXPECT_CALL(req_info_, protocol()).Times(2).WillRepeatedly(ReturnPointee(&protocol_)); + EXPECT_CALL(req_info_, protocols()).Times(1).WillRepeatedly(Return(protocol_)); EXPECT_CALL(req_info_, startTime()).Times(1).WillOnce(Return(SystemTime())); } @@ -91,7 +91,7 @@ class CheckRequestUtilsTest : public testing::Test { } Network::Address::InstanceConstSharedPtr addr_; - absl::optional protocol_; + std::vector protocol_; CheckRequestUtils check_request_generator_; NiceMock callbacks_; NiceMock net_callbacks_; @@ -216,7 +216,7 @@ TEST_F(CheckRequestUtilsTest, CheckAttrContextPeer) { EXPECT_CALL(callbacks_, streamId()).WillRepeatedly(Return(0)); EXPECT_CALL(callbacks_, streamInfo()).WillRepeatedly(ReturnRef(req_info_)); EXPECT_CALL(callbacks_, decodingBuffer()).Times(1); - EXPECT_CALL(req_info_, protocol()).WillRepeatedly(ReturnPointee(&protocol_)); + EXPECT_CALL(req_info_, protocols()).WillRepeatedly(Return(protocol_)); EXPECT_CALL(*ssl_, uriSanPeerCertificate()).WillOnce(Return(std::vector{"source"})); EXPECT_CALL(*ssl_, uriSanLocalCertificate()) .WillOnce(Return(std::vector{"destination"})); diff --git a/test/extensions/filters/http/common/fuzz/uber_filter.h b/test/extensions/filters/http/common/fuzz/uber_filter.h index 260e4476cb014..f210c453d0bb7 100644 --- a/test/extensions/filters/http/common/fuzz/uber_filter.h +++ b/test/extensions/filters/http/common/fuzz/uber_filter.h @@ -45,7 +45,8 @@ class UberFilterFuzzer { ON_CALL(callbacks_, connection()).WillByDefault(testing::Return(&connection_)); ON_CALL(callbacks_, activeSpan()) .WillByDefault(testing::ReturnRef(Tracing::NullSpan::instance())); - callbacks_.stream_info_.protocol_ = Envoy::Http::Protocol::Http2; + callbacks_.stream_info_.protocols_ = + std::vector({StreamInfo::ProtocolStrings::get().Http2String}); } void prepareCache() { diff --git a/test/extensions/filters/http/ext_authz/ext_authz_test.cc b/test/extensions/filters/http/ext_authz/ext_authz_test.cc index 7f9c9e32a9e3e..7b8c1123ed08b 100644 --- a/test/extensions/filters/http/ext_authz/ext_authz_test.cc +++ b/test/extensions/filters/http/ext_authz/ext_authz_test.cc @@ -517,7 +517,7 @@ TEST_F(HttpFilterTest, H2UpgradeRequest) { request_headers_.addCopy(Http::Headers::get().Method, Http::Headers::get().MethodValues.Connect); request_headers_.addCopy(Http::Headers::get().Protocol, - Http::Headers::get().ProtocolStrings.Http2String); + StreamInfo::ProtocolStrings::get().Http2String); EXPECT_CALL(*client_, check(_, _, testing::A(), _)) .WillOnce( diff --git a/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc b/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc index 178418616833d..86ef8f07b6367 100644 --- a/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc +++ b/test/extensions/filters/http/grpc_http1_bridge/http1_bridge_filter_test.cc @@ -29,7 +29,8 @@ class GrpcHttp1BridgeFilterTest : public testing::Test { GrpcHttp1BridgeFilterTest() : context_(*symbol_table_), filter_(context_) { filter_.setDecoderFilterCallbacks(decoder_callbacks_); filter_.setEncoderFilterCallbacks(encoder_callbacks_); - ON_CALL(decoder_callbacks_.stream_info_, protocol()).WillByDefault(ReturnPointee(&protocol_)); + ON_CALL(decoder_callbacks_.stream_info_, protocols()) + .WillByDefault(Return(absl::Span(protocols_))); } ~GrpcHttp1BridgeFilterTest() override { filter_.onDestroy(); } @@ -39,11 +40,11 @@ class GrpcHttp1BridgeFilterTest : public testing::Test { Http1BridgeFilter filter_; NiceMock decoder_callbacks_; NiceMock encoder_callbacks_; - absl::optional protocol_{Http::Protocol::Http11}; + std::vector protocols_{StreamInfo::ProtocolStrings::get().Http11String}; }; TEST_F(GrpcHttp1BridgeFilterTest, NoRoute) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; ON_CALL(decoder_callbacks_, route()).WillByDefault(Return(nullptr)); Http::TestRequestHeaderMapImpl request_headers{ @@ -58,7 +59,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, NoRoute) { } TEST_F(GrpcHttp1BridgeFilterTest, NoCluster) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; ON_CALL(decoder_callbacks_, clusterInfo()).WillByDefault(Return(nullptr)); Http::TestRequestHeaderMapImpl request_headers{ @@ -71,7 +72,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, NoCluster) { } TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2HeaderOnlyResponse) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; Http::TestRequestHeaderMapImpl request_headers{ {"content-type", "application/grpc"}, @@ -98,7 +99,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2HeaderOnlyResponse) { } TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2NormalResponse) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; Http::TestRequestHeaderMapImpl request_headers{ {"content-type", "application/grpc"}, @@ -123,7 +124,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2NormalResponse) { } TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2ContentTypeGrpcPlusProto) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; Http::TestRequestHeaderMapImpl request_headers{ {"content-type", "application/grpc+proto"}, @@ -146,7 +147,7 @@ TEST_F(GrpcHttp1BridgeFilterTest, StatsHttp2ContentTypeGrpcPlusProto) { } TEST_F(GrpcHttp1BridgeFilterTest, NotHandlingHttp2) { - protocol_ = Http::Protocol::Http2; + protocols_ = {StreamInfo::ProtocolStrings::get().Http2String}; Http::TestRequestHeaderMapImpl request_headers{{"content-type", "application/foo"}}; EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_.decodeHeaders(request_headers, false)); diff --git a/test/extensions/filters/http/lua/lua_filter_test.cc b/test/extensions/filters/http/lua/lua_filter_test.cc index 8de472b120ab0..18db3034d7d9b 100644 --- a/test/extensions/filters/http/lua/lua_filter_test.cc +++ b/test/extensions/filters/http/lua/lua_filter_test.cc @@ -1720,7 +1720,8 @@ TEST_F(LuaHttpFilterTest, GetCurrentProtocol) { setup(SCRIPT); EXPECT_CALL(decoder_callbacks_, streamInfo()).WillOnce(ReturnRef(stream_info_)); - EXPECT_CALL(stream_info_, protocol()).WillOnce(Return(Http::Protocol::Http11)); + std::vector protocols({StreamInfo::ProtocolStrings::get().Http11String}); + EXPECT_CALL(stream_info_, protocols()).WillOnce(Return(protocols)); Http::TestRequestHeaderMapImpl request_headers{{":path", "/"}}; EXPECT_CALL(*filter_, scriptLog(spdlog::level::trace, StrEq("HTTP/1.1"))); diff --git a/test/extensions/filters/http/lua/wrappers_test.cc b/test/extensions/filters/http/lua/wrappers_test.cc index 32c003951e1f4..f1805136d9110 100644 --- a/test/extensions/filters/http/lua/wrappers_test.cc +++ b/test/extensions/filters/http/lua/wrappers_test.cc @@ -10,7 +10,7 @@ #include "test/test_common/utility.h" using testing::InSequence; -using testing::ReturnPointee; +using testing::Return; namespace Envoy { namespace Extensions { @@ -239,7 +239,8 @@ class LuaStreamInfoWrapperTest setup(SCRIPT); NiceMock stream_info; - ON_CALL(stream_info, protocol()).WillByDefault(ReturnPointee(&protocol)); + std::vector protocols({Envoy::Http::Utility::getProtocolString(protocol.value())}); + ON_CALL(stream_info, protocols()).WillByDefault(Return(protocols)); Filters::Common::Lua::LuaDeathRef wrapper( StreamInfoWrapper::create(coroutine_->luaState(), stream_info), true); EXPECT_CALL(*this, diff --git a/test/extensions/filters/network/direct_response/direct_response_integration_test.cc b/test/extensions/filters/network/direct_response/direct_response_integration_test.cc index 76e326e056bcf..51c41a6d9e4a1 100644 --- a/test/extensions/filters/network/direct_response/direct_response_integration_test.cc +++ b/test/extensions/filters/network/direct_response/direct_response_integration_test.cc @@ -25,7 +25,7 @@ class DirectResponseIntegrationTest : public testing::TestWithParam { // Setup read filter. envoy_quic_session_.addReadFilter(read_filter_); EXPECT_EQ(Http::Protocol::Http3, - read_filter_->callbacks_->connection().streamInfo().protocol().value()); + Http::Utility::getProtocol( + read_filter_->callbacks_->connection().streamInfo().protocols())); EXPECT_EQ(envoy_quic_session_.id(), read_filter_->callbacks_->connection().id()); EXPECT_EQ(&envoy_quic_session_, &read_filter_->callbacks_->connection()); read_filter_->callbacks_->connection().addConnectionCallbacks(network_connection_callbacks_); diff --git a/test/mocks/stream_info/mocks.cc b/test/mocks/stream_info/mocks.cc index 79cb4f41763f7..9f332c9ff225d 100644 --- a/test/mocks/stream_info/mocks.cc +++ b/test/mocks/stream_info/mocks.cc @@ -86,7 +86,9 @@ MockStreamInfo::MockStreamInfo() ON_CALL(*this, upstreamSslConnection()).WillByDefault(Invoke([this]() { return upstream_connection_info_; })); - ON_CALL(*this, protocol()).WillByDefault(ReturnPointee(&protocol_)); + ON_CALL(*this, protocols()).WillByDefault(Invoke([this]() { + return absl::Span(protocols_); + })); ON_CALL(*this, responseCode()).WillByDefault(ReturnPointee(&response_code_)); ON_CALL(*this, responseCodeDetails()).WillByDefault(ReturnPointee(&response_code_details_)); ON_CALL(*this, addBytesReceived(_)).WillByDefault(Invoke([this](uint64_t bytes_received) { @@ -111,6 +113,7 @@ MockStreamInfo::MockStreamInfo() ON_CALL(*this, dynamicMetadata()).WillByDefault(ReturnRef(metadata_)); ON_CALL(Const(*this), dynamicMetadata()).WillByDefault(ReturnRef(metadata_)); + ON_CALL(*this, mutableFilterState()).WillByDefault(ReturnRef(filter_state_)); ON_CALL(*this, filterState()).WillByDefault(ReturnRef(filter_state_)); ON_CALL(Const(*this), filterState()).WillByDefault(ReturnRef(*filter_state_)); ON_CALL(*this, upstreamFilterState()).WillByDefault(ReturnRef(upstream_filter_state_)); diff --git a/test/mocks/stream_info/mocks.h b/test/mocks/stream_info/mocks.h index 4ca1498133fff..faea360b4d988 100644 --- a/test/mocks/stream_info/mocks.h +++ b/test/mocks/stream_info/mocks.h @@ -46,8 +46,8 @@ class MockStreamInfo : public StreamInfo { MOCK_METHOD(uint64_t, bytesReceived, (), (const)); MOCK_METHOD(void, setRouteName, (absl::string_view route_name)); MOCK_METHOD(const std::string&, getRouteName, (), (const)); - MOCK_METHOD(absl::optional, protocol, (), (const)); - MOCK_METHOD(void, protocol, (Http::Protocol protocol)); + MOCK_METHOD(absl::Span, protocols, (), (const)); + MOCK_METHOD(void, addProtocol, (absl::string_view protocol)); MOCK_METHOD(absl::optional, responseCode, (), (const)); MOCK_METHOD(const absl::optional&, responseCodeDetails, (), (const)); MOCK_METHOD(void, addBytesSent, (uint64_t)); @@ -79,6 +79,7 @@ class MockStreamInfo : public StreamInfo { MOCK_METHOD(void, setDynamicMetadata, (const std::string&, const ProtobufWkt::Struct&)); MOCK_METHOD(void, setDynamicMetadata, (const std::string&, const std::string&, const std::string&)); + MOCK_METHOD(FilterStateSharedPtr&, mutableFilterState, ()); MOCK_METHOD(const FilterStateSharedPtr&, filterState, ()); MOCK_METHOD(const FilterState&, filterState, (), (const)); MOCK_METHOD(const FilterStateSharedPtr&, upstreamFilterState, (), (const)); @@ -106,7 +107,7 @@ class MockStreamInfo : public StreamInfo { absl::optional first_downstream_tx_byte_sent_; absl::optional last_downstream_tx_byte_sent_; absl::optional end_time_; - absl::optional protocol_; + std::vector protocols_; absl::optional response_code_; absl::optional response_code_details_; uint64_t response_flags_{};