http_types_rs/transfer/trailers.rs
1//! HTTP trailing headers.
2//!
3//! Trailing headers are headers that are send *after* the body payload has
4//! been sent. This is for example useful for sending integrity checks of
5//! streamed payloads that are computed on the fly.
6//!
7//! The way trailing headers are sent over the wire varies per protocol. But in
8//! `http-types` we provide a `Trailers` struct that's used to contain the headers.
9//!
10//! To send trailing headers, see `Request::{`[`send_trailers, `][req_send]
11//! [`recv_trailers`][req_recv]`}` and
12//! `Response::{`[`send_trailers, `][res_send][`recv_trailers`][res_recv]`}`.
13//!
14//! [req_send]: ../struct.Request.html#method.send_trailers
15//! [req_recv]: ../struct.Request.html#method.recv_trailers
16//! [res_send]: ../struct.Response.html#method.send_trailers
17//! [res_recv]: ../struct.Response.html#method.recv_trailers
18//!
19//! ## Example
20//!
21//! ```
22//! # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
23//! # async_std::task::block_on(async {
24//! #
25//! use http_types_rs::{Url, Method, Request};
26//! use http_types_rs::transfer::Trailers;
27//! use http_types_rs::headers::{HeaderName, HeaderValue};
28//! use async_std::task;
29//! use std::str::FromStr;
30//!
31//! let mut req = Request::new(Method::Get, Url::parse("https://example.com").unwrap());
32//!
33//! let sender = req.send_trailers();
34//! let mut trailers = Trailers::new();
35//! trailers.insert("Content-Type", "text/plain");
36//!
37//! task::spawn(async move {
38//! let trailers = req.recv_trailers().await;
39//! # drop(trailers)
40//! });
41//!
42//! sender.send(trailers).await;
43//! #
44//! # Ok(()) })}
45//! ```
46//!
47//! ## See Also
48//! - [MDN HTTP Headers: Trailer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer)
49//! - [HTTP/2 spec: HTTP Sequence](https://http2.github.io/http2-spec/#HttpSequence)
50
51use crate::headers::{HeaderName, HeaderValues, Headers, Iter, IterMut, Names, ToHeaderValues, Values};
52use async_channel::TryRecvError;
53
54use std::convert::Into;
55use std::future::Future;
56use std::ops::{Deref, DerefMut, Index};
57use std::pin::Pin;
58use std::task::{Context, Poll};
59
60/// A collection of trailing HTTP headers.
61#[derive(Debug)]
62pub struct Trailers {
63 headers: Headers,
64}
65
66impl Trailers {
67 /// Create a new instance of `Trailers`.
68 pub fn new() -> Self {
69 Self { headers: Headers::new() }
70 }
71
72 /// Insert a header into the headers.
73 ///
74 /// # Examples
75 ///
76 /// ```
77 /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
78 /// #
79 /// use http_types_rs::transfer::Trailers;
80 ///
81 /// let mut trailers = Trailers::new();
82 /// trailers.insert("Content-Type", "text/plain");
83 /// #
84 /// # Ok(()) }
85 /// ```
86 pub fn insert(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) -> crate::Result<Option<HeaderValues>> {
87 self.headers.insert(name, values)
88 }
89
90 /// Append a header to the headers.
91 ///
92 /// Unlike `insert` this function will not override the contents of a header, but insert a
93 /// header if there aren't any. Or else append to the existing list of headers.
94 ///
95 /// # Examples
96 ///
97 /// ```
98 /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
99 /// #
100 /// use http_types_rs::transfer::Trailers;
101 ///
102 /// let mut trailers = Trailers::new();
103 /// trailers.append("Content-Type", "text/plain");
104 /// #
105 /// # Ok(()) }
106 /// ```
107 pub fn append(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) -> crate::Result<()> {
108 self.headers.append(name, values)
109 }
110
111 /// Get a reference to a header.
112 pub fn get(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
113 self.headers.get(name)
114 }
115
116 /// Get a mutable reference to a header.
117 pub fn get_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
118 self.headers.get_mut(name)
119 }
120
121 /// Remove a header.
122 pub fn remove(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
123 self.headers.remove(name)
124 }
125
126 /// An iterator visiting all header pairs in arbitrary order.
127 pub fn iter(&self) -> Iter<'_> {
128 self.headers.iter()
129 }
130
131 /// An iterator visiting all header pairs in arbitrary order, with mutable references to the
132 /// values.
133 pub fn iter_mut(&mut self) -> IterMut<'_> {
134 self.headers.iter_mut()
135 }
136
137 /// An iterator visiting all header names in arbitrary order.
138 pub fn names(&self) -> Names<'_> {
139 self.headers.names()
140 }
141
142 /// An iterator visiting all header values in arbitrary order.
143 pub fn values(&self) -> Values<'_> {
144 self.headers.values()
145 }
146}
147
148impl Clone for Trailers {
149 fn clone(&self) -> Self {
150 Self {
151 headers: Headers {
152 headers: self.headers.headers.clone(),
153 },
154 }
155 }
156}
157
158impl Deref for Trailers {
159 type Target = Headers;
160
161 fn deref(&self) -> &Self::Target {
162 &self.headers
163 }
164}
165
166impl DerefMut for Trailers {
167 fn deref_mut(&mut self) -> &mut Self::Target {
168 &mut self.headers
169 }
170}
171
172impl Index<HeaderName> for Trailers {
173 type Output = HeaderValues;
174
175 /// Returns a reference to the value corresponding to the supplied name.
176 ///
177 /// # Panics
178 ///
179 /// Panics if the name is not present in `Trailers`.
180 #[inline]
181 fn index(&self, name: HeaderName) -> &HeaderValues {
182 self.headers.index(name)
183 }
184}
185
186impl Index<&str> for Trailers {
187 type Output = HeaderValues;
188
189 /// Returns a reference to the value corresponding to the supplied name.
190 ///
191 /// # Panics
192 ///
193 /// Panics if the name is not present in `Trailers`.
194 #[inline]
195 fn index(&self, name: &str) -> &HeaderValues {
196 self.headers.index(name)
197 }
198}
199
200/// The sending half of a channel to send trailers.
201///
202/// Unlike `async_channel::Sender` the `send` method on this type can only be
203/// called once, and cannot be cloned. That's because only a single instance of
204/// `Trailers` should be created.
205#[derive(Debug)]
206pub struct Sender {
207 sender: async_channel::Sender<Trailers>,
208}
209
210impl Sender {
211 /// Create a new instance of `Sender`.
212 #[doc(hidden)]
213 pub fn new(sender: async_channel::Sender<Trailers>) -> Self {
214 Self { sender }
215 }
216
217 /// Send a `Trailer`.
218 ///
219 /// The channel will be consumed after having sent trailers.
220 pub async fn send(self, trailers: Trailers) {
221 let _ = self.sender.send(trailers).await;
222 }
223}
224
225/// The receiving half of a channel to send trailers.
226///
227/// Unlike `async_channel::Sender` the `send` method on this type can only be
228/// called once, and cannot be cloned. That's because only a single instance of
229/// `Trailers` should be created.
230#[must_use = "Futures do nothing unless polled or .awaited"]
231#[derive(Debug)]
232pub struct Receiver {
233 receiver: async_channel::Receiver<Trailers>,
234}
235
236impl Receiver {
237 /// Create a new instance of `Receiver`.
238 pub(crate) fn new(receiver: async_channel::Receiver<Trailers>) -> Self {
239 Self { receiver }
240 }
241}
242
243impl Future for Receiver {
244 type Output = Option<Trailers>;
245
246 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
247 match self.receiver.try_recv() {
248 Ok(conn) => Poll::Ready(Some(conn)),
249 Err(TryRecvError::Closed) => Poll::Ready(None),
250 Err(TryRecvError::Empty) => Poll::Pending,
251 }
252 }
253}