Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Virtual Host in Route Entry #314

Merged
merged 3 commits into from
Jan 5, 2017
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
17 changes: 15 additions & 2 deletions include/envoy/router/router.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,19 @@ class VirtualCluster {
virtual Upstream::ResourcePriority priority() const PURE;
};

/**
* Virtual host defintion.
*/
class VirtualHost {
public:
virtual ~VirtualHost() {}

/**
* @return const std::string& the name of the virtual host.
*/
virtual const std::string& name() const PURE;
};

class RateLimitPolicy;

/**
Expand Down Expand Up @@ -177,9 +190,9 @@ class RouteEntry {
virtual const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const PURE;

/**
* @return const std::string& the virtual host that owns the route.
* @return const VirtualHost& the virtual host that owns the route.
*/
virtual const std::string& virtualHostName() const PURE;
virtual const VirtualHost& virtualHost() const PURE;
};

/**
Expand Down
1 change: 1 addition & 0 deletions source/common/http/async_client_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const std::vector<std::reference_wrapper<const Router::RateLimitPolicyEntry>>
const AsyncRequestImpl::NullRateLimitPolicy AsyncRequestImpl::RouteEntryImpl::rate_limit_policy_;
const AsyncRequestImpl::NullRetryPolicy AsyncRequestImpl::RouteEntryImpl::retry_policy_;
const AsyncRequestImpl::NullShadowPolicy AsyncRequestImpl::RouteEntryImpl::shadow_policy_;
const AsyncRequestImpl::NullVirtualHost AsyncRequestImpl::RouteEntryImpl::virtual_host_;

AsyncClientImpl::AsyncClientImpl(const Upstream::ClusterInfo& cluster, Stats::Store& stats_store,
Event::Dispatcher& dispatcher, const std::string& local_zone_name,
Expand Down
8 changes: 7 additions & 1 deletion source/common/http/async_client_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ class AsyncRequestImpl final : public AsyncClient::Request,
const std::string& runtimeKey() const override { return EMPTY_STRING; }
};

struct NullVirtualHost : public Router::VirtualHost {
// Router::VirtualHost
const std::string& name() const override { return EMPTY_STRING; }
};

struct RouteEntryImpl : public Router::RouteEntry {
RouteEntryImpl(const std::string& cluster_name,
const Optional<std::chrono::milliseconds>& timeout)
Expand All @@ -108,11 +113,12 @@ class AsyncRequestImpl final : public AsyncClient::Request,
const Router::VirtualCluster* virtualCluster(const Http::HeaderMap&) const override {
return nullptr;
}
const std::string& virtualHostName() const { return EMPTY_STRING; }
const Router::VirtualHost& virtualHost() const override { return virtual_host_; }

static const NullRateLimitPolicy rate_limit_policy_;
static const NullRetryPolicy retry_policy_;
static const NullShadowPolicy shadow_policy_;
static const NullVirtualHost virtual_host_;

const std::string& cluster_name_;
Optional<std::chrono::milliseconds> timeout_;
Expand Down
39 changes: 20 additions & 19 deletions source/common/router/config_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool ConfigUtility::matchHeaders(const Http::HeaderMap& headers,
return matches;
}

RouteEntryImplBase::RouteEntryImplBase(const VirtualHost& vhost, const Json::Object& route,
RouteEntryImplBase::RouteEntryImplBase(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader)
: case_sensitive_(route.getBoolean("case_sensitive", true)),
prefix_rewrite_(route.getString("prefix_rewrite", "")),
Expand Down Expand Up @@ -169,7 +169,7 @@ std::string RouteEntryImplBase::newPath(const Http::HeaderMap& headers) const {
final_path);
}

PrefixRouteEntryImpl::PrefixRouteEntryImpl(const VirtualHost& vhost, const Json::Object& route,
PrefixRouteEntryImpl::PrefixRouteEntryImpl(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader)
: RouteEntryImplBase(vhost, route, loader), prefix_(route.getString("prefix")) {}

Expand All @@ -184,7 +184,7 @@ bool PrefixRouteEntryImpl::matches(const Http::HeaderMap& headers, uint64_t rand
StringUtil::startsWith(headers.Path()->value().c_str(), prefix_, case_sensitive_);
}

PathRouteEntryImpl::PathRouteEntryImpl(const VirtualHost& vhost, const Json::Object& route,
PathRouteEntryImpl::PathRouteEntryImpl(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader)
: RouteEntryImplBase(vhost, route, loader), path_(route.getString("path")) {}

Expand All @@ -211,8 +211,8 @@ bool PathRouteEntryImpl::matches(const Http::HeaderMap& headers, uint64_t random
return false;
}

VirtualHost::VirtualHost(const Json::Object& virtual_host, Runtime::Loader& runtime,
Upstream::ClusterManager& cm)
VirtualHostImpl::VirtualHostImpl(const Json::Object& virtual_host, Runtime::Loader& runtime,
Upstream::ClusterManager& cm)
: name_(virtual_host.getString("name")) {

std::string require_ssl = virtual_host.getString("require_ssl", "");
Expand Down Expand Up @@ -257,7 +257,7 @@ VirtualHost::VirtualHost(const Json::Object& virtual_host, Runtime::Loader& runt
}
}

bool VirtualHost::usesRuntime() const {
bool VirtualHostImpl::usesRuntime() const {
bool uses = false;
for (const RouteEntryImplBasePtr& route : routes_) {
// Currently a base runtime rule as well as a shadow rule can use runtime.
Expand All @@ -267,7 +267,7 @@ bool VirtualHost::usesRuntime() const {
return uses;
}

VirtualHost::VirtualClusterEntry::VirtualClusterEntry(const Json::Object& virtual_cluster) {
VirtualHostImpl::VirtualClusterEntry::VirtualClusterEntry(const Json::Object& virtual_cluster) {
if (virtual_cluster.hasObject("method")) {
method_ = virtual_cluster.getString("method");
}
Expand All @@ -280,7 +280,7 @@ VirtualHost::VirtualClusterEntry::VirtualClusterEntry(const Json::Object& virtua
RouteMatcher::RouteMatcher(const Json::Object& config, Runtime::Loader& runtime,
Upstream::ClusterManager& cm) {
for (const Json::ObjectPtr& virtual_host_config : config.getObjectArray("virtual_hosts")) {
VirtualHostPtr virtual_host(new VirtualHost(*virtual_host_config, runtime, cm));
VirtualHostPtr virtual_host(new VirtualHostImpl(*virtual_host_config, runtime, cm));
uses_runtime_ |= virtual_host->usesRuntime();

for (const std::string& domain : virtual_host_config->getStringArray("domains")) {
Expand All @@ -301,8 +301,8 @@ RouteMatcher::RouteMatcher(const Json::Object& config, Runtime::Loader& runtime,
}
}

const RedirectEntry* VirtualHost::redirectFromEntries(const Http::HeaderMap& headers,
uint64_t random_value) const {
const RedirectEntry* VirtualHostImpl::redirectFromEntries(const Http::HeaderMap& headers,
uint64_t random_value) const {
// First we check to see if we have any vhost level SSL requirements.
if (ssl_requirements_ == SslRequirements::ALL && headers.ForwardedProto()->value() != "https") {
return &SSL_REDIRECTOR;
Expand All @@ -316,9 +316,9 @@ const RedirectEntry* VirtualHost::redirectFromEntries(const Http::HeaderMap& hea
}
}

const RouteEntryImplBase* VirtualHost::routeFromEntries(const Http::HeaderMap& headers,
bool redirect,
uint64_t random_value) const {
const RouteEntryImplBase* VirtualHostImpl::routeFromEntries(const Http::HeaderMap& headers,
bool redirect,
uint64_t random_value) const {
for (const RouteEntryImplBasePtr& route : routes_) {
if (redirect == route->isRedirect() && route->matches(headers, random_value)) {
return route.get();
Expand All @@ -328,7 +328,7 @@ const RouteEntryImplBase* VirtualHost::routeFromEntries(const Http::HeaderMap& h
return nullptr;
}

const VirtualHost* RouteMatcher::findVirtualHost(const Http::HeaderMap& headers) const {
const VirtualHostImpl* RouteMatcher::findVirtualHost(const Http::HeaderMap& headers) const {
// Fast path the case where we only have a default virtual host.
if (virtual_hosts_.empty() && default_virtual_host_) {
return default_virtual_host_.get();
Expand All @@ -346,7 +346,7 @@ const VirtualHost* RouteMatcher::findVirtualHost(const Http::HeaderMap& headers)

const RedirectEntry* RouteMatcher::redirectRequest(const Http::HeaderMap& headers,
uint64_t random_value) const {
const VirtualHost* virtual_host = findVirtualHost(headers);
const VirtualHostImpl* virtual_host = findVirtualHost(headers);
if (virtual_host) {
return virtual_host->redirectFromEntries(headers, random_value);
} else {
Expand All @@ -356,18 +356,19 @@ const RedirectEntry* RouteMatcher::redirectRequest(const Http::HeaderMap& header

const RouteEntry* RouteMatcher::routeForRequest(const Http::HeaderMap& headers,
uint64_t random_value) const {
const VirtualHost* virtual_host = findVirtualHost(headers);
const VirtualHostImpl* virtual_host = findVirtualHost(headers);
if (virtual_host) {
return virtual_host->routeFromEntries(headers, false, random_value);
} else {
return nullptr;
}
}

const VirtualHost::CatchAllVirtualCluster VirtualHost::VIRTUAL_CLUSTER_CATCH_ALL;
const SslRedirector VirtualHost::SSL_REDIRECTOR;
const VirtualHostImpl::CatchAllVirtualCluster VirtualHostImpl::VIRTUAL_CLUSTER_CATCH_ALL;
const SslRedirector VirtualHostImpl::SSL_REDIRECTOR;

const VirtualCluster* VirtualHost::virtualClusterFromEntries(const Http::HeaderMap& headers) const {
const VirtualCluster*
VirtualHostImpl::virtualClusterFromEntries(const Http::HeaderMap& headers) const {
for (const VirtualClusterEntry& entry : virtual_clusters_) {
bool method_matches =
!entry.method_.valid() || headers.Method()->value().c_str() == entry.method_.value();
Expand Down
26 changes: 15 additions & 11 deletions source/common/router/config_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,21 @@ class ConfigUtility {
/**
* Holds all routing configuration for an entire virtual host.
*/
class VirtualHost {
class VirtualHostImpl : public VirtualHost {
public:
VirtualHost(const Json::Object& virtual_host, Runtime::Loader& runtime,
Upstream::ClusterManager& cm);
VirtualHostImpl(const Json::Object& virtual_host, Runtime::Loader& runtime,
Upstream::ClusterManager& cm);

const std::string& name() const { return name_; }
const RedirectEntry* redirectFromEntries(const Http::HeaderMap& headers,
uint64_t random_value) const;
const RouteEntryImplBase* routeFromEntries(const Http::HeaderMap& headers, bool redirect,
uint64_t random_value) const;
bool usesRuntime() const;
const VirtualCluster* virtualClusterFromEntries(const Http::HeaderMap& headers) const;

// Router::VirtualHost
const std::string& name() const override { return name_; }

private:
enum class SslRequirements { NONE, EXTERNAL_ONLY, ALL };

Expand Down Expand Up @@ -120,7 +122,7 @@ class VirtualHost {
SslRequirements ssl_requirements_;
};

typedef std::shared_ptr<VirtualHost> VirtualHostPtr;
typedef std::shared_ptr<VirtualHostImpl> VirtualHostPtr;

/**
* Implementation of RetryPolicy that reads from the JSON route config.
Expand Down Expand Up @@ -159,7 +161,8 @@ class ShadowPolicyImpl : public ShadowPolicy {
*/
class RouteEntryImplBase : public RouteEntry, public Matchable, public RedirectEntry {
public:
RouteEntryImplBase(const VirtualHost& vhost, const Json::Object& route, Runtime::Loader& loader);
RouteEntryImplBase(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader);

bool isRedirect() const { return !host_redirect_.empty() || !path_redirect_.empty(); }
bool usesRuntime() const { return runtime_.valid(); }
Expand All @@ -174,8 +177,8 @@ class RouteEntryImplBase : public RouteEntry, public Matchable, public RedirectE
const VirtualCluster* virtualCluster(const Http::HeaderMap& headers) const override {
return vhost_.virtualClusterFromEntries(headers);
}
const std::string& virtualHostName() const override { return vhost_.name(); }
std::chrono::milliseconds timeout() const override { return timeout_; }
const VirtualHost& virtualHost() const override { return vhost_; }

// Router::RedirectEntry
std::string newPath(const Http::HeaderMap& headers) const override;
Expand All @@ -201,7 +204,7 @@ class RouteEntryImplBase : public RouteEntry, public Matchable, public RedirectE
// Default timeout is 15s if nothing is specified in the route config.
static const uint64_t DEFAULT_ROUTE_TIMEOUT_MS = 15000;

const VirtualHost& vhost_;
const VirtualHostImpl& vhost_;
const std::string cluster_name_;
const std::chrono::milliseconds timeout_;
const Optional<RuntimeData> runtime_;
Expand All @@ -220,7 +223,7 @@ class RouteEntryImplBase : public RouteEntry, public Matchable, public RedirectE
*/
class PrefixRouteEntryImpl : public RouteEntryImplBase {
public:
PrefixRouteEntryImpl(const VirtualHost& vhost, const Json::Object& route,
PrefixRouteEntryImpl(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader);

// Router::RouteEntry
Expand All @@ -238,7 +241,8 @@ class PrefixRouteEntryImpl : public RouteEntryImplBase {
*/
class PathRouteEntryImpl : public RouteEntryImplBase {
public:
PathRouteEntryImpl(const VirtualHost& vhost, const Json::Object& route, Runtime::Loader& loader);
PathRouteEntryImpl(const VirtualHostImpl& vhost, const Json::Object& route,
Runtime::Loader& loader);

// Router::RouteEntry
void finalizeRequestHeaders(Http::HeaderMap& headers) const override;
Expand All @@ -263,7 +267,7 @@ class RouteMatcher {
bool usesRuntime() const { return uses_runtime_; }

private:
const VirtualHost* findVirtualHost(const Http::HeaderMap& headers) const;
const VirtualHostImpl* findVirtualHost(const Http::HeaderMap& headers) const;

std::unordered_map<std::string, VirtualHostPtr> virtual_hosts_;
VirtualHostPtr default_virtual_host_;
Expand Down
4 changes: 2 additions & 2 deletions source/common/router/router.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void Filter::chargeUpstreamCode(const Http::HeaderMap& response_headers,

Http::CodeUtility::ResponseStatInfo info{
config_.stats_store_, cluster_->statPrefix(), response_headers, internal_request,
route_->virtualHostName(), request_vcluster_ ? request_vcluster_->name() : "",
route_->virtualHost().name(), request_vcluster_ ? request_vcluster_->name() : "",
config_.service_zone_, upstreamZone(upstream_host), is_canary};

Http::CodeUtility::chargeResponseStat(info);
Expand Down Expand Up @@ -480,7 +480,7 @@ void Filter::onUpstreamComplete() {

Http::CodeUtility::ResponseTimingInfo info{
config_.stats_store_, cluster_->statPrefix(), response_time,
upstream_request_->upstream_canary_, internal_request, route_->virtualHostName(),
upstream_request_->upstream_canary_, internal_request, route_->virtualHost().name(),
request_vcluster_ ? request_vcluster_->name() : "", config_.service_zone_,
upstreamZone(upstream_request_->upstream_host_)};

Expand Down
2 changes: 1 addition & 1 deletion test/common/router/config_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ TEST(RouteMatcherTest, TestRoutes) {
Http::TestHeaderMapImpl headers = genHeaders("www.lyft.com", "/new_endpoint/foo", "GET");
const RouteEntry* route = config.routeForRequest(headers, 0);
EXPECT_EQ("www2", route->clusterName());
EXPECT_EQ("www2", route->virtualHostName());
EXPECT_EQ("www2", route->virtualHost().name());
route->finalizeRequestHeaders(headers);
EXPECT_EQ("/api/new_endpoint/foo", headers.get_(Http::Headers::get().Path));
}
Expand Down
Loading