Skip to content

Conversation

@cratelyn
Copy link
Member

@cratelyn cratelyn commented Jan 22, 2025

this branch contains a sequence of commits that refactor PeekTrailersBody<B>.

this branch is specifically focused on making this body middleware
forward-compatible with the 1.0 interface(s) of http_body::Body and
http_body_util::BodyExt.

it does this in two main steps: (1) temporarily vendoring http_body::Frame<T>
and providing a compatibility shim that provides a frame() method for a body,
and (2) modeling PeekTrailersBody<B> and its peeking logic in terms of this
Frame<'a, T> future.

feat(http/retry): add Frame<T> compatibility facilities

this commit introduces a compat submodule to linkerd-http-retry.

this helps us frontrun the task of replacing all of the finicky control flow in
PeekTrailersBody<B> using the antiquated data() and trailers() future
combinators. instead, we can perform our peeking in terms of an approximation
of http_body_util::BodyExt::frame().

to accomplish this, this commit vendors a copy of the Frame<T> type. we can
use this to preemptively model our peek body in terms of this type, and move to
the "real" version of it when we're upgrading in pr #3504.

additionally, this commit includes a type called ForwardCompatibleBody<B>,
and a variant of the Frame<'a, T> combinator. these are a bit boilerplate-y,
admittedly, but the pleasant part of this is that we have, in effect, migrated
the trickiest body middleware in advance of #3504. once we upgrade to http-body
1.0, all of these types can be removed.

Signed-off-by: katelyn martin [email protected]

refactor(http/retry): PeekTrailersBody<B> uses BodyExt::frame()

this commit reworks PeekTrailersBody<B>.

the most important goal here is replacing the control flow of read_body(),
which polls a body using BodyExt future combinators data() and frame()
for up to two frames, with varying levels of persistence depending on outcomes.

to quote #3556:

the intent of this type is to only yield the asynchronous task
responsible for reading the body once. depending on what the inner
body yields, and when, this can result in combinations of: no data
frames and no trailers, no data frames with trailers, one data frame
and no trailers, one data frame with trailers, or two data frames.
moreover, depending on which of these are yielded, the body will call
.await some scenarios, and only poll functions once in others.

migrating this to the Frame and poll_frame() style of the 1.0 Body
interface, away from the 0.4 interface that provides distinct
poll_data() and poll_trailers() methods, is fundamentally tricky.

this means that PeekTrailersBody<B> is notably difficult to port across the
http-body 0.4/1.0 upgrade boundary.

this body middleware must navigate a number of edge conditions, and once it
has obtained a Frame<T>, make use of conversion methods to ascertain
whether it is a data or trailers frame, due to the fact that its internal enum
representation is not exposed publicly. one it has done all of that, it must do
the same thing once more to examine the second frame.

this commit uses the compatibility facilities and backported Frame<T>
introduced in the previous commit, and rewrites this control flow using a form
of the BodyExt::frame() combinator.

this means that this middleware is forward-compatible with http-body 1.0, which
will dramatically simplify the remaining migration work to be done in #3504.

see linkerd/linkerd2#8733 for more information and
other links related to this ongoing migration work.

refactor(http/retry): mock body enforces poll_trailers() contract

this commit addresses a TODO note, and tightens the enforcement of a rule
defined by the v0.4 signature of the Body trait.

this commit changes the mock body type, used in tests, so that it will panic if
the caller improperly polls for a trailers frame before the final data frame
has been yielded.

previously, a comment indicated that we were "fairly sure" this was okay. while
that may have been acceptable in practice, the changes in the previous commit
mean that we now properly respect these rules.

thus, a panic can be placed here, to enforce that "[is] only be called once
poll_data() returns None", per the documentation.

Base automatically changed from kate/http-retry.peek-body-observes-empty-end-of-stream-correctly to main January 22, 2025 20:24
@cratelyn cratelyn force-pushed the kate/http-retry.prepare-peek-trailers-body-for-http-body-1.0 branch from 6a2e600 to bc29711 Compare January 23, 2025 06:19
@cratelyn cratelyn changed the title feat(http/retry): model PeekTrailersBody<B> with Frame<T> (work-in-progress) feat(http/retry): model PeekTrailersBody<B> with Frame<T> Jan 23, 2025
this commit introduces a `compat` submodule to `linkerd-http-retry`.

