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

Code before:
  // that get handled by earlier filters.
  stats_.rq_total_.inc();

  // Determine if there is a route entry or a direct response for the request.
  route_ = callbacks_->route();
  if (!route_) {
    stats_.no_route_.inc();
    ENVOY_STREAM_LOG(debug, "no route match for URL '{}'", *callbacks_, headers.getPathValue());

    callbacks_->streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::NoRouteFound);
    callbacks_->sendLocalReply(Http::Code::NotFound, "", nullptr, absl::nullopt,
                               StreamInfo::ResponseCodeDetails::get().RouteNotFound);
    return Http::FilterHeadersStatus::StopIteration;
  }

  // Determine if there is a direct response for the request.
  const auto* direct_response = route_->directResponseEntry();
  if (direct_response != nullptr) {
    stats_.rq_direct_response_.inc();
    direct_response->rewritePathHeader(headers, !config_->suppress_envoy_headers_);
    std::string direct_response_body;
    if (downstream_headers_ != nullptr) {
      direct_response->formatBody(*downstream_headers_,
                                  *Http::StaticEmptyHeaders::get().response_headers,
                                  callbacks_->streamInfo(), direct_response_body);
    }

    callbacks_->sendLocalReply(
        direct_response->responseCode(), direct_response_body,
        [this, direct_response](Http::ResponseHeaderMap& response_headers) -> void {
          std::string new_uri;
          ASSERT(downstream_headers_ != nullptr);
          if (downstream_headers_->Path()) {
            new_uri = direct_response->newUri(*downstream_headers_);
          }
          // See https://tools.ietf.org/html/rfc7231#section-7.1.2.
          const auto add_location =
              direct_response->responseCode() == Http::Code::Created ||
              Http::CodeUtility::is3xx(enumToInt(direct_response->responseCode()));
          if (!new_uri.empty() && add_location) {
            response_headers.addReferenceKey(Http::Headers::get().Location, new_uri);
          }
          const Formatter::Context formatter_context(downstream_headers_, &response_headers, {}, {},
                                                     {}, &callbacks_->activeSpan());
          direct_response->finalizeResponseHeaders(response_headers, formatter_context,
                                                   callbacks_->streamInfo());
        },
        absl::nullopt, StreamInfo::ResponseCodeDetails::get().DirectResponse);
    return Http::FilterHeadersStatus::StopIteration;
  }


Review comment (bug):
This appears to be changing the behavior of the old code path in the case that downstream_headers_ is nullptr, and also not really covering that case very well. Would suggest instead:

```suggestion
    direct_response->formatBody((downstream_headers_ == nullptr) ? *Http::StaticEmptyHeaders::get().request_headers : *downstream_headers_,
                                *Http::StaticEmptyHeaders::get().response_headers,
                                callbacks_->streamInfo(), direct_response_body);
```

Code after:
  // that get handled by earlier filters.
  stats_.rq_total_.inc();

  // Determine if there is a route entry or a direct response for the request.
  route_ = callbacks_->route();
  if (!route_) {
    stats_.no_route_.inc();
    ENVOY_STREAM_LOG(debug, "no route match for URL '{}'", *callbacks_, headers.getPathValue());

    callbacks_->streamInfo().setResponseFlag(StreamInfo::CoreResponseFlag::NoRouteFound);
    callbacks_->sendLocalReply(Http::Code::NotFound, "", nullptr, absl::nullopt,
                               StreamInfo::ResponseCodeDetails::get().RouteNotFound);
    return Http::FilterHeadersStatus::StopIteration;
  }

  // Determine if there is a direct response for the request.
  const auto* direct_response = route_->directResponseEntry();
  if (direct_response != nullptr) {
    stats_.rq_direct_response_.inc();
    direct_response->rewritePathHeader(headers, !config_->suppress_envoy_headers_);
    std::string body;
    absl::string_view direct_response_body = direct_response->formatBody(
        (downstream_headers_ == nullptr) ? *Http::StaticEmptyHeaders::get().request_headers
                                         : *downstream_headers_,
        *Http::StaticEmptyHeaders::get().response_headers, callbacks_->streamInfo(), body);

    callbacks_->sendLocalReply(
        direct_response->responseCode(), direct_response_body,
        [this, direct_response](Http::ResponseHeaderMap& response_headers) -> void {
          std::string new_uri;
          ASSERT(downstream_headers_ != nullptr);
          if (downstream_headers_->Path()) {
            new_uri = direct_response->newUri(*downstream_headers_);
          }
          // See https://tools.ietf.org/html/rfc7231#section-7.1.2.
          const auto add_location =
              direct_response->responseCode() == Http::Code::Created ||
              Http::CodeUtility::is3xx(enumToInt(direct_response->responseCode()));
          if (!new_uri.empty() && add_location) {
            response_headers.addReferenceKey(Http::Headers::get().Location, new_uri);
          }
          const Formatter::Context formatter_context(downstream_headers_, &response_headers, {}, {},
                                                     {}, &callbacks_->activeSpan());
          direct_response->finalizeResponseHeaders(response_headers, formatter_context,
                                                   callbacks_->streamInfo());
        },
        absl::nullopt, StreamInfo::ResponseCodeDetails::get().DirectResponse);
    return Http::FilterHeadersStatus::StopIteration;
  }

  // A route entry matches for the request.