Skip to main content

trillium/
handler.rs

1use crate::{Conn, Headers, Info, Status, Upgrade};
2use std::{borrow::Cow, future::Future};
3
4/// # The building block for Trillium applications.
5///
6/// ## Concept
7///
8/// Many other frameworks have a notion of `middleware` and `endpoints`,
9/// in which the model is that a request passes through a router and then
10/// any number of middlewares, then a single endpoint that returns a
11/// response, and then passes a response back through the middleware
12/// stack.
13///
14/// Because a Trillium Conn represents both a request and response, there
15/// is no distinction between middleware and endpoints, as all of these
16/// can be modeled as `Fn(Conn) -> Future<Output = Conn>`.
17///
18/// ## Implementing Handler
19///
20/// The simplest handler is an async closure or
21/// async fn that receives a Conn and returns a Conn, and Handler has a
22/// blanket implementation for any such Fn.
23///
24/// ```
25/// # use trillium_testing::TestServer;
26/// // as a closure
27/// let handler = |conn: trillium::Conn| async move { conn.ok("trillium!") };
28///
29/// # trillium_testing::block_on(async {
30/// let app = TestServer::new(handler).await;
31/// app.get("/").await.assert_ok().assert_body("trillium!");
32/// # });
33/// ```
34///
35/// ```
36/// # use trillium_testing::TestServer;
37/// // as an async function
38/// async fn handler(conn: trillium::Conn) -> trillium::Conn {
39///     conn.ok("trillium!")
40/// }
41/// # trillium_testing::block_on(async {
42/// let app = TestServer::new(handler).await;
43/// app.get("/").await.assert_ok().assert_body("trillium!");
44/// # });
45/// ```
46///
47/// The simplest implementation of Handler for a named type looks like this:
48/// ```
49/// # use trillium_testing::TestServer;
50/// pub struct MyHandler;
51/// impl trillium::Handler for MyHandler {
52///     async fn run(&self, conn: trillium::Conn) -> trillium::Conn {
53///         conn
54///     }
55/// }
56///
57/// # trillium_testing::block_on(async {
58/// let app = TestServer::new(MyHandler).await;
59/// app.get("/").await.assert_status(404); // we did not halt or set a body status
60/// //
61/// # });
62/// ```
63///
64/// See each of the function definitions below for advanced implementation.
65///
66/// For most application code and even trillium-packaged framework code,
67/// `run` is the only trait function that needs to be implemented.
68pub trait Handler: Send + Sync + 'static {
69    /// Executes this handler, performing any modifications to the Conn that are desired.
70    fn run(&self, conn: Conn) -> impl Future<Output = Conn> + Send {
71        async { conn }
72    }
73
74    /// Performs one-time async set up on a mutable borrow of the Handler before the server starts
75    /// accepting requests. This allows a Handler to be defined in synchronous code but perform
76    /// async setup such as establishing a database connection or fetching some state from an
77    /// external source. This is optional, and chances are high that you do not need this.
78    ///
79    /// It also receives a mutable borrow of the [`Info`] that represents the current connection.
80    fn init(&mut self, info: &mut Info) -> impl Future<Output = ()> + Send {
81        let _ = info;
82        std::future::ready(())
83    }
84
85    /// Performs any final modifications to this conn after all handlers have been run. Although
86    /// this is a slight deviation from the simple conn->conn->conn chain represented by most
87    /// Handlers, it provides an easy way for libraries to effectively inject a second handler into
88    /// a response chain. This is useful for loggers that need to record information both before and
89    /// after other handlers have run, as well as database transaction handlers and similar library
90    /// code.
91    ///
92    /// **❗IMPORTANT NOTE FOR LIBRARY AUTHORS:** Please note that this will run __whether or not
93    /// the conn was halted before [`Handler::run`] was called on a given conn__. This means
94    /// that if you want to make your `before_send` callback conditional on whether `run` was
95    /// called, you need to put a unit type into the conn's state and check for that.
96    ///
97    /// stability note: I don't love this for the exact reason that it breaks the simplicity of the
98    /// conn->conn->model, but it is currently the best compromise between that simplicity and
99    /// convenience for the application author, who should not have to add two Handlers to achieve
100    /// an "around" effect.
101    fn before_send(&self, conn: Conn) -> impl Future<Output = Conn> + Send {
102        std::future::ready(conn)
103    }
104
105    /// predicate function answering the question of whether this Handler would like to take
106    /// ownership of the negotiated Upgrade. If this returns true, you must implement
107    /// [`Handler::upgrade`]. The first handler that responds true to this will receive
108    /// ownership of the [`trillium::Upgrade`][crate::Upgrade] in a subsequent call to
109    /// [`Handler::upgrade`]
110    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
111        let _ = upgrade;
112        false
113    }
114
115    /// This will only be called if the handler reponds true to [`Handler::has_upgrade`] and will
116    /// only be called once for this upgrade. There is no return value, and this function takes
117    /// exclusive ownership of the underlying transport once this is called. You can downcast
118    /// the transport to whatever the source transport type is and perform any non-http protocol
119    /// communication that has been negotiated. You probably don't want this unless you're
120    /// implementing something like websockets. Please note that for many transports such as
121    /// `TcpStreams`, dropping the transport (and therefore the Upgrade) will hang up /
122    /// disconnect.
123    fn upgrade(&self, upgrade: Upgrade) -> impl Future<Output = ()> + Send {
124        let _ = upgrade;
125        async { unimplemented!("if has_upgrade returns true, you must also implement upgrade") }
126    }
127
128    /// Customize the name of your handler. This is used in Debug implementations. The default is
129    /// the type name of this handler.
130    fn name(&self) -> Cow<'static, str> {
131        std::any::type_name::<Self>().into()
132    }
133}
134
135impl Handler for Status {
136    async fn run(&self, conn: Conn) -> Conn {
137        conn.with_status(*self)
138    }
139}
140
141impl<H: Handler> Handler for Vec<H> {
142    async fn run(&self, mut conn: Conn) -> Conn {
143        for handler in self {
144            log::debug!("running {}", handler.name());
145            conn = handler.run(conn).await;
146            if conn.is_halted() {
147                break;
148            }
149        }
150        conn
151    }
152
153    async fn init(&mut self, info: &mut Info) {
154        for handler in self {
155            handler.init(info).await;
156        }
157    }
158
159    async fn before_send(&self, mut conn: Conn) -> Conn {
160        for handler in self.iter().rev() {
161            conn = handler.before_send(conn).await;
162        }
163        conn
164    }
165
166    fn name(&self) -> Cow<'static, str> {
167        self.iter()
168            .map(Handler::name)
169            .collect::<Vec<_>>()
170            .join(",")
171            .into()
172    }
173
174    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
175        self.iter().any(|g| g.has_upgrade(upgrade))
176    }
177
178    async fn upgrade(&self, upgrade: Upgrade) {
179        if let Some(handler) = self.iter().find(|g| g.has_upgrade(&upgrade)) {
180            handler.upgrade(upgrade).await;
181        }
182    }
183}
184
185impl<const L: usize, H: Handler> Handler for [H; L] {
186    async fn run(&self, mut conn: Conn) -> Conn {
187        for handler in self {
188            log::debug!("running {}", handler.name());
189            conn = handler.run(conn).await;
190            if conn.is_halted() {
191                break;
192            }
193        }
194        conn
195    }
196
197    async fn init(&mut self, info: &mut Info) {
198        for handler in self {
199            handler.init(info).await;
200        }
201    }
202
203    async fn before_send(&self, mut conn: Conn) -> Conn {
204        for handler in self.iter().rev() {
205            conn = handler.before_send(conn).await;
206        }
207        conn
208    }
209
210    fn name(&self) -> Cow<'static, str> {
211        self.iter()
212            .map(Handler::name)
213            .collect::<Vec<_>>()
214            .join(",")
215            .into()
216    }
217
218    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
219        self.iter().any(|g| g.has_upgrade(upgrade))
220    }
221
222    async fn upgrade(&self, upgrade: Upgrade) {
223        if let Some(handler) = self.iter().find(|g| g.has_upgrade(&upgrade)) {
224            handler.upgrade(upgrade).await;
225        }
226    }
227}
228
229impl<Fun, Fut> Handler for Fun
230where
231    Fun: Fn(Conn) -> Fut + Send + Sync + 'static,
232    Fut: Future<Output = Conn> + Send + 'static,
233{
234    async fn run(&self, conn: Conn) -> Conn {
235        (self)(conn).await
236    }
237}
238
239impl Handler for &'static str {
240    async fn run(&self, conn: Conn) -> Conn {
241        conn.ok(*self)
242    }
243
244    fn name(&self) -> Cow<'static, str> {
245        format!("conn.ok({:?})", &self).into()
246    }
247}
248
249impl Handler for String {
250    async fn run(&self, conn: Conn) -> Conn {
251        conn.ok(self.clone())
252    }
253
254    fn name(&self) -> Cow<'static, str> {
255        format!("conn.ok({:?})", &self).into()
256    }
257}
258
259impl Handler for () {
260    async fn run(&self, conn: Conn) -> Conn {
261        conn
262    }
263}
264
265impl<H: Handler> Handler for Option<H> {
266    async fn run(&self, conn: Conn) -> Conn {
267        let handler = crate::conn_unwrap!(self, conn);
268        handler.run(conn).await
269    }
270
271    async fn init(&mut self, info: &mut Info) {
272        if let Some(handler) = self {
273            handler.init(info).await;
274        }
275    }
276
277    async fn before_send(&self, conn: Conn) -> Conn {
278        let handler = crate::conn_unwrap!(self, conn);
279        handler.before_send(conn).await
280    }
281
282    fn name(&self) -> Cow<'static, str> {
283        self.as_ref().map_or_else(|| "-".into(), Handler::name)
284    }
285
286    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
287        self.as_ref().is_some_and(|h| h.has_upgrade(upgrade))
288    }
289
290    async fn upgrade(&self, upgrade: Upgrade) {
291        if let Some(handler) = self {
292            handler.upgrade(upgrade).await;
293        }
294    }
295}
296
297impl Handler for Headers {
298    async fn run(&self, mut conn: Conn) -> Conn {
299        conn.response_headers_mut().append_all(self.clone());
300        conn
301    }
302}
303
304impl<T, E> Handler for Result<T, E>
305where
306    T: Handler,
307    E: Handler,
308{
309    async fn run(&self, conn: Conn) -> Conn {
310        match self {
311            Ok(t) => t.run(conn).await,
312            Err(e) => e.run(conn).await,
313        }
314    }
315
316    async fn init(&mut self, info: &mut Info) {
317        match self {
318            Ok(t) => t.init(info).await,
319            Err(e) => e.init(info).await,
320        }
321    }
322
323    async fn before_send(&self, conn: Conn) -> Conn {
324        match self {
325            Ok(t) => t.before_send(conn).await,
326            Err(e) => e.before_send(conn).await,
327        }
328    }
329
330    fn name(&self) -> Cow<'static, str> {
331        match self {
332            Ok(t) => format!("Ok({})", t.name()).into(),
333            Err(e) => format!("Err({})", e.name()).into(),
334        }
335    }
336
337    fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
338        match self {
339            Ok(t) => t.has_upgrade(upgrade),
340            Err(e) => e.has_upgrade(upgrade),
341        }
342    }
343
344    async fn upgrade(&self, upgrade: Upgrade) {
345        match self {
346            Ok(t) => t.upgrade(upgrade).await,
347            Err(e) => e.upgrade(upgrade).await,
348        }
349    }
350}
351
352macro_rules! reverse_before_send {
353    ($conn:ident, $name:ident) => (
354        let $conn = ($name).before_send($conn).await;
355    );
356
357    ($conn:ident, $name:ident $($other_names:ident)+) => (
358        reverse_before_send!($conn, $($other_names)*);
359        reverse_before_send!($conn, $name);
360    );
361}
362
363macro_rules! impl_handler_tuple {
364        ($($name:ident)+) => (
365            impl<$($name),*> Handler for ($($name,)*) where $($name: Handler),* {
366                #[allow(non_snake_case)]
367                async fn run(&self, conn: Conn) -> Conn {
368                    let ($(ref $name,)*) = *self;
369                    $(
370                        log::debug!("running {}", ($name).name());
371                        let conn = ($name).run(conn).await;
372                        if conn.is_halted() { return conn }
373                    )*
374                    conn
375                }
376
377                #[allow(non_snake_case)]
378                async fn init(&mut self, info: &mut Info) {
379                    let ($(ref mut $name,)*) = *self;
380                    $(
381                        log::trace!("initializing {}", ($name).name());
382                        ($name).init(info).await;
383                    )*
384                }
385
386                #[allow(non_snake_case)]
387                async fn before_send(&self, conn: Conn) -> Conn {
388                    let ($(ref $name,)*) = *self;
389                    reverse_before_send!(conn, $($name)+);
390                    conn
391                }
392
393                #[allow(non_snake_case)]
394                fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
395                    let ($(ref $name,)*) = *self;
396                    $(if ($name).has_upgrade(upgrade) { return true })*
397                    false
398                }
399
400                #[allow(non_snake_case)]
401                async fn upgrade(&self, upgrade: Upgrade) {
402                    let ($(ref $name,)*) = *self;
403                    $(if ($name).has_upgrade(&upgrade) {
404                        return ($name).upgrade(upgrade).await;
405                    })*
406                }
407
408                #[allow(non_snake_case)]
409                fn name(&self) -> Cow<'static, str> {
410                    let ($(ref $name,)*) = *self;
411                    format!(concat!("(\n", $(
412                        concat!("  {",stringify!($name) ,":},\n")
413                    ),*, ")"), $($name = ($name).name()),*).into()
414                }
415            }
416        );
417    }
418
419impl_handler_tuple! { A B }
420impl_handler_tuple! { A B C }
421impl_handler_tuple! { A B C D }
422impl_handler_tuple! { A B C D E }
423impl_handler_tuple! { A B C D E F }
424impl_handler_tuple! { A B C D E F G }
425impl_handler_tuple! { A B C D E F G H }
426impl_handler_tuple! { A B C D E F G H I }
427impl_handler_tuple! { A B C D E F G H I J }
428impl_handler_tuple! { A B C D E F G H I J K }
429impl_handler_tuple! { A B C D E F G H I J K L }
430impl_handler_tuple! { A B C D E F G H I J K L M }
431impl_handler_tuple! { A B C D E F G H I J K L M N }
432impl_handler_tuple! { A B C D E F G H I J K L M N O }