this helps us frontrun the task of replacing all of the finicky control
flow in `PeekTrailersBody<B>` using the antiquated `data()` and
`trailers()` future combinators. instead, we can perform our peeking
in terms of an approximation of `http_body_util::BodyExt::frame()`.

to accomplish this, this commit vendors a copy of the `Frame<T>` type.
we can use this to preemptively model our peek body in terms of this
type, and move to the "real" version of it when we're upgrading in
pr #3504.

additionally, this commit includes a type called
`ForwardCompatibleBody<B>`, and a variant of the `Frame<'a, T>`
combinator. these are a bit boilerplate-y, admittedly, but the pleasant
part of this is that we have, in effect, migrated the trickiest body
middleware in advance of #3504. once we upgrade to http-body 1.0, all of
these types can be removed.

https://docs.rs/http-body-util/latest/http_body_util/trait.BodyExt.html#method.frame
https://docs.rs/http-body-util/0.1.2/src/http_body_util/combinators/frame.rs.html#10

Signed-off-by: katelyn martin <[email protected]>
@cratelyn cratelyn force-pushed the kate/http-retry.prepare-peek-trailers-body-for-http-body-1.0 branch from bc29711 to 5d34dc0 Compare January 23, 2025 06:23
@cratelyn

This comment was marked as resolved.

@cratelyn cratelyn force-pushed the kate/http-retry.prepare-peek-trailers-body-for-http-body-1.0 branch from 5d34dc0 to ada0f6d Compare January 23, 2025 16:36
this commit reworks `PeekTrailersBody<B>`.

the most important goal here is replacing the control flow of
`read_body()`, which polls a body using `BodyExt` future combinators
`data()` and `frame()` for up to two frames, with varying levels of
persistence depending on outcomes.

to quote #3556:

> the intent of this type is to only yield the asynchronous task
> responsible for reading the body once. depending on what the inner
> body yields, and when, this can result in combinations of: no data
> frames and no trailers, no data frames with trailers, one data frame
> and no trailers, one data frame with trailers, or two data frames.
> moreover, depending on which of these are yielded, the body will call
> .await some scenarios, and only poll functions once in others.
>
> migrating this to the Frame<T> and poll_frame() style of the 1.0 Body
> interface, away from the 0.4 interface that provides distinct
> poll_data() and poll_trailers() methods, is fundamentally tricky.

this means that `PeekTrailersBody<B>` is notably difficult to port
across the http-body 0.4/1.0 upgrade boundary.

this body middleware must navigate a number of edge conditions, and once
it _has_ obtained a `Frame<T>`, make use of conversion methods to
ascertain whether it is a data or trailers frame, due to the fact that
its internal enum representation is not exposed publicly. one it has
done all of that, it must do the same thing once more to examine the
second frame.

this commit uses the compatibility facilities and backported `Frame<T>`
introduced in the previous commit, and rewrites this control flow using
a form of the `BodyExt::frame()` combinator.

this means that this middleware is forward-compatible with http-body
1.0, which will dramatically simplify the remaining migration work to be
done in #3504.

see linkerd/linkerd2#8733 for more information
and other links related to this ongoing migration work.

Signed-off-by: katelyn martin <[email protected]>
this commit addresses a `TODO` note, and tightens the enforcement of a
rule defined by the v0.4 signature of the `Body` trait.

this commit changes the mock body type, used in tests, so that it will
panic if the caller improperly polls for a trailers frame before the
final data frame has been yielded.

previously, a comment indicated that we were "fairly sure" this was
okay. while that may have been acceptable in practice, the changes in
the previous commit mean that we now properly respect these rules.

thus, a panic can be placed here, to enforce that "[is] only be called
once `poll_data()` returns `None`", per the documentation.

Signed-off-by: katelyn martin <[email protected]>
@cratelyn cratelyn force-pushed the kate/http-retry.prepare-peek-trailers-body-for-http-body-1.0 branch from ada0f6d to 8bd1dc9 Compare January 23, 2025 16:57
@cratelyn cratelyn marked this pull request as ready for review January 23, 2025 17:13
@cratelyn cratelyn requested a review from a team as a code owner January 23, 2025 17:13
Copy link
Member Author

