mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 07:53:00 +01:00
Allow to construct Data instances to avoid double Arc for Send + Sync types.
This commit is contained in:
parent
b51b5b763c
commit
29a841529f
@ -1,5 +1,10 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Allow to construct `Data` instances to avoid double `Arc` for `Send + Sync` types.
|
||||||
|
|
||||||
|
|
||||||
## [1.0.0-beta.2] - 2019-04-24
|
## [1.0.0-beta.2] - 2019-04-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
10
src/app.rs
10
src/app.rs
@ -95,8 +95,8 @@ where
|
|||||||
/// web::get().to(index)));
|
/// web::get().to(index)));
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn data<S: 'static>(mut self, data: S) -> Self {
|
pub fn data<U: Into<Data<U>> + 'static>(mut self, data: U) -> Self {
|
||||||
self.data.push(Box::new(Data::new(data)));
|
self.data.push(Box::new(data.into()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,14 +301,14 @@ where
|
|||||||
/// lifecycle (request -> response), modifying request/response as
|
/// lifecycle (request -> response), modifying request/response as
|
||||||
/// necessary, across all requests managed by the *Application*.
|
/// necessary, across all requests managed by the *Application*.
|
||||||
///
|
///
|
||||||
/// Use middleware when you need to read or modify *every* request or
|
/// Use middleware when you need to read or modify *every* request or
|
||||||
/// response in some way.
|
/// response in some way.
|
||||||
///
|
///
|
||||||
/// Notice that the keyword for registering middleware is `wrap`. As you
|
/// Notice that the keyword for registering middleware is `wrap`. As you
|
||||||
/// register middleware using `wrap` in the App builder, imagine wrapping
|
/// register middleware using `wrap` in the App builder, imagine wrapping
|
||||||
/// layers around an inner App. The first middleware layer exposed to a
|
/// layers around an inner App. The first middleware layer exposed to a
|
||||||
/// Request is the outermost layer-- the *last* registered in
|
/// Request is the outermost layer-- the *last* registered in
|
||||||
/// the builder chain. Consequently, the *first* middleware registered
|
/// the builder chain. Consequently, the *first* middleware registered
|
||||||
/// in the builder chain is the *last* to execute during request processing.
|
/// in the builder chain is the *last* to execute during request processing.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
31
src/data.rs
31
src/data.rs
@ -33,29 +33,33 @@ pub(crate) trait DataFactoryResult {
|
|||||||
/// instance for each thread, thus application data must be constructed
|
/// instance for each thread, thus application data must be constructed
|
||||||
/// multiple times. If you want to share data between different
|
/// multiple times. If you want to share data between different
|
||||||
/// threads, a shareable object should be used, e.g. `Send + Sync`. Application
|
/// threads, a shareable object should be used, e.g. `Send + Sync`. Application
|
||||||
/// data does not need to be `Send` or `Sync`. Internally `Data` instance
|
/// data does not need to be `Send` or `Sync`. Internally `Data` type
|
||||||
/// uses `Arc`.
|
/// uses `Arc`. if your data implements `Send` + `Sync` traits you can
|
||||||
|
/// use `web::Data::new()` and avoid double `Arc`.
|
||||||
///
|
///
|
||||||
/// If route data is not set for a handler, using `Data<T>` extractor would
|
/// If route data is not set for a handler, using `Data<T>` extractor would
|
||||||
/// cause *Internal Server Error* response.
|
/// cause *Internal Server Error* response.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::cell::Cell;
|
/// use std::sync::Mutex;
|
||||||
/// use actix_web::{web, App};
|
/// use actix_web::{web, App};
|
||||||
///
|
///
|
||||||
/// struct MyData {
|
/// struct MyData {
|
||||||
/// counter: Cell<usize>,
|
/// counter: usize,
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// /// Use `Data<T>` extractor to access data in handler.
|
/// /// Use `Data<T>` extractor to access data in handler.
|
||||||
/// fn index(data: web::Data<MyData>) {
|
/// fn index(data: web::Data<Mutex<MyData>>) {
|
||||||
/// data.counter.set(data.counter.get() + 1);
|
/// let mut data = data.lock().unwrap();
|
||||||
|
/// data.counter += 1;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
|
/// let data = web::Data::new(Mutex::new(MyData{ counter: 0 }));
|
||||||
|
///
|
||||||
/// let app = App::new()
|
/// let app = App::new()
|
||||||
/// // Store `MyData` in application storage.
|
/// // Store `MyData` in application storage.
|
||||||
/// .data(MyData{ counter: Cell::new(0) })
|
/// .data(data.clone())
|
||||||
/// .service(
|
/// .service(
|
||||||
/// web::resource("/index.html").route(
|
/// web::resource("/index.html").route(
|
||||||
/// web::get().to(index)));
|
/// web::get().to(index)));
|
||||||
@ -65,7 +69,12 @@ pub(crate) trait DataFactoryResult {
|
|||||||
pub struct Data<T>(Arc<T>);
|
pub struct Data<T>(Arc<T>);
|
||||||
|
|
||||||
impl<T> Data<T> {
|
impl<T> Data<T> {
|
||||||
pub(crate) fn new(state: T) -> Data<T> {
|
/// Create new `Data` instance.
|
||||||
|
///
|
||||||
|
/// Internally `Data` type uses `Arc`. if your data implements
|
||||||
|
/// `Send` + `Sync` traits you can use `web::Data::new()` and
|
||||||
|
/// avoid double `Arc`.
|
||||||
|
pub fn new(state: T) -> Data<T> {
|
||||||
Data(Arc::new(state))
|
Data(Arc::new(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +98,12 @@ impl<T> Clone for Data<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for Data<T> {
|
||||||
|
fn from(data: T) -> Self {
|
||||||
|
Data::new(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: 'static> FromRequest for Data<T> {
|
impl<T: 'static> FromRequest for Data<T> {
|
||||||
type Config = ();
|
type Config = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
@ -555,7 +555,7 @@ mod tests {
|
|||||||
web::resource("/index.html")
|
web::resource("/index.html")
|
||||||
.route(web::put().to(|| HttpResponse::Ok().body("put!")))
|
.route(web::put().to(|| HttpResponse::Ok().body("put!")))
|
||||||
.route(web::patch().to(|| HttpResponse::Ok().body("patch!")))
|
.route(web::patch().to(|| HttpResponse::Ok().body("patch!")))
|
||||||
.route(web::delete().to(|| HttpResponse::Ok().body("delete!")))
|
.route(web::delete().to(|| HttpResponse::Ok().body("delete!"))),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -575,9 +575,7 @@ mod tests {
|
|||||||
let result = read_response(&mut app, patch_req);
|
let result = read_response(&mut app, patch_req);
|
||||||
assert_eq!(result, Bytes::from_static(b"patch!"));
|
assert_eq!(result, Bytes::from_static(b"patch!"));
|
||||||
|
|
||||||
let delete_req = TestRequest::delete()
|
let delete_req = TestRequest::delete().uri("/index.html").to_request();
|
||||||
.uri("/index.html")
|
|
||||||
.to_request();
|
|
||||||
let result = read_response(&mut app, delete_req);
|
let result = read_response(&mut app, delete_req);
|
||||||
assert_eq!(result, Bytes::from_static(b"delete!"));
|
assert_eq!(result, Bytes::from_static(b"delete!"));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user