1 use std::{any::type_name, ops::Deref, sync::Arc}; 2 3 use actix_http::Extensions; 4 use actix_utils::future::{err, ok, Ready}; 5 use futures_core::future::LocalBoxFuture; 6 use serde::Serialize; 7 8 use crate::{ 9 dev::Payload, error::ErrorInternalServerError, extract::FromRequest, request::HttpRequest, 10 Error, 11 }; 12 13 /// Data factory. 14 pub(crate) trait DataFactory { 15 /// Return true if modifications were made to extensions map. create(&self, extensions: &mut Extensions) -> bool16 fn create(&self, extensions: &mut Extensions) -> bool; 17 } 18 19 pub(crate) type FnDataFactory = 20 Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>; 21 22 /// Application data. 23 /// 24 /// Application level data is a piece of arbitrary data attached to the app, scope, or resource. 25 /// Application data is available to all routes and can be added during the application 26 /// configuration process via `App::data()`. 27 /// 28 /// Application data can be accessed by using `Data<T>` extractor where `T` is data type. 29 /// 30 /// **Note**: HTTP server accepts an application factory rather than an application instance. HTTP 31 /// server constructs an application instance for each thread, thus application data must be 32 /// constructed multiple times. If you want to share data between different threads, a shareable 33 /// object should be used, e.g. `Send + Sync`. Application data does not need to be `Send` 34 /// or `Sync`. Internally `Data` uses `Arc`. 35 /// 36 /// If route data is not set for a handler, using `Data<T>` extractor would cause *Internal 37 /// Server Error* response. 38 /// 39 // TODO: document `dyn T` functionality through converting an Arc 40 // TODO: note equivalence of req.app_data<Data<T>> and Data<T> extractor 41 // TODO: note that data must be inserted using Data<T> in order to extract it 42 /// 43 /// # Examples 44 /// ``` 45 /// use std::sync::Mutex; 46 /// use actix_web::{web, App, HttpResponse, Responder}; 47 /// 48 /// struct MyData { 49 /// counter: usize, 50 /// } 51 /// 52 /// /// Use the `Data<T>` extractor to access data in a handler. 53 /// async fn index(data: web::Data<Mutex<MyData>>) -> impl Responder { 54 /// let mut data = data.lock().unwrap(); 55 /// data.counter += 1; 56 /// HttpResponse::Ok() 57 /// } 58 /// 59 /// fn main() { 60 /// let data = web::Data::new(Mutex::new(MyData{ counter: 0 })); 61 /// 62 /// let app = App::new() 63 /// // Store `MyData` in application storage. 64 /// .app_data(data.clone()) 65 /// .service( 66 /// web::resource("/index.html").route( 67 /// web::get().to(index))); 68 /// } 69 /// ``` 70 #[derive(Debug)] 71 pub struct Data<T: ?Sized>(Arc<T>); 72 73 impl<T> Data<T> { 74 /// Create new `Data` instance. new(state: T) -> Data<T>75 pub fn new(state: T) -> Data<T> { 76 Data(Arc::new(state)) 77 } 78 79 /// Get reference to inner app data. get_ref(&self) -> &T80 pub fn get_ref(&self) -> &T { 81 self.0.as_ref() 82 } 83 84 /// Convert to the internal Arc<T> into_inner(self) -> Arc<T>85 pub fn into_inner(self) -> Arc<T> { 86 self.0 87 } 88 } 89 90 impl<T: ?Sized> Deref for Data<T> { 91 type Target = Arc<T>; 92 deref(&self) -> &Arc<T>93 fn deref(&self) -> &Arc<T> { 94 &self.0 95 } 96 } 97 98 impl<T: ?Sized> Clone for Data<T> { clone(&self) -> Data<T>99 fn clone(&self) -> Data<T> { 100 Data(self.0.clone()) 101 } 102 } 103 104 impl<T: ?Sized> From<Arc<T>> for Data<T> { from(arc: Arc<T>) -> Self105 fn from(arc: Arc<T>) -> Self { 106 Data(arc) 107 } 108 } 109 110 impl<T> Serialize for Data<T> 111 where 112 T: Serialize, 113 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,114 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 115 where 116 S: serde::Serializer, 117 { 118 self.0.serialize(serializer) 119 } 120 } 121 122 impl<T: ?Sized + 'static> FromRequest for Data<T> { 123 type Config = (); 124 type Error = Error; 125 type Future = Ready<Result<Self, Error>>; 126 127 #[inline] from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future128 fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { 129 if let Some(st) = req.app_data::<Data<T>>() { 130 ok(st.clone()) 131 } else { 132 log::debug!( 133 "Failed to construct App-level Data extractor. \ 134 Request path: {:?} (type: {})", 135 req.path(), 136 type_name::<T>(), 137 ); 138 err(ErrorInternalServerError( 139 "App data is not configured, to configure use App::data()", 140 )) 141 } 142 } 143 } 144 145 impl<T: ?Sized + 'static> DataFactory for Data<T> { create(&self, extensions: &mut Extensions) -> bool146 fn create(&self, extensions: &mut Extensions) -> bool { 147 extensions.insert(Data(self.0.clone())); 148 true 149 } 150 } 151 152 #[cfg(test)] 153 mod tests { 154 use super::*; 155 use crate::{ 156 dev::Service, 157 http::StatusCode, 158 test::{init_service, TestRequest}, 159 web, App, HttpResponse, 160 }; 161 162 // allow deprecated App::data 163 #[allow(deprecated)] 164 #[actix_rt::test] test_data_extractor()165 async fn test_data_extractor() { 166 let srv = init_service(App::new().data("TEST".to_string()).service( 167 web::resource("/").to(|data: web::Data<String>| { 168 assert_eq!(data.to_lowercase(), "test"); 169 HttpResponse::Ok() 170 }), 171 )) 172 .await; 173 174 let req = TestRequest::default().to_request(); 175 let resp = srv.call(req).await.unwrap(); 176 assert_eq!(resp.status(), StatusCode::OK); 177 178 let srv = init_service( 179 App::new() 180 .data(10u32) 181 .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())), 182 ) 183 .await; 184 let req = TestRequest::default().to_request(); 185 let resp = srv.call(req).await.unwrap(); 186 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 187 188 let srv = init_service( 189 App::new() 190 .data(10u32) 191 .data(13u32) 192 .app_data(12u64) 193 .app_data(15u64) 194 .default_service(web::to(|n: web::Data<u32>, req: HttpRequest| { 195 // in each case, the latter insertion should be preserved 196 assert_eq!(*req.app_data::<u64>().unwrap(), 15); 197 assert_eq!(*n.into_inner(), 13); 198 HttpResponse::Ok() 199 })), 200 ) 201 .await; 202 let req = TestRequest::default().to_request(); 203 let resp = srv.call(req).await.unwrap(); 204 assert_eq!(resp.status(), StatusCode::OK); 205 } 206 207 #[actix_rt::test] test_app_data_extractor()208 async fn test_app_data_extractor() { 209 let srv = init_service( 210 App::new() 211 .app_data(Data::new(10usize)) 212 .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())), 213 ) 214 .await; 215 216 let req = TestRequest::default().to_request(); 217 let resp = srv.call(req).await.unwrap(); 218 assert_eq!(resp.status(), StatusCode::OK); 219 220 let srv = init_service( 221 App::new() 222 .app_data(Data::new(10u32)) 223 .service(web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok())), 224 ) 225 .await; 226 let req = TestRequest::default().to_request(); 227 let resp = srv.call(req).await.unwrap(); 228 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 229 } 230 231 // allow deprecated App::data 232 #[allow(deprecated)] 233 #[actix_rt::test] test_route_data_extractor()234 async fn test_route_data_extractor() { 235 let srv = init_service( 236 App::new().service( 237 web::resource("/") 238 .data(10usize) 239 .route(web::get().to(|_data: web::Data<usize>| HttpResponse::Ok())), 240 ), 241 ) 242 .await; 243 244 let req = TestRequest::default().to_request(); 245 let resp = srv.call(req).await.unwrap(); 246 assert_eq!(resp.status(), StatusCode::OK); 247 248 // different type 249 let srv = init_service( 250 App::new().service( 251 web::resource("/") 252 .data(10u32) 253 .route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())), 254 ), 255 ) 256 .await; 257 let req = TestRequest::default().to_request(); 258 let resp = srv.call(req).await.unwrap(); 259 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 260 } 261 262 // allow deprecated App::data 263 #[allow(deprecated)] 264 #[actix_rt::test] test_override_data()265 async fn test_override_data() { 266 let srv = 267 init_service(App::new().data(1usize).service( 268 web::resource("/").data(10usize).route(web::get().to( 269 |data: web::Data<usize>| { 270 assert_eq!(**data, 10); 271 HttpResponse::Ok() 272 }, 273 )), 274 )) 275 .await; 276 277 let req = TestRequest::default().to_request(); 278 let resp = srv.call(req).await.unwrap(); 279 assert_eq!(resp.status(), StatusCode::OK); 280 } 281 282 #[actix_rt::test] test_data_from_arc()283 async fn test_data_from_arc() { 284 let data_new = Data::new(String::from("test-123")); 285 let data_from_arc = Data::from(Arc::new(String::from("test-123"))); 286 assert_eq!(data_new.0, data_from_arc.0) 287 } 288 289 #[actix_rt::test] test_data_from_dyn_arc()290 async fn test_data_from_dyn_arc() { 291 trait TestTrait { 292 fn get_num(&self) -> i32; 293 } 294 struct A {} 295 impl TestTrait for A { 296 fn get_num(&self) -> i32 { 297 42 298 } 299 } 300 // This works when Sized is required 301 let dyn_arc_box: Arc<Box<dyn TestTrait>> = Arc::new(Box::new(A {})); 302 let data_arc_box = Data::from(dyn_arc_box); 303 // This works when Data Sized Bound is removed 304 let dyn_arc: Arc<dyn TestTrait> = Arc::new(A {}); 305 let data_arc = Data::from(dyn_arc); 306 assert_eq!(data_arc_box.get_num(), data_arc.get_num()) 307 } 308 } 309