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