1 use std::ops::Deref; 2 use std::sync::Arc; 3 4 use actix_http::error::{Error, ErrorInternalServerError}; 5 use actix_http::Extensions; 6 use futures::future::{err, ok, Ready}; 7 8 use crate::dev::Payload; 9 use crate::extract::FromRequest; 10 use crate::request::HttpRequest; 11 12 /// Application data factory 13 pub(crate) trait DataFactory { create(&self, extensions: &mut Extensions) -> bool14 fn create(&self, extensions: &mut Extensions) -> bool; 15 } 16 17 /// Application data. 18 /// 19 /// Application data is an arbitrary data attached to the app. 20 /// Application data is available to all routes and could be added 21 /// during application configuration process 22 /// with `App::data()` method. 23 /// 24 /// Application data could be accessed by using `Data<T>` 25 /// extractor where `T` is data type. 26 /// 27 /// **Note**: http server accepts an application factory rather than 28 /// an application instance. Http server constructs an application 29 /// instance for each thread, thus application data must be constructed 30 /// multiple times. If you want to share data between different 31 /// threads, a shareable object should be used, e.g. `Send + Sync`. Application 32 /// data does not need to be `Send` or `Sync`. Internally `Data` type 33 /// uses `Arc`. if your data implements `Send` + `Sync` traits you can 34 /// use `web::Data::new()` and avoid double `Arc`. 35 /// 36 /// If route data is not set for a handler, using `Data<T>` extractor would 37 /// cause *Internal Server Error* response. 38 /// 39 /// ```rust 40 /// use std::sync::Mutex; 41 /// use actix_web::{web, App, HttpResponse, Responder}; 42 /// 43 /// struct MyData { 44 /// counter: usize, 45 /// } 46 /// 47 /// /// Use `Data<T>` extractor to access data in handler. 48 /// async fn index(data: web::Data<Mutex<MyData>>) -> impl Responder { 49 /// let mut data = data.lock().unwrap(); 50 /// data.counter += 1; 51 /// HttpResponse::Ok() 52 /// } 53 /// 54 /// fn main() { 55 /// let data = web::Data::new(Mutex::new(MyData{ counter: 0 })); 56 /// 57 /// let app = App::new() 58 /// // Store `MyData` in application storage. 59 /// .app_data(data.clone()) 60 /// .service( 61 /// web::resource("/index.html").route( 62 /// web::get().to(index))); 63 /// } 64 /// ``` 65 #[derive(Debug)] 66 pub struct Data<T>(Arc<T>); 67 68 impl<T> Data<T> { 69 /// Create new `Data` instance. 70 /// 71 /// Internally `Data` type uses `Arc`. if your data implements 72 /// `Send` + `Sync` traits you can use `web::Data::new()` and 73 /// avoid double `Arc`. new(state: T) -> Data<T>74 pub fn new(state: T) -> Data<T> { 75 Data(Arc::new(state)) 76 } 77 78 /// Get reference to inner app data. get_ref(&self) -> &T79 pub fn get_ref(&self) -> &T { 80 self.0.as_ref() 81 } 82 83 /// Convert to the internal Arc<T> into_inner(self) -> Arc<T>84 pub fn into_inner(self) -> Arc<T> { 85 self.0 86 } 87 } 88 89 impl<T> Deref for Data<T> { 90 type Target = Arc<T>; 91 deref(&self) -> &Arc<T>92 fn deref(&self) -> &Arc<T> { 93 &self.0 94 } 95 } 96 97 impl<T> Clone for Data<T> { clone(&self) -> Data<T>98 fn clone(&self) -> Data<T> { 99 Data(self.0.clone()) 100 } 101 } 102 103 impl<T: 'static> FromRequest for Data<T> { 104 type Config = (); 105 type Error = Error; 106 type Future = Ready<Result<Self, Error>>; 107 108 #[inline] from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future109 fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { 110 if let Some(st) = req.app_data::<Data<T>>() { 111 ok(st.clone()) 112 } else { 113 log::debug!( 114 "Failed to construct App-level Data extractor. \ 115 Request path: {:?}", 116 req.path() 117 ); 118 err(ErrorInternalServerError( 119 "App data is not configured, to configure use App::data()", 120 )) 121 } 122 } 123 } 124 125 impl<T: 'static> DataFactory for Data<T> { create(&self, extensions: &mut Extensions) -> bool126 fn create(&self, extensions: &mut Extensions) -> bool { 127 if !extensions.contains::<Data<T>>() { 128 extensions.insert(Data(self.0.clone())); 129 true 130 } else { 131 false 132 } 133 } 134 } 135 136 #[cfg(test)] 137 mod tests { 138 use actix_service::Service; 139 use std::sync::atomic::{AtomicUsize, Ordering}; 140 141 use super::*; 142 use crate::http::StatusCode; 143 use crate::test::{self, init_service, TestRequest}; 144 use crate::{web, App, HttpResponse}; 145 146 #[actix_rt::test] test_data_extractor()147 async fn test_data_extractor() { 148 let mut srv = init_service(App::new().data("TEST".to_string()).service( 149 web::resource("/").to(|data: web::Data<String>| { 150 assert_eq!(data.to_lowercase(), "test"); 151 HttpResponse::Ok() 152 }), 153 )) 154 .await; 155 156 let req = TestRequest::default().to_request(); 157 let resp = srv.call(req).await.unwrap(); 158 assert_eq!(resp.status(), StatusCode::OK); 159 160 let mut srv = 161 init_service(App::new().data(10u32).service( 162 web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), 163 )) 164 .await; 165 let req = TestRequest::default().to_request(); 166 let resp = srv.call(req).await.unwrap(); 167 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 168 } 169 170 #[actix_rt::test] test_app_data_extractor()171 async fn test_app_data_extractor() { 172 let mut srv = 173 init_service(App::new().app_data(Data::new(10usize)).service( 174 web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), 175 )) 176 .await; 177 178 let req = TestRequest::default().to_request(); 179 let resp = srv.call(req).await.unwrap(); 180 assert_eq!(resp.status(), StatusCode::OK); 181 182 let mut srv = 183 init_service(App::new().app_data(Data::new(10u32)).service( 184 web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), 185 )) 186 .await; 187 let req = TestRequest::default().to_request(); 188 let resp = srv.call(req).await.unwrap(); 189 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 190 } 191 192 #[actix_rt::test] test_route_data_extractor()193 async fn test_route_data_extractor() { 194 let mut srv = 195 init_service(App::new().service(web::resource("/").data(10usize).route( 196 web::get().to(|data: web::Data<usize>| { 197 let _ = data.clone(); 198 HttpResponse::Ok() 199 }), 200 ))) 201 .await; 202 203 let req = TestRequest::default().to_request(); 204 let resp = srv.call(req).await.unwrap(); 205 assert_eq!(resp.status(), StatusCode::OK); 206 207 // different type 208 let mut srv = init_service( 209 App::new().service( 210 web::resource("/") 211 .data(10u32) 212 .route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())), 213 ), 214 ) 215 .await; 216 let req = TestRequest::default().to_request(); 217 let resp = srv.call(req).await.unwrap(); 218 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); 219 } 220 221 #[actix_rt::test] test_override_data()222 async fn test_override_data() { 223 let mut srv = init_service(App::new().data(1usize).service( 224 web::resource("/").data(10usize).route(web::get().to( 225 |data: web::Data<usize>| { 226 assert_eq!(**data, 10); 227 let _ = data.clone(); 228 HttpResponse::Ok() 229 }, 230 )), 231 )) 232 .await; 233 234 let req = TestRequest::default().to_request(); 235 let resp = srv.call(req).await.unwrap(); 236 assert_eq!(resp.status(), StatusCode::OK); 237 } 238 239 #[actix_rt::test] test_data_drop()240 async fn test_data_drop() { 241 struct TestData(Arc<AtomicUsize>); 242 243 impl TestData { 244 fn new(inner: Arc<AtomicUsize>) -> Self { 245 let _ = inner.fetch_add(1, Ordering::SeqCst); 246 Self(inner) 247 } 248 } 249 250 impl Clone for TestData { 251 fn clone(&self) -> Self { 252 let inner = self.0.clone(); 253 let _ = inner.fetch_add(1, Ordering::SeqCst); 254 Self(inner) 255 } 256 } 257 258 impl Drop for TestData { 259 fn drop(&mut self) { 260 let _ = self.0.fetch_sub(1, Ordering::SeqCst); 261 } 262 } 263 264 let num = Arc::new(AtomicUsize::new(0)); 265 let data = TestData::new(num.clone()); 266 assert_eq!(num.load(Ordering::SeqCst), 1); 267 268 let srv = test::start(move || { 269 let data = data.clone(); 270 271 App::new() 272 .data(data) 273 .service(web::resource("/").to(|_data: Data<TestData>| async { "ok" })) 274 }); 275 276 assert!(srv.get("/").send().await.unwrap().status().is_success()); 277 srv.stop().await; 278 279 assert_eq!(num.load(Ordering::SeqCst), 0); 280 } 281 } 282