From 6a2e600b09044d14d58fe6d220e25580cc40864c Mon Sep 17 00:00:00 2001 From: katelyn martin Date: Mon, 13 Jan 2025 00:00:00 +0000 Subject: [PATCH] chore(http/retry): vendor `http_body::Frame` this vendors a copy of the `Frame` 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 #3504. Signed-off-by: katelyn martin --- linkerd/http/retry/src/frame.rs | 131 ++++++++++++++++++++++++++++++++ linkerd/http/retry/src/lib.rs | 2 + 2 files changed, 133 insertions(+) create mode 100644 linkerd/http/retry/src/frame.rs diff --git a/linkerd/http/retry/src/frame.rs b/linkerd/http/retry/src/frame.rs new file mode 100644 index 0000000000..3e03ca0ea2 --- /dev/null +++ b/linkerd/http/retry/src/frame.rs @@ -0,0 +1,131 @@ +#![allow(unused, reason = "this code is vendored from `http-body v1.0.1")] + +//! A frame of any kind related to an HTTP stream (body). +//! +//! NB: This is a vendored stand-in for [`Frame`][frame], and and can be replaced once +//! we upgrade from http-body 0.4 to 1.0. This file was vendored at commit 86fdf00. +//! +//! See linkerd/linkerd2#8733 for more information. +//! +//! [frame]: https://docs.rs/http-body/1.0.1/http_body/struct.Frame.html> + +use http::HeaderMap; + +/// A frame of any kind related to an HTTP stream (body). +#[derive(Debug)] +pub struct Frame { + kind: Kind, +} + +#[derive(Debug)] +enum Kind { + // The first two variants are "inlined" since they are undoubtedly + // the most common. This saves us from having to allocate a + // boxed trait object for them. + Data(T), + Trailers(HeaderMap), + //Unknown(Box), +} + +impl Frame { + /// Create a DATA frame with the provided `Buf`. + pub fn data(buf: T) -> Self { + Self { + kind: Kind::Data(buf), + } + } + + /// Create a trailers frame. + pub fn trailers(map: HeaderMap) -> Self { + Self { + kind: Kind::Trailers(map), + } + } + + /// Maps this frame's data to a different type. + pub fn map_data(self, f: F) -> Frame + where + F: FnOnce(T) -> D, + { + match self.kind { + Kind::Data(data) => Frame { + kind: Kind::Data(f(data)), + }, + Kind::Trailers(trailers) => Frame { + kind: Kind::Trailers(trailers), + }, + } + } + + /// Returns whether this is a DATA frame. + pub fn is_data(&self) -> bool { + matches!(self.kind, Kind::Data(..)) + } + + /// Consumes self into the buf of the DATA frame. + /// + /// Returns an [`Err`] containing the original [`Frame`] when frame is not a DATA frame. + /// `Frame::is_data` can also be used to determine if the frame is a DATA frame. + pub fn into_data(self) -> Result { + match self.kind { + Kind::Data(data) => Ok(data), + _ => Err(self), + } + } + + /// If this is a DATA frame, returns a reference to it. + /// + /// Returns `None` if not a DATA frame. + pub fn data_ref(&self) -> Option<&T> { + match self.kind { + Kind::Data(ref data) => Some(data), + _ => None, + } + } + + /// If this is a DATA frame, returns a mutable reference to it. + /// + /// Returns `None` if not a DATA frame. + pub fn data_mut(&mut self) -> Option<&mut T> { + match self.kind { + Kind::Data(ref mut data) => Some(data), + _ => None, + } + } + + /// Returns whether this is a trailers frame. + pub fn is_trailers(&self) -> bool { + matches!(self.kind, Kind::Trailers(..)) + } + + /// Consumes self into the buf of the trailers frame. + /// + /// Returns an [`Err`] containing the original [`Frame`] when frame is not a trailers frame. + /// `Frame::is_trailers` can also be used to determine if the frame is a trailers frame. + pub fn into_trailers(self) -> Result { + match self.kind { + Kind::Trailers(trailers) => Ok(trailers), + _ => Err(self), + } + } + + /// If this is a trailers frame, returns a reference to it. + /// + /// Returns `None` if not a trailers frame. + pub fn trailers_ref(&self) -> Option<&HeaderMap> { + match self.kind { + Kind::Trailers(ref trailers) => Some(trailers), + _ => None, + } + } + + /// If this is a trailers frame, returns a mutable reference to it. + /// + /// Returns `None` if not a trailers frame. + pub fn trailers_mut(&mut self) -> Option<&mut HeaderMap> { + match self.kind { + Kind::Trailers(ref mut trailers) => Some(trailers), + _ => None, + } + } +} diff --git a/linkerd/http/retry/src/lib.rs b/linkerd/http/retry/src/lib.rs index 5aedecf8bf..5359165996 100644 --- a/linkerd/http/retry/src/lib.rs +++ b/linkerd/http/retry/src/lib.rs @@ -4,6 +4,8 @@ pub mod peek_trailers; pub mod replay; +mod frame; + pub use self::{peek_trailers::PeekTrailersBody, replay::ReplayBody}; pub use tower::retry::budget::Budget;