rama_core/context/
mod.rs

1//! Context passed to and between services as input.
2//!
3//! # State
4//!
5//! [`rama`] supports two kinds of states:
6//!
7//! 1. type-safe state: this is the `S` generic parameter in [`Context`] and is to be used
8//!    as much as possible, given its existence and type properties can be validated at compile time
9//! 2. dynamic state: these can be injected as [`Extensions`]s using methods such as [`Context::insert`]
10//!
11//! As a rule of thumb one should use the type-safe state (1) in case:
12//!
13//! - the state is always expected to exist at the point the middleware/service is called
14//! - the state is specific to the app or middleware
15//! - and the state can be constructed in a default/empty state
16//!
17//! The latter is important given the state is often created (or at least reserved) prior to
18//! it is actually being populated by the relevant middleware. This is not the case for app-specific state
19//! such as Database pools which are created since the start and shared among many different tasks.
20//!
21//! The rule could be be simplified to "if you need to `.unwrap()` you probably want type-safe state instead".
22//! It's however just a guideline and not a hard rule. As maintainers of [`rama`] we'll do our best to respect it though,
23//! and we recommend you to do the same.
24//!
25//! Any state that is optional, and especially optional state injected by middleware, can be inserted using extensions.
26//! It is however important to try as much as possible to then also consume this state in an approach that deals
27//! gracefully with its absence. Good examples of this are header-related inputs. Headers might be set or not,
28//! and so absence of [`Extensions`]s that might be created as a result of these might reasonably not exist.
29//! It might of course still mean the app returns an error response when it is absent, but it should not unwrap/panic.
30//!
31//! [`rama`]: crate
32//!
33//! # Examples
34//!
35//! ```
36//! use rama_core::Context;
37//!
38//! #[derive(Debug)]
39//! struct ServiceState {
40//!     value: i32,
41//! }
42//!
43//! let state = ServiceState{ value: 5 };
44//! let ctx = Context::with_state(state);
45//! ```
46//!
47//! ## Example: Extensions
48//!
49//! The [`Context`] can be extended with additional data using the [`Extensions`] type.
50//!
51//! [`Context`]: crate::Context
52//! [`Extensions`]: crate::context::Extensions
53//!
54//! ```
55//! use rama_core::Context;
56//!
57//! let mut ctx = Context::default();
58//! ctx.insert(5i32);
59//! assert_eq!(ctx.get::<i32>(), Some(&5i32));
60//! ```
61//!
62//! ## State Wraps
63//!
64//! > 📖 [rustdoc link](https://ramaproxy.org/docs/rama/context/struct.Context.html#method.map_state)
65//!
66//! `rama` was built from the ground up to operate on and between different layers of the network stack.
67//! This has also an impact on state. Because sure, typed state is nice, but state leakage is not. What do I mean with that?
68//!
69//! When creating a `TcpListener` with state the state will be owned by that `TcpListener`. By default
70//! it will clone the state and pass a clone to each incoming `tcp` connection. You can however also
71//! inject your own state provider to customise that behaviour. Pretty much the same goes for an `HttpServer`,
72//! where it will do the same for each incoming http request. This is great for stuff that is okay to share, but it is not desired
73//! for state that you wish to have a narrower scope. Examples are state that are tied to a single _tcp_ connection and thus
74//! you do not wish to keep a global cache for this, as it would either be shared or get overly complicated to ensure
75//! you keep things separate and clean.
76//!
77//! One solution is to wrap your state.
78//!
79//! > See for reference: [/examples/http_conn_state.rs](https://github.com/plabayo/rama/tree/main/examples/http_conn_state.rs)
80//!
81//! In that example we make use of:
82//!
83//! - [`MapStateLayer`](https://ramaproxy.org/docs/rama/layer/struct.MapStateLayer.html):
84//!   this generic layer allows you to map the state from one type to another,
85//!   which is great in cases like this where you want the Application layer (http)
86//!   to have a different type compared to the network layer (tpc).
87//! - the [`derive_more` third-party crate](https://docs.rs/derive_more/latest/derive_more/) is used
88//!   as an example how one can use such crates to make services or layers which do not
89//!   depend on a specific state type, but instead only require a reference (mutable or not)
90//!   to specific properties they need, which can be useful in case that service
91//!   is used in multiple branches, each with their own concrete _state_ type.
92
93use crate::graceful::ShutdownGuard;
94use crate::rt::Executor;
95use std::fmt;
96use std::ops::{Deref, DerefMut};
97use tokio::task::JoinHandle;
98
99mod extensions;
100#[doc(inline)]
101pub use extensions::Extensions;
102
103#[derive(Debug, Clone)]
104/// Wrapper type that can be injected into the dynamic extensions of a "Response",
105/// in order to preserve the [`Context`]'s extensions of the _Request_
106/// which was used to produce the _Response_.
107pub struct RequestContextExt(Extensions);
108
109impl From<Extensions> for RequestContextExt {
110    fn from(value: Extensions) -> Self {
111        Self(value)
112    }
113}
114
115impl From<RequestContextExt> for Extensions {
116    fn from(value: RequestContextExt) -> Self {
117        value.0
118    }
119}
120
121impl AsRef<Extensions> for RequestContextExt {
122    fn as_ref(&self) -> &Extensions {
123        &self.0
124    }
125}
126
127impl AsMut<Extensions> for RequestContextExt {
128    fn as_mut(&mut self) -> &mut Extensions {
129        &mut self.0
130    }
131}
132
133impl Deref for RequestContextExt {
134    type Target = Extensions;
135
136    fn deref(&self) -> &Self::Target {
137        &self.0
138    }
139}
140impl DerefMut for RequestContextExt {
141    fn deref_mut(&mut self) -> &mut Self::Target {
142        &mut self.0
143    }
144}
145
146/// Context passed to and between services as input.
147///
148/// See [`crate::context`] for more information.
149pub struct Context<S> {
150    state: S,
151    executor: Executor,
152    extensions: Extensions,
153}
154
155impl<S: fmt::Debug> fmt::Debug for Context<S> {
156    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157        f.debug_struct("Context")
158            .field("state", &self.state)
159            .field("executor", &self.executor)
160            .field("extensions", &self.extensions)
161            .finish()
162    }
163}
164
165/// Component parts of [`Context`].
166pub struct Parts<S> {
167    pub state: S,
168    pub executor: Executor,
169    pub extensions: Extensions,
170}
171
172impl<S: fmt::Debug> fmt::Debug for Parts<S> {
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        f.debug_struct("Parts")
175            .field("state", &self.state)
176            .field("executor", &self.executor)
177            .field("extensions", &self.extensions)
178            .finish()
179    }
180}
181
182impl Default for Context<()> {
183    fn default() -> Self {
184        Self::new((), Executor::default())
185    }
186}
187
188impl<S: Clone> Clone for Context<S> {
189    fn clone(&self) -> Self {
190        Self {
191            state: self.state.clone(),
192            executor: self.executor.clone(),
193            extensions: self.extensions.clone(),
194        }
195    }
196}
197
198impl<S> Context<S> {
199    /// Create a new [`Context`] with the given state.
200    pub fn new(state: S, executor: Executor) -> Self {
201        Self {
202            state,
203            executor,
204            extensions: Extensions::new(),
205        }
206    }
207
208    pub fn from_parts(parts: Parts<S>) -> Self {
209        Self {
210            state: parts.state,
211            executor: parts.executor,
212            extensions: parts.extensions,
213        }
214    }
215
216    pub fn into_parts(self) -> Parts<S> {
217        Parts {
218            state: self.state,
219            executor: self.executor,
220            extensions: self.extensions,
221        }
222    }
223
224    /// Create a new [`Context`] with the given state and default extension.
225    pub fn with_state(state: S) -> Self {
226        Self::new(state, Executor::default())
227    }
228
229    /// Get a reference to the state.
230    pub fn state(&self) -> &S {
231        &self.state
232    }
233
234    /// Get an exclusive reference to the state.
235    pub fn state_mut(&mut self) -> &mut S {
236        &mut self.state
237    }
238
239    /// Map the state from one type to another.
240    pub fn map_state<F, W>(self, f: F) -> Context<W>
241    where
242        F: FnOnce(S) -> W,
243    {
244        Context {
245            state: f(self.state),
246            executor: self.executor,
247            extensions: self.extensions,
248        }
249    }
250
251    /// Swap the state from one type to another,
252    /// returning the new object as well as the previously defined state.
253    pub fn swap_state<W>(self, state: W) -> (Context<W>, S) {
254        (
255            Context {
256                state,
257                executor: self.executor,
258                extensions: self.extensions,
259            },
260            self.state,
261        )
262    }
263
264    /// Clones the internals of this [`Context`]
265    /// to provide a new context, but while mapping the state
266    /// into a new state.
267    pub fn clone_map_state<F, W>(&self, f: F) -> Context<W>
268    where
269        S: Clone,
270        F: FnOnce(S) -> W,
271    {
272        Context {
273            state: f(self.state.clone()),
274            executor: self.executor.clone(),
275            extensions: self.extensions.clone(),
276        }
277    }
278
279    /// Clones the internals of this [`Context`]
280    /// to provide a new context, but using the given state, instead of
281    /// the one defined in the current [`Context`].
282    pub fn clone_with_state<W>(&self, state: W) -> Context<W> {
283        Context {
284            state,
285            executor: self.executor.clone(),
286            extensions: self.extensions.clone(),
287        }
288    }
289
290    /// Get a reference to the executor.
291    pub fn executor(&self) -> &Executor {
292        &self.executor
293    }
294
295    /// Spawn a future on the current executor,
296    /// this is spawned gracefully in case a shutdown guard has been registered.
297    pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
298    where
299        F: Future<Output: Send + 'static> + Send + 'static,
300    {
301        self.executor.spawn_task(future)
302    }
303
304    /// Returns true if the `Context` contains the given type.
305    ///
306    /// Use [`Self::get`] in case you want to have access to the type
307    /// or [`Self::get_mut`] if you also need to mutate it.
308    pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
309        self.extensions.contains::<T>()
310    }
311
312    /// Get a shared reference to an extension.
313    ///
314    /// An extension is a type that implements `Send + Sync + 'static`,
315    /// and can be used to inject dynamic data into the [`Context`].
316    ///
317    /// Extensions are specific to this [`Context`]. It will be cloned when the [`Context`] is cloned,
318    /// but extensions inserted using [`Context::insert`] will not be visible the
319    /// original [`Context`], or any other cloned [`Context`].
320    ///
321    /// Please use the statically typed state (see [`Context::state`]) for data that is shared between
322    /// all context clones.
323    ///
324    /// # Example
325    ///
326    /// ```
327    /// # use rama_core::Context;
328    /// # let mut ctx = Context::default();
329    /// # ctx.insert(5i32);
330    /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
331    /// ```
332    pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
333        self.extensions.get::<T>()
334    }
335
336    /// Get an exclusive reference to an extension.
337    ///
338    /// An extension is a type that implements `Send + Sync + 'static`,
339    /// and can be used to inject dynamic data into the [`Context`].
340    ///
341    /// Extensions are specific to this [`Context`]. It will be cloned when the [`Context`] is cloned,
342    /// but extensions inserted using [`Context::insert`] will not be visible the
343    /// original [`Context`], or any other cloned [`Context`].
344    ///
345    /// Please use the statically typed state (see [`Context::state`]) for data that is shared between
346    /// all context clones.
347    ///
348    /// # Example
349    ///
350    /// ```
351    /// # use rama_core::Context;
352    /// # let mut ctx = Context::default();
353    /// # ctx.insert(5i32);
354    /// let x = ctx.get_mut::<i32>().unwrap();
355    /// assert_eq!(*x, 5i32);
356    /// *x = 8;
357    /// assert_eq!(*x, 8i32);
358    /// assert_eq!(ctx.get::<i32>(), Some(&8i32));
359    /// ```
360    pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
361        self.extensions.get_mut::<T>()
362    }
363
364    /// Inserts a value into the map computed from `f` into if it is [`None`],
365    /// then returns an exclusive reference to the contained value.
366    ///
367    /// # Example
368    ///
369    /// ```
370    /// # use rama_core::Context;
371    /// let mut ctx = Context::default();
372    /// let value: &i32 = ctx.get_or_insert_with(|| 42);
373    /// assert_eq!(*value, 42);
374    /// let existing_value: &mut i32 = ctx.get_or_insert_with(|| 0);
375    /// assert_eq!(*existing_value, 42);
376    /// ```
377    pub fn get_or_insert_with<T: Clone + Send + Sync + 'static>(
378        &mut self,
379        f: impl FnOnce() -> T,
380    ) -> &mut T {
381        self.extensions.get_or_insert_with(f)
382    }
383
384    /// Inserts a value into the map computed from `f` into if it is [`None`],
385    /// then returns an exclusive reference to the contained value.
386    ///
387    /// Use the cheaper [`Self::get_or_insert_with`] in case you do not need access to
388    /// the [`Context`] for the creation of `T`, as this function comes with
389    /// an extra cost.
390    ///
391    /// # Example
392    ///
393    /// ```
394    /// # use rama_core::Context;
395    /// # use std::sync::Arc;
396    /// # #[derive(Debug, Clone)]
397    /// struct State {
398    ///     mul: i32,
399    /// }
400    /// let mut ctx = Context::with_state(Arc::new(State{ mul: 2 }));
401    /// ctx.insert(true);
402    /// let value: &i32 = ctx.get_or_insert_with_ctx(|ctx| ctx.state().mul * 21);
403    /// assert_eq!(*value, 42);
404    /// let existing_value: &mut i32 = ctx.get_or_insert_default();
405    /// assert_eq!(*existing_value, 42);
406    /// ```
407    pub fn get_or_insert_with_ctx<T: Clone + Send + Sync + 'static>(
408        &mut self,
409        f: impl FnOnce(&Self) -> T,
410    ) -> &mut T {
411        if self.extensions.contains::<T>() {
412            // NOTE: once <https://github.com/rust-lang/polonius>
413            // is merged into rust we can use directly `if let Some(v) = self.extensions.get_mut()`,
414            // until then we need this work around.
415            return self.extensions.get_mut().unwrap();
416        }
417        let v = f(self);
418        self.extensions.insert(v);
419        self.extensions.get_mut().unwrap()
420    }
421
422    /// Try to insert a value into the map computed from `f` into if it is [`None`],
423    /// then returns an exclusive reference to the contained value.
424    ///
425    /// Similar to [`Self::get_or_insert_with_ctx`] but fallible.
426    pub fn get_or_try_insert_with_ctx<T: Clone + Send + Sync + 'static, E>(
427        &mut self,
428        f: impl FnOnce(&Self) -> Result<T, E>,
429    ) -> Result<&mut T, E> {
430        if self.extensions.contains::<T>() {
431            // NOTE: once <https://github.com/rust-lang/polonius>
432            // is merged into rust we can use directly `if let Some(v) = self.extensions.get_mut()`,
433            // until then we need this work around.
434            return Ok(self.extensions.get_mut().unwrap());
435        }
436        let v = f(self)?;
437        self.extensions.insert(v);
438        Ok(self.extensions.get_mut().unwrap())
439    }
440
441    /// Inserts a value into the map computed from converting `U` into `T if no value was already inserted is [`None`],
442    /// then returns an exclusive reference to the contained value.
443    pub fn get_or_insert_from<T, U>(&mut self, src: U) -> &mut T
444    where
445        T: Clone + Send + Sync + 'static,
446        U: Into<T>,
447    {
448        self.extensions.get_or_insert_from(src)
449    }
450
451    /// Retrieves a value of type `T` from the context.
452    ///
453    /// If the value does not exist, the provided value is inserted
454    /// and an exclusive reference to it is returned.
455    ///
456    /// See [`Context::get`] for more details.
457    ///
458    /// # Example
459    ///
460    /// ```
461    /// # use rama_core::Context;
462    /// let mut ctx = Context::default();
463    /// ctx.insert(5i32);
464    ///
465    /// assert_eq!(*ctx.get_or_insert::<i32>(10), 5);
466    /// assert_eq!(*ctx.get_or_insert::<f64>(2.5), 2.5);
467    /// ```
468    pub fn get_or_insert<T: Send + Sync + Clone + 'static>(&mut self, fallback: T) -> &mut T {
469        self.extensions.get_or_insert(fallback)
470    }
471
472    /// Get an extension or `T`'s [`Default`].
473    ///
474    /// See [`Context::get`] for more details.
475    ///
476    /// # Example
477    ///
478    /// ```
479    /// # use rama_core::Context;
480    /// # let mut ctx = Context::default();
481    /// # ctx.insert(5i32);
482    ///
483    /// assert_eq!(*ctx.get_or_insert_default::<i32>(), 5i32);
484    /// assert_eq!(*ctx.get_or_insert_default::<f64>(), 0f64);
485    /// ```
486    pub fn get_or_insert_default<T: Clone + Default + Send + Sync + 'static>(&mut self) -> &mut T {
487        self.extensions.get_or_insert_default()
488    }
489
490    /// Insert an extension into the [`Context`].
491    ///
492    /// If a extension of this type already existed, it will
493    /// be returned.
494    ///
495    /// See [`Context::get`] for more details regarding extensions.
496    ///
497    /// # Example
498    ///
499    /// ```
500    /// # use rama_core::Context;
501    /// let mut ctx = Context::default();
502    ///
503    /// assert_eq!(ctx.insert(5i32), None);
504    /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
505    ///
506    /// assert_eq!(ctx.insert(4i32), Some(5i32));
507    /// assert_eq!(ctx.get::<i32>(), Some(&4i32));
508    /// ```
509    pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, extension: T) -> Option<T> {
510        self.extensions.insert(extension)
511    }
512
513    /// Insert a type only into this [`Context`], if the extension is `Some(T)`.
514    ///
515    /// See [`Self::insert`] for more information.
516    pub fn maybe_insert<T: Clone + Send + Sync + 'static>(
517        &mut self,
518        extension: Option<T>,
519    ) -> Option<T> {
520        self.extensions.maybe_insert(extension)
521    }
522
523    /// Return the entire dynamic state of the [`Context`] by reference.
524    ///
525    /// Useful only in case you have a function which works with [`Extensions`] rather
526    /// then the [`Context`] itself. In case you want to have access to a specific dynamic state,
527    /// it is more suitable to use [`Context::get`] directly.
528    pub fn extensions(&self) -> &Extensions {
529        &self.extensions
530    }
531
532    /// Return the entire dynamic state of the [`Context`] by mutable reference.
533    ///
534    /// Useful only in case you have a function which works with [`Extensions`] rather
535    /// then the [`Context`] itself. In case you want to have access to a specific dynamic state,
536    /// it is more suitable to use [`Context::get_or_insert`] or [`Context::insert`] directly.
537    ///
538    /// # Rollback
539    ///
540    /// Extensions do not have "rollback" support. In case you are not yet certain if you want to keep
541    /// the to be inserted [`Extensions`], you are better to create a new [`Extensions`] object using
542    /// [`Extensions::default`] and use [`Context::extend`] once you wish to commit the new
543    /// dynamic data into the [`Context`].
544    pub fn extensions_mut(&mut self) -> &mut Extensions {
545        &mut self.extensions
546    }
547
548    /// Extend The [`Context`] [`Extensions`] with another [`Extensions`].
549    ///
550    /// # Example
551    ///
552    /// ```
553    /// # use rama_core::{context::Extensions, Context};
554    /// let mut ctx = Context::default();
555    /// let mut ext = Extensions::default();
556    ///
557    /// ctx.insert(true);
558    /// ext.insert(5i32);
559    /// ctx.extend(ext);
560    ///
561    /// assert_eq!(ctx.get::<bool>(), Some(&true));
562    /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
563    /// ```
564    pub fn extend(&mut self, extensions: Extensions) {
565        self.extensions.extend(extensions);
566    }
567
568    /// Clear the [`Context`] of all inserted [`Extensions`].
569    ///
570    /// # Example
571    ///
572    /// ```
573    /// # use rama_core::Context;
574    /// let mut ctx = Context::default();
575    ///
576    /// ctx.insert(5i32);
577    /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
578    ///
579    /// ctx.clear();
580    /// assert_eq!(ctx.get::<i32>(), None);
581    /// ```
582    pub fn clear(&mut self) {
583        self.extensions.clear();
584    }
585
586    /// Remove an extension from this [`Context`]
587    pub fn remove<T: Clone + Send + Sync + 'static>(&mut self) -> Option<T> {
588        self.extensions.remove()
589    }
590
591    /// Get a reference to the shutdown guard,
592    /// if and only if the context was created within a graceful environment.
593    pub fn guard(&self) -> Option<&ShutdownGuard> {
594        self.executor.guard()
595    }
596}
597
598impl<S: Clone> Context<S> {
599    /// Get a cloned reference to the state.
600    pub fn state_clone(&self) -> S {
601        self.state.clone()
602    }
603}