axum_cometd/context/
build_router.rs

1use crate::{handlers::*, LongPollingServiceContext};
2use axum::{routing::post, Extension, Router};
3use core::fmt::Debug;
4use std::sync::Arc;
5
6/// A builder to construct `axum::Route` of CometD server.
7#[derive(Debug)]
8pub struct RouterBuilder {
9    subscribe_base_path: &'static str,
10    handshake_base_path: &'static str,
11    connect_base_path: &'static str,
12    disconnect_base_path: &'static str,
13}
14
15impl Default for RouterBuilder {
16    #[inline(always)]
17    fn default() -> Self {
18        Self {
19            subscribe_base_path: "/",
20            handshake_base_path: "",
21            connect_base_path: "",
22            disconnect_base_path: "",
23        }
24    }
25}
26
27impl RouterBuilder {
28    /// Construct a new `RouterBuilder`.
29    #[inline(always)]
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    /// Return a `axum::Router`.
35    ///
36    /// # Example
37    /// ```rust,no_run
38    /// use std::sync::Arc;
39    /// use axum_cometd::RouterBuilder;
40    ///
41    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build();
42    /// let app = RouterBuilder::new().build::<()>(Arc::clone(&context));
43    /// ```
44    #[inline(always)]
45    pub fn build<CustomData>(
46        self,
47        context: Arc<LongPollingServiceContext<(), CustomData>>,
48    ) -> Router
49    where
50        CustomData: Send + Sync + 'static,
51    {
52        self.build_with_additional_data(context)
53            .layer(Extension(()))
54    }
55
56    /// Return a `axum::Router`.
57    ///
58    /// # Example
59    /// ```rust,no_run
60    /// use std::sync::Arc;
61    /// use axum::Extension;
62    /// use axum_cometd::RouterBuilder;
63    ///
64    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build::<ContextData, ()>();
65    /// #[derive(Clone)]
66    /// struct ContextData {
67    ///     server_name: String,
68    /// }
69    ///
70    /// let app = RouterBuilder::new()
71    ///     .build_with_additional_data(Arc::clone(&context))
72    ///     .layer(Extension(ContextData {
73    ///         server_name: std::env::var("SERVER_NAME").unwrap_or_else(|_| "Skalica".to_owned()),
74    ///     }));
75    /// ```
76    #[inline]
77    pub fn build_with_additional_data<AdditionalData, CustomData>(
78        self,
79        context: Arc<LongPollingServiceContext<AdditionalData, CustomData>>,
80    ) -> Router
81    where
82        AdditionalData: Clone + Send + Sync + 'static,
83        CustomData: Send + Sync + 'static,
84    {
85        let Self {
86            subscribe_base_path,
87            handshake_base_path,
88            connect_base_path,
89            disconnect_base_path,
90        } = self;
91
92        Router::new()
93            .route(subscribe_base_path, post(subscribe))
94            .route(&format!("{handshake_base_path}/handshake"), post(handshake))
95            .route(&format!("{connect_base_path}/connect"), post(connect))
96            .route(
97                &format!("{disconnect_base_path}/disconnect"),
98                post(disconnect),
99            )
100            .with_state(context)
101    }
102
103    /// Set subscribe base-path for routers.
104    ///
105    /// # Example
106    /// ```rust,no_run
107    /// use std::sync::Arc;
108    /// use axum_cometd::RouterBuilder;
109    ///
110    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build();
111    /// let app = RouterBuilder::new()
112    ///     // Ex: `/` -> `/bar`
113    ///     .subscribe_base_path("/bar")
114    ///     .build::<()>(Arc::clone(&context));
115    /// ```
116    #[inline(always)]
117    #[must_use]
118    pub const fn subscribe_base_path(self, path: &'static str) -> Self {
119        Self {
120            subscribe_base_path: path,
121            ..self
122        }
123    }
124
125    /// Set handshake base-path for routers.
126    ///
127    /// # Example
128    /// ```rust,no_run
129    /// use std::sync::Arc;
130    /// use axum_cometd::RouterBuilder;
131    ///
132    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build();
133    /// let app = RouterBuilder::new()
134    ///     // Ex: `/handshake` -> `/bar/handshake`
135    ///     .handshake_base_path("/bar")
136    ///     .build::<()>(Arc::clone(&context));
137    /// ```
138    #[inline(always)]
139    #[must_use]
140    pub const fn handshake_base_path(self, path: &'static str) -> Self {
141        Self {
142            handshake_base_path: path,
143            ..self
144        }
145    }
146
147    /// Set connect base-path for routers.
148    ///
149    /// # Example
150    /// ```rust,no_run
151    /// use std::sync::Arc;
152    /// use axum_cometd::RouterBuilder;
153    ///
154    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build();
155    /// let app = RouterBuilder::new()
156    ///     // Ex: `/connect` -> `/bar/connect`
157    ///     .connect_base_path("/bar")
158    ///     .build::<()>(Arc::clone(&context));
159    /// ```
160    #[inline(always)]
161    #[must_use]
162    pub const fn connect_base_path(self, path: &'static str) -> Self {
163        Self {
164            connect_base_path: path,
165            ..self
166        }
167    }
168
169    /// Set disconnect base-path for routers.
170    ///
171    /// # Example
172    /// ```rust,no_run
173    /// use std::sync::Arc;
174    /// use axum_cometd::RouterBuilder;
175    ///
176    /// # let context = axum_cometd::LongPollingServiceContextBuilder::new().build();
177    /// let app = RouterBuilder::new()
178    ///     // Ex: `/disconnect` -> `/bar/disconnect`
179    ///     .disconnect_base_path("/bar")
180    ///     .build::<()>(Arc::clone(&context));
181    /// ```
182    #[inline(always)]
183    #[must_use]
184    pub const fn disconnect_base_path(self, path: &'static str) -> Self {
185        Self {
186            disconnect_base_path: path,
187            ..self
188        }
189    }
190}