Skip to content

ext_proc: attributes based on request headers are not populated if ext_proc only run on encode path #41744

@mpwarres

Description

@mpwarres

PR #40800 made it possible for filters to be conditionally executed based on response headers. The ext_proc filter functions properly in this setup (where only encode-direction callbacks are invoked on it), though I have hit one problem: attributes that are based on request header values (e.g. "request.host") do not get populated in ProcessingRequests sent to ext_proc servers.

Sequence, supposing that the ext_proc filter has been configured to send the "request.host" attribute, but is under an ExtensionWithMatcher that causes it to only be invoked in the encode* direction:

  1. Because ext_proc filter doesn't have decodeHeaders called on it, setRequestHeaders never called here
  2. Therefore, state.requestHeaders() returns nullptr here
  3. Therefore, activation_request_headers_ is nullptr here
  4. Therefore, RequestWrapper::operator[] doesn't find an entry when passed key = "host" here (for resolving the "host" part of "request.host")
  5. Therefore, CEL expression evaluation for "request.host" fails, and no value for it is included in the ext_proc ProcessingRequest.

IOW, ext_proc attribute CEL evaluation is basing its view of request headers on a locally stored pointer to the RequestHeaderMap that is null if decode callbacks are skipped/disabled.

The fix is to instead feed the CEL evaluator the per-request StreamInfo object, which always has requestHeaders regardless of what callbacks are invoked on the ext_proc filter. IOW, change the Filters::Common::Expr::createActivation call here from:

  auto activation_ptr = Filters::Common::Expr::createActivation(
      &config_->expressionManager().localInfo(), state.callbacks()->streamInfo(),
      state.requestHeaders(), dynamic_cast<const Http::ResponseHeaderMap*>(state.responseHeaders()),
      dynamic_cast<const Http::ResponseTrailerMap*>(state.responseTrailers()));

to:

  auto activation_ptr = Filters::Common::Expr::createActivation(
      &config_->expressionManager().localInfo(), state.callbacks()->streamInfo(),
      state.callbacks()->streamInfo().getRequestHeaders(), dynamic_cast<const Http::ResponseHeaderMap*>(state.responseHeaders()),
      dynamic_cast<const Http::ResponseTrailerMap*>(state.responseTrailers()));

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions