Skip to content

Filter can't add data from encodeTrailers #8402

@ascheglov

Description

@ascheglov

Calling addEncodedData from the encodeTrailers callback fails when encodeHeaders had previously returned StopIteration.

A filter (e.g. the grpc-json transcoder) wants to turn a headers-only response into a response with a body. And StreamEncoderFilterCallbacks::addEncodedData allows that:

 1) If a headers only response needs to be turned into a response with a body, this method can
 be called to add body in the encodeHeaders() callback. Subsequent filters will receive
 encodeHeaders(..., false) followed by encodeData(..., true). This works both in the direct
 iteration as well as the continuation case.

However it doesn't work when upstream sends a header frame and a trailer frame:
The filter returns StopIteration from encodeHeaders.
In encodeTrailers, it calls addEncodedData.
ConnectionManagerImpl::ActiveStream::addEncodedData has a special branch for EncodeTrailers, which calls encodeData with the comment:

// In this case we need to inline dispatch the data to further filters. If those filters
// choose to buffer/stop iteration that's fine.

Now there are two cases:

  1. if there is another filter, encodeData will call its encodeData callback, and then fail the ASSERT(headers_continued_) in ActiveStreamFilterBase::commonHandleAfterDataCallback - this filter never had its encodeHeaders called.
  2. if there is no filter to iterate, ActiveStream::encodeData will call response_encoder_->encodeData and write response body before writing any headers.

For HTTP/1.1 downstream it will assume chunked transfer-encoding and write something like:

4
body
HTTP/1.1 200 OK
other: headers

How to fix that:

For EncodeTrailers, the ActiveStream::addEncodedData should buffer data when filter stopped iteration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementFeature requests. Not bugs or questions.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions