Line data Source code
1 : #pragma once 2 : 3 : #include <cstdint> 4 : 5 : #include "envoy/access_log/access_log.h" 6 : #include "envoy/api/api.h" 7 : #include "envoy/common/random_generator.h" 8 : #include "envoy/config/core/v3/health_check.pb.h" 9 : #include "envoy/data/core/v3/health_check_event.pb.h" 10 : #include "envoy/grpc/status.h" 11 : #include "envoy/network/socket.h" 12 : #include "envoy/server/health_checker_config.h" 13 : #include "envoy/type/v3/http.pb.h" 14 : #include "envoy/type/v3/range.pb.h" 15 : 16 : #include "source/common/common/dump_state_utils.h" 17 : #include "source/common/common/logger.h" 18 : #include "source/common/grpc/codec.h" 19 : #include "source/common/http/codec_client.h" 20 : #include "source/common/router/header_parser.h" 21 : #include "source/common/stream_info/stream_info_impl.h" 22 : #include "source/common/upstream/health_checker_impl.h" 23 : #include "source/extensions/health_checkers/common/health_checker_base_impl.h" 24 : 25 : #include "src/proto/grpc/health/v1/health.pb.h" 26 : 27 : namespace Envoy { 28 : namespace Upstream { 29 : 30 : class HttpHealthCheckerFactory : public Server::Configuration::CustomHealthCheckerFactory { 31 : public: 32 : Upstream::HealthCheckerSharedPtr 33 : createCustomHealthChecker(const envoy::config::core::v3::HealthCheck& config, 34 : Server::Configuration::HealthCheckerFactoryContext& context) override; 35 : 36 148 : std::string name() const override { return "envoy.health_checkers.http"; } 37 12 : ProtobufTypes::MessagePtr createEmptyConfigProto() override { 38 12 : return ProtobufTypes::MessagePtr{new envoy::config::core::v3::HealthCheck::HttpHealthCheck()}; 39 12 : } 40 : }; 41 : 42 : DECLARE_FACTORY(HttpHealthCheckerFactory); 43 : 44 : /** 45 : * HTTP health checker implementation. Connection keep alive is used where possible. 46 : */ 47 : class HttpHealthCheckerImpl : public HealthCheckerImplBase { 48 : public: 49 : HttpHealthCheckerImpl(const Cluster& cluster, const envoy::config::core::v3::HealthCheck& config, 50 : Event::Dispatcher& dispatcher, Runtime::Loader& runtime, 51 : Random::RandomGenerator& random, HealthCheckEventLoggerPtr&& event_logger); 52 : 53 : // Returns the HTTP protocol used for the health checker. 54 : Http::Protocol protocol() const; 55 : 56 : /** 57 : * Utility class checking if given http status matches configured expectations. 58 : */ 59 : class HttpStatusChecker { 60 : public: 61 : HttpStatusChecker( 62 : const Protobuf::RepeatedPtrField<envoy::type::v3::Int64Range>& expected_statuses, 63 : const Protobuf::RepeatedPtrField<envoy::type::v3::Int64Range>& retriable_statuses, 64 : uint64_t default_expected_status); 65 : 66 : bool inRetriableRanges(uint64_t http_status) const; 67 : bool inExpectedRanges(uint64_t http_status) const; 68 : 69 : private: 70 : static bool inRanges(uint64_t http_status, 71 : const std::vector<std::pair<uint64_t, uint64_t>>& ranges); 72 : static void validateRange(uint64_t start, uint64_t end, absl::string_view range_type); 73 : 74 : std::vector<std::pair<uint64_t, uint64_t>> expected_ranges_; 75 : std::vector<std::pair<uint64_t, uint64_t>> retriable_ranges_; 76 : }; 77 : 78 : private: 79 : struct HttpActiveHealthCheckSession : public ActiveHealthCheckSession, 80 : public Http::ResponseDecoder, 81 : public Http::StreamCallbacks { 82 : HttpActiveHealthCheckSession(HttpHealthCheckerImpl& parent, const HostSharedPtr& host); 83 : ~HttpActiveHealthCheckSession() override; 84 : 85 : void onResponseComplete(); 86 : enum class HealthCheckResult { Succeeded, Degraded, Failed, Retriable }; 87 : HealthCheckResult healthCheckResult(); 88 : bool shouldClose() const; 89 : 90 : // ActiveHealthCheckSession 91 : void onInterval() override; 92 : void onTimeout() override; 93 : void onDeferredDelete() final; 94 : 95 : // Http::StreamDecoder 96 : void decodeData(Buffer::Instance& data, bool end_stream) override; 97 0 : void decodeMetadata(Http::MetadataMapPtr&&) override {} 98 : 99 : // Http::ResponseDecoder 100 0 : void decode1xxHeaders(Http::ResponseHeaderMapPtr&&) override {} 101 : void decodeHeaders(Http::ResponseHeaderMapPtr&& headers, bool end_stream) override; 102 0 : void decodeTrailers(Http::ResponseTrailerMapPtr&&) override { onResponseComplete(); } 103 0 : void dumpState(std::ostream& os, int indent_level) const override { 104 0 : DUMP_STATE_UNIMPLEMENTED(HttpActiveHealthCheckSession); 105 0 : } 106 : 107 : // Http::StreamCallbacks 108 : void onResetStream(Http::StreamResetReason reason, 109 : absl::string_view transport_failure_reason) override; 110 0 : void onAboveWriteBufferHighWatermark() override {} 111 0 : void onBelowWriteBufferLowWatermark() override {} 112 : 113 : void onEvent(Network::ConnectionEvent event); 114 : void onGoAway(Http::GoAwayErrorCode error_code); 115 : 116 : class ConnectionCallbackImpl : public Network::ConnectionCallbacks { 117 : public: 118 22 : ConnectionCallbackImpl(HttpActiveHealthCheckSession& parent) : parent_(parent) {} 119 : // Network::ConnectionCallbacks 120 31 : void onEvent(Network::ConnectionEvent event) override { parent_.onEvent(event); } 121 0 : void onAboveWriteBufferHighWatermark() override {} 122 0 : void onBelowWriteBufferLowWatermark() override {} 123 : 124 : private: 125 : HttpActiveHealthCheckSession& parent_; 126 : }; 127 : 128 : class HttpConnectionCallbackImpl : public Http::ConnectionCallbacks { 129 : public: 130 22 : HttpConnectionCallbackImpl(HttpActiveHealthCheckSession& parent) : parent_(parent) {} 131 : // Http::ConnectionCallbacks 132 0 : void onGoAway(Http::GoAwayErrorCode error_code) override { parent_.onGoAway(error_code); } 133 : 134 : private: 135 : HttpActiveHealthCheckSession& parent_; 136 : }; 137 : 138 : ConnectionCallbackImpl connection_callback_impl_{*this}; 139 : HttpConnectionCallbackImpl http_connection_callback_impl_{*this}; 140 : HttpHealthCheckerImpl& parent_; 141 : Http::CodecClientPtr client_; 142 : Http::ResponseHeaderMapPtr response_headers_; 143 : Buffer::InstancePtr response_body_; 144 : const std::string& hostname_; 145 : Network::ConnectionInfoProviderSharedPtr local_connection_info_provider_; 146 : // Keep small members (bools and enums) at the end of class, to reduce alignment overhead. 147 : const Http::Protocol protocol_; 148 : bool expect_reset_ : 1; 149 : bool reuse_connection_ : 1; 150 : bool request_in_flight_ : 1; 151 : }; 152 : 153 : using HttpActiveHealthCheckSessionPtr = std::unique_ptr<HttpActiveHealthCheckSession>; 154 : 155 : virtual Http::CodecClient* createCodecClient(Upstream::Host::CreateConnectionData& data) PURE; 156 : 157 : // HealthCheckerImplBase 158 22 : ActiveHealthCheckSessionPtr makeSession(HostSharedPtr host) override { 159 22 : return std::make_unique<HttpActiveHealthCheckSession>(*this, host); 160 22 : } 161 21 : envoy::data::core::v3::HealthCheckerType healthCheckerType() const override { 162 21 : return envoy::data::core::v3::HTTP; 163 21 : } 164 : 165 : Http::CodecType codecClientType(const envoy::type::v3::CodecClientType& type); 166 : 167 : const std::string path_; 168 : const std::string host_value_; 169 : PayloadMatcher::MatchSegments receive_bytes_; 170 : const envoy::config::core::v3::RequestMethod method_; 171 : uint64_t response_buffer_size_; 172 : absl::optional<Matchers::StringMatcherImpl<envoy::type::matcher::v3::StringMatcher>> 173 : service_name_matcher_; 174 : Router::HeaderParserPtr request_headers_parser_; 175 : const HttpStatusChecker http_status_checker_; 176 : 177 : protected: 178 : const Http::CodecType codec_client_type_; 179 : Random::RandomGenerator& random_generator_; 180 : }; 181 : 182 : /** 183 : * Production implementation of the HTTP health checker that allocates a real codec client. 184 : */ 185 : class ProdHttpHealthCheckerImpl : public HttpHealthCheckerImpl { 186 : public: 187 : using HttpHealthCheckerImpl::HttpHealthCheckerImpl; 188 : 189 : // HttpHealthCheckerImpl 190 : Http::CodecClient* createCodecClient(Upstream::Host::CreateConnectionData& data) override; 191 : }; 192 : 193 : } // namespace Upstream 194 : } // namespace Envoy