@cratelyn cratelyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 breadcrumbs for review...

.map_err(|frame| match frame.into_trailers() {
Ok(trls) => trls,
// Safety: this is not reachable, we called `into_data()` above.
Err(_) => unreachable!("into_data() and `into_trailers()` both returned `Err(_)`"),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm unsure how much to worry about the commented out //Unknown(Box<dyn Frameish>), variant in the vendored frame code. in other words, might this someday be reachable?

Result<T, E> gives us something we can pattern match on, which Frame<T> does not for the sake of semantic versioning. if we fear hitting this in the future, we could define a local enum like so...

enum ParsedFrame<T> {
    Data(T),
    Trailers(HeaderMap),
    Other(Frame<T>),
}

...and return that here. what do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or this could be Option<Either<B::Data, HeaderMap>>, and then the caller can be adapted so this is handled as an Empty body... Since the API specifically doesn't give us exhaustive matching it's probably best to handle it cleanly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. this is addressed in 501b3cf

Copy link
Member

@olix0r olix0r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool! A few suggestions

.map_err(|frame| match frame.into_trailers() {
Ok(trls) => trls,
// Safety: this is not reachable, we called `into_data()` above.
Err(_) => unreachable!("into_data() and `into_trailers()` both returned `Err(_)`"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or this could be Option<Either<B::Data, HeaderMap>>, and then the caller can be adapted so this is handled as an Empty body... Since the API specifically doesn't give us exhaustive matching it's probably best to handle it cleanly.

@olix0r olix0r self-assigned this Jan 24, 2025
<#3559 (comment)>

this is a nicer name than `Unknown` for this case. not to mention, we'll
want that name shortly to address the possibility of unknown frame
variants.

Signed-off-by: katelyn martin <[email protected]>
this commit makes the inner enum variants private.

#3559 (comment)

Signed-off-by: katelyn martin <[email protected]>
@cratelyn
Copy link
Member Author

@olix0r, review comments have been addressed! i'd love if you could take a quick look before i hit the merge button 🙂

Copy link
Member

@olix0r olix0r left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great!

@cratelyn cratelyn merged commit dd4fbcd into main Jan 24, 2025
15 checks passed
@cratelyn cratelyn deleted the kate/http-retry.prepare-peek-trailers-body-for-http-body-1.0 branch January 24, 2025 20:40
cratelyn added a commit that referenced this pull request Jan 27, 2025
see linkerd/linkerd2#8733.

pr #3559 introduced some compatibility facilities to allow us to write
code in terms of `http_body_util::BodyExt::frame()`, front-running the
upgrade to be performed in #3504.

some `ReplayBody` tests use the defunct `data()` and `trailers()`
interfaces. this branch ports _two_ such unit tests. other tests are
saved for a fast follow-on, as the `chunk(..)` and `read_to_string(..)`
helpers will need some slightly more involved tweaks.

dd4fbcd

---

* refactor(http/retry): `replays_trailers()` uses `Frame<T>`

see linkerd/linkerd2#8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <[email protected]>

* refactor(http/retry): `trailers_only()` uses `Frame<T>`

see linkerd/linkerd2#8733.

this commit upgrades a test that uses defunct `data()` and `trailers()`
futures.

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 6, 2025
pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this commit performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we now longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations. we do still
report the end properly, we just won't be quite as prescient on the
initial playthrough.

see:
- linkerd/linkerd2#8733.
- #3559

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 6, 2025
pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this commit performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we now longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(hyperium/http-body#143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

see:
- linkerd/linkerd2#8733.
- #3559

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 6, 2025
pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this commit performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we now longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(hyperium/http-body#143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

see:
- linkerd/linkerd2#8733.
- #3559

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 6, 2025
pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this branch performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we no longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(hyperium/http-body#143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

in the same manner as the existing `frame()` method mimics
`http_body_util::BodyExt::frame()`, this branch introduces
a new `ForwardCompatibleBody::poll_frame()` method.

this allows us to poll the compatibility layer for a `Frame<T>`.

see:
- linkerd/linkerd2#8733.
- #3559

---

* nit(http/retry): install tracing subscriber in tests

some tests do not set up a tracing subscriber, because they do not use
the shared `Test::new()` helper function used elsewhere in this test
suite.

to provide a trace of the test's execution in the event of a failure,
initialize a tracing subscriber in some additional unit tests.

Signed-off-by: katelyn martin <[email protected]>

* feat(http/retry): `ForwardCompatibleBody<B>` exposes hints

this commit removes the `cfg(test)` gate on the method exposing
`B::is_end_stream()`, and introduces another method also exposing the
`size_hint()` method.

we will want these in order to implement these methods for
`ReplayBody<B>`.

Signed-off-by: katelyn martin <[email protected]>

* refactor(http/retry): `ForwardCompatibleBody::poll_frame()`

in the same manner as the existing `frame()` method mimics
`http_body_util::BodyExt::frame()`, this commit introduces
a new `ForwardCompatibleBody::poll_frame()` method.

this allows us to poll the compatibility layer for a `Frame<T>`.

Signed-off-by: katelyn martin <[email protected]>

* feat(http/retry): `ReplayBody<B>` polls for frames

pr #3559 (dd4fbcd) refactored our trailer peeking body middleware to
model its buffering in terms of the `Frame<T>` type used in
`http-body`'s 1.0 release.

this commit performs a similar change for the other piece of body
middleware that super linkerd's retry facilities: `ReplayBody<B>`. the
inner body `B` is now wrapped in the `ForwardCompatibleBody<B>` adapter,
and we now poll it in terms of frames.

NB: polling the underlying in terms of frames has a subtle knock-on
effect regarding when we observe the trailers, in the liminal period
between this refactor and the subsequent upgrade to hyper 1.0, whilst we
must still implement the existing 0.4 interface for `Body` that includes
`poll_trailers()`.

see the comment above `replay_trailers` for more on this, describing why
we now initialize this to `true`. relatedly, this is why we now longer
delegate down to `B::poll_trailers` ourselves. it will have already been
called by our adapter.

`ReplayBody::is_end_stream()` now behaves identically when initially
polling a body compared to subsequent replays. this is fine, as
`is_end_stream()` is a hint that facilitates optimizations
(hyperium/http-body#143). we do still report the end properly, we just
won't be quite as prescient on the initial playthrough.

see:
- linkerd/linkerd2#8733.
- #3559

Signed-off-by: katelyn martin <[email protected]>

* feat(http/retry): `is_end_stream()` traces

this commit introduces some trace-level diagnostics tracking how the
replay body has determined whether or not it has reached the end of the
stream.

Signed-off-by: katelyn martin <[email protected]>

* nit(http/retry): capitalize trace event messages

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 12, 2025
in #3559 (4b53081), we introduced a backported `Frame<T>` type, and a
`ForwardCompatibleBody<B>` type that allows us to interact with a
`http_body::Body` circa 0.4.6 in terms of frame-based interfaces that
match those of the 1.0 interface.

see linkerd/linkerd2#8733 for more information on upgrading hyper.

in #3559, we narrowly added this as an internal submodule of the
`linkerd-http-retry` library. these facilities however, would have
utility in other places such as `linkerd-app-core`.

this commit pulls these compatibility shims out into a
`linkerd-http-body-compat` library so that they can be imported and
reused elsewhere.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 13, 2025
* refactor(http/retry): outline `ForwardCompatibleBody<B>`

in #3559 (4b53081), we introduced a backported `Frame<T>` type, and a
`ForwardCompatibleBody<B>` type that allows us to interact with a
`http_body::Body` circa 0.4.6 in terms of frame-based interfaces that
match those of the 1.0 interface.

see linkerd/linkerd2#8733 for more information on upgrading hyper.

in #3559, we narrowly added this as an internal submodule of the
`linkerd-http-retry` library. these facilities however, would have
utility in other places such as `linkerd-app-core`.

this commit pulls these compatibility shims out into a
`linkerd-http-body-compat` library so that they can be imported and
reused elsewhere.

Signed-off-by: katelyn martin <[email protected]>

* nit(http/body-compat): tidy `combinators` imports

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 13, 2025
`linkerd-app-core` includes an error recovery body middleware. this middleware will gracefully catch and report errors encountered when polling an inner body, and via an `R`-typed recovery strategy provided by the caller, will attempt to map the error to a gRPC status code denoting an error.

before we upgrade to hyper 1.0 in service of linkerd/linkerd2#8733, we add some test coverage to ensure that we preserve the behavior of this middleware.

see:
* linkerd/linkerd2#8733
* #3614.

for historical context on this tower layer, see:
* #222
* #1246
* #1282

---

* refactor(http/retry): outline `ForwardCompatibleBody<B>`

in #3559 (4b53081), we introduced a backported `Frame<T>` type, and a
`ForwardCompatibleBody<B>` type that allows us to interact with a
`http_body::Body` circa 0.4.6 in terms of frame-based interfaces that
match those of the 1.0 interface.

see linkerd/linkerd2#8733 for more information on upgrading hyper.

in #3559, we narrowly added this as an internal submodule of the
`linkerd-http-retry` library. these facilities however, would have
utility in other places such as `linkerd-app-core`.

this commit pulls these compatibility shims out into a
`linkerd-http-body-compat` library so that they can be imported and
reused elsewhere.

Signed-off-by: katelyn martin <[email protected]>

* nit(http/body-compat): tidy `combinators` imports

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): hoist `errors::code_header` helper

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): `l5d-*` constants are headers

these are header values. `http::HeaderName` has a const fn constructor,
so let's use that.

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): grpc constants are headers

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): hoist `l5d-` and `grpc-` constants

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): outline `ResponseBody` middleware

we'll add a few tests for this middleware shortly.

this commit moves this middleware out into its own submodule.

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): encapsulate `ResponseBody` enum

for other body middleware, we hide inner enum variants and their
constituent members by using the "inner" pattern.

this commit tweaks `ResponseBody` to follow suit, such that it now holds
an `Inner`, but does not expose its passthrough and rescue variants to
callers.

Signed-off-by: katelyn martin <[email protected]>

* docs(app/core): document `ResponseBody<R, B>`

this adds a small documentation comment describing what this type does.

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/core): a unit test suite for rescue body

this commit introduces a test suite for our error recovery middleware.

this body middleware provides a mechanism to "rescue" errors, gracefully
mapping an error encountered when polling a gRPC body into e.g. trailers
with a gRPC status code.

before we upgrade this middleware in service of linkerd/linkerd2#8733,
we add some test coverage to ensure that we preserve this middleware.

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 28, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-inbound` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

see #3672 and #3673, which perform the same change for
`linkerd-app-outbound` and `linkerd-app-integration`, respectively.

---

* refactor(app/inbound): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/inbound): use `ForwardCompatibleBody`

see linkerd/linkerd2#8733.

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 28, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-outbound` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671 and #3673, which perform the same change for
`linkerd-app-inbound` and `linkerd-app-integration`, respectively.

---

* chore(app/outbound): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/outbound): use `Response::into_body()`

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/outbound): use `ForwardCompatibleBody`

