Repository: envoyproxy/envoy
File: source/extensions/filters/http/on_demand/on_demand_update.cc (C++)

Code before:
    // Old behavior: reject all requests with bodies.
    can_recreate_stream = !callbacks_->decodingBuffer();
  }
  if (route_exists &&        // route can be resolved after an on-demand
                             // VHDS update
      can_recreate_stream && // Redirects require fully read body.
      callbacks_->recreateStream(/*headers=*/nullptr)) {
    return;
  }

  // route cannot be resolved after an on-demand VHDS update or
  // recreating stream failed, continue the filter-chain
  callbacks_->continueDecoding();
}

void OnDemandRouteUpdate::onClusterDiscoveryCompletion(
    Upstream::ClusterDiscoveryStatus cluster_status) {
  filter_iteration_state_ = Http::FilterHeadersStatus::Continue;
  cluster_discovery_handle_.reset();

  if (Runtime::runtimeFeatureEnabled(
          "envoy.reloadable_features.on_demand_cluster_no_recreate_stream")) {
    callbacks_->continueDecoding();
    return;
  }

  bool can_recreate_stream = false;
  if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.on_demand_track_end_stream")) {
    // New behavior: track end_stream state to support stream recreation with fully read bodies.
    can_recreate_stream = downstream_end_stream_;
  } else {
    // Old behavior: reject all requests with bodies.
    can_recreate_stream = !callbacks_->decodingBuffer();
  }
  if (cluster_status == Upstream::ClusterDiscoveryStatus::Available && can_recreate_stream) {
    // Redirects require fully read body.
    const Http::ResponseHeaderMap* headers = nullptr;
    if (callbacks_->recreateStream(headers)) {
      callbacks_->downstreamCallbacks()->clearRouteCache();
      return;
    }
  }

  // Cluster still does not exist or we did not recreate the stream. Either way,
  // continue with the filter chain.
  callbacks_->continueDecoding();
}

} // namespace OnDemand
} // namespace HttpFilters
} // namespace Extensions

Review comment (suggestion):
Please add a comment explaining why it makes sense to continue decoding, regardless of the `cluster_status` value.

Code after:
    // Old behavior: reject all requests with bodies.
    can_recreate_stream = !callbacks_->decodingBuffer();
  }
  if (route_exists &&        // route can be resolved after an on-demand
                             // VHDS update
      can_recreate_stream && // Redirects require fully read body.
      callbacks_->recreateStream(/*headers=*/nullptr)) {
    return;
  }

  // route cannot be resolved after an on-demand VHDS update or
  // recreating stream failed, continue the filter-chain
  callbacks_->continueDecoding();
}

void OnDemandRouteUpdate::onClusterDiscoveryCompletion(
    Upstream::ClusterDiscoveryStatus cluster_status) {
  filter_iteration_state_ = Http::FilterHeadersStatus::Continue;
  cluster_discovery_handle_.reset();

  if (Runtime::runtimeFeatureEnabled(
          "envoy.reloadable_features.on_demand_cluster_no_recreate_stream")) {
    // Whether or not the cluster exists, we continue decoding. Filters further down the
    // chain may want to weigh in on cluster selection, so we don't send a local reply
    // here.
    callbacks_->continueDecoding();
    return;
  }

  bool can_recreate_stream = false;
  if (Runtime::runtimeFeatureEnabled("envoy.reloadable_features.on_demand_track_end_stream")) {
    // New behavior: track end_stream state to support stream recreation with fully read bodies.
    can_recreate_stream = downstream_end_stream_;
  } else {
    // Old behavior: reject all requests with bodies.
    can_recreate_stream = !callbacks_->decodingBuffer();
  }
  if (cluster_status == Upstream::ClusterDiscoveryStatus::Available && can_recreate_stream) {
    // Redirects require fully read body.
    const Http::ResponseHeaderMap* headers = nullptr;
    if (callbacks_->recreateStream(headers)) {
      callbacks_->downstreamCallbacks()->clearRouteCache();
      return;
    }
  }

  // Cluster still does not exist or we did not recreate the stream. Either way,
  // continue with the filter chain.
  callbacks_->continueDecoding();
}