mirror of https://github.com/fafhrd91/actix-web
Merge 1e6b528e4b
into 37799df978
This commit is contained in:
commit
2764c867ce
|
@ -106,6 +106,7 @@ smallvec = "1.6.1"
|
||||||
socket2 = "0.4.0"
|
socket2 = "0.4.0"
|
||||||
time = { version = "0.3", default-features = false, features = ["formatting"] }
|
time = { version = "0.3", default-features = false, features = ["formatting"] }
|
||||||
url = "2.1"
|
url = "2.1"
|
||||||
|
tokio = { version = "1.7.1", features = ["sync"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-files = "0.6.0-beta.15"
|
actix-files = "0.6.0-beta.15"
|
||||||
|
|
81
src/data.rs
81
src/data.rs
|
@ -1,9 +1,11 @@
|
||||||
use std::{any::type_name, ops::Deref, sync::Arc};
|
use std::{any::type_name, cell::Cell, fmt, future::Future, ops::Deref, rc::Rc, sync::Arc};
|
||||||
|
|
||||||
use actix_http::Extensions;
|
use actix_http::Extensions;
|
||||||
use actix_utils::future::{err, ok, Ready};
|
use actix_utils::future::{err, ok, Ready};
|
||||||
use futures_core::future::LocalBoxFuture;
|
use futures_core::future::LocalBoxFuture;
|
||||||
|
use futures_util::FutureExt;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use tokio::sync::OnceCell;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dev::Payload, error::ErrorInternalServerError, extract::FromRequest, request::HttpRequest,
|
dev::Payload, error::ErrorInternalServerError, extract::FromRequest, request::HttpRequest,
|
||||||
|
@ -175,6 +177,83 @@ impl<T: ?Sized + 'static> DataFactory for Data<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A lazy extractor for thread-local data.
|
||||||
|
pub struct LazyData<T> {
|
||||||
|
inner: Rc<LazyDataInner<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LazyDataInner<T> {
|
||||||
|
cell: OnceCell<T>,
|
||||||
|
fut: Cell<Option<LocalBoxFuture<'static, T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Clone for LazyData<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
inner: self.inner.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Debug> fmt::Debug for LazyData<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Lazy")
|
||||||
|
.field("cell", &self.inner.cell)
|
||||||
|
.field("fut", &"..")
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> LazyData<T> {
|
||||||
|
pub fn new<F, Fut>(init: F) -> LazyData<T>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Fut,
|
||||||
|
Fut: Future<Output = T> + 'static,
|
||||||
|
{
|
||||||
|
Self {
|
||||||
|
inner: Rc::new(LazyDataInner {
|
||||||
|
cell: OnceCell::new(),
|
||||||
|
fut: Cell::new(Some(init().boxed_local())),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get(&self) -> &T {
|
||||||
|
self.inner
|
||||||
|
.cell
|
||||||
|
.get_or_init(|| async move {
|
||||||
|
match self.inner.fut.take() {
|
||||||
|
Some(fut) => fut.await,
|
||||||
|
None => panic!("LazyData instance has previously been poisoned"),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: 'static> FromRequest for LazyData<T> {
|
||||||
|
type Config = ();
|
||||||
|
type Error = Error;
|
||||||
|
type Future = Ready<Result<Self, Error>>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
|
||||||
|
if let Some(lazy) = req.app_data::<LazyData<T>>() {
|
||||||
|
ok(lazy.clone())
|
||||||
|
} else {
|
||||||
|
log::debug!(
|
||||||
|
"Failed to construct App-level LazyData extractor. \
|
||||||
|
Request path: {:?} (type: {})",
|
||||||
|
req.path(),
|
||||||
|
type_name::<T>(),
|
||||||
|
);
|
||||||
|
err(ErrorInternalServerError(
|
||||||
|
"App data is not configured, to configure use App::data()",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use crate::config::ServiceConfig;
|
pub use crate::config::ServiceConfig;
|
||||||
pub use crate::data::Data;
|
pub use crate::data::{Data, LazyData};
|
||||||
pub use crate::request::HttpRequest;
|
pub use crate::request::HttpRequest;
|
||||||
pub use crate::request_data::ReqData;
|
pub use crate::request_data::ReqData;
|
||||||
pub use crate::response::HttpResponse;
|
pub use crate::response::HttpResponse;
|
||||||
|
|
Loading…
Reference in New Issue