1 use std::ops::Deref; 2 3 use crate::Rocket; 4 use crate::request::{self, FromRequest, Request}; 5 use crate::outcome::Outcome; 6 use crate::http::Status; 7 8 /// Request guard to retrieve managed state. 9 /// 10 /// This type can be used as a request guard to retrieve the state Rocket is 11 /// managing for some type `T`. This allows for the sharing of state across any 12 /// number of handlers. A value for the given type must previously have been 13 /// registered to be managed by Rocket via 14 /// [`Rocket::manage()`]. The type being managed must be 15 /// thread safe and sendable across thread boundaries. In other words, it must 16 /// implement [`Send`] + [`Sync`] + `'static`. 17 /// 18 /// # Example 19 /// 20 /// Imagine you have some configuration struct of the type `MyConfig` that you'd 21 /// like to initialize at start-up and later access it in several handlers. The 22 /// following example does just this: 23 /// 24 /// ```rust 25 /// # #![feature(proc_macro_hygiene)] 26 /// # #[macro_use] extern crate rocket; 27 /// use rocket::State; 28 /// 29 /// // In a real application, this would likely be more complex. 30 /// struct MyConfig { 31 /// user_val: String 32 /// } 33 /// 34 /// #[get("/")] 35 /// fn index(state: State<MyConfig>) -> String { 36 /// format!("The config value is: {}", state.user_val) 37 /// } 38 /// 39 /// #[get("/raw")] 40 /// fn raw_config_value<'r>(state: State<'r, MyConfig>) -> &'r str { 41 /// // use `inner()` to get a lifetime longer than `deref` gives us 42 /// state.inner().user_val.as_str() 43 /// } 44 /// 45 /// fn main() { 46 /// let config = MyConfig { 47 /// user_val: "user input".to_string() 48 /// }; 49 /// 50 /// # if false { // We don't actually want to launch the server in an example. 51 /// rocket::ignite() 52 /// .mount("/", routes![index, raw_config_value]) 53 /// .manage(config) 54 /// .launch(); 55 /// # } 56 /// } 57 /// ``` 58 /// 59 /// # Within Request Guards 60 /// 61 /// Because `State` is itself a request guard, managed state can be retrieved 62 /// from another request guard's implementation. In the following code example, 63 /// `Item` retrieves the `MyConfig` managed state in its [`FromRequest`] 64 /// implementation using the [`Request::guard()`] method. 65 /// 66 /// ```rust 67 /// use rocket::State; 68 /// use rocket::request::{self, Request, FromRequest}; 69 /// 70 /// # struct MyConfig{ user_val: String }; 71 /// struct Item(String); 72 /// 73 /// impl FromRequest<'_, '_> for Item { 74 /// type Error = (); 75 /// 76 /// fn from_request(request: &Request<'_>) -> request::Outcome<Item, ()> { 77 /// request.guard::<State<MyConfig>>() 78 /// .map(|my_config| Item(my_config.user_val.clone())) 79 /// } 80 /// } 81 /// ``` 82 /// 83 /// # Testing with `State` 84 /// 85 /// When unit testing your application, you may find it necessary to manually 86 /// construct a type of `State` to pass to your functions. To do so, use the 87 /// [`State::from()`] static method: 88 /// 89 /// ```rust 90 /// # #![feature(proc_macro_hygiene)] 91 /// # #[macro_use] extern crate rocket; 92 /// use rocket::State; 93 /// 94 /// struct MyManagedState(usize); 95 /// 96 /// #[get("/")] 97 /// fn handler(state: State<MyManagedState>) -> String { 98 /// state.0.to_string() 99 /// } 100 /// 101 /// let rocket = rocket::ignite().manage(MyManagedState(127)); 102 /// let state = State::from(&rocket).expect("managing `MyManagedState`"); 103 /// assert_eq!(handler(state), "127"); 104 /// ``` 105 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] 106 pub struct State<'r, T: Send + Sync + 'static>(&'r T); 107 108 impl<'r, T: Send + Sync + 'static> State<'r, T> { 109 /// Retrieve a borrow to the underlying value with a lifetime of `'r`. 110 /// 111 /// Using this method is typically unnecessary as `State` implements 112 /// [`Deref`] with a [`Deref::Target`] of `T`. This means Rocket will 113 /// automatically coerce a `State<T>` to an `&T` as required. This method 114 /// should only be used when a longer lifetime is required. 115 /// 116 /// # Example 117 /// 118 /// ```rust 119 /// use rocket::State; 120 /// 121 /// struct MyConfig { 122 /// user_val: String 123 /// } 124 /// 125 /// // Use `inner()` to get a lifetime of `'r` 126 /// fn handler1<'r>(config: State<'r, MyConfig>) -> &'r str { 127 /// &config.inner().user_val 128 /// } 129 /// 130 /// // Use the `Deref` implementation which coerces implicitly 131 /// fn handler2(config: State<MyConfig>) -> String { 132 /// config.user_val.clone() 133 /// } 134 /// ``` 135 #[inline(always)] inner(&self) -> &'r T136 pub fn inner(&self) -> &'r T { 137 self.0 138 } 139 140 /// Returns the managed state value in `rocket` for the type `T` if it is 141 /// being managed by `rocket`. Otherwise, returns `None`. 142 /// 143 /// # Example 144 /// 145 /// ```rust 146 /// use rocket::State; 147 /// 148 /// #[derive(Debug, PartialEq)] 149 /// struct Managed(usize); 150 /// 151 /// #[derive(Debug, PartialEq)] 152 /// struct Unmanaged(usize); 153 /// 154 /// let rocket = rocket::ignite().manage(Managed(7)); 155 /// 156 /// let state: Option<State<Managed>> = State::from(&rocket); 157 /// assert_eq!(state.map(|s| s.inner()), Some(&Managed(7))); 158 /// 159 /// let state: Option<State<Unmanaged>> = State::from(&rocket); 160 /// assert_eq!(state, None); 161 /// ``` 162 #[inline(always)] from(rocket: &'r Rocket) -> Option<Self>163 pub fn from(rocket: &'r Rocket) -> Option<Self> { 164 rocket.state.try_get::<T>().map(State) 165 } 166 } 167 168 impl<'r, T: Send + Sync + 'static> FromRequest<'_, 'r> for State<'r, T> { 169 type Error = (); 170 171 #[inline(always)] from_request(req: &Request<'r>) -> request::Outcome<State<'r, T>, ()>172 fn from_request(req: &Request<'r>) -> request::Outcome<State<'r, T>, ()> { 173 match req.state.managed.try_get::<T>() { 174 Some(state) => Outcome::Success(State(state)), 175 None => { 176 error_!("Attempted to retrieve unmanaged state!"); 177 Outcome::Failure((Status::InternalServerError, ())) 178 } 179 } 180 } 181 } 182 183 impl<T: Send + Sync + 'static> Deref for State<'_, T> { 184 type Target = T; 185 186 #[inline(always)] deref(&self) -> &T187 fn deref(&self) -> &T { 188 self.0 189 } 190 } 191