- 
                Notifications
    
You must be signed in to change notification settings  - Fork 5.1k
 
Description
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:
- Because ext_proc filter doesn't have 
decodeHeaderscalled on it,setRequestHeadersnever called here - Therefore, 
state.requestHeaders()returnsnullptrhere - Therefore, 
activation_request_headers_isnullptrhere - Therefore, 
RequestWrapper::operator[]doesn't find an entry when passedkey= "host" here (for resolving the "host" part of "request.host") - 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()));