Skip to main content

topcoat_session/
router.rs

1use topcoat_core::context::CxBuilder;
2use topcoat_router::{Body, Layer, LayerFuture, Next, Path, RouterBuilder};
3
4use crate::{Config, OriginLayer, SessionState};
5
6/// A router layer that makes the session state available for the current
7/// request.
8#[derive(Debug, Clone, Copy, Default)]
9pub struct SessionLayer;
10
11impl SessionLayer {
12    /// Creates a session layer.
13    #[must_use]
14    pub const fn new() -> Self {
15        Self
16    }
17}
18
19impl Layer for SessionLayer {
20    fn path(&self) -> &Path {
21        Path::new("/")
22    }
23
24    fn handle<'a>(&'a self, cx: &'a mut CxBuilder, body: Body, next: Next<'a>) -> LayerFuture<'a> {
25        cx.insert(SessionState::new());
26        next.run(cx, body)
27    }
28}
29
30/// Installs session support on a [`RouterBuilder`].
31pub trait RouterBuilderSessionExt {
32    /// Registers the session `config` on the app context, the root session
33    /// layer, and the [`OriginLayer`] rejecting state-changing cross-origin
34    /// requests (unless disabled with
35    /// [`ConfigBuilder::dangerous_disable_origin_verification`](crate::ConfigBuilder::dangerous_disable_origin_verification)).
36    ///
37    /// The default cookie token store also needs the cookie layer, registered
38    /// with the cookie crate's `cookies` extension method.
39    #[must_use]
40    fn sessions(self, config: Config) -> Self;
41}
42
43impl RouterBuilderSessionExt for RouterBuilder {
44    fn sessions(mut self, config: Config) -> Self {
45        let verify_origin = config.verify_origin;
46        self = self.app_context(config);
47        self = self.layer(SessionLayer::new());
48        if verify_origin {
49            self = self.layer(OriginLayer::new());
50        }
51        self
52    }
53}