Skip to content

Commit d06d133

Browse files
committed
refactor(http/retry): PeekTrailersBody<B> only peeks empty bodies
this commit makes a small, subtle change to the `PeekTrailersBody<B>` http response body middleware. to help facilitate upgrading to http-body 1.x, we remove some tricky logic that involves `Body` interfaces that no longer exist after the 0.4 release. currently, a `PeekTrailersBody<B>` is not fully consistent about the conditions in which it will peek the trailers of a response body: the inner body is allowed to yield _either_ (a) **zero** DATA frames, in which case the body will be `.await`'ed and polled until the trailers are obtained, or (b) **one** DATA frame, so long as the inner body immediately yields a trailer. meanwhile, the documentation comment for the type claims: > An HTTP body that allows inspecting the body's trailers, if a > `TRAILERS` frame was the first frame after the initial headers frame. we won't have distinct `data()` and `trailers()` interfaces in the 1.0 release. we have a single [`BodyExt::frame()`](https://docs.rs/http-body-util/latest/http_body_util/trait.BodyExt.html#method.frame) method. consequently, porting this middleware as-is would be somewhat difficult. we might have to hold two frames, should we receive one frame, `now_or_never()` the second frame, and discover that we've been provided a second data frame rather than the trailers. this all runs slightly against the invariants of `Body`, see this comment originally added in 7f817b5: ``` // Peek to see if there's immediately a trailers frame, and grab // it if so. Otherwise, bail. // XXX(eliza): the documentation for the `http::Body` trait says // that `poll_trailers` should only be called after `poll_data` // returns `None`...but, in practice, I'm fairly sure that this just // means that it *will not return `Ready`* until there are no data // frames left, which is fine for us here, because we `now_or_never` // it. ``` this isn't quite true, as `Trailers` is just a wrapper calling `poll_trailers`: <https://docs.rs/http-body/0.4.6/src/http_body/next.rs.html#28-30> so, let's remove this. doing so will make the task of porting this middleware to http-body 1.0 in the short term, and additionally prevents any potential future misbehavior due to inner bodies not handling this eager trailer polling gracefully. see linkerd/linkerd2#8733. see #3504. Signed-off-by: katelyn martin <[email protected]>
1 parent b07b0d8 commit d06d133

File tree

1 file changed

+1
-11
lines changed

1 file changed

+1
-11
lines changed

linkerd/http/retry/src/peek_trailers.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct PeekTrailersBody<B: Body = BoxBody> {
2626
first_data: Option<Result<B::Data, B::Error>>,
2727

2828
/// The inner body's trailers, if it was terminated by a `TRAILERS` frame
29-
/// after 0-1 DATA frames, or an error if polling for trailers failed.
29+
/// after 0 DATA frames, or an error if polling for trailers failed.
3030
///
3131
/// Yes, this is a bit of a complex type, so let's break it down:
3232
/// - the outer `Option` indicates whether any trailers were received by
@@ -98,16 +98,6 @@ impl<B: Body> PeekTrailersBody<B> {
9898
if let Some(data) = body.inner.data().await {
9999
// The body has data; stop waiting for trailers.
100100
body.first_data = Some(data);
101-
102-
// Peek to see if there's immediately a trailers frame, and grab
103-
// it if so. Otherwise, bail.
104-
// XXX(eliza): the documentation for the `http::Body` trait says
105-
// that `poll_trailers` should only be called after `poll_data`
106-
// returns `None`...but, in practice, I'm fairly sure that this just
107-
// means that it *will not return `Ready`* until there are no data
108-
// frames left, which is fine for us here, because we `now_or_never`
109-
// it.
110-
body.trailers = body.inner.trailers().now_or_never();
111101
} else {
112102
// Okay, `poll_data` has returned `None`, so there are no data
113103
// frames left. Let's see if there's trailers...

0 commit comments

Comments
 (0)