Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions RAW_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,5 @@ final version.
namespace can be used by prepending '@' to a socket path.
* Added `GEORADIUS_RO` and `GEORADIUSBYMEMBER_RO` to the Redis command splitter whitelist.
* Added support for trusting additional hops in the X-Forwarded-For request header.
* Added setting host header value for http health check request.

5 changes: 3 additions & 2 deletions source/common/upstream/health_checker_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ HttpHealthCheckerImpl::HttpHealthCheckerImpl(const Cluster& cluster,
Runtime::Loader& runtime,
Runtime::RandomGenerator& random)
: HealthCheckerImplBase(cluster, config, dispatcher, runtime, random),
path_(config.http_health_check().path()) {
path_(config.http_health_check().path()), host_value_(config.http_health_check().host()) {
if (!config.http_health_check().service_name().empty()) {
service_name_.value(config.http_health_check().service_name());
}
Expand Down Expand Up @@ -332,7 +332,8 @@ void HttpHealthCheckerImpl::HttpActiveHealthCheckSession::onInterval() {

Http::HeaderMapImpl request_headers{
{Http::Headers::get().Method, "GET"},
{Http::Headers::get().Host, parent_.cluster_.info()->name()},
{Http::Headers::get().Host,
parent_.host_value_.empty() ? parent_.cluster_.info()->name() : parent_.host_value_},
{Http::Headers::get().Path, parent_.path_},
{Http::Headers::get().UserAgent, Http::Headers::get().UserAgentValues.EnvoyHealthChecker}};

Expand Down
1 change: 1 addition & 0 deletions source/common/upstream/health_checker_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ class HttpHealthCheckerImpl : public HealthCheckerImplBase {
}

const std::string path_;
const std::string host_value_;
Optional<std::string> service_name_;
};

Expand Down
72 changes: 72 additions & 0 deletions test/common/upstream/health_checker_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ envoy::api::v2::core::HealthCheck parseHealthCheckFromJson(const std::string& js
return health_check;
}

envoy::api::v2::core::HealthCheck parseHealthCheckFromYaml(const std::string& yaml_string) {
envoy::api::v2::core::HealthCheck health_check;
MessageUtil::loadFromYaml(yaml_string, health_check);
return health_check;
}

envoy::api::v2::core::HealthCheck createGrpcHealthCheckConfig() {
envoy::api::v2::core::HealthCheck health_check;
health_check.mutable_timeout()->set_seconds(1);
Expand Down Expand Up @@ -220,6 +226,27 @@ class HttpHealthCheckerImplTest : public testing::Test {
});
}

void setupServiceValidationWithCustomHostValueHC(const std::string& host) {
std::string yaml = fmt::format(R"EOF(
timeout: 1s
interval: 1s
interval_jitter: 1s
unhealthy_threshold: 2
healthy_threshold: 2
http_health_check:
service_name: locations
path: /healthcheck
host: {0}
)EOF",
host);

health_checker_.reset(new TestHttpHealthCheckerImpl(*cluster_, parseHealthCheckFromYaml(yaml),
dispatcher_, runtime_, random_));
health_checker_->addHostCheckCompleteCb([this](HostSharedPtr host, bool changed_state) -> void {
onHostStatus(host, changed_state);
});
}

void expectSessionCreate() {
// Expectations are in LIFO order.
TestSessionPtr new_test_session(new TestSession());
Expand Down Expand Up @@ -426,6 +453,51 @@ TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheck) {
expectSessionCreate();
expectStreamCreate(0);
EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_));
EXPECT_CALL(test_sessions_[0]->request_encoder_, encodeHeaders(_, true))
.WillOnce(Invoke([&](const Http::HeaderMap& headers, bool) {
EXPECT_TRUE(headers.Host());
EXPECT_TRUE(headers.Path());
EXPECT_NE(nullptr, headers.Host());
EXPECT_NE(nullptr, headers.Path());
EXPECT_EQ(headers.Host()->value().c_str(), std::string("fake_cluster"));
EXPECT_EQ(headers.Path()->value().c_str(), std::string("/healthcheck"));
}));
health_checker_->start();

EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _));
EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.min_interval", _))
.WillOnce(Return(45000));
EXPECT_CALL(*test_sessions_[0]->interval_timer_, enableTimer(std::chrono::milliseconds(45000)));
EXPECT_CALL(*test_sessions_[0]->timeout_timer_, disableTimer());
Optional<std::string> health_checked_cluster("locations-production-iad");
respond(0, "200", false, true, false, health_checked_cluster);
EXPECT_TRUE(cluster_->prioritySet().getMockHostSet(0)->hosts_[0]->healthy());
}

TEST_F(HttpHealthCheckerImplTest, SuccessServiceCheckWithCustomHostValue) {
std::string host = "www.envoyproxy.io";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: const

setupServiceValidationWithCustomHostValueHC(host);
// requires non-empty `service_name` in config.
EXPECT_CALL(runtime_.snapshot_, featureEnabled("health_check.verify_cluster", 100))
.WillOnce(Return(true));

EXPECT_CALL(*this, onHostStatus(_, false)).Times(1);

cluster_->prioritySet().getMockHostSet(0)->hosts_ = {
makeTestHost(cluster_->info_, "tcp://127.0.0.1:80")};
cluster_->info_->stats().upstream_cx_total_.inc();
expectSessionCreate();
expectStreamCreate(0);
EXPECT_CALL(*test_sessions_[0]->timeout_timer_, enableTimer(_));
EXPECT_CALL(test_sessions_[0]->request_encoder_, encodeHeaders(_, true))
.WillOnce(Invoke([&](const Http::HeaderMap& headers, bool) {
EXPECT_TRUE(headers.Host());
EXPECT_TRUE(headers.Path());
EXPECT_NE(nullptr, headers.Host());
EXPECT_NE(nullptr, headers.Path());
EXPECT_EQ(headers.Host()->value().c_str(), std::string(host));
EXPECT_EQ(headers.Path()->value().c_str(), std::string("/healthcheck"));
}));
health_checker_->start();

EXPECT_CALL(runtime_.snapshot_, getInteger("health_check.max_interval", _));
Expand Down