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 /// Set a new [`Executor`] to the [`Context`].
296 pub fn set_executor(&mut self, exec: Executor) -> &mut Self {
297 self.executor = exec;
298 self
299 }
300
301 /// Set a new [`Executor`] to the [`Context`].
302 #[must_use]
303 pub fn with_executor(mut self, exec: Executor) -> Self {
304 self.executor = exec;
305 self
306 }
307
308 /// Spawn a future on the current executor,
309 /// this is spawned gracefully in case a shutdown guard has been registered.
310 pub fn spawn<F>(&self, future: F) -> JoinHandle<F::Output>
311 where
312 F: Future<Output: Send + 'static> + Send + 'static,
313 {
314 self.executor.spawn_task(future)
315 }
316
317 /// Returns true if the `Context` contains the given type.
318 ///
319 /// Use [`Self::get`] in case you want to have access to the type
320 /// or [`Self::get_mut`] if you also need to mutate it.
321 pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
322 self.extensions.contains::<T>()
323 }
324
325 /// Get a shared reference to an extension.
326 ///
327 /// An extension is a type that implements `Send + Sync + 'static`,
328 /// and can be used to inject dynamic data into the [`Context`].
329 ///
330 /// Extensions are specific to this [`Context`]. It will be cloned when the [`Context`] is cloned,
331 /// but extensions inserted using [`Context::insert`] will not be visible the
332 /// original [`Context`], or any other cloned [`Context`].
333 ///
334 /// Please use the statically typed state (see [`Context::state`]) for data that is shared between
335 /// all context clones.
336 ///
337 /// # Example
338 ///
339 /// ```
340 /// # use rama_core::Context;
341 /// # let mut ctx = Context::default();
342 /// # ctx.insert(5i32);
343 /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
344 /// ```
345 pub fn get<T: Send + Sync + 'static>(&self) -> Option<&T> {
346 self.extensions.get::<T>()
347 }
348
349 /// Get an exclusive reference to an extension.
350 ///
351 /// An extension is a type that implements `Send + Sync + 'static`,
352 /// and can be used to inject dynamic data into the [`Context`].
353 ///
354 /// Extensions are specific to this [`Context`]. It will be cloned when the [`Context`] is cloned,
355 /// but extensions inserted using [`Context::insert`] will not be visible the
356 /// original [`Context`], or any other cloned [`Context`].
357 ///
358 /// Please use the statically typed state (see [`Context::state`]) for data that is shared between
359 /// all context clones.
360 ///
361 /// # Example
362 ///
363 /// ```
364 /// # use rama_core::Context;
365 /// # let mut ctx = Context::default();
366 /// # ctx.insert(5i32);
367 /// let x = ctx.get_mut::<i32>().unwrap();
368 /// assert_eq!(*x, 5i32);
369 /// *x = 8;
370 /// assert_eq!(*x, 8i32);
371 /// assert_eq!(ctx.get::<i32>(), Some(&8i32));
372 /// ```
373 pub fn get_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
374 self.extensions.get_mut::<T>()
375 }
376
377 /// Inserts a value into the map computed from `f` into if it is [`None`],
378 /// then returns an exclusive reference to the contained value.
379 ///
380 /// # Example
381 ///
382 /// ```
383 /// # use rama_core::Context;
384 /// let mut ctx = Context::default();
385 /// let value: &i32 = ctx.get_or_insert_with(|| 42);
386 /// assert_eq!(*value, 42);
387 /// let existing_value: &mut i32 = ctx.get_or_insert_with(|| 0);
388 /// assert_eq!(*existing_value, 42);
389 /// ```
390 pub fn get_or_insert_with<T: Clone + Send + Sync + 'static>(
391 &mut self,
392 f: impl FnOnce() -> T,
393 ) -> &mut T {
394 self.extensions.get_or_insert_with(f)
395 }
396
397 /// Inserts a value into the map computed from `f` into if it is [`None`],
398 /// then returns an exclusive reference to the contained value.
399 ///
400 /// Use the cheaper [`Self::get_or_insert_with`] in case you do not need access to
401 /// the [`Context`] for the creation of `T`, as this function comes with
402 /// an extra cost.
403 ///
404 /// # Example
405 ///
406 /// ```
407 /// # use rama_core::Context;
408 /// # use std::sync::Arc;
409 /// # #[derive(Debug, Clone)]
410 /// struct State {
411 /// mul: i32,
412 /// }
413 /// let mut ctx = Context::with_state(Arc::new(State{ mul: 2 }));
414 /// ctx.insert(true);
415 /// let value: &i32 = ctx.get_or_insert_with_ctx(|ctx| ctx.state().mul * 21);
416 /// assert_eq!(*value, 42);
417 /// let existing_value: &mut i32 = ctx.get_or_insert_default();
418 /// assert_eq!(*existing_value, 42);
419 /// ```
420 pub fn get_or_insert_with_ctx<T: Clone + Send + Sync + 'static>(
421 &mut self,
422 f: impl FnOnce(&Self) -> T,
423 ) -> &mut T {
424 if self.extensions.contains::<T>() {
425 // NOTE: once <https://github.com/rust-lang/polonius>
426 // is merged into rust we can use directly `if let Some(v) = self.extensions.get_mut()`,
427 // until then we need this work around.
428 return self.extensions.get_mut().unwrap();
429 }
430 let v = f(self);
431 self.extensions.insert(v);
432 self.extensions.get_mut().unwrap()
433 }
434
435 /// Try to insert a value into the map computed from `f` into if it is [`None`],
436 /// then returns an exclusive reference to the contained value.
437 ///
438 /// Similar to [`Self::get_or_insert_with_ctx`] but fallible.
439 pub fn get_or_try_insert_with_ctx<T: Clone + Send + Sync + 'static, E>(
440 &mut self,
441 f: impl FnOnce(&Self) -> Result<T, E>,
442 ) -> Result<&mut T, E> {
443 if self.extensions.contains::<T>() {
444 // NOTE: once <https://github.com/rust-lang/polonius>
445 // is merged into rust we can use directly `if let Some(v) = self.extensions.get_mut()`,
446 // until then we need this work around.
447 return Ok(self.extensions.get_mut().unwrap());
448 }
449 let v = f(self)?;
450 self.extensions.insert(v);
451 Ok(self.extensions.get_mut().unwrap())
452 }
453
454 /// Inserts a value into the map computed from converting `U` into `T if no value was already inserted is [`None`],
455 /// then returns an exclusive reference to the contained value.
456 pub fn get_or_insert_from<T, U>(&mut self, src: U) -> &mut T
457 where
458 T: Clone + Send + Sync + 'static,
459 U: Into<T>,
460 {
461 self.extensions.get_or_insert_from(src)
462 }
463
464 /// Retrieves a value of type `T` from the context.
465 ///
466 /// If the value does not exist, the provided value is inserted
467 /// and an exclusive reference to it is returned.
468 ///
469 /// See [`Context::get`] for more details.
470 ///
471 /// # Example
472 ///
473 /// ```
474 /// # use rama_core::Context;
475 /// let mut ctx = Context::default();
476 /// ctx.insert(5i32);
477 ///
478 /// assert_eq!(*ctx.get_or_insert::<i32>(10), 5);
479 /// assert_eq!(*ctx.get_or_insert::<f64>(2.5), 2.5);
480 /// ```
481 pub fn get_or_insert<T: Send + Sync + Clone + 'static>(&mut self, fallback: T) -> &mut T {
482 self.extensions.get_or_insert(fallback)
483 }
484
485 /// Get an extension or `T`'s [`Default`].
486 ///
487 /// See [`Context::get`] for more details.
488 ///
489 /// # Example
490 ///
491 /// ```
492 /// # use rama_core::Context;
493 /// # let mut ctx = Context::default();
494 /// # ctx.insert(5i32);
495 ///
496 /// assert_eq!(*ctx.get_or_insert_default::<i32>(), 5i32);
497 /// assert_eq!(*ctx.get_or_insert_default::<f64>(), 0f64);
498 /// ```
499 pub fn get_or_insert_default<T: Clone + Default + Send + Sync + 'static>(&mut self) -> &mut T {
500 self.extensions.get_or_insert_default()
501 }
502
503 /// Insert an extension into the [`Context`].
504 ///
505 /// If a extension of this type already existed, it will
506 /// be returned.
507 ///
508 /// See [`Context::get`] for more details regarding extensions.
509 ///
510 /// # Example
511 ///
512 /// ```
513 /// # use rama_core::Context;
514 /// let mut ctx = Context::default();
515 ///
516 /// assert_eq!(ctx.insert(5i32), None);
517 /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
518 ///
519 /// assert_eq!(ctx.insert(4i32), Some(5i32));
520 /// assert_eq!(ctx.get::<i32>(), Some(&4i32));
521 /// ```
522 pub fn insert<T: Clone + Send + Sync + 'static>(&mut self, extension: T) -> Option<T> {
523 self.extensions.insert(extension)
524 }
525
526 /// Insert a type only into this [`Context`], if the extension is `Some(T)`.
527 ///
528 /// See [`Self::insert`] for more information.
529 pub fn maybe_insert<T: Clone + Send + Sync + 'static>(
530 &mut self,
531 extension: Option<T>,
532 ) -> Option<T> {
533 self.extensions.maybe_insert(extension)
534 }
535
536 /// Return the entire dynamic state of the [`Context`] by reference.
537 ///
538 /// Useful only in case you have a function which works with [`Extensions`] rather
539 /// then the [`Context`] itself. In case you want to have access to a specific dynamic state,
540 /// it is more suitable to use [`Context::get`] directly.
541 pub fn extensions(&self) -> &Extensions {
542 &self.extensions
543 }
544
545 /// Return the entire dynamic state of the [`Context`] by mutable reference.
546 ///
547 /// Useful only in case you have a function which works with [`Extensions`] rather
548 /// then the [`Context`] itself. In case you want to have access to a specific dynamic state,
549 /// it is more suitable to use [`Context::get_or_insert`] or [`Context::insert`] directly.
550 ///
551 /// # Rollback
552 ///
553 /// Extensions do not have "rollback" support. In case you are not yet certain if you want to keep
554 /// the to be inserted [`Extensions`], you are better to create a new [`Extensions`] object using
555 /// [`Extensions::default`] and use [`Context::extend`] once you wish to commit the new
556 /// dynamic data into the [`Context`].
557 pub fn extensions_mut(&mut self) -> &mut Extensions {
558 &mut self.extensions
559 }
560
561 /// Extend The [`Context`] [`Extensions`] with another [`Extensions`].
562 ///
563 /// # Example
564 ///
565 /// ```
566 /// # use rama_core::{context::Extensions, Context};
567 /// let mut ctx = Context::default();
568 /// let mut ext = Extensions::default();
569 ///
570 /// ctx.insert(true);
571 /// ext.insert(5i32);
572 /// ctx.extend(ext);
573 ///
574 /// assert_eq!(ctx.get::<bool>(), Some(&true));
575 /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
576 /// ```
577 pub fn extend(&mut self, extensions: Extensions) {
578 self.extensions.extend(extensions);
579 }
580
581 /// Clear the [`Context`] of all inserted [`Extensions`].
582 ///
583 /// # Example
584 ///
585 /// ```
586 /// # use rama_core::Context;
587 /// let mut ctx = Context::default();
588 ///
589 /// ctx.insert(5i32);
590 /// assert_eq!(ctx.get::<i32>(), Some(&5i32));
591 ///
592 /// ctx.clear();
593 /// assert_eq!(ctx.get::<i32>(), None);
594 /// ```
595 pub fn clear(&mut self) {
596 self.extensions.clear();
597 }
598
599 /// Remove an extension from this [`Context`]
600 pub fn remove<T: Clone + Send + Sync + 'static>(&mut self) -> Option<T> {
601 self.extensions.remove()
602 }
603
604 /// Get a reference to the shutdown guard,
605 /// if and only if the context was created within a graceful environment.
606 pub fn guard(&self) -> Option<&ShutdownGuard> {
607 self.executor.guard()
608 }
609}
610
611impl<S: Clone> Context<S> {
612 /// Get a cloned reference to the state.
613 pub fn state_clone(&self) -> S {
614 self.state.clone()
615 }
616}