Repository: envoyproxy/envoy
File: source/extensions/filters/common/ext_authz/ext_authz_http_impl.cc (C++)

Code before:
                       .setChildSpanName(config_->tracingName())
                       .setSampled(absl::nullopt);

    options.setSendXff(false);

    // Apply retry policy if configured.
    if (config_->retryPolicy().has_value()) {
      envoy::config::route::v3::RetryPolicy route_retry_policy =
          Http::Utility::convertCoreToRouteRetryPolicy(config_->retryPolicy().value(),
                                                       "5xx,gateway-error,connect-failure,reset");
      options.setRetryPolicy(route_retry_policy);
      options.setBufferBodyForRetry(true);
    }

    request_ = thread_local_cluster->httpAsyncClient().send(std::move(message), *this, options);
  }
}

void RawHttpClientImpl::onSuccess(const Http::AsyncClient::Request&,
                                  Http::ResponseMessagePtr&& message) {
  callbacks_->onComplete(toResponse(std::move(message)));
  callbacks_ = nullptr;
}

void RawHttpClientImpl::onFailure(const Http::AsyncClient::Request&,
                                  Http::AsyncClient::FailureReason reason) {
  // TODO(botengyao): handle different failure reasons.
  ASSERT(reason == Http::AsyncClient::FailureReason::Reset ||
         reason == Http::AsyncClient::FailureReason::ExceedResponseBufferLimit);
  callbacks_->onComplete(std::make_unique<Response>(errorResponse()));
  callbacks_ = nullptr;
}

void RawHttpClientImpl::onBeforeFinalizeUpstreamSpan(
    Tracing::Span& span, const Http::ResponseHeaderMap* response_headers) {
  if (response_headers != nullptr) {
    const uint64_t status_code = Http::Utility::getResponseStatus(*response_headers);
    span.setTag(TracingConstants::get().HttpStatus,
                Http::CodeUtility::toString(static_cast<Http::Code>(status_code)));
    span.setTag(TracingConstants::get().TraceStatus, status_code == enumToInt(Http::Code::OK)
                                                         ? TracingConstants::get().TraceOk
                                                         : TracingConstants::get().TraceUnauthz);
  }
}

ResponsePtr RawHttpClientImpl::toResponse(Http::ResponseMessagePtr message) {
  const uint64_t status_code = Http::Utility::getResponseStatus(message->headers());

  // Set an error status if the call to the authorization server returns any of the 5xx HTTP error
  // codes. A Forbidden response is sent to the client if the filter has not been configured with
  // failure_mode_allow.

Review comment (suggestion):
Please load the retry policy when loading the configuration. Then we needn't to load it again and again for every request.

Code after:
  const std::string& cluster = config_->cluster();

  // It's possible that the cluster specified in the filter configuration no longer exists due to a
  // CDS removal.
  const auto thread_local_cluster = cm_.getThreadLocalCluster(cluster);
  if (thread_local_cluster == nullptr) {
    // TODO(dio): Add stats related to this.
    ENVOY_LOG(debug, "ext_authz cluster '{}' does not exist", cluster);
    callbacks_->onComplete(std::make_unique<Response>(errorResponse()));
    callbacks_ = nullptr;
  } else {
    // Do not enforce a sampling decision on this span; instead keep the parent's sampling status.
    auto options = Http::AsyncClient::RequestOptions()
                       .setTimeout(config_->timeout())
                       .setParentSpan(parent_span)
                       .setChildSpanName(config_->tracingName())
                       .setSampled(absl::nullopt);

    options.setSendXff(false);

    // Apply retry policy if configured.
    if (config_->retryPolicy() != nullptr) {
      options.setRetryPolicy(config_->retryPolicy());
      options.setBufferBodyForRetry(true);
    }

    request_ = thread_local_cluster->httpAsyncClient().send(std::move(message), *this, options);
  }
}

void RawHttpClientImpl::onSuccess(const Http::AsyncClient::Request&,
                                  Http::ResponseMessagePtr&& message) {
  callbacks_->onComplete(toResponse(std::move(message)));
  callbacks_ = nullptr;
}

void RawHttpClientImpl::onFailure(const Http::AsyncClient::Request&,
                                  Http::AsyncClient::FailureReason reason) {
  // TODO(botengyao): handle different failure reasons.
  ASSERT(reason == Http::AsyncClient::FailureReason::Reset ||
         reason == Http::AsyncClient::FailureReason::ExceedResponseBufferLimit);
  callbacks_->onComplete(std::make_unique<Response>(errorResponse()));
  callbacks_ = nullptr;
}

void RawHttpClientImpl::onBeforeFinalizeUpstreamSpan(
    Tracing::Span& span, const Http::ResponseHeaderMap* response_headers) {
  if (response_headers != nullptr) {
    const uint64_t status_code = Http::Utility::getResponseStatus(*response_headers);
    span.setTag(TracingConstants::get().HttpStatus,
                Http::CodeUtility::toString(static_cast<Http::Code>(status_code)));