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

Code before:
    decoder_callbacks_->setUpstreamOverrideHost(
        std::make_pair(upstream_address.value(), effective_config_->isStrict()));
  }
  return Http::FilterHeadersStatus::Continue;
}

Http::FilterHeadersStatus StatefulSession::encodeHeaders(Http::ResponseHeaderMap& headers, bool) {
  if (session_state_ == nullptr) {
    return Http::FilterHeadersStatus::Continue;
  }

  auto upstream_info = encoder_callbacks_->streamInfo().upstreamInfo();
  if (upstream_info == nullptr) {
    return Http::FilterHeadersStatus::Continue;
  }

  auto host = upstream_info->upstreamHost();

  // Check for failed_closed: no healthy upstream in strict mode.
  const bool has_uh_flag = encoder_callbacks_->streamInfo().hasResponseFlag(
      StreamInfo::CoreResponseFlag::NoHealthyUpstream);

  if (has_uh_flag && effective_config_->isStrict()) {
    markFailedClosed();
    return Http::FilterHeadersStatus::Continue;
  }

  if (host != nullptr) {
    const bool host_changed = session_state_->onUpdate(host->address()->asStringView(), headers);

    // Track stats based on whether the host changed.
    if (host_changed) {
      // Host changed means override failed and fallback occurred (non-strict mode).
      if (!effective_config_->isStrict()) {
        markFailedOpen();
      }
    } else {
      // Host didn't change, meaning the override was successful.
      markRouted();
    }
  }

  return Http::FilterHeadersStatus::Continue;
}

} // namespace StatefulSession
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy


Review comment (bug):
Note, if there is no candidate host could be selected, the upstream info should be nullptr and the code here cannot works as expected. You may should only add a else branch at previous if check:

```
if (auto upstream_info = encoder_callbacks_->streamInfo().upstreamInfo();
      upstream_info != nullptr) {
  // ....
} else {
  // check whether the uh flag is set.
}
```

Code after:
    decoder_callbacks_->setUpstreamOverrideHost(
        std::make_pair(upstream_address.value(), effective_config_->isStrict()));
  }
  return Http::FilterHeadersStatus::Continue;
}

Http::FilterHeadersStatus StatefulSession::encodeHeaders(Http::ResponseHeaderMap& headers, bool) {
  if (session_state_ == nullptr) {
    return Http::FilterHeadersStatus::Continue;
  }

  if (auto upstream_info = encoder_callbacks_->streamInfo().upstreamInfo();
      upstream_info != nullptr) {
    auto host = upstream_info->upstreamHost();

    if (host != nullptr) {
      const bool host_changed = session_state_->onUpdate(host->address()->asStringView(), headers);

      // Track stats based on whether the host changed.
      if (host_changed) {
        // Host changed means override failed and fallback occurred (non-strict mode).
        if (!effective_config_->isStrict()) {
          markFailedOpen();
        }
      } else {
        // Host didn't change, meaning the override was successful.
        markRouted();
      }
    }
  } else {
    // No upstream info. We should check for failed_closed or no healthy upstream
    // in the strict mode.
    const bool has_uh_flag = encoder_callbacks_->streamInfo().hasResponseFlag(
        StreamInfo::CoreResponseFlag::NoHealthyUpstream);

    if (has_uh_flag && effective_config_->isStrict()) {
      markFailedClosed();
    }
  }

  return Http::FilterHeadersStatus::Continue;
}

} // namespace StatefulSession
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy