LCOV - code coverage report
Current view: top level - source/common/router - router.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 57 148 38.5 %
Date: 2024-01-05 06:35:25 Functions: 21 37 56.8 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <chrono>
       4             : #include <cstdint>
       5             : #include <functional>
       6             : #include <memory>
       7             : #include <optional>
       8             : #include <string>
       9             : 
      10             : #include "envoy/common/random_generator.h"
      11             : #include "envoy/extensions/filters/http/router/v3/router.pb.h"
      12             : #include "envoy/http/codec.h"
      13             : #include "envoy/http/codes.h"
      14             : #include "envoy/http/filter.h"
      15             : #include "envoy/http/filter_factory.h"
      16             : #include "envoy/http/hash_policy.h"
      17             : #include "envoy/http/stateful_session.h"
      18             : #include "envoy/local_info/local_info.h"
      19             : #include "envoy/router/router_filter_interface.h"
      20             : #include "envoy/router/shadow_writer.h"
      21             : #include "envoy/runtime/runtime.h"
      22             : #include "envoy/server/factory_context.h"
      23             : #include "envoy/server/filter_config.h"
      24             : #include "envoy/stats/scope.h"
      25             : #include "envoy/stats/stats_macros.h"
      26             : #include "envoy/stream_info/stream_info.h"
      27             : #include "envoy/upstream/cluster_manager.h"
      28             : 
      29             : #include "source/common/access_log/access_log_impl.h"
      30             : #include "source/common/buffer/watermark_buffer.h"
      31             : #include "source/common/common/cleanup.h"
      32             : #include "source/common/common/hash.h"
      33             : #include "source/common/common/hex.h"
      34             : #include "source/common/common/linked_object.h"
      35             : #include "source/common/common/logger.h"
      36             : #include "source/common/config/utility.h"
      37             : #include "source/common/config/well_known_names.h"
      38             : #include "source/common/http/filter_chain_helper.h"
      39             : #include "source/common/http/utility.h"
      40             : #include "source/common/router/config_impl.h"
      41             : #include "source/common/router/context_impl.h"
      42             : #include "source/common/router/upstream_request.h"
      43             : #include "source/common/stats/symbol_table.h"
      44             : #include "source/common/stream_info/stream_info_impl.h"
      45             : #include "source/common/upstream/load_balancer_impl.h"
      46             : #include "source/common/upstream/upstream_factory_context_impl.h"
      47             : 
      48             : namespace Envoy {
      49             : namespace Router {
      50             : 
      51             : /**
      52             :  * Struct definition for all router filter stats. @see stats_macros.h
      53             :  */
      54             : MAKE_STATS_STRUCT(FilterStats, StatNames, ALL_ROUTER_STATS);
      55             : 
      56             : /**
      57             :  * Router filter utilities split out for ease of testing.
      58             :  */
      59             : class FilterUtility {
      60             : public:
      61             :   struct HedgingParams {
      62             :     bool hedge_on_per_try_timeout_ : 1;
      63             :   };
      64             : 
      65             :   class StrictHeaderChecker {
      66             :   public:
      67             :     struct HeaderCheckResult {
      68             :       bool valid_ = true;
      69             :       const Http::HeaderEntry* entry_;
      70             :     };
      71             : 
      72             :     /**
      73             :      * Determine whether a given header's value passes the strict validation
      74             :      * defined for that header.
      75             :      * @param headers supplies the headers from which to get the target header.
      76             :      * @param target_header is the header to be validated.
      77             :      * @return HeaderCheckResult containing the entry for @param target_header
      78             :      *         and valid_ set to FALSE if @param target_header is set to an
      79             :      *         invalid value. If @param target_header doesn't appear in
      80             :      *         @param headers, return a result with valid_ set to TRUE.
      81             :      */
      82             :     static const HeaderCheckResult checkHeader(Http::RequestHeaderMap& headers,
      83             :                                                const Http::LowerCaseString& target_header);
      84             : 
      85             :     using ParseRetryFlagsFunc = std::function<std::pair<uint32_t, bool>(absl::string_view)>;
      86             : 
      87             :   private:
      88             :     static HeaderCheckResult hasValidRetryFields(const Http::HeaderEntry* header_entry,
      89           0 :                                                  const ParseRetryFlagsFunc& parse_fn) {
      90           0 :       HeaderCheckResult r;
      91           0 :       if (header_entry) {
      92           0 :         const auto flags_and_validity = parse_fn(header_entry->value().getStringView());
      93           0 :         r.valid_ = flags_and_validity.second;
      94           0 :         r.entry_ = header_entry;
      95           0 :       }
      96           0 :       return r;
      97           0 :     }
      98             : 
      99           0 :     static HeaderCheckResult isInteger(const Http::HeaderEntry* header_entry) {
     100           0 :       HeaderCheckResult r;
     101           0 :       if (header_entry) {
     102           0 :         uint64_t out;
     103           0 :         r.valid_ = absl::SimpleAtoi(header_entry->value().getStringView(), &out);
     104           0 :         r.entry_ = header_entry;
     105           0 :       }
     106           0 :       return r;
     107           0 :     }
     108             :   };
     109             : 
     110             :   /**
     111             :    * Returns response_time / timeout, as a  percentage as [0, 100]. Returns 0
     112             :    * if there is no timeout.
     113             :    * @param response_time supplies the response time thus far.
     114             :    * @param timeout supplies  the timeout to get the percentage of.
     115             :    * @return the percentage of timeout [0, 100] for stats use.
     116             :    */
     117             :   static uint64_t percentageOfTimeout(const std::chrono::milliseconds response_time,
     118             :                                       const std::chrono::milliseconds timeout);
     119             : 
     120             :   /**
     121             :    * Set the :scheme header using the best information available. In order this is
     122             :    * - existing scheme header if valid
     123             :    * - x-forwarded-proto header if valid
     124             :    * - security of downstream connection
     125             :    */
     126             :   static void setUpstreamScheme(Http::RequestHeaderMap& headers, bool downstream_secure);
     127             : 
     128             :   /**
     129             :    * Determine whether a request should be shadowed.
     130             :    * @param policy supplies the route's shadow policy.
     131             :    * @param runtime supplies the runtime to lookup the shadow key in.
     132             :    * @param stable_random supplies the random number to use when determining whether shadowing
     133             :    *        should take place.
     134             :    * @return TRUE if shadowing should take place.
     135             :    */
     136             :   static bool shouldShadow(const ShadowPolicy& policy, Runtime::Loader& runtime,
     137             :                            uint64_t stable_random);
     138             : 
     139             :   /**
     140             :    * Determine the final timeout to use based on the route as well as the request headers.
     141             :    * @param route supplies the request route.
     142             :    * @param request_headers supplies the request headers.
     143             :    * @param insert_envoy_expected_request_timeout_ms insert
     144             :    *        x-envoy-expected-request-timeout-ms?
     145             :    * @param grpc_request tells if the request is a gRPC request.
     146             :    * @return TimeoutData for both the global and per try timeouts.
     147             :    */
     148             :   static TimeoutData finalTimeout(const RouteEntry& route, Http::RequestHeaderMap& request_headers,
     149             :                                   bool insert_envoy_expected_request_timeout_ms, bool grpc_request,
     150             :                                   bool per_try_timeout_hedging_enabled,
     151             :                                   bool respect_expected_rq_timeout);
     152             : 
     153             :   /**
     154             :    * Set the x-envoy-expected-request-timeout-ms and grpc-timeout headers if needed.
     155             :    * @param elapsed_time time elapsed since completion of the downstream request
     156             :    * @param timeout final TimeoutData to use for the request
     157             :    * @param request_headers the request headers to modify
     158             :    * @param insert_envoy_expected_request_timeout_ms insert
     159             :    *        x-envoy-expected-request-timeout-ms?
     160             :    * @param grpc_request tells if the request is a gRPC request.
     161             :    * @param per_try_timeout_headging_enabled is request hedging enabled?
     162             :    */
     163             :   static void setTimeoutHeaders(uint64_t elapsed_time, const TimeoutData& timeout,
     164             :                                 const RouteEntry& route, Http::RequestHeaderMap& request_headers,
     165             :                                 bool insert_envoy_expected_request_timeout_ms, bool grpc_request,
     166             :                                 bool per_try_timeout_hedging_enabled);
     167             : 
     168             :   /**
     169             :    * Try to parse a header entry that may have a timeout field
     170             :    *
     171             :    * @param header_timeout_entry header entry which may contain a timeout value.
     172             :    * @return result timeout value from header. It will return nullopt if parse failed.
     173             :    */
     174             :   static absl::optional<std::chrono::milliseconds>
     175             :   tryParseHeaderTimeout(const Http::HeaderEntry& header_timeout_entry);
     176             : 
     177             :   /**
     178             :    * Try to set global timeout.
     179             :    *
     180             :    * @param header_timeout_entry header entry which may contain a timeout value.
     181             :    * @param timeout timeout data to set from header timeout entry.
     182             :    */
     183             :   static void trySetGlobalTimeout(const Http::HeaderEntry& header_timeout_entry,
     184             :                                   TimeoutData& timeout);
     185             : 
     186             :   /**
     187             :    * Determine the final hedging settings after applying randomized behavior.
     188             :    * @param route supplies the request route.
     189             :    * @param request_headers supplies the request headers.
     190             :    * @return HedgingParams the final parameters to use for request hedging.
     191             :    */
     192             :   static HedgingParams finalHedgingParams(const RouteEntry& route,
     193             :                                           Http::RequestHeaderMap& request_headers);
     194             : };
     195             : 
     196             : /**
     197             :  * Configuration for the router filter.
     198             :  */
     199             : class FilterConfig : Http::FilterChainFactory {
     200             : public:
     201             :   FilterConfig(Stats::StatName stat_prefix, const LocalInfo::LocalInfo& local_info,
     202             :                Stats::Scope& scope, Upstream::ClusterManager& cm, Runtime::Loader& runtime,
     203             :                Random::RandomGenerator& random, ShadowWriterPtr&& shadow_writer,
     204             :                bool emit_dynamic_stats, bool start_child_span, bool suppress_envoy_headers,
     205             :                bool respect_expected_rq_timeout, bool suppress_grpc_request_failure_code_stats,
     206             :                bool flush_upstream_log_on_upstream_stream,
     207             :                const Protobuf::RepeatedPtrField<std::string>& strict_check_headers,
     208             :                TimeSource& time_source, Http::Context& http_context,
     209             :                Router::Context& router_context)
     210             :       : router_context_(router_context), scope_(scope), local_info_(local_info), cm_(cm),
     211             :         runtime_(runtime), default_stats_(router_context_.statNames(), scope_, stat_prefix),
     212             :         async_stats_(router_context_.statNames(), scope, http_context.asyncClientStatPrefix()),
     213             :         random_(random), emit_dynamic_stats_(emit_dynamic_stats),
     214             :         start_child_span_(start_child_span), suppress_envoy_headers_(suppress_envoy_headers),
     215             :         respect_expected_rq_timeout_(respect_expected_rq_timeout),
     216             :         suppress_grpc_request_failure_code_stats_(suppress_grpc_request_failure_code_stats),
     217             :         flush_upstream_log_on_upstream_stream_(flush_upstream_log_on_upstream_stream),
     218             :         http_context_(http_context), zone_name_(local_info_.zoneStatName()),
     219         175 :         shadow_writer_(std::move(shadow_writer)), time_source_(time_source) {
     220         175 :     if (!strict_check_headers.empty()) {
     221           2 :       strict_check_headers_ = std::make_unique<HeaderVector>();
     222           2 :       for (const auto& header : strict_check_headers) {
     223           2 :         strict_check_headers_->emplace_back(Http::LowerCaseString(header));
     224           2 :       }
     225           2 :     }
     226         175 :   }
     227             : 
     228             :   FilterConfig(Stats::StatName stat_prefix, Server::Configuration::FactoryContext& context,
     229             :                ShadowWriterPtr&& shadow_writer,
     230             :                const envoy::extensions::filters::http::router::v3::Router& config);
     231             : 
     232             :   bool createFilterChain(
     233             :       Http::FilterChainManager& manager, bool only_create_if_configured = false,
     234         251 :       const Http::FilterChainOptions& options = Http::EmptyFilterChainOptions{}) const override {
     235             :     // Currently there is no default filter chain, so only_create_if_configured true doesn't make
     236             :     // sense.
     237         251 :     ASSERT(!only_create_if_configured);
     238         251 :     if (upstream_http_filter_factories_.empty()) {
     239         251 :       return false;
     240         251 :     }
     241           0 :     Http::FilterChainUtility::createFilterChainForFactories(manager, options,
     242           0 :                                                             upstream_http_filter_factories_);
     243           0 :     return true;
     244         251 :   }
     245             : 
     246             :   bool createUpgradeFilterChain(absl::string_view, const UpgradeMap*,
     247           0 :                                 Http::FilterChainManager&) const override {
     248             :     // Upgrade filter chains not yet supported for upstream HTTP filters.
     249           0 :     return false;
     250           0 :   }
     251             : 
     252             :   using HeaderVector = std::vector<Http::LowerCaseString>;
     253             :   using HeaderVectorPtr = std::unique_ptr<HeaderVector>;
     254             : 
     255           0 :   ShadowWriter& shadowWriter() { return *shadow_writer_; }
     256         251 :   TimeSource& timeSource() { return time_source_; }
     257             : 
     258             :   Router::Context& router_context_;
     259             :   Stats::Scope& scope_;
     260             :   const LocalInfo::LocalInfo& local_info_;
     261             :   Upstream::ClusterManager& cm_;
     262             :   Runtime::Loader& runtime_;
     263             :   FilterStats default_stats_;
     264             :   FilterStats async_stats_;
     265             :   Random::RandomGenerator& random_;
     266             :   const bool emit_dynamic_stats_;
     267             :   const bool start_child_span_;
     268             :   const bool suppress_envoy_headers_;
     269             :   const bool respect_expected_rq_timeout_;
     270             :   const bool suppress_grpc_request_failure_code_stats_;
     271             :   // TODO(xyu-stripe): Make this a bitset to keep cluster memory footprint down.
     272             :   HeaderVectorPtr strict_check_headers_;
     273             :   const bool flush_upstream_log_on_upstream_stream_;
     274             :   absl::optional<std::chrono::milliseconds> upstream_log_flush_interval_;
     275             :   std::list<AccessLog::InstanceSharedPtr> upstream_logs_;
     276             :   Http::Context& http_context_;
     277             :   Stats::StatName zone_name_;
     278             :   Stats::StatName empty_stat_name_;
     279             :   std::unique_ptr<Server::Configuration::UpstreamFactoryContext> upstream_ctx_;
     280             :   Http::FilterChainUtility::FilterFactoriesList upstream_http_filter_factories_;
     281             : 
     282             : private:
     283             :   ShadowWriterPtr shadow_writer_;
     284             :   TimeSource& time_source_;
     285             : };
     286             : 
     287             : using FilterConfigSharedPtr = std::shared_ptr<FilterConfig>;
     288             : 
     289             : class UpstreamRequest;
     290             : using UpstreamRequestPtr = std::unique_ptr<UpstreamRequest>;
     291             : 
     292             : /**
     293             :  * Service routing filter.
     294             :  */
     295             : class Filter : Logger::Loggable<Logger::Id::router>,
     296             :                public Http::StreamDecoderFilter,
     297             :                public Upstream::LoadBalancerContextBase,
     298             :                public RouterFilterInterface {
     299             : public:
     300             :   Filter(FilterConfig& config, FilterStats& stats)
     301             :       : config_(config), stats_(stats), grpc_request_(false), exclude_http_code_stats_(false),
     302             :         downstream_response_started_(false), downstream_end_stream_(false), is_retry_(false),
     303             :         request_buffer_overflowed_(false), streaming_shadows_(Runtime::runtimeFeatureEnabled(
     304         545 :                                                "envoy.reloadable_features.streaming_shadow")) {}
     305             : 
     306             :   ~Filter() override;
     307             : 
     308             :   static StreamInfo::ResponseFlag
     309             :   streamResetReasonToResponseFlag(Http::StreamResetReason reset_reason);
     310             : 
     311             :   // Http::StreamFilterBase
     312             :   void onDestroy() override;
     313             : 
     314             :   // Http::StreamDecoderFilter
     315             :   Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& headers,
     316             :                                           bool end_stream) override;
     317             :   Http::FilterDataStatus decodeData(Buffer::Instance& data, bool end_stream) override;
     318             :   Http::FilterTrailersStatus decodeTrailers(Http::RequestTrailerMap& trailers) override;
     319             :   Http::FilterMetadataStatus decodeMetadata(Http::MetadataMap& metadata_map) override;
     320             :   void setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callbacks) override;
     321             : 
     322             :   // Upstream::LoadBalancerContext
     323           0 :   absl::optional<uint64_t> computeHashKey() override {
     324           0 :     if (route_entry_ && downstream_headers_) {
     325           0 :       auto hash_policy = route_entry_->hashPolicy();
     326           0 :       if (hash_policy) {
     327           0 :         return hash_policy->generateHash(
     328           0 :             callbacks_->streamInfo().downstreamAddressProvider().remoteAddress().get(),
     329           0 :             *downstream_headers_,
     330           0 :             [this](const std::string& key, const std::string& path, std::chrono::seconds max_age,
     331           0 :                    Http::CookieAttributeRefVector attributes) {
     332           0 :               return addDownstreamSetCookie(key, path, max_age, attributes);
     333           0 :             },
     334           0 :             callbacks_->streamInfo().filterState());
     335           0 :       }
     336           0 :     }
     337           0 :     return {};
     338           0 :   }
     339           0 :   const Router::MetadataMatchCriteria* metadataMatchCriteria() override {
     340           0 :     if (route_entry_) {
     341             :       // Have we been called before? If so, there's no need to recompute because
     342             :       // by the time this method is called for the first time, route_entry_ should
     343             :       // not change anymore.
     344           0 :       if (metadata_match_ != nullptr) {
     345           0 :         return metadata_match_.get();
     346           0 :       }
     347             : 
     348             :       // The request's metadata, if present, takes precedence over the route's.
     349           0 :       const auto& request_metadata = callbacks_->streamInfo().dynamicMetadata().filter_metadata();
     350           0 :       const auto filter_it = request_metadata.find(Envoy::Config::MetadataFilters::get().ENVOY_LB);
     351           0 :       if (filter_it != request_metadata.end()) {
     352           0 :         if (route_entry_->metadataMatchCriteria() != nullptr) {
     353           0 :           metadata_match_ =
     354           0 :               route_entry_->metadataMatchCriteria()->mergeMatchCriteria(filter_it->second);
     355           0 :         } else {
     356           0 :           metadata_match_ = std::make_unique<Router::MetadataMatchCriteriaImpl>(filter_it->second);
     357           0 :         }
     358           0 :         return metadata_match_.get();
     359           0 :       }
     360           0 :       return route_entry_->metadataMatchCriteria();
     361           0 :     }
     362           0 :     return nullptr;
     363           0 :   }
     364         685 :   const Network::Connection* downstreamConnection() const override {
     365         685 :     return callbacks_->connection().ptr();
     366         685 :   }
     367           0 :   const StreamInfo::StreamInfo* requestStreamInfo() const override {
     368           0 :     return &callbacks_->streamInfo();
     369           0 :   }
     370           0 :   const Http::RequestHeaderMap* downstreamHeaders() const override { return downstream_headers_; }
     371             : 
     372         251 :   bool shouldSelectAnotherHost(const Upstream::Host& host) override {
     373             :     // We only care about host selection when performing a retry, at which point we consult the
     374             :     // RetryState to see if we're configured to avoid certain hosts during retries.
     375         251 :     if (!is_retry_) {
     376         251 :       return false;
     377         251 :     }
     378             : 
     379           0 :     ASSERT(retry_state_);
     380           0 :     return retry_state_->shouldSelectAnotherHost(host);
     381         251 :   }
     382             : 
     383             :   const Upstream::HealthyAndDegradedLoad& determinePriorityLoad(
     384             :       const Upstream::PrioritySet& priority_set,
     385             :       const Upstream::HealthyAndDegradedLoad& original_priority_load,
     386         251 :       const Upstream::RetryPriority::PriorityMappingFunc& priority_mapping_func) override {
     387             :     // We only modify the priority load on retries.
     388         251 :     if (!is_retry_) {
     389         251 :       return original_priority_load;
     390         251 :     }
     391           0 :     return retry_state_->priorityLoadForRetry(priority_set, original_priority_load,
     392           0 :                                               priority_mapping_func);
     393         251 :   }
     394             : 
     395         251 :   uint32_t hostSelectionRetryCount() const override {
     396         251 :     if (!is_retry_) {
     397         251 :       return 1;
     398         251 :     }
     399           0 :     return retry_state_->hostSelectionMaxAttempts();
     400         251 :   }
     401             : 
     402         251 :   Network::Socket::OptionsSharedPtr upstreamSocketOptions() const override {
     403         251 :     return (upstream_options_ != nullptr) ? upstream_options_
     404         251 :                                           : callbacks_->getUpstreamSocketOptions();
     405         251 :   }
     406             : 
     407         574 :   Network::TransportSocketOptionsConstSharedPtr upstreamTransportSocketOptions() const override {
     408         574 :     return transport_socket_options_;
     409         574 :   }
     410             : 
     411         502 :   absl::optional<OverrideHost> overrideHostToSelect() const override {
     412         502 :     if (is_retry_) {
     413           0 :       return {};
     414           0 :     }
     415         502 :     return callbacks_->upstreamOverrideHost();
     416         502 :   }
     417             : 
     418             :   /**
     419             :    * Set a computed cookie to be sent with the downstream headers.
     420             :    * @param key supplies the size of the cookie
     421             :    * @param max_age the lifetime of the cookie
     422             :    * @param  path the path of the cookie, or ""
     423             :    * @return std::string the value of the new cookie
     424             :    */
     425             :   std::string addDownstreamSetCookie(const std::string& key, const std::string& path,
     426             :                                      std::chrono::seconds max_age,
     427           0 :                                      Http::CookieAttributeRefVector attributes) {
     428             :     // The cookie value should be the same per connection so that if multiple
     429             :     // streams race on the same path, they all receive the same cookie.
     430             :     // Since the downstream port is part of the hashed value, multiple HTTP1
     431             :     // connections can receive different cookies if they race on requests.
     432           0 :     std::string value;
     433           0 :     const Network::Connection* conn = downstreamConnection();
     434             :     // Need to check for null conn if this is ever used by Http::AsyncClient in the future.
     435           0 :     value = conn->connectionInfoProvider().remoteAddress()->asString() +
     436           0 :             conn->connectionInfoProvider().localAddress()->asString();
     437             : 
     438           0 :     const std::string cookie_value = Hex::uint64ToHex(HashUtil::xxHash64(value));
     439           0 :     downstream_set_cookies_.emplace_back(
     440           0 :         Http::Utility::makeSetCookieValue(key, cookie_value, path, max_age, true, attributes));
     441           0 :     return cookie_value;
     442           0 :   }
     443             : 
     444             :   // RouterFilterInterface
     445             :   void onUpstream1xxHeaders(Http::ResponseHeaderMapPtr&& headers,
     446             :                             UpstreamRequest& upstream_request) override;
     447             :   void onUpstreamHeaders(uint64_t response_code, Http::ResponseHeaderMapPtr&& headers,
     448             :                          UpstreamRequest& upstream_request, bool end_stream) override;
     449             :   void onUpstreamData(Buffer::Instance& data, UpstreamRequest& upstream_request,
     450             :                       bool end_stream) override;
     451             :   void onUpstreamTrailers(Http::ResponseTrailerMapPtr&& trailers,
     452             :                           UpstreamRequest& upstream_request) override;
     453             :   void onUpstreamMetadata(Http::MetadataMapPtr&& metadata_map) override;
     454             :   void onUpstreamReset(Http::StreamResetReason reset_reason, absl::string_view transport_failure,
     455             :                        UpstreamRequest& upstream_request) override;
     456             :   void onUpstreamHostSelected(Upstream::HostDescriptionConstSharedPtr host,
     457             :                               bool pool_success) override;
     458             :   void onPerTryTimeout(UpstreamRequest& upstream_request) override;
     459             :   void onPerTryIdleTimeout(UpstreamRequest& upstream_request) override;
     460             :   void onStreamMaxDurationReached(UpstreamRequest& upstream_request) override;
     461        7035 :   Http::StreamDecoderFilterCallbacks* callbacks() override { return callbacks_; }
     462        1385 :   Upstream::ClusterInfoConstSharedPtr cluster() override { return cluster_; }
     463        1170 :   FilterConfig& config() override { return config_; }
     464         294 :   TimeoutData timeout() override { return timeout_; }
     465         202 :   absl::optional<std::chrono::milliseconds> dynamicMaxStreamDuration() const override {
     466         202 :     return dynamic_max_stream_duration_;
     467         202 :   }
     468        2083 :   Http::RequestHeaderMap* downstreamHeaders() override { return downstream_headers_; }
     469        1436 :   Http::RequestTrailerMap* downstreamTrailers() override { return downstream_trailers_; }
     470          16 :   bool downstreamResponseStarted() const override { return downstream_response_started_; }
     471         202 :   bool downstreamEndStream() const override { return downstream_end_stream_; }
     472           0 :   uint32_t attemptCount() const override { return attempt_count_; }
     473           0 :   const std::list<UpstreamRequestPtr>& upstreamRequests() const { return upstream_requests_; }
     474             : 
     475           0 :   TimeSource& timeSource() { return config_.timeSource(); }
     476           0 :   const Route* route() const { return route_.get(); }
     477           0 :   const FilterStats& stats() { return stats_; }
     478             : 
     479             : protected:
     480           0 :   void setRetryShadowBufferLimit(uint32_t retry_shadow_buffer_limit) {
     481           0 :     ASSERT(retry_shadow_buffer_limit_ > retry_shadow_buffer_limit);
     482           0 :     retry_shadow_buffer_limit_ = retry_shadow_buffer_limit;
     483           0 :   }
     484             : 
     485             : private:
     486             :   friend class UpstreamRequest;
     487             : 
     488             :   enum class TimeoutRetry { Yes, No };
     489             : 
     490             :   void onPerTryTimeoutCommon(UpstreamRequest& upstream_request, Stats::Counter& error_counter,
     491             :                              const std::string& response_code_details);
     492             :   Stats::StatName upstreamZone(Upstream::HostDescriptionConstSharedPtr upstream_host);
     493             :   void chargeUpstreamCode(uint64_t response_status_code,
     494             :                           const Http::ResponseHeaderMap& response_headers,
     495             :                           Upstream::HostDescriptionConstSharedPtr upstream_host, bool dropped);
     496             :   void chargeUpstreamCode(Http::Code code, Upstream::HostDescriptionConstSharedPtr upstream_host,
     497             :                           bool dropped);
     498             :   void chargeUpstreamAbort(Http::Code code, bool dropped, UpstreamRequest& upstream_request);
     499             :   void cleanup();
     500             :   virtual RetryStatePtr
     501             :   createRetryState(const RetryPolicy& policy, Http::RequestHeaderMap& request_headers,
     502             :                    const Upstream::ClusterInfo& cluster, const VirtualCluster* vcluster,
     503             :                    RouteStatsContextOptRef route_stats_context, Runtime::Loader& runtime,
     504             :                    Random::RandomGenerator& random, Event::Dispatcher& dispatcher,
     505             :                    TimeSource& time_source, Upstream::ResourcePriority priority) PURE;
     506             : 
     507             :   std::unique_ptr<GenericConnPool>
     508             :   createConnPool(Upstream::ThreadLocalCluster& thread_local_cluster);
     509             :   UpstreamRequestPtr createUpstreamRequest();
     510             :   absl::optional<absl::string_view> getShadowCluster(const ShadowPolicy& shadow_policy,
     511             :                                                      const Http::HeaderMap& headers) const;
     512             : 
     513             :   void maybeDoShadowing();
     514             :   bool maybeRetryReset(Http::StreamResetReason reset_reason, UpstreamRequest& upstream_request,
     515             :                        TimeoutRetry is_timeout_retry);
     516             :   uint32_t numRequestsAwaitingHeaders();
     517             :   void onGlobalTimeout();
     518             :   void onRequestComplete();
     519             :   void onResponseTimeout();
     520             :   // Handle an upstream request aborted due to a local timeout.
     521             :   void onSoftPerTryTimeout();
     522             :   void onSoftPerTryTimeout(UpstreamRequest& upstream_request);
     523             :   void onUpstreamTimeoutAbort(StreamInfo::ResponseFlag response_flag, absl::string_view details);
     524             :   // Handle an "aborted" upstream request, meaning we didn't see response
     525             :   // headers (e.g. due to a reset). Handles recording stats and responding
     526             :   // downstream if appropriate.
     527             :   void onUpstreamAbort(Http::Code code, StreamInfo::ResponseFlag response_flag,
     528             :                        absl::string_view body, bool dropped, absl::string_view details);
     529             :   void onUpstreamComplete(UpstreamRequest& upstream_request);
     530             :   // Reset all in-flight upstream requests.
     531             :   void resetAll();
     532             :   // Reset all in-flight upstream requests that do NOT match the passed argument. This is used
     533             :   // if a "good" response comes back and we return downstream, so there is no point in waiting
     534             :   // for the remaining upstream requests to return.
     535             :   void resetOtherUpstreams(UpstreamRequest& upstream_request);
     536             :   void sendNoHealthyUpstreamResponse();
     537             :   bool setupRedirect(const Http::ResponseHeaderMap& headers);
     538             :   bool convertRequestHeadersForInternalRedirect(Http::RequestHeaderMap& downstream_headers,
     539             :                                                 const Http::ResponseHeaderMap& upstream_headers,
     540             :                                                 const Http::HeaderEntry& internal_redirect,
     541             :                                                 uint64_t status_code);
     542             :   void updateOutlierDetection(Upstream::Outlier::Result result, UpstreamRequest& upstream_request,
     543             :                               absl::optional<uint64_t> code);
     544             :   void doRetry(bool can_send_early_data, bool can_use_http3, TimeoutRetry is_timeout_retry);
     545             :   void runRetryOptionsPredicates(UpstreamRequest& retriable_request);
     546             :   // Called immediately after a non-5xx header is received from upstream, performs stats accounting
     547             :   // and handle difference between gRPC and non-gRPC requests.
     548             :   void handleNon5xxResponseHeaders(absl::optional<Grpc::Status::GrpcStatus> grpc_status,
     549             :                                    UpstreamRequest& upstream_request, bool end_stream,
     550             :                                    uint64_t grpc_to_http_status);
     551         272 :   Http::Context& httpContext() { return config_.http_context_; }
     552             :   bool checkDropOverload(Upstream::ThreadLocalCluster& cluster,
     553             :                          std::function<void(Http::ResponseHeaderMap&)>& modify_headers);
     554             : 
     555             :   RetryStatePtr retry_state_;
     556             :   FilterConfig& config_;
     557             :   Http::StreamDecoderFilterCallbacks* callbacks_{};
     558             :   RouteConstSharedPtr route_;
     559             :   const RouteEntry* route_entry_{};
     560             :   Upstream::ClusterInfoConstSharedPtr cluster_;
     561             :   std::unique_ptr<Stats::StatNameDynamicStorage> alt_stat_prefix_;
     562             :   const VirtualCluster* request_vcluster_{};
     563             :   RouteStatsContextOptRef route_stats_context_;
     564             :   Event::TimerPtr response_timeout_;
     565             :   TimeoutData timeout_;
     566             :   std::list<UpstreamRequestPtr> upstream_requests_;
     567             :   FilterStats stats_;
     568             :   // Tracks which upstream request "wins" and will have the corresponding
     569             :   // response forwarded downstream
     570             :   UpstreamRequest* final_upstream_request_ = nullptr;
     571             :   Http::RequestHeaderMap* downstream_headers_{};
     572             :   Http::RequestTrailerMap* downstream_trailers_{};
     573             :   MonotonicTime downstream_request_complete_time_;
     574             :   MetadataMatchCriteriaConstPtr metadata_match_;
     575             :   std::function<void(Http::ResponseHeaderMap&)> modify_headers_;
     576             :   std::vector<std::reference_wrapper<const ShadowPolicy>> active_shadow_policies_{};
     577             :   std::unique_ptr<Http::RequestHeaderMap> shadow_headers_;
     578             :   std::unique_ptr<Http::RequestTrailerMap> shadow_trailers_;
     579             :   // The stream lifetime configured by request header.
     580             :   absl::optional<std::chrono::milliseconds> dynamic_max_stream_duration_;
     581             :   // list of cookies to add to upstream headers
     582             :   std::vector<std::string> downstream_set_cookies_;
     583             : 
     584             :   Network::TransportSocketOptionsConstSharedPtr transport_socket_options_;
     585             :   Network::Socket::OptionsSharedPtr upstream_options_;
     586             :   // Set of ongoing shadow streams which have not yet received end stream.
     587             :   absl::flat_hash_set<Http::AsyncClient::OngoingRequest*> shadow_streams_;
     588             : 
     589             :   // Keep small members (bools and enums) at the end of class, to reduce alignment overhead.
     590             :   uint32_t retry_shadow_buffer_limit_{std::numeric_limits<uint32_t>::max()};
     591             :   uint32_t attempt_count_{1};
     592             :   uint32_t pending_retries_{0};
     593             :   Http::Code timeout_response_code_ = Http::Code::GatewayTimeout;
     594             :   FilterUtility::HedgingParams hedging_params_;
     595             :   bool grpc_request_ : 1;
     596             :   bool exclude_http_code_stats_ : 1;
     597             :   bool downstream_response_started_ : 1;
     598             :   bool downstream_end_stream_ : 1;
     599             :   bool is_retry_ : 1;
     600             :   bool include_attempt_count_in_request_ : 1;
     601             :   bool include_timeout_retry_header_in_request_ : 1;
     602             :   bool request_buffer_overflowed_ : 1;
     603             :   const bool streaming_shadows_ : 1;
     604             : };
     605             : 
     606             : class ProdFilter : public Filter {
     607             : public:
     608             :   using Filter::Filter;
     609             : 
     610             : private:
     611             :   // Filter
     612             :   RetryStatePtr createRetryState(const RetryPolicy& policy, Http::RequestHeaderMap& request_headers,
     613             :                                  const Upstream::ClusterInfo& cluster,
     614             :                                  const VirtualCluster* vcluster,
     615             :                                  RouteStatsContextOptRef route_stats_context,
     616             :                                  Runtime::Loader& runtime, Random::RandomGenerator& random,
     617             :                                  Event::Dispatcher& dispatcher, TimeSource& time_source,
     618             :                                  Upstream::ResourcePriority priority) override;
     619             : };
     620             : 
     621             : } // namespace Router
     622             : } // namespace Envoy

Generated by: LCOV version 1.15