Repository: envoyproxy/envoy
File: source/common/router/config_impl.cc (C++)

Code before:
                                    regex_rewrite_.get(), regex_rewrite_substitution_);
}

std::string RouteEntryImplBase::newUri(const Http::RequestHeaderMap& headers) const {
  ASSERT(isDirectResponse());
  return ::Envoy::Http::Utility::newUri(
      ::Envoy::makeOptRefFromPtr(
          const_cast<const ::Envoy::Http::Utility::RedirectConfig*>(redirect_config_.get())),
      headers);
}

std::string RouteEntryImplBase::formatBody(const Http::RequestHeaderMap& request_headers,
                                           const Http::ResponseHeaderMap& response_headers,
                                           const StreamInfo::StreamInfo& stream_info) const {
  std::string body;
  if (direct_response_body_provider_ != nullptr) {
    body = direct_response_body_provider_->data();
  }

  if (direct_response_body_formatter_ != nullptr) {
    body = direct_response_body_formatter_->format(
        {&request_headers, &response_headers, nullptr, body}, stream_info);
  }
  return body;
}

std::multimap<std::string, std::string>
RouteEntryImplBase::parseOpaqueConfig(const envoy::config::route::v3::Route& route) {
  std::multimap<std::string, std::string> ret;
  if (route.has_metadata()) {
    auto filter_metadata = route.metadata().filter_metadata().find("envoy.filters.http.router");
    if (filter_metadata == route.metadata().filter_metadata().end()) {
      return ret;
    }
    for (const auto& it : filter_metadata->second.fields()) {
      if (it.second.kind_case() == Protobuf::Value::kStringValue) {
        ret.emplace(it.first, it.second.string_value());
      }
    }
  }
  return ret;
}

std::unique_ptr<HedgePolicyImpl> RouteEntryImplBase::buildHedgePolicy(
    HedgePolicyConstOptRef vhost_hedge_policy,
    const envoy::config::route::v3::RouteAction& route_config) const {
  // Route specific policy wins, if available.
  if (route_config.has_hedge_policy()) {
    return std::make_unique<HedgePolicyImpl>(route_config.hedge_policy());
  }


Review comment (bug):
Sorry to be doing this after you've got something that works; looking over what's changed with fresh eyes I realize some of our more performance-oriented reviewers would likely complain that this change makes the old configuration require a string-copy that it previously did not require (which may be a large string).

To remedy that, what you might have to do is make formatBody take a string reference to populate (like you had before), but *also* return a string reference. That way the caller passes in a string the caller owns, and if format() is being called, that reference is updated and is the return value, and if the formatter is **not** configured, the passed-in reference is **not** updated and a reference to ->data() is returned. The caller should then use the returned reference either way.

This is a horrible and error-prone thing to have to do (as callers may incorrectly assume their string will be updated), but performance-wise it can be a pretty significant saving.

(Since it's error-prone, it's worth commenting the function declaration explicitly, explaining that this is what's going to happen.)

Code after:
                                    regex_rewrite_.get(), regex_rewrite_substitution_);
}

std::string RouteEntryImplBase::newUri(const Http::RequestHeaderMap& headers) const {
  ASSERT(isDirectResponse());
  return ::Envoy::Http::Utility::newUri(
      ::Envoy::makeOptRefFromPtr(
          const_cast<const ::Envoy::Http::Utility::RedirectConfig*>(redirect_config_.get())),
      headers);
}

absl::string_view RouteEntryImplBase::formatBody(const Http::RequestHeaderMap& request_headers,
                                                 const Http::ResponseHeaderMap& response_headers,
                                                 const StreamInfo::StreamInfo& stream_info,
                                                 std::string& body_out) const {
  absl::string_view direct_body = direct_response_body_provider_ != nullptr
                                      ? direct_response_body_provider_->data()
                                      : EMPTY_STRING;
  if (direct_response_body_formatter_ == nullptr) {
    return direct_body;
  }

  body_out = direct_response_body_formatter_->format(
      {&request_headers, &response_headers, nullptr, direct_body}, stream_info);
  return body_out;
}

std::multimap<std::string, std::string>
RouteEntryImplBase::parseOpaqueConfig(const envoy::config::route::v3::Route& route) {
  std::multimap<std::string, std::string> ret;
  if (route.has_metadata()) {
    auto filter_metadata = route.metadata().filter_metadata().find("envoy.filters.http.router");
    if (filter_metadata == route.metadata().filter_metadata().end()) {
      return ret;
    }
    for (const auto& it : filter_metadata->second.fields()) {
      if (it.second.kind_case() == Protobuf::Value::kStringValue) {
        ret.emplace(it.first, it.second.string_value());
      }
    }
  }
  return ret;
}

std::unique_ptr<HedgePolicyImpl> RouteEntryImplBase::buildHedgePolicy(
    HedgePolicyConstOptRef vhost_hedge_policy,
    const envoy::config::route::v3::RouteAction& route_config) const {
  // Route specific policy wins, if available.
  if (route_config.has_hedge_policy()) {
    return std::make_unique<HedgePolicyImpl>(route_config.hedge_policy());
  }