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