mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into 1384
This commit is contained in:
commit
507c0beca2
11
CHANGES.md
11
CHANGES.md
|
@ -4,12 +4,21 @@
|
|||
|
||||
### Changed
|
||||
|
||||
* Resources and Scopes can now access non-overridden data types set on App (or containing scopes) when setting their own data. [#1486]
|
||||
|
||||
## [3.0.0-alpha.2] - 2020-05-08
|
||||
|
||||
### Changed
|
||||
|
||||
* `{Resource,Scope}::default_service(f)` handlers now support app data extraction. [#1452]
|
||||
* Implement `std::error::Error` for our custom errors [#1422]
|
||||
* NormalizePath middleware now appends trailing / so that routes of form /example/ respond to /example requests.
|
||||
* NormalizePath middleware now appends trailing / so that routes of form /example/ respond to /example requests. [#1433]
|
||||
* Remove the `failure` feature and support.
|
||||
|
||||
[#1422]: https://github.com/actix/actix-web/pull/1422
|
||||
[#1433]: https://github.com/actix/actix-web/pull/1433
|
||||
[#1452]: https://github.com/actix/actix-web/pull/1452
|
||||
[#1486]: https://github.com/actix/actix-web/pull/1486
|
||||
|
||||
## [3.0.0-alpha.1] - 2020-03-11
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "actix-web"
|
||||
version = "3.0.0-alpha.1"
|
||||
version = "3.0.0-alpha.2"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust."
|
||||
readme = "README.md"
|
||||
|
@ -81,7 +81,7 @@ actix-threadpool = "0.3.1"
|
|||
actix-tls = "2.0.0-alpha.1"
|
||||
|
||||
actix-web-codegen = "0.2.0"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
awc = { version = "2.0.0-alpha.1", default-features = false }
|
||||
|
||||
bytes = "0.5.3"
|
||||
|
@ -101,6 +101,7 @@ time = { version = "0.2.7", default-features = false, features = ["std"] }
|
|||
url = "2.1"
|
||||
open-ssl = { version="0.10", package = "openssl", optional = true }
|
||||
rust-tls = { version = "0.17.0", package = "rustls", optional = true }
|
||||
tinyvec = { version = "0.3", features = ["alloc"] }
|
||||
|
||||
[dev-dependencies]
|
||||
actix = "0.10.0-alpha.1"
|
||||
|
|
|
@ -18,8 +18,8 @@ name = "actix_files"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "3.0.0-alpha.1", default-features = false }
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-web = { version = "3.0.0-alpha.2", default-features = false }
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
actix-service = "1.0.1"
|
||||
bitflags = "1"
|
||||
bytes = "0.5.3"
|
||||
|
@ -33,4 +33,4 @@ v_htmlescape = "0.4"
|
|||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0"
|
||||
actix-web = { version = "3.0.0-alpha.1", features=["openssl"] }
|
||||
actix-web = { version = "3.0.0-alpha.2", features = ["openssl"] }
|
||||
|
|
|
@ -23,7 +23,7 @@ actix-codec = "0.2.0"
|
|||
actix-service = "1.0.1"
|
||||
actix-router = "0.2.1"
|
||||
actix-rt = "1.0.0"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
|
||||
bytes = "0.5.3"
|
||||
futures = "0.3.1"
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
# Changes
|
||||
|
||||
## [Unreleased]
|
||||
## [2.0.0-alpha.3] - 2020-05-08
|
||||
|
||||
### Fixed
|
||||
|
||||
* Correct spelling of ConnectError::Unresolved [#1487]
|
||||
* Fix a mistake in the encoding of websocket continuation messages wherein
|
||||
Item::FirstText and Item::FirstBinary are each encoded as the other.
|
||||
|
||||
### Changed
|
||||
|
||||
* Implement `std::error::Error` for our custom errors [#1422]
|
||||
* Remove `failure` support for `ResponseError` since that crate
|
||||
will be deprecated in the near future.
|
||||
* Fix a mistake in the encoding of websocket continuation messages wherein
|
||||
Item::FirstText and Item::FirstBinary are each encoded as the other.
|
||||
|
||||
[#1422]: https://github.com/actix/actix-web/pull/1422
|
||||
[#1487]: https://github.com/actix/actix-web/pull/1487
|
||||
|
||||
## [2.0.0-alpha.2] - 2020-03-07
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "actix-http"
|
||||
version = "2.0.0-alpha.2"
|
||||
version = "2.0.0-alpha.3"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix http primitives"
|
||||
readme = "README.md"
|
||||
|
@ -42,7 +42,7 @@ actors = ["actix"]
|
|||
[dependencies]
|
||||
actix-service = "1.0.5"
|
||||
actix-codec = "0.2.0"
|
||||
actix-connect = "2.0.0-alpha.2"
|
||||
actix-connect = "2.0.0-alpha.3"
|
||||
actix-utils = "1.0.6"
|
||||
actix-rt = "1.0.0"
|
||||
actix-threadpool = "0.3.1"
|
||||
|
|
|
@ -48,7 +48,7 @@ pub enum ConnectError {
|
|||
|
||||
/// Unresolved host name
|
||||
#[display(fmt = "Connector received `Connect` method with unresolved host")]
|
||||
Unresolverd,
|
||||
Unresolved,
|
||||
|
||||
/// Connection io error
|
||||
#[display(fmt = "{}", _0)]
|
||||
|
@ -63,7 +63,7 @@ impl From<actix_connect::ConnectError> for ConnectError {
|
|||
actix_connect::ConnectError::Resolver(e) => ConnectError::Resolver(e),
|
||||
actix_connect::ConnectError::NoRecords => ConnectError::NoRecords,
|
||||
actix_connect::ConnectError::InvalidInput => panic!(),
|
||||
actix_connect::ConnectError::Unresolverd => ConnectError::Unresolverd,
|
||||
actix_connect::ConnectError::Unresolved => ConnectError::Unresolved,
|
||||
actix_connect::ConnectError::Io(e) => ConnectError::Io(e),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ where
|
|||
let key = if let Some(authority) = req.uri.authority() {
|
||||
authority.clone().into()
|
||||
} else {
|
||||
return Err(ConnectError::Unresolverd);
|
||||
return Err(ConnectError::Unresolved);
|
||||
};
|
||||
|
||||
// acquire connection
|
||||
|
@ -195,7 +195,7 @@ where
|
|||
if let Some(i) = self.inner.take() {
|
||||
let mut inner = i.as_ref().borrow_mut();
|
||||
inner.release_waiter(&self.key, self.token);
|
||||
inner.check_availibility();
|
||||
inner.check_availability();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ where
|
|||
if let Some(i) = self.inner.take() {
|
||||
let mut inner = i.as_ref().borrow_mut();
|
||||
inner.release();
|
||||
inner.check_availibility();
|
||||
inner.check_availability();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ where
|
|||
created,
|
||||
used: Instant::now(),
|
||||
});
|
||||
self.check_availibility();
|
||||
self.check_availability();
|
||||
}
|
||||
|
||||
fn release_close(&mut self, io: ConnectionType<Io>) {
|
||||
|
@ -369,10 +369,10 @@ where
|
|||
actix_rt::spawn(CloseConnection::new(io, timeout))
|
||||
}
|
||||
}
|
||||
self.check_availibility();
|
||||
self.check_availability();
|
||||
}
|
||||
|
||||
fn check_availibility(&self) {
|
||||
fn check_availability(&self) {
|
||||
if !self.waiters_queue.is_empty() && self.acquired < self.config.limit {
|
||||
self.waker.wake();
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ where
|
|||
if let Some(inner) = self.project().inner.take() {
|
||||
let mut inner = inner.as_ref().borrow_mut();
|
||||
inner.release();
|
||||
inner.check_availibility();
|
||||
inner.check_availability();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ name = "actix_multipart"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "3.0.0-alpha.1", default-features = false }
|
||||
actix-web = { version = "3.0.0-alpha.2", default-features = false }
|
||||
actix-service = "1.0.1"
|
||||
actix-utils = "1.0.3"
|
||||
bytes = "0.5.3"
|
||||
|
@ -29,4 +29,4 @@ twoway = "0.2"
|
|||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
# Changes
|
||||
|
||||
# [3.0.0-alpha.1] - 2020-05-08
|
||||
|
||||
* Update the actix-web dependency to 3.0.0-alpha.1
|
||||
* Update the actix dependency to 0.10.0-alpha.2
|
||||
* Update the actix-http dependency to 2.0.0-alpha.3
|
||||
|
||||
## [2.0.0] - 2019-12-20
|
||||
|
||||
* Release
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "actix-web-actors"
|
||||
version = "2.0.0"
|
||||
version = "3.0.0-alpha.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Actix actors support for actix web framework."
|
||||
readme = "README.md"
|
||||
|
@ -16,9 +16,9 @@ name = "actix_web_actors"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.10.0-alpha.1"
|
||||
actix-web = "3.0.0-alpha.1"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix = "0.10.0-alpha.2"
|
||||
actix-web = "3.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
actix-codec = "0.2.0"
|
||||
bytes = "0.5.2"
|
||||
futures = "0.3.1"
|
||||
|
@ -26,4 +26,4 @@ pin-project = "0.4.6"
|
|||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0"
|
||||
env_logger = "0.6"
|
||||
env_logger = "0.7"
|
||||
|
|
|
@ -174,7 +174,7 @@ where
|
|||
|
||||
// frames
|
||||
if let Some(data) = self.fut.ctx().stream.pop_front() {
|
||||
Poll::Ready(data.map(|b| Ok(b)))
|
||||
Poll::Ready(data.map(Ok))
|
||||
} else if self.fut.alive() {
|
||||
Poll::Pending
|
||||
} else {
|
||||
|
|
|
@ -18,5 +18,5 @@ proc-macro2 = "^1"
|
|||
|
||||
[dev-dependencies]
|
||||
actix-rt = "1.0.0"
|
||||
actix-web = "3.0.0-alpha.1"
|
||||
actix-web = "3.0.0-alpha.2"
|
||||
futures = "0.3.1"
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
//!
|
||||
//! - `"path"` - Raw literal string with path for which to register handle. Mandatory.
|
||||
//! - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
||||
//! - `wrap="Middleware"` - Registers a resource middleware.
|
||||
//!
|
||||
//! ## Notes
|
||||
//!
|
||||
|
@ -54,6 +55,7 @@ use proc_macro::TokenStream;
|
|||
///
|
||||
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
||||
/// - `guard="function_name"` - Registers function as guard using `actix_web::guard::fn_guard`
|
||||
/// - `wrap="Middleware"` - Registers a resource middleware.
|
||||
#[proc_macro_attribute]
|
||||
pub fn get(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
route::generate(args, input, route::GuardType::Get)
|
||||
|
|
|
@ -56,12 +56,14 @@ impl ToTokens for GuardType {
|
|||
struct Args {
|
||||
path: syn::LitStr,
|
||||
guards: Vec<Ident>,
|
||||
wrappers: Vec<syn::Type>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
fn new(args: AttributeArgs) -> syn::Result<Self> {
|
||||
let mut path = None;
|
||||
let mut guards = Vec::new();
|
||||
let mut wrappers = Vec::new();
|
||||
for arg in args {
|
||||
match arg {
|
||||
NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
|
||||
|
@ -85,10 +87,19 @@ impl Args {
|
|||
"Attribute guard expects literal string!",
|
||||
));
|
||||
}
|
||||
} else if nv.path.is_ident("wrap") {
|
||||
if let syn::Lit::Str(lit) = nv.lit {
|
||||
wrappers.push(lit.parse()?);
|
||||
} else {
|
||||
return Err(syn::Error::new_spanned(
|
||||
nv.lit,
|
||||
"Attribute wrap expects type",
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(syn::Error::new_spanned(
|
||||
nv.path,
|
||||
"Unknown attribute key is specified. Allowed: guard.",
|
||||
"Unknown attribute key is specified. Allowed: guard and wrap",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +111,7 @@ impl Args {
|
|||
Ok(Args {
|
||||
path: path.unwrap(),
|
||||
guards,
|
||||
wrappers,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -184,7 +196,7 @@ impl ToTokens for Route {
|
|||
name,
|
||||
guard,
|
||||
ast,
|
||||
args: Args { path, guards },
|
||||
args: Args { path, guards, wrappers },
|
||||
resource_type,
|
||||
} = self;
|
||||
let resource_name = name.to_string();
|
||||
|
@ -199,6 +211,7 @@ impl ToTokens for Route {
|
|||
.name(#resource_name)
|
||||
.guard(actix_web::guard::#guard())
|
||||
#(.guard(actix_web::guard::fn_guard(#guards)))*
|
||||
#(.wrap(#wrappers))*
|
||||
.#resource_type(#name);
|
||||
|
||||
actix_web::dev::HttpServiceFactory::register(__resource, __config)
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use actix_web::{http, test, web::Path, App, HttpResponse, Responder};
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_web::{http, test, web::Path, App, HttpResponse, Responder, Error};
|
||||
use actix_web::dev::{Service, Transform, ServiceRequest, ServiceResponse};
|
||||
use actix_web_codegen::{connect, delete, get, head, options, patch, post, put, trace};
|
||||
use futures::{future, Future};
|
||||
use actix_web::http::header::{HeaderName, HeaderValue};
|
||||
|
||||
// Make sure that we can name function as 'config'
|
||||
#[get("/config")]
|
||||
|
@ -73,6 +78,65 @@ async fn get_param_test(_: Path<String>) -> impl Responder {
|
|||
HttpResponse::Ok()
|
||||
}
|
||||
|
||||
pub struct ChangeStatusCode;
|
||||
|
||||
impl<S, B> Transform<S> for ChangeStatusCode
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
type Transform = ChangeStatusCodeMiddleware<S>;
|
||||
type Future = future::Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
future::ok(ChangeStatusCodeMiddleware { service })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChangeStatusCodeMiddleware<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for ChangeStatusCodeMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.service.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, req: ServiceRequest) -> Self::Future {
|
||||
|
||||
let fut = self.service.call(req);
|
||||
|
||||
Box::pin(async move {
|
||||
let mut res = fut.await?;
|
||||
let headers = res.headers_mut();
|
||||
let header_name = HeaderName::from_lowercase(b"custom-header").unwrap();
|
||||
let header_value = HeaderValue::from_str("hello").unwrap();
|
||||
headers.insert(header_name, header_value);
|
||||
Ok(res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/test/wrap", wrap = "ChangeStatusCode")]
|
||||
async fn get_wrap(_: Path<String>) -> impl Responder {
|
||||
HttpResponse::Ok()
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_params() {
|
||||
let srv = test::start(|| {
|
||||
|
@ -155,3 +219,15 @@ async fn test_auto_async() {
|
|||
let response = request.send().await.unwrap();
|
||||
assert!(response.status().is_success());
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_wrap() {
|
||||
let srv = test::start(|| {
|
||||
App::new()
|
||||
.service(get_wrap)
|
||||
});
|
||||
|
||||
let request = srv.request(http::Method::GET, srv.url("/test/wrap"));
|
||||
let response = request.send().await.unwrap();
|
||||
assert!(response.headers().contains_key("custom-header"));
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ compress = ["actix-http/compress"]
|
|||
[dependencies]
|
||||
actix-codec = "0.2.0"
|
||||
actix-service = "1.0.1"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
actix-rt = "1.0.0"
|
||||
|
||||
base64 = "0.11"
|
||||
|
@ -50,17 +50,17 @@ rand = "0.7"
|
|||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_urlencoded = "0.6.1"
|
||||
open-ssl = { version="0.10", package="openssl", optional = true }
|
||||
rust-tls = { version = "0.17.0", package="rustls", optional = true, features = ["dangerous_configuration"] }
|
||||
open-ssl = { version = "0.10", package = "openssl", optional = true }
|
||||
rust-tls = { version = "0.17.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-connect = { version = "2.0.0-alpha.2", features=["openssl"] }
|
||||
actix-web = { version = "3.0.0-alpha.1", features=["openssl"] }
|
||||
actix-http = { version = "2.0.0-alpha.2", features=["openssl"] }
|
||||
actix-http-test = { version = "1.0.0", features=["openssl"] }
|
||||
actix-connect = { version = "2.0.0-alpha.2", features = ["openssl"] }
|
||||
actix-web = { version = "3.0.0-alpha.2", features = ["openssl"] }
|
||||
actix-http = { version = "2.0.0-alpha.3", features = ["openssl"] }
|
||||
actix-http-test = { version = "1.0.0", features = ["openssl"] }
|
||||
actix-utils = "1.0.3"
|
||||
actix-server = "1.0.0"
|
||||
actix-tls = { version = "2.0.0-alpha.1", features=["openssl", "rustls"] }
|
||||
actix-tls = { version = "2.0.0-alpha.1", features = ["openssl", "rustls"] }
|
||||
brotli2 = "0.3.2"
|
||||
flate2 = "1.0.13"
|
||||
futures = "0.3.1"
|
||||
|
|
|
@ -245,7 +245,7 @@ where
|
|||
inner.path.reset();
|
||||
inner.head = head;
|
||||
inner.payload = payload;
|
||||
inner.app_data = self.data.clone();
|
||||
inner.app_data.push(self.data.clone());
|
||||
req
|
||||
} else {
|
||||
HttpRequest::new(
|
||||
|
|
|
@ -6,6 +6,7 @@ use actix_http::http::{HeaderMap, Method, Uri, Version};
|
|||
use actix_http::{Error, Extensions, HttpMessage, Message, Payload, RequestHead};
|
||||
use actix_router::{Path, Url};
|
||||
use futures::future::{ok, Ready};
|
||||
use tinyvec::TinyVec;
|
||||
|
||||
use crate::config::AppConfig;
|
||||
use crate::error::UrlGenerationError;
|
||||
|
@ -21,7 +22,7 @@ pub(crate) struct HttpRequestInner {
|
|||
pub(crate) head: Message<RequestHead>,
|
||||
pub(crate) path: Path<Url>,
|
||||
pub(crate) payload: Payload,
|
||||
pub(crate) app_data: Rc<Extensions>,
|
||||
pub(crate) app_data: TinyVec<[Rc<Extensions>; 4]>,
|
||||
rmap: Rc<ResourceMap>,
|
||||
config: AppConfig,
|
||||
pool: &'static HttpRequestPool,
|
||||
|
@ -38,13 +39,16 @@ impl HttpRequest {
|
|||
app_data: Rc<Extensions>,
|
||||
pool: &'static HttpRequestPool,
|
||||
) -> HttpRequest {
|
||||
let mut data = TinyVec::<[Rc<Extensions>; 4]>::new();
|
||||
data.push(app_data);
|
||||
|
||||
HttpRequest(Rc::new(HttpRequestInner {
|
||||
head,
|
||||
path,
|
||||
payload,
|
||||
rmap,
|
||||
config,
|
||||
app_data,
|
||||
app_data: data,
|
||||
pool,
|
||||
}))
|
||||
}
|
||||
|
@ -215,12 +219,14 @@ impl HttpRequest {
|
|||
/// let opt_t = req.app_data::<Data<T>>();
|
||||
/// ```
|
||||
pub fn app_data<T: 'static>(&self) -> Option<&T> {
|
||||
if let Some(st) = self.0.app_data.get::<T>() {
|
||||
Some(&st)
|
||||
} else {
|
||||
None
|
||||
for container in self.0.app_data.iter().rev() {
|
||||
if let Some(data) = container.get::<T>() {
|
||||
return Some(data);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl HttpMessage for HttpRequest {
|
||||
|
@ -342,10 +348,13 @@ impl HttpRequestPool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_service::Service;
|
||||
use bytes::Bytes;
|
||||
|
||||
use super::*;
|
||||
use crate::dev::{ResourceDef, ResourceMap};
|
||||
use crate::http::{header, StatusCode};
|
||||
use crate::test::{call_service, init_service, TestRequest};
|
||||
use crate::test::{call_service, init_service, read_body, TestRequest};
|
||||
use crate::{web, App, HttpResponse};
|
||||
|
||||
#[test]
|
||||
|
@ -494,6 +503,68 @@ mod tests {
|
|||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_cascading_data() {
|
||||
#[allow(dead_code)]
|
||||
fn echo_usize(req: HttpRequest) -> HttpResponse {
|
||||
let num = req.app_data::<usize>().unwrap();
|
||||
HttpResponse::Ok().body(num.to_string())
|
||||
}
|
||||
|
||||
let mut srv = init_service(
|
||||
App::new()
|
||||
.app_data(88usize)
|
||||
.service(web::resource("/").route(web::get().to(echo_usize)))
|
||||
.service(
|
||||
web::resource("/one")
|
||||
.app_data(1u32)
|
||||
.route(web::get().to(echo_usize)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::get().uri("/").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"88"));
|
||||
|
||||
let req = TestRequest::get().uri("/one").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"88"));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_overwrite_data() {
|
||||
#[allow(dead_code)]
|
||||
fn echo_usize(req: HttpRequest) -> HttpResponse {
|
||||
let num = req.app_data::<usize>().unwrap();
|
||||
HttpResponse::Ok().body(num.to_string())
|
||||
}
|
||||
|
||||
let mut srv = init_service(
|
||||
App::new()
|
||||
.app_data(88usize)
|
||||
.service(web::resource("/").route(web::get().to(echo_usize)))
|
||||
.service(
|
||||
web::resource("/one")
|
||||
.app_data(1usize)
|
||||
.route(web::get().to(echo_usize)),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::get().uri("/").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"88"));
|
||||
|
||||
let req = TestRequest::get().uri("/one").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"1"));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_extensions_dropped() {
|
||||
struct Tracker {
|
||||
|
|
|
@ -198,9 +198,7 @@ where
|
|||
|
||||
/// Add resource data.
|
||||
///
|
||||
/// If used, this method will create a new data context used for extracting
|
||||
/// from requests. Data added here is *not* merged with data added on App
|
||||
/// or containing scopes.
|
||||
/// Data of different types from parent contexts will still be accessible.
|
||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||
if self.data.is_none() {
|
||||
self.data = Some(Extensions::new());
|
||||
|
@ -539,14 +537,14 @@ impl Service for ResourceService {
|
|||
for route in self.routes.iter_mut() {
|
||||
if route.check(&mut req) {
|
||||
if let Some(ref data) = self.data {
|
||||
req.set_data_container(data.clone());
|
||||
req.add_data_container(data.clone());
|
||||
}
|
||||
return Either::Right(route.call(req));
|
||||
}
|
||||
}
|
||||
if let Some(ref mut default) = self.default {
|
||||
if let Some(ref data) = self.data {
|
||||
req.set_data_container(data.clone());
|
||||
req.add_data_container(data.clone());
|
||||
}
|
||||
Either::Right(default.call(req))
|
||||
} else {
|
||||
|
@ -590,14 +588,13 @@ mod tests {
|
|||
|
||||
use actix_rt::time::delay_for;
|
||||
use actix_service::Service;
|
||||
use bytes::Bytes;
|
||||
use futures::future::ok;
|
||||
|
||||
use crate::http::{header, HeaderValue, Method, StatusCode};
|
||||
use crate::middleware::DefaultHeaders;
|
||||
use crate::service::ServiceRequest;
|
||||
use crate::test::{call_service, init_service, read_body, TestRequest};
|
||||
use crate::{guard, web, App, Error, HttpRequest, HttpResponse};
|
||||
use crate::test::{call_service, init_service, TestRequest};
|
||||
use crate::{guard, web, App, Error, HttpResponse};
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_middleware() {
|
||||
|
@ -623,79 +620,6 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_overwritten_data() {
|
||||
#[allow(dead_code)]
|
||||
fn echo_usize(req: HttpRequest) -> HttpResponse {
|
||||
let num = req.app_data::<usize>().unwrap();
|
||||
HttpResponse::Ok().body(format!("{}", num))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn echo_u32(req: HttpRequest) -> HttpResponse {
|
||||
let num = req.app_data::<u32>().unwrap();
|
||||
HttpResponse::Ok().body(format!("{}", num))
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn echo_both(req: HttpRequest) -> HttpResponse {
|
||||
let num = req.app_data::<usize>().unwrap();
|
||||
let num2 = req.app_data::<u32>().unwrap();
|
||||
HttpResponse::Ok().body(format!("{}-{}", num, num2))
|
||||
}
|
||||
|
||||
let mut srv = init_service(
|
||||
App::new()
|
||||
.app_data(88usize)
|
||||
.service(web::resource("/").route(web::get().to(echo_usize)))
|
||||
.service(
|
||||
web::resource("/one")
|
||||
.app_data(1usize)
|
||||
.route(web::get().to(echo_usize)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/two")
|
||||
.app_data(2usize)
|
||||
.route(web::get().to(echo_usize)),
|
||||
)
|
||||
.service(
|
||||
web::resource("/three")
|
||||
.app_data(3u32)
|
||||
// this doesnt work because app_data "overrides" the
|
||||
// entire data field potentially passed down
|
||||
// .route(web::get().to(echo_both)),
|
||||
.route(web::get().to(echo_u32)),
|
||||
)
|
||||
.service(web::resource("/eight").route(web::get().to(echo_usize))),
|
||||
)
|
||||
.await;
|
||||
|
||||
let req = TestRequest::get().uri("/").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"88"));
|
||||
|
||||
let req = TestRequest::get().uri("/one").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"1"));
|
||||
|
||||
let req = TestRequest::get().uri("/two").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"2"));
|
||||
|
||||
// let req = TestRequest::get().uri("/three").to_request();
|
||||
// let resp = srv.call(req).await.unwrap();
|
||||
// let body = read_body(resp).await;
|
||||
// assert_eq!(body, Bytes::from_static(b"88-3"));
|
||||
|
||||
let req = TestRequest::get().uri("/eight").to_request();
|
||||
let resp = srv.call(req).await.unwrap();
|
||||
let body = read_body(resp).await;
|
||||
assert_eq!(body, Bytes::from_static(b"88"));
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn test_middleware_fn() {
|
||||
let mut srv = init_service(
|
||||
|
|
|
@ -153,9 +153,7 @@ where
|
|||
|
||||
/// Add scope data.
|
||||
///
|
||||
/// If used, this method will create a new data context used for extracting
|
||||
/// from requests. Data added here is *not* merged with data added on App
|
||||
/// or containing scopes.
|
||||
/// Data of different types from parent contexts will still be accessible.
|
||||
pub fn app_data<U: 'static>(mut self, data: U) -> Self {
|
||||
if self.data.is_none() {
|
||||
self.data = Some(Extensions::new());
|
||||
|
@ -624,12 +622,12 @@ impl Service for ScopeService {
|
|||
|
||||
if let Some((srv, _info)) = res {
|
||||
if let Some(ref data) = self.data {
|
||||
req.set_data_container(data.clone());
|
||||
req.add_data_container(data.clone());
|
||||
}
|
||||
Either::Left(srv.call(req))
|
||||
} else if let Some(ref mut default) = self.default {
|
||||
if let Some(ref data) = self.data {
|
||||
req.set_data_container(data.clone());
|
||||
req.add_data_container(data.clone());
|
||||
}
|
||||
Either::Left(default.call(req))
|
||||
} else {
|
||||
|
|
|
@ -217,22 +217,27 @@ impl ServiceRequest {
|
|||
/// Get an application data stored with `App::data()` method during
|
||||
/// application configuration.
|
||||
pub fn app_data<T: 'static>(&self) -> Option<Data<T>> {
|
||||
if let Some(st) = (self.0).0.app_data.get::<Data<T>>() {
|
||||
Some(st.clone())
|
||||
} else {
|
||||
None
|
||||
for container in (self.0).0.app_data.iter().rev() {
|
||||
if let Some(data) = container.get::<Data<T>>() {
|
||||
return Some(Data::clone(&data));
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Set request payload.
|
||||
pub fn set_payload(&mut self, payload: Payload) {
|
||||
Rc::get_mut(&mut (self.0).0).unwrap().payload = payload;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Set new app data container
|
||||
pub fn set_data_container(&mut self, extensions: Rc<Extensions>) {
|
||||
Rc::get_mut(&mut (self.0).0).unwrap().app_data = extensions;
|
||||
/// Add app data container to request's resolution set.
|
||||
pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
|
||||
Rc::get_mut(&mut (self.0).0)
|
||||
.unwrap()
|
||||
.app_data
|
||||
.push(extensions);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,7 +583,6 @@ mod tests {
|
|||
let resp = srv.call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), http::StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fmt_debug() {
|
||||
let req = TestRequest::get()
|
||||
|
|
|
@ -52,8 +52,8 @@ sha1 = "0.6"
|
|||
slab = "0.4"
|
||||
serde_urlencoded = "0.6.1"
|
||||
time = { version = "0.2.7", default-features = false, features = ["std"] }
|
||||
open-ssl = { version="0.10", package = "openssl", optional = true }
|
||||
open-ssl = { version = "0.10", package = "openssl", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-web = "3.0.0-alpha.1"
|
||||
actix-http = "2.0.0-alpha.2"
|
||||
actix-web = "3.0.0-alpha.2"
|
||||
actix-http = "2.0.0-alpha.3"
|
||||
|
|
Loading…
Reference in New Issue