see linkerd/linkerd2#8733.

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/outbound): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 28, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671 and #3672, which perform the same change for
`linkerd-app-inbound` and `linkerd-app-outbound`, respectively.

---

* chore(app/integration): `linkerd-http-body-compat` test dependency

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/integration): generalize `hyper::Body`

Signed-off-by: katelyn martin <[email protected]>

* refactor(app/integration): use `ForwardCompatibleBody`

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 28, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-outbound` related to
timeouts so that it interacts with request and response bodies via an
adapter that polls for frames in a manner consistent with the 1.0 api of
`http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671, #3672, and #3673, which performed the same change for
`linkerd-app-inbound`, other code in `linkerd-app-outbound`, and
`linkerd-app-integration`, respectively.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Feb 28, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

this branch updates test code in `linkerd-app-outbound` related to
timeouts so that it interacts with request and response bodies via an
adapter that polls for frames in a manner consistent with the 1.0 api of
`http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

see #3671, #3672, and #3673, which performed the same change for
`linkerd-app-inbound`, other code in `linkerd-app-outbound`, and
`linkerd-app-integration`, respectively.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 4, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

`telemetry::log_stream::collect_logs` is a function responsible for
digesting a streaming body, and deserializing each chunk into a
`serde_json::Value`, until either (a) a shutdown signal is received, or
(b) the end of the body is reached.

this commit updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

* linkerd/linkerd2#8733
* #3671
* #3672
* #3673
* #3676

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 4, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

`telemetry::log_stream::collect_logs` is a function responsible for
digesting a streaming body, and deserializing each chunk into a
`serde_json::Value`, until either (a) a shutdown signal is received, or
(b) the end of the body is reached.

this commit updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

* linkerd/linkerd2#8733
* #3671
* #3672
* #3673
* #3676

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 4, 2025
see linkerd/linkerd2#8733 for more
information.

see #3559 and
#3614 for more information
on the `ForwardCompatibleBody<B>` wrapper.

`telemetry::log_stream::collect_logs` is a function responsible for
digesting a streaming body, and deserializing each chunk into a
`serde_json::Value`, until either (a) a shutdown signal is received, or
(b) the end of the body is reached.

this commit updates test code in `linkerd-app-integration` so that it
interacts with request and response bodies via an adapter that polls for
frames in a manner consistent with the 1.0 api of `http_body`.

this allows us to limit the diff in
#3504, which will only
need to remove this adapter once using hyper 1.0.

* linkerd/linkerd2#8733
* #3671
* #3672
* #3673
* #3676

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 10, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 11, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 12, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 12, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 14, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 18, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 18, 2025
note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Mar 21, 2025
## ✨ chore(deps): upgrade to hyperium 1.x crates

this branch performs an exciting upgrade for our proxy.

this branch upgrades a number of our dependencies so that we use the 1.0
release family of the `hyper` http framework, and its ecosystem. see the
[v1.0 announcement][hyper-v1] for more information.

this branch upgrades the following dependencies:

* `h2`: 0.3 -> 0.4
* `http`: 0.2 -> 1
* `http-body`: 0.4 -> 1
* `hyper`: 0.14.32 -> 1
* `prost`: 0.12 -> 0.13
* `prost-build`: 0.12 -> 0.13
* `prost-types`: 0.12 -> 0.13
* `tonic`: 0.10 -> 0.12
* `tonic-build`: 0.10 -> 0.12

a `hyper-util` dependency is added, which provides among other things,
legacy-compatible interfaces such as `hyper_util::client::legacy::Client`, or
glue to use `hyper` with the tokio runtime.

see <https://docs.rs/hyper-util/latest/hyper_util/> for more information.

a `http-body-util` dependency is added, which provides a `BodyExt` trait and a
channel-backed body for use in unit tests. the `deprecated` feature flag that
was active on our `0.14` hyper dependency has been removed, along with the
`stream` and `runtime` feature flags.

the `linkerd2-proxy-api` dependency is updated. see:
<linkerd/linkerd2-proxy-api#421>

### 📝 notes for review

bear particular attention to changes involving `http_body::Body` middleware.

the change from two separate `poll_data()` and `poll_trailers()` functions,
to a single `poll_frame()` method, induces some subtle changes to various
pieces of middleware.

also bear in mind that failing to set a timer, in our case
`hyper_util::rt::TokioTimer`, can cause http/2 clients, or http/1 and http/2
servers, to panic. make sure that any uses of
`hyper::server::conn::http1::Builder`, `hyper::client::conn::http1::Builder`,
or `hyper::client::conn::http2::Builder` install a timer.

### ❗ breaking change: `l5d-proxy-error` values

the `l5d-proxy-error` header can be examined to observe the cause of proxy
errors encountered when sending meshed traffic. by virtue of this using a newer
`hyper` client in the proxy, some error messages may in turn look different.
for example, an error like `"connect timed out after 1s"` may now appear as
`"client error (Connect)"`.

### 📚 other notes

this work, by virtue of touching so many parts of the system, is carried out
in distinct commits. an initial commit upgrades the dependencies at th
workspace level. subsequent commits will not compile if the `--workspace` flag
is provided, but the intent of this branch is to update each crate
individually.

use commands like, e.g. `cargo check --tests -p linkerd-proxy-http` to build
particular crates at intermediate commits within this branch.

this commit is also only the final leaf in an _extended_ line of work. this
has been done to mitigate the effort of reviewing this change, and the risk of
churn in the event of any unanticipated errors. see the top-level comment in
linkerd/linkerd2#8733 for an overview of all of the
work that brought us to this juncture.

[hyper-v1]: https://seanmonstar.com/blog/hyper-v1/

---

* chore(deps): upgrade to hyper 1.x

note: this commit will not compile, code changes are intentionally
elided from this commit.

this commit upgrades hyper, http, tonic, prost, related dependencies,
and their assorted cargo features.

see <linkerd/linkerd2#8733>.

see also:

* #3379
* #3380
* #3382
* #3405
* hyperium/hyper#3796
* #3411
* #3421
* #3427
* #3428
* #3432
* #3433
* #3444
* #3445
* #3454
* #3455
* #3456
* #3457
* #3461
* #3459
* #3465
* #3466
* #3467
* #3468
* linkerd/linkerd2-proxy-api#421
* linkerd/linkerd2#13492
* linkerd/linkerd2#13493
* hyperium/hyper#3816
* #3472
* #3473
* #3479
* tokio-rs/tokio#7059
* #3509
* hyperium/http-body#140
* #3515
* hyperium/http-body#141
* #3530
* #3531
* #3540
* #3556
* #3558
* #3559
* #3564
* #3567
* #3573
* #3583
* hyperium/http-body#144
* #3585
* #3586
* #3597
* #3598
* #3611
* #3614
* #3615
* #3616
* #3647
* #3651
* #3653
* #3654
* #3655
* #3656
* #3657
* #3660
* #3671
* #3672
* #3673
* #3676
* hyperium/http-body#147
* #3692
* #3699
* #3700
* #3701
* #3708
* linkerd/drain-rs#36
* #3715
* #3717
* eminence/procfs#340

---

squash:

chore(deps): add hyper-util workspace dependency

chore(deps): add http-body-util workspace dependency

chore(deps): upgrade linkerd2-proxy-api

this commit represents main as of linkerd/linkerd2-proxy-api#421.

Signed-off-by: katelyn martin <[email protected]>

* chore(http/box): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(hyper-balance): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/retain): ugrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/stream-timeouts): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/classify): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/upgrade): upgrade to hyper 1.x

NOTE: there is a comment noting that the upgrade middleware does not
expect to be cloneable. it is unfortunately, however, at odds with the
new bounds expected of extensions.

so, `Http11Upgrade` is now Clone'able, but a comment is left in place
noting this weakened invariant.

it's worth investigating how upgrades have changed since, in more
detail, but for the current moment we are interested in being
especially conservative about changing behavior, and focusing on api
changes like `Body::poll_frame(..)`.

Signed-off-by: katelyn martin <[email protected]>

* chore(metrics): upgrade to hyper 1.x

a brief note; this commit happened to tickle an unfortunate sharp edge
in `BoxBody` and `Full`'s respective constructors. type inference could
not figure out how to construct the body, so we refrain from boxing the
response body now.

Signed-off-by: katelyn martin <[email protected]>

* chore(http/metrics): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/prom): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/insert): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/retry): deprecate linkerd-http-body-compat

Signed-off-by: katelyn martin <[email protected]>

* chore(mock/http-body): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(http/retry): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(proxy/tap): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(proxy/http): update to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/core): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/test): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/admin): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/outbound): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/inbound): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app/integration): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(app): upgrade to hyper 1.x

Signed-off-by: katelyn martin <[email protected]>

* chore(transport-header): update generated code

Signed-off-by: katelyn martin <[email protected]>

* chore(spiffe-proto): update generated code

Signed-off-by: katelyn martin <[email protected]>

* chore(opencensus-proto): update generated code

Signed-off-by: katelyn martin <[email protected]>

* chore(opentelemetry-proto): update generated code

Signed-off-by: katelyn martin <[email protected]>

* chore(deny.toml): update cargo-deny directives

this commit updates the contents of `deny.toml`.

Signed-off-by: katelyn martin <[email protected]>

* chore: `compile` has been renamed to `compile_protos`

this addresses deprecation warnings, updating calls to a function that
has since been renamed.

Signed-off-by: katelyn martin <[email protected]>

* chore(deps): remove `linkerd-http-body-compat` dependencies

this commit removes this crate, which we added to future proof code for
this upgrade, from its dependents.

Signed-off-by: katelyn martin <[email protected]>

* chore(http/body-compat): remove `linkerd-http-body-compat` crate

Signed-off-by: katelyn martin <[email protected]>

* chore(deps): update to drain 0.2.1

see linkerd/drain-rs#41.

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Jun 2, 2025
this commit fixes a logical bug with
`linkerd_http_retry::peek_trailers::PeekTrailersBody::<B>::read_body(..)`.

`read_body(..)` constructs a `PeekTrailersBody<B>`, by polling the inner
body to see whether or not it can reach the end of the stream by only
yielding to the asynchronous runtime once.

in #3559, we restructured this middleware's
internal modeling to reflect the `Frame<T>`-oriented signatures of the
`http_body::Body` trait's 1.0 interface.

unfortunately, this included a bug which could cause the first frame in
a stream to be discarded if the second `Body::poll_frame()` call
(_invoked via `now_or_never()`_) returns `Pending`. this could cause
non-deterministic errors for users when sending traffic to HTTPRoutes
and GRPCRoutes with retry annotations applied.

this commit rectifies this problem, ensuring that the first frame is not
discarded when attempting to peek a body's trailers.

Signed-off-by: katelyn martin <[email protected]>
cratelyn added a commit that referenced this pull request Jun 2, 2025
see linkerd/linkerd2#14050.

this change fixes a logical bug with
`linkerd_http_retry::peek_trailers::PeekTrailersBody::<B>::read_body(..)`.

`read_body(..)` constructs a `PeekTrailersBody<B>`, by polling the inner
body to see whether or not it can reach the end of the stream by only
yielding to the asynchronous runtime once.

in #3559, we restructured this middleware's
internal modeling to reflect the `Frame<T>`-oriented signatures of the
`http_body::Body` trait's 1.0 interface.

unfortunately, this included a bug which could cause the first frame in
a stream to be discarded if the second `Body::poll_frame()` call
(_invoked via `now_or_never()`_) returns `Pending`. this could cause
non-deterministic errors for users when sending traffic to HTTPRoutes
and GRPCRoutes with retry annotations applied.

this change rectifies this problem, ensuring that the first frame is not
discarded when attempting to peek a body's trailers.

to confirm that this works as expected, additional test coverage is
introduced that confirms that the data and trailers of the inner body
are passed through faithfully.

---

* feat(http/retry): additional `PeekTrailersBody<B>` test coverage

this commit introduces additional test coverage to
`linker_http_retry::peek_trailers::PeekTrailersBody<B>`.

this body middleware is used to facilitate transparent http retries, and
allows callers to possibly inspect the trailers for a response, by
polling an `http_body::Body`.

this commit introduces additional unit test coverage that confirms that
the data and trailers of the inner body are passed through faithfully.

Signed-off-by: katelyn martin <[email protected]>

* feat(http/retry): another `PeekTrailersBody<B>` test case

this commit introduces some additional coverage for bodies that return
`Pending` when polled a second time.

Signed-off-by: katelyn martin <[email protected]>

* fix(http/retry): `PeekTrailersBody<B>` retains first frame

this commit fixes a logical bug with
`linkerd_http_retry::peek_trailers::PeekTrailersBody::<B>::read_body(..)`.

`read_body(..)` constructs a `PeekTrailersBody<B>`, by polling the inner
body to see whether or not it can reach the end of the stream by only
yielding to the asynchronous runtime once.

in #3559, we restructured this middleware's
internal modeling to reflect the `Frame<T>`-oriented signatures of the
`http_body::Body` trait's 1.0 interface.

unfortunately, this included a bug which could cause the first frame in
a stream to be discarded if the second `Body::poll_frame()` call
(_invoked via `now_or_never()`_) returns `Pending`. this could cause
non-deterministic errors for users when sending traffic to HTTPRoutes
and GRPCRoutes with retry annotations applied.

this commit rectifies this problem, ensuring that the first frame is not
discarded when attempting to peek a body's trailers.

Signed-off-by: katelyn martin <[email protected]>

---------

Signed-off-by: katelyn martin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants