1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-23 23:51:06 +01:00

use actix_rt::test for test setup

This commit is contained in:
Nikolay Kim 2019-11-26 11:25:50 +06:00
parent c1c44a7dd6
commit 4dc31aac93
80 changed files with 6502 additions and 7237 deletions

View File

@ -36,9 +36,12 @@ before_script:
script: script:
- cargo update - cargo update
- cargo check --all --no-default-features - cargo check --all --no-default-features
- cargo test --all-features --all -- --nocapture - |
# - cd actix-http; cargo test --no-default-features --features="rustls" -- --nocapture; cd .. if [[ "$TRAVIS_RUST_VERSION" == "stable" || "$TRAVIS_RUST_VERSION" == "beta" ]]; then
# - cd awc; cargo test --no-default-features --features="rustls" -- --nocapture; cd .. cargo test --all-features --all -- --nocapture
cd actix-http; cargo test --no-default-features --features="rustls" -- --nocapture; cd ..
cd awc; cargo test --no-default-features --features="rustls" -- --nocapture; cd ..
fi
# Upload docs # Upload docs
after_success: after_success:
@ -51,7 +54,7 @@ after_success:
echo "Uploaded documentation" echo "Uploaded documentation"
fi fi
- | - |
if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-11-20" ]]; then if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-11-20" ]]; then
taskset -c 0 cargo tarpaulin --out Xml --all --all-features taskset -c 0 cargo tarpaulin --out Xml --all --all-features
bash <(curl -s https://codecov.io/bash) bash <(curl -s https://codecov.io/bash)
echo "Uploaded code coverage" echo "Uploaded code coverage"

View File

@ -66,7 +66,7 @@ fail = ["actix-http/fail"]
openssl = ["open-ssl", "actix-server/openssl", "awc/openssl"] openssl = ["open-ssl", "actix-server/openssl", "awc/openssl"]
# rustls # rustls
# rustls = ["rust-tls", "actix-server/rustls", "awc/rustls"] rustls = ["rust-tls", "actix-server/rustls", "awc/rustls"]
[dependencies] [dependencies]
actix-codec = "0.2.0-alpha.1" actix-codec = "0.2.0-alpha.1"
@ -110,7 +110,6 @@ actix-http-test = "0.3.0-alpha.1"
rand = "0.7" rand = "0.7"
env_logger = "0.6" env_logger = "0.6"
serde_derive = "1.0" serde_derive = "1.0"
tokio-timer = "0.3.0-alpha.6"
brotli2 = "0.3.2" brotli2 = "0.3.2"
flate2 = "1.0.2" flate2 = "1.0.2"
@ -135,19 +134,9 @@ awc = { path = "awc" }
actix-codec = { git = "https://github.com/actix/actix-net.git" } actix-codec = { git = "https://github.com/actix/actix-net.git" }
actix-connect = { git = "https://github.com/actix/actix-net.git" } actix-connect = { git = "https://github.com/actix/actix-net.git" }
actix-rt = { git = "https://github.com/actix/actix-net.git" } actix-rt = { git = "https://github.com/actix/actix-net.git" }
actix-macros = { git = "https://github.com/actix/actix-net.git" }
actix-server = { git = "https://github.com/actix/actix-net.git" } actix-server = { git = "https://github.com/actix/actix-net.git" }
actix-server-config = { git = "https://github.com/actix/actix-net.git" } actix-server-config = { git = "https://github.com/actix/actix-net.git" }
actix-service = { git = "https://github.com/actix/actix-net.git" } actix-service = { git = "https://github.com/actix/actix-net.git" }
actix-testing = { git = "https://github.com/actix/actix-net.git" } actix-testing = { git = "https://github.com/actix/actix-net.git" }
actix-threadpool = { git = "https://github.com/actix/actix-net.git" }
actix-utils = { git = "https://github.com/actix/actix-net.git" } actix-utils = { git = "https://github.com/actix/actix-net.git" }
# actix-codec = { path = "../actix-net/actix-codec" }
# actix-connect = { path = "../actix-net/actix-connect" }
# actix-rt = { path = "../actix-net/actix-rt" }
# actix-server = { path = "../actix-net/actix-server" }
# actix-server-config = { path = "../actix-net/actix-server-config" }
# actix-service = { path = "../actix-net/actix-service" }
# actix-testing = { path = "../actix-net/actix-testing" }
# actix-threadpool = { path = "../actix-net/actix-threadpool" }
# actix-utils = { path = "../actix-net/actix-utils" }

View File

@ -21,3 +21,6 @@ actix-web = "2.0.0-alpha.1"
actix-service = "1.0.0-alpha.1" actix-service = "1.0.0-alpha.1"
derive_more = "0.99.2" derive_more = "0.99.2"
futures = "0.3.1" futures = "0.3.1"
[dev-dependencies]
actix-rt = "1.0.0-alpha.1"

View File

@ -814,142 +814,136 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use actix_service::{service_fn2, Transform}; use actix_service::{service_fn2, Transform};
use actix_web::test::{self, block_on, TestRequest}; use actix_web::test::{self, TestRequest};
use super::*; use super::*;
#[test] #[actix_rt::test]
#[should_panic(expected = "Credentials are allowed, but the Origin is set to")] #[should_panic(expected = "Credentials are allowed, but the Origin is set to")]
fn cors_validates_illegal_allow_credentials() { async fn cors_validates_illegal_allow_credentials() {
let _cors = Cors::new().supports_credentials().send_wildcard().finish(); let _cors = Cors::new().supports_credentials().send_wildcard().finish();
} }
#[test] #[actix_rt::test]
fn validate_origin_allows_all_origins() { async fn validate_origin_allows_all_origins() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap(); let req = TestRequest::with_header("Origin", "https://www.example.com")
let req = TestRequest::with_header("Origin", "https://www.example.com") .to_srv_request();
.to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
})
} }
#[test] #[actix_rt::test]
fn default() { async fn default() {
block_on(async { let mut cors = Cors::default()
let mut cors = Cors::default() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap(); let req = TestRequest::with_header("Origin", "https://www.example.com")
let req = TestRequest::with_header("Origin", "https://www.example.com") .to_srv_request();
.to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
})
} }
#[test] #[actix_rt::test]
fn test_preflight() { async fn test_preflight() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .send_wildcard()
.send_wildcard() .max_age(3600)
.max_age(3600) .allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST]) .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) .allowed_header(header::CONTENT_TYPE)
.allowed_header(header::CONTENT_TYPE) .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.header(header::ACCESS_CONTROL_REQUEST_HEADERS, "X-Not-Allowed") .header(header::ACCESS_CONTROL_REQUEST_HEADERS, "X-Not-Allowed")
.to_srv_request(); .to_srv_request();
assert!(cors.inner.validate_allowed_method(req.head()).is_err()); assert!(cors.inner.validate_allowed_method(req.head()).is_err());
assert!(cors.inner.validate_allowed_headers(req.head()).is_err()); assert!(cors.inner.validate_allowed_headers(req.head()).is_err());
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST); assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "put") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "put")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
assert!(cors.inner.validate_allowed_method(req.head()).is_err()); assert!(cors.inner.validate_allowed_method(req.head()).is_err());
assert!(cors.inner.validate_allowed_headers(req.head()).is_ok()); assert!(cors.inner.validate_allowed_headers(req.head()).is_ok());
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
.header( .header(
header::ACCESS_CONTROL_REQUEST_HEADERS, header::ACCESS_CONTROL_REQUEST_HEADERS,
"AUTHORIZATION,ACCEPT", "AUTHORIZATION,ACCEPT",
) )
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"*"[..], &b"*"[..],
resp.headers() resp.headers()
.get(&header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(&header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap()
.as_bytes()
);
assert_eq!(
&b"3600"[..],
resp.headers()
.get(&header::ACCESS_CONTROL_MAX_AGE)
.unwrap()
.as_bytes()
);
let hdr = resp
.headers()
.get(&header::ACCESS_CONTROL_ALLOW_HEADERS)
.unwrap() .unwrap()
.to_str() .as_bytes()
.unwrap(); );
assert!(hdr.contains("authorization")); assert_eq!(
assert!(hdr.contains("accept")); &b"3600"[..],
assert!(hdr.contains("content-type")); resp.headers()
.get(&header::ACCESS_CONTROL_MAX_AGE)
let methods = resp
.headers()
.get(header::ACCESS_CONTROL_ALLOW_METHODS)
.unwrap() .unwrap()
.to_str() .as_bytes()
.unwrap(); );
assert!(methods.contains("POST")); let hdr = resp
assert!(methods.contains("GET")); .headers()
assert!(methods.contains("OPTIONS")); .get(&header::ACCESS_CONTROL_ALLOW_HEADERS)
.unwrap()
.to_str()
.unwrap();
assert!(hdr.contains("authorization"));
assert!(hdr.contains("accept"));
assert!(hdr.contains("content-type"));
Rc::get_mut(&mut cors.inner).unwrap().preflight = false; let methods = resp
.headers()
.get(header::ACCESS_CONTROL_ALLOW_METHODS)
.unwrap()
.to_str()
.unwrap();
assert!(methods.contains("POST"));
assert!(methods.contains("GET"));
assert!(methods.contains("OPTIONS"));
let req = TestRequest::with_header("Origin", "https://www.example.com") Rc::get_mut(&mut cors.inner).unwrap().preflight = false;
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
.header(
header::ACCESS_CONTROL_REQUEST_HEADERS,
"AUTHORIZATION,ACCEPT",
)
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await; let req = TestRequest::with_header("Origin", "https://www.example.com")
assert_eq!(resp.status(), StatusCode::OK); .header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
}) .header(
header::ACCESS_CONTROL_REQUEST_HEADERS,
"AUTHORIZATION,ACCEPT",
)
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
assert_eq!(resp.status(), StatusCode::OK);
} }
// #[test] // #[actix_rt::test]
// #[should_panic(expected = "MissingOrigin")] // #[should_panic(expected = "MissingOrigin")]
// fn test_validate_missing_origin() { // async fn test_validate_missing_origin() {
// let cors = Cors::build() // let cors = Cors::build()
// .allowed_origin("https://www.example.com") // .allowed_origin("https://www.example.com")
// .finish(); // .finish();
@ -957,257 +951,245 @@ mod tests {
// cors.start(&req).unwrap(); // cors.start(&req).unwrap();
// } // }
#[test] #[actix_rt::test]
#[should_panic(expected = "OriginNotAllowed")] #[should_panic(expected = "OriginNotAllowed")]
fn test_validate_not_allowed_origin() { async fn test_validate_not_allowed_origin() {
block_on(async { let cors = Cors::new()
let cors = Cors::new() .allowed_origin("https://www.example.com")
.allowed_origin("https://www.example.com") .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.unknown.com") let req = TestRequest::with_header("Origin", "https://www.unknown.com")
.method(Method::GET) .method(Method::GET)
.to_srv_request(); .to_srv_request();
cors.inner.validate_origin(req.head()).unwrap(); cors.inner.validate_origin(req.head()).unwrap();
cors.inner.validate_allowed_method(req.head()).unwrap(); cors.inner.validate_allowed_method(req.head()).unwrap();
cors.inner.validate_allowed_headers(req.head()).unwrap(); cors.inner.validate_allowed_headers(req.head()).unwrap();
})
} }
#[test] #[actix_rt::test]
fn test_validate_origin() { async fn test_validate_origin() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .allowed_origin("https://www.example.com")
.allowed_origin("https://www.example.com") .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::GET) .method(Method::GET)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
})
} }
#[test] #[actix_rt::test]
fn test_no_origin_response() { async fn test_no_origin_response() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .disable_preflight()
.disable_preflight() .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::default().method(Method::GET).to_srv_request(); let req = TestRequest::default().method(Method::GET).to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert!(resp assert!(resp
.headers() .headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.is_none()); .is_none());
let req = TestRequest::with_header("Origin", "https://www.example.com") let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"https://www.example.com"[..], &b"https://www.example.com"[..],
resp.headers() resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap()
.as_bytes()
);
})
}
#[test]
fn test_response() {
block_on(async {
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
let mut cors = Cors::new()
.send_wildcard()
.disable_preflight()
.max_age(3600)
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
.allowed_headers(exposed_headers.clone())
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish()
.new_transform(test::ok_service())
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
assert_eq!(
&b"*"[..],
resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap()
.as_bytes()
);
assert_eq!(
&b"Origin"[..],
resp.headers().get(header::VARY).unwrap().as_bytes()
);
{
let headers = resp
.headers()
.get(header::ACCESS_CONTROL_EXPOSE_HEADERS)
.unwrap()
.to_str()
.unwrap()
.split(',')
.map(|s| s.trim())
.collect::<Vec<&str>>();
for h in exposed_headers {
assert!(headers.contains(&h.as_str()));
}
}
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
let mut cors = Cors::new()
.send_wildcard()
.disable_preflight()
.max_age(3600)
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
.allowed_headers(exposed_headers.clone())
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish()
.new_transform(service_fn2(|req: ServiceRequest| {
ok(req.into_response(
HttpResponse::Ok().header(header::VARY, "Accept").finish(),
))
}))
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
assert_eq!(
&b"Accept, Origin"[..],
resp.headers().get(header::VARY).unwrap().as_bytes()
);
let mut cors = Cors::new()
.disable_vary_header()
.allowed_origin("https://www.example.com")
.allowed_origin("https://www.google.com")
.finish()
.new_transform(test::ok_service())
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
let origins_str = resp
.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap() .unwrap()
.as_bytes()
);
}
#[actix_rt::test]
async fn test_response() {
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
let mut cors = Cors::new()
.send_wildcard()
.disable_preflight()
.max_age(3600)
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
.allowed_headers(exposed_headers.clone())
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish()
.new_transform(test::ok_service())
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
assert_eq!(
&b"*"[..],
resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap()
.as_bytes()
);
assert_eq!(
&b"Origin"[..],
resp.headers().get(header::VARY).unwrap().as_bytes()
);
{
let headers = resp
.headers()
.get(header::ACCESS_CONTROL_EXPOSE_HEADERS)
.unwrap()
.to_str() .to_str()
.unwrap(); .unwrap()
.split(',')
.map(|s| s.trim())
.collect::<Vec<&str>>();
assert_eq!("https://www.example.com", origins_str); for h in exposed_headers {
}) assert!(headers.contains(&h.as_str()));
}
}
let exposed_headers = vec![header::AUTHORIZATION, header::ACCEPT];
let mut cors = Cors::new()
.send_wildcard()
.disable_preflight()
.max_age(3600)
.allowed_methods(vec![Method::GET, Method::OPTIONS, Method::POST])
.allowed_headers(exposed_headers.clone())
.expose_headers(exposed_headers.clone())
.allowed_header(header::CONTENT_TYPE)
.finish()
.new_transform(service_fn2(|req: ServiceRequest| {
ok(req.into_response(
HttpResponse::Ok().header(header::VARY, "Accept").finish(),
))
}))
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
assert_eq!(
&b"Accept, Origin"[..],
resp.headers().get(header::VARY).unwrap().as_bytes()
);
let mut cors = Cors::new()
.disable_vary_header()
.allowed_origin("https://www.example.com")
.allowed_origin("https://www.google.com")
.finish()
.new_transform(test::ok_service())
.await
.unwrap();
let req = TestRequest::with_header("Origin", "https://www.example.com")
.method(Method::OPTIONS)
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
.to_srv_request();
let resp = test::call_service(&mut cors, req).await;
let origins_str = resp
.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap()
.to_str()
.unwrap();
assert_eq!("https://www.example.com", origins_str);
} }
#[test] #[actix_rt::test]
fn test_multiple_origins() { async fn test_multiple_origins() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .allowed_origin("https://example.com")
.allowed_origin("https://example.com") .allowed_origin("https://example.org")
.allowed_origin("https://example.org") .allowed_methods(vec![Method::GET])
.allowed_methods(vec![Method::GET]) .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::with_header("Origin", "https://example.com") let req = TestRequest::with_header("Origin", "https://example.com")
.method(Method::GET) .method(Method::GET)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"https://example.com"[..], &b"https://example.com"[..],
resp.headers() resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap() .unwrap()
.as_bytes() .as_bytes()
); );
let req = TestRequest::with_header("Origin", "https://example.org") let req = TestRequest::with_header("Origin", "https://example.org")
.method(Method::GET) .method(Method::GET)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"https://example.org"[..], &b"https://example.org"[..],
resp.headers() resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap() .unwrap()
.as_bytes() .as_bytes()
); );
})
} }
#[test] #[actix_rt::test]
fn test_multiple_origins_preflight() { async fn test_multiple_origins_preflight() {
block_on(async { let mut cors = Cors::new()
let mut cors = Cors::new() .allowed_origin("https://example.com")
.allowed_origin("https://example.com") .allowed_origin("https://example.org")
.allowed_origin("https://example.org") .allowed_methods(vec![Method::GET])
.allowed_methods(vec![Method::GET]) .finish()
.finish() .new_transform(test::ok_service())
.new_transform(test::ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::with_header("Origin", "https://example.com") let req = TestRequest::with_header("Origin", "https://example.com")
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"https://example.com"[..], &b"https://example.com"[..],
resp.headers() resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap() .unwrap()
.as_bytes() .as_bytes()
); );
let req = TestRequest::with_header("Origin", "https://example.org") let req = TestRequest::with_header("Origin", "https://example.org")
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET") .header(header::ACCESS_CONTROL_REQUEST_METHOD, "GET")
.method(Method::OPTIONS) .method(Method::OPTIONS)
.to_srv_request(); .to_srv_request();
let resp = test::call_service(&mut cors, req).await; let resp = test::call_service(&mut cors, req).await;
assert_eq!( assert_eq!(
&b"https://example.org"[..], &b"https://example.org"[..],
resp.headers() resp.headers()
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN) .get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
.unwrap() .unwrap()
.as_bytes() .as_bytes()
); );
})
} }
} }

View File

@ -32,4 +32,5 @@ percent-encoding = "2.1"
v_htmlescape = "0.4" v_htmlescape = "0.4"
[dev-dependencies] [dev-dependencies]
actix-rt = "1.0.0-alpha.1"
actix-web = { version = "2.0.0-alpha.1", features=["openssl"] } actix-web = { version = "2.0.0-alpha.1", features=["openssl"] }

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@ use actix_http::http::header::{Header, HeaderName, IntoHeaderValue};
use actix_http::http::{HttpTryFrom, Method, Uri, Version}; use actix_http::http::{HttpTryFrom, Method, Uri, Version};
use actix_http::test::{TestBuffer, TestRequest as HttpTestRequest}; use actix_http::test::{TestBuffer, TestRequest as HttpTestRequest};
use actix_router::{Path, Url}; use actix_router::{Path, Url};
use actix_rt::Runtime;
use crate::{FramedRequest, State}; use crate::{FramedRequest, State};
@ -119,13 +118,12 @@ impl<S> TestRequest<S> {
} }
/// This method generates `FramedRequest` instance and executes async handler /// This method generates `FramedRequest` instance and executes async handler
pub fn run<F, R, I, E>(self, f: F) -> Result<I, E> pub async fn run<F, R, I, E>(self, f: F) -> Result<I, E>
where where
F: FnOnce(FramedRequest<TestBuffer, S>) -> R, F: FnOnce(FramedRequest<TestBuffer, S>) -> R,
R: Future<Output = Result<I, E>>, R: Future<Output = Result<I, E>>,
{ {
let mut rt = Runtime::new().unwrap(); f(self.finish()).await
rt.block_on(f(self.finish()))
} }
} }

View File

@ -1,6 +1,6 @@
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_http::{body, http::StatusCode, ws, Error, HttpService, Response}; use actix_http::{body, http::StatusCode, ws, Error, HttpService, Response};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_service::{pipeline_factory, IntoServiceFactory, ServiceFactory}; use actix_service::{pipeline_factory, IntoServiceFactory, ServiceFactory};
use actix_utils::framed::FramedTransport; use actix_utils::framed::FramedTransport;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
@ -38,126 +38,121 @@ async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
Ok(msg) Ok(msg)
} }
#[test] #[actix_rt::test]
fn test_simple() { async fn test_simple() {
block_on(async { let mut srv = TestServer::start(|| {
let mut srv = TestServer::start(|| { HttpService::build()
HttpService::build() .upgrade(
.upgrade( FramedApp::new().service(FramedRoute::get("/index.html").to(ws_service)),
FramedApp::new()
.service(FramedRoute::get("/index.html").to(ws_service)),
)
.finish(|_| future::ok::<_, Error>(Response::NotFound()))
});
assert!(srv.ws_at("/test").await.is_err());
// client service
let mut framed = srv.ws_at("/index.html").await.unwrap();
framed
.send(ws::Message::Text("text".to_string()))
.await
.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Text(Some(BytesMut::from("text")))
);
framed
.send(ws::Message::Binary("text".into()))
.await
.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
);
framed.send(ws::Message::Ping("text".into())).await.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Pong("text".to_string().into())
);
framed
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
.await
.unwrap();
let (item, _) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
);
})
}
#[test]
fn test_service() {
block_on(async {
let mut srv = TestServer::start(|| {
pipeline_factory(actix_http::h1::OneRequest::new().map_err(|_| ())).and_then(
pipeline_factory(
pipeline_factory(VerifyWebSockets::default())
.then(SendError::default())
.map_err(|_| ()),
)
.and_then(
FramedApp::new()
.service(FramedRoute::get("/index.html").to(ws_service))
.into_factory()
.map_err(|_| ()),
),
) )
}); .finish(|_| future::ok::<_, Error>(Response::NotFound()))
});
// non ws request assert!(srv.ws_at("/test").await.is_err());
let res = srv.get("/index.html").send().await.unwrap();
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
// not found // client service
assert!(srv.ws_at("/test").await.is_err()); let mut framed = srv.ws_at("/index.html").await.unwrap();
framed
.send(ws::Message::Text("text".to_string()))
.await
.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Text(Some(BytesMut::from("text")))
);
// client service framed
let mut framed = srv.ws_at("/index.html").await.unwrap(); .send(ws::Message::Binary("text".into()))
framed .await
.send(ws::Message::Text("text".to_string())) .unwrap();
.await let (item, mut framed) = framed.into_future().await;
.unwrap(); assert_eq!(
let (item, mut framed) = framed.into_future().await; item.unwrap().unwrap(),
assert_eq!( ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
item.unwrap().unwrap(), );
ws::Frame::Text(Some(BytesMut::from("text")))
);
framed framed.send(ws::Message::Ping("text".into())).await.unwrap();
.send(ws::Message::Binary("text".into())) let (item, mut framed) = framed.into_future().await;
.await assert_eq!(
.unwrap(); item.unwrap().unwrap(),
let (item, mut framed) = framed.into_future().await; ws::Frame::Pong("text".to_string().into())
assert_eq!( );
item.unwrap().unwrap(),
ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
);
framed.send(ws::Message::Ping("text".into())).await.unwrap(); framed
let (item, mut framed) = framed.into_future().await; .send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
assert_eq!( .await
item.unwrap().unwrap(), .unwrap();
ws::Frame::Pong("text".to_string().into())
);
framed let (item, _) = framed.into_future().await;
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into()))) assert_eq!(
.await item.unwrap().unwrap(),
.unwrap(); ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
);
let (item, _) = framed.into_future().await; }
assert_eq!(
item.unwrap().unwrap(), #[actix_rt::test]
ws::Frame::Close(Some(ws::CloseCode::Normal.into())) async fn test_service() {
); let mut srv = TestServer::start(|| {
}) pipeline_factory(actix_http::h1::OneRequest::new().map_err(|_| ())).and_then(
pipeline_factory(
pipeline_factory(VerifyWebSockets::default())
.then(SendError::default())
.map_err(|_| ()),
)
.and_then(
FramedApp::new()
.service(FramedRoute::get("/index.html").to(ws_service))
.into_factory()
.map_err(|_| ()),
),
)
});
// non ws request
let res = srv.get("/index.html").send().await.unwrap();
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
// not found
assert!(srv.ws_at("/test").await.is_err());
// client service
let mut framed = srv.ws_at("/index.html").await.unwrap();
framed
.send(ws::Message::Text("text".to_string()))
.await
.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Text(Some(BytesMut::from("text")))
);
framed
.send(ws::Message::Binary("text".into()))
.await
.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
);
framed.send(ws::Message::Ping("text".into())).await.unwrap();
let (item, mut framed) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Pong("text".to_string().into())
);
framed
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
.await
.unwrap();
let (item, _) = framed.into_future().await;
assert_eq!(
item.unwrap().unwrap(),
ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
);
} }

View File

@ -29,7 +29,7 @@ default = []
openssl = ["open-ssl", "actix-connect/openssl", "tokio-openssl"] openssl = ["open-ssl", "actix-connect/openssl", "tokio-openssl"]
# rustls support # rustls support
# rustls = ["rust-tls", "webpki-roots", "actix-connect/rustls"] rustls = ["rust-tls", "webpki-roots", "actix-connect/rustls"]
# brotli encoding, requires c compiler # brotli encoding, requires c compiler
brotli = ["brotli2"] brotli = ["brotli2"]
@ -52,6 +52,7 @@ actix-codec = "0.2.0-alpha.1"
actix-connect = "1.0.0-alpha.1" actix-connect = "1.0.0-alpha.1"
actix-utils = "0.5.0-alpha.1" actix-utils = "0.5.0-alpha.1"
actix-server-config = "0.3.0-alpha.1" actix-server-config = "0.3.0-alpha.1"
actix-rt = "1.0.0-alpha.1"
actix-threadpool = "0.2.0-alpha.1" actix-threadpool = "0.2.0-alpha.1"
base64 = "0.10" base64 = "0.10"
@ -83,11 +84,7 @@ slab = "0.4"
serde_urlencoded = "0.6.1" serde_urlencoded = "0.6.1"
time = "0.1.42" time = "0.1.42"
tokio = "=0.2.0-alpha.6"
tokio-io = "=0.2.0-alpha.6"
tokio-net = "=0.2.0-alpha.6" tokio-net = "=0.2.0-alpha.6"
tokio-timer = "0.3.0-alpha.6"
tokio-executor = "=0.2.0-alpha.6"
trust-dns-resolver = { version="0.18.0-alpha.1", default-features = false } trust-dns-resolver = { version="0.18.0-alpha.1", default-features = false }
# for secure cookie # for secure cookie
@ -106,8 +103,7 @@ rust-tls = { version = "0.16.0", package="rustls", optional = true }
webpki-roots = { version = "0.18", optional = true } webpki-roots = { version = "0.18", optional = true }
[dev-dependencies] [dev-dependencies]
actix-rt = "1.0.0-alpha.1" actix-server = { version = "0.8.0-alpha.1", features=["openssl", "rustls"] }
actix-server = { version = "0.8.0-alpha.1", features=["openssl"] }
actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] } actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] }
actix-http-test = { version = "0.3.0-alpha.1", features=["openssl"] } actix-http-test = { version = "0.3.0-alpha.1", features=["openssl"] }
env_logger = "0.6" env_logger = "0.6"

View File

@ -432,8 +432,7 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use actix_http_test::block_on; use futures::future::poll_fn;
use futures::future::{lazy, poll_fn};
impl Body { impl Body {
pub(crate) fn get_ref(&self) -> &[u8] { pub(crate) fn get_ref(&self) -> &[u8] {
@ -453,21 +452,21 @@ mod tests {
} }
} }
#[test] #[actix_rt::test]
fn test_static_str() { async fn test_static_str() {
assert_eq!(Body::from("").size(), BodySize::Sized(0)); assert_eq!(Body::from("").size(), BodySize::Sized(0));
assert_eq!(Body::from("test").size(), BodySize::Sized(4)); assert_eq!(Body::from("test").size(), BodySize::Sized(4));
assert_eq!(Body::from("test").get_ref(), b"test"); assert_eq!(Body::from("test").get_ref(), b"test");
assert_eq!("test".size(), BodySize::Sized(4)); assert_eq!("test".size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| "test".poll_next(cx))).unwrap().ok(), poll_fn(|cx| "test".poll_next(cx)).await.unwrap().ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_static_bytes() { async fn test_static_bytes() {
assert_eq!(Body::from(b"test".as_ref()).size(), BodySize::Sized(4)); assert_eq!(Body::from(b"test".as_ref()).size(), BodySize::Sized(4));
assert_eq!(Body::from(b"test".as_ref()).get_ref(), b"test"); assert_eq!(Body::from(b"test".as_ref()).get_ref(), b"test");
assert_eq!( assert_eq!(
@ -478,55 +477,57 @@ mod tests {
assert_eq!((&b"test"[..]).size(), BodySize::Sized(4)); assert_eq!((&b"test"[..]).size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| (&b"test"[..]).poll_next(cx))) poll_fn(|cx| (&b"test"[..]).poll_next(cx))
.await
.unwrap() .unwrap()
.ok(), .ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_vec() { async fn test_vec() {
assert_eq!(Body::from(Vec::from("test")).size(), BodySize::Sized(4)); assert_eq!(Body::from(Vec::from("test")).size(), BodySize::Sized(4));
assert_eq!(Body::from(Vec::from("test")).get_ref(), b"test"); assert_eq!(Body::from(Vec::from("test")).get_ref(), b"test");
assert_eq!(Vec::from("test").size(), BodySize::Sized(4)); assert_eq!(Vec::from("test").size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| Vec::from("test").poll_next(cx))) poll_fn(|cx| Vec::from("test").poll_next(cx))
.await
.unwrap() .unwrap()
.ok(), .ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_bytes() { async fn test_bytes() {
let mut b = Bytes::from("test"); let mut b = Bytes::from("test");
assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4)); assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4));
assert_eq!(Body::from(b.clone()).get_ref(), b"test"); assert_eq!(Body::from(b.clone()).get_ref(), b"test");
assert_eq!(b.size(), BodySize::Sized(4)); assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(), poll_fn(|cx| b.poll_next(cx)).await.unwrap().ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_bytes_mut() { async fn test_bytes_mut() {
let mut b = BytesMut::from("test"); let mut b = BytesMut::from("test");
assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4)); assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4));
assert_eq!(Body::from(b.clone()).get_ref(), b"test"); assert_eq!(Body::from(b.clone()).get_ref(), b"test");
assert_eq!(b.size(), BodySize::Sized(4)); assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(), poll_fn(|cx| b.poll_next(cx)).await.unwrap().ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_string() { async fn test_string() {
let mut b = "test".to_owned(); let mut b = "test".to_owned();
assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4)); assert_eq!(Body::from(b.clone()).size(), BodySize::Sized(4));
assert_eq!(Body::from(b.clone()).get_ref(), b"test"); assert_eq!(Body::from(b.clone()).get_ref(), b"test");
@ -535,26 +536,26 @@ mod tests {
assert_eq!(b.size(), BodySize::Sized(4)); assert_eq!(b.size(), BodySize::Sized(4));
assert_eq!( assert_eq!(
block_on(poll_fn(|cx| b.poll_next(cx))).unwrap().ok(), poll_fn(|cx| b.poll_next(cx)).await.unwrap().ok(),
Some(Bytes::from("test")) Some(Bytes::from("test"))
); );
} }
#[test] #[actix_rt::test]
fn test_unit() { async fn test_unit() {
assert_eq!(().size(), BodySize::Empty); assert_eq!(().size(), BodySize::Empty);
assert!(block_on(poll_fn(|cx| ().poll_next(cx))).is_none()); assert!(poll_fn(|cx| ().poll_next(cx)).await.is_none());
} }
#[test] #[actix_rt::test]
fn test_box() { async fn test_box() {
let mut val = Box::new(()); let mut val = Box::new(());
assert_eq!(val.size(), BodySize::Empty); assert_eq!(val.size(), BodySize::Empty);
assert!(block_on(poll_fn(|cx| val.poll_next(cx))).is_none()); assert!(poll_fn(|cx| val.poll_next(cx)).await.is_none());
} }
#[test] #[actix_rt::test]
fn test_body_eq() { async fn test_body_eq() {
assert!(Body::None == Body::None); assert!(Body::None == Body::None);
assert!(Body::None != Body::Empty); assert!(Body::None != Body::Empty);
assert!(Body::Empty == Body::Empty); assert!(Body::Empty == Body::Empty);
@ -566,15 +567,15 @@ mod tests {
assert!(Body::Bytes(Bytes::from_static(b"1")) != Body::None); assert!(Body::Bytes(Bytes::from_static(b"1")) != Body::None);
} }
#[test] #[actix_rt::test]
fn test_body_debug() { async fn test_body_debug() {
assert!(format!("{:?}", Body::None).contains("Body::None")); assert!(format!("{:?}", Body::None).contains("Body::None"));
assert!(format!("{:?}", Body::Empty).contains("Body::Empty")); assert!(format!("{:?}", Body::Empty).contains("Body::Empty"));
assert!(format!("{:?}", Body::Bytes(Bytes::from_static(b"1"))).contains("1")); assert!(format!("{:?}", Body::Bytes(Bytes::from_static(b"1"))).contains("1"));
} }
#[test] #[actix_rt::test]
fn test_serde_json() { async fn test_serde_json() {
use serde_json::json; use serde_json::json;
assert_eq!( assert_eq!(
Body::from(serde_json::Value::String("test".into())).size(), Body::from(serde_json::Value::String("test".into())).size(),

View File

@ -1,8 +1,5 @@
use std::fmt; use std::fmt;
use std::future::Future;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
@ -11,7 +8,6 @@ use actix_connect::{
}; };
use actix_service::{apply_fn, Service}; use actix_service::{apply_fn, Service};
use actix_utils::timeout::{TimeoutError, TimeoutService}; use actix_utils::timeout::{TimeoutError, TimeoutService};
use futures::future::Ready;
use http::Uri; use http::Uri;
use tokio_net::tcp::TcpStream; use tokio_net::tcp::TcpStream;
@ -344,7 +340,6 @@ mod connect_impl {
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use futures::future::{err, Either, Ready}; use futures::future::{err, Either, Ready};
use futures::ready;
use super::*; use super::*;
use crate::client::connection::IoConnection; use crate::client::connection::IoConnection;
@ -402,7 +397,10 @@ mod connect_impl {
#[cfg(any(feature = "openssl", feature = "rustls"))] #[cfg(any(feature = "openssl", feature = "rustls"))]
mod connect_impl { mod connect_impl {
use std::future::Future;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};
use futures::future::Either; use futures::future::Either;
use futures::ready; use futures::ready;

View File

@ -1,4 +1,3 @@
use std::future::Future;
use std::io::Write; use std::io::Write;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@ -6,8 +5,8 @@ use std::{io, time};
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed};
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use futures::future::{ok, poll_fn, Either}; use futures::future::poll_fn;
use futures::{Sink, SinkExt, Stream, StreamExt}; use futures::{SinkExt, Stream, StreamExt};
use crate::error::PayloadError; use crate::error::PayloadError;
use crate::h1; use crate::h1;

View File

@ -1,11 +1,8 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time; use std::time;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use bytes::Bytes; use bytes::Bytes;
use futures::future::{err, poll_fn, Either}; use futures::future::poll_fn;
use h2::{client::SendRequest, SendStream}; use h2::{client::SendRequest, SendStream};
use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING}; use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING};
use http::{request::Request, HttpTryFrom, Method, Version}; use http::{request::Request, HttpTryFrom, Method, Version};

View File

@ -1,23 +1,22 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::future::Future; use std::future::Future;
use std::io;
use std::pin::Pin; use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_rt::time::{delay_for, Delay};
use actix_service::Service; use actix_service::Service;
use actix_utils::{oneshot, task::LocalWaker}; use actix_utils::{oneshot, task::LocalWaker};
use bytes::Bytes; use bytes::Bytes;
use futures::future::{err, ok, poll_fn, Either, FutureExt, LocalBoxFuture, Ready}; use futures::future::{poll_fn, FutureExt, LocalBoxFuture};
use h2::client::{handshake, Connection, SendRequest}; use h2::client::{handshake, Connection, SendRequest};
use hashbrown::HashMap; use hashbrown::HashMap;
use http::uri::Authority; use http::uri::Authority;
use indexmap::IndexSet; use indexmap::IndexSet;
use slab::Slab; use slab::Slab;
use tokio_timer::{delay_for, Delay};
use super::connection::{ConnectionType, IoConnection}; use super::connection::{ConnectionType, IoConnection};
use super::error::ConnectError; use super::error::ConnectError;
@ -100,7 +99,7 @@ where
fn call(&mut self, req: Connect) -> Self::Future { fn call(&mut self, req: Connect) -> Self::Future {
// start support future // start support future
tokio_executor::current_thread::spawn(ConnectorPoolSupport { actix_rt::spawn(ConnectorPoolSupport {
connector: self.0.clone(), connector: self.0.clone(),
inner: self.1.clone(), inner: self.1.clone(),
}); });
@ -139,7 +138,7 @@ where
)) ))
} else { } else {
let (snd, connection) = handshake(io).await?; let (snd, connection) = handshake(io).await?;
tokio_executor::current_thread::spawn(connection.map(|_| ())); actix_rt::spawn(connection.map(|_| ()));
Ok(IoConnection::new( Ok(IoConnection::new(
ConnectionType::H2(snd), ConnectionType::H2(snd),
Instant::now(), Instant::now(),
@ -328,9 +327,7 @@ where
{ {
if let Some(timeout) = self.disconnect_timeout { if let Some(timeout) = self.disconnect_timeout {
if let ConnectionType::H1(io) = conn.io { if let ConnectionType::H1(io) = conn.io {
tokio_executor::current_thread::spawn(CloseConnection::new( actix_rt::spawn(CloseConnection::new(io, timeout))
io, timeout,
))
} }
} }
} else { } else {
@ -342,9 +339,9 @@ where
Poll::Ready(Ok(n)) if n > 0 => { Poll::Ready(Ok(n)) if n > 0 => {
if let Some(timeout) = self.disconnect_timeout { if let Some(timeout) = self.disconnect_timeout {
if let ConnectionType::H1(io) = io { if let ConnectionType::H1(io) = io {
tokio_executor::current_thread::spawn( actix_rt::spawn(CloseConnection::new(
CloseConnection::new(io, timeout), io, timeout,
) ))
} }
} }
continue; continue;
@ -376,7 +373,7 @@ where
self.acquired -= 1; self.acquired -= 1;
if let Some(timeout) = self.disconnect_timeout { if let Some(timeout) = self.disconnect_timeout {
if let ConnectionType::H1(io) = io { if let ConnectionType::H1(io) = io {
tokio_executor::current_thread::spawn(CloseConnection::new(io, timeout)) actix_rt::spawn(CloseConnection::new(io, timeout))
} }
} }
self.check_availibility(); self.check_availibility();
@ -518,7 +515,7 @@ where
inner: Rc<RefCell<Inner<Io>>>, inner: Rc<RefCell<Inner<Io>>>,
fut: F, fut: F,
) { ) {
tokio_executor::current_thread::spawn(OpenWaitingConnection { actix_rt::spawn(OpenWaitingConnection {
key, key,
fut, fut,
h2: None, h2: None,
@ -554,7 +551,7 @@ where
if let Some(ref mut h2) = this.h2 { if let Some(ref mut h2) = this.h2 {
return match Pin::new(h2).poll(cx) { return match Pin::new(h2).poll(cx) {
Poll::Ready(Ok((snd, connection))) => { Poll::Ready(Ok((snd, connection))) => {
tokio_executor::current_thread::spawn(connection.map(|_| ())); actix_rt::spawn(connection.map(|_| ()));
let rx = this.rx.take().unwrap(); let rx = this.rx.take().unwrap();
let _ = rx.send(Ok(IoConnection::new( let _ = rx.send(Ok(IoConnection::new(
ConnectionType::H2(snd), ConnectionType::H2(snd),

View File

@ -4,10 +4,10 @@ use std::fmt::Write;
use std::rc::Rc; use std::rc::Rc;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use actix_rt::time::{delay, delay_for, Delay};
use bytes::BytesMut; use bytes::BytesMut;
use futures::{future, Future, FutureExt}; use futures::{future, FutureExt};
use time; use time;
use tokio_timer::{delay, delay_for, Delay};
// "Sun, 06 Nov 1994 08:49:37 GMT".len() // "Sun, 06 Nov 1994 08:49:37 GMT".len()
const DATE_VALUE_LENGTH: usize = 29; const DATE_VALUE_LENGTH: usize = 29;
@ -242,12 +242,10 @@ impl DateService {
// periodic date update // periodic date update
let s = self.clone(); let s = self.clone();
tokio_executor::current_thread::spawn( actix_rt::spawn(delay_for(Duration::from_millis(500)).then(move |_| {
delay_for(Duration::from_millis(500)).then(move |_| { s.0.reset();
s.0.reset(); future::ready(())
future::ready(()) }));
}),
);
} }
} }
@ -265,26 +263,19 @@ impl DateService {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use actix_rt::System;
use futures::future;
#[test] #[test]
fn test_date_len() { fn test_date_len() {
assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len()); assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
} }
#[test] #[actix_rt::test]
fn test_date() { async fn test_date() {
let mut rt = System::new("test"); let settings = ServiceConfig::new(KeepAlive::Os, 0, 0);
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
let _ = rt.block_on(future::lazy(|_| { settings.set_date(&mut buf1);
let settings = ServiceConfig::new(KeepAlive::Os, 0, 0); let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10); settings.set_date(&mut buf2);
settings.set_date(&mut buf1); assert_eq!(buf1, buf2);
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
settings.set_date(&mut buf2);
assert_eq!(buf1, buf2);
future::ok::<_, ()>(())
}));
} }
} }

View File

@ -1,5 +1,4 @@
use ring::hkdf::{Algorithm, KeyType, Prk, HKDF_SHA256}; use ring::hkdf::{Algorithm, KeyType, Prk, HKDF_SHA256};
use ring::hmac;
use ring::rand::{SecureRandom, SystemRandom}; use ring::rand::{SecureRandom, SystemRandom};
use super::private::KEY_LEN as PRIVATE_KEY_LEN; use super::private::KEY_LEN as PRIVATE_KEY_LEN;

View File

@ -16,7 +16,6 @@ use httparse;
use serde::de::value::Error as DeError; use serde::de::value::Error as DeError;
use serde_json::error::Error as JsonError; use serde_json::error::Error as JsonError;
use serde_urlencoded::ser::Error as FormError; use serde_urlencoded::ser::Error as FormError;
use tokio_timer::Error as TimerError;
// re-export for convinience // re-export for convinience
use crate::body::Body; use crate::body::Body;
@ -178,9 +177,6 @@ impl ResponseError for JsonError {}
/// `InternalServerError` for `FormError` /// `InternalServerError` for `FormError`
impl ResponseError for FormError {} impl ResponseError for FormError {}
/// `InternalServerError` for `TimerError`
impl ResponseError for TimerError {}
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
/// `InternalServerError` for `openssl::ssl::Error` /// `InternalServerError` for `openssl::ssl::Error`
impl ResponseError for open_ssl::ssl::Error {} impl ResponseError for open_ssl::ssl::Error {}

View File

@ -1,9 +1,7 @@
use std::future::Future;
use std::io; use std::io;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::pin::Pin; use std::task::Poll;
use std::task::{Context, Poll};
use actix_codec::Decoder; use actix_codec::Decoder;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};

View File

@ -3,15 +3,15 @@ use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Instant; use std::time::Instant;
use std::{fmt, io, io::Write, net}; use std::{fmt, io, net};
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts}; use actix_codec::{AsyncRead, Decoder, Encoder, Framed, FramedParts};
use actix_rt::time::{delay, Delay};
use actix_server_config::IoStream; use actix_server_config::IoStream;
use actix_service::Service; use actix_service::Service;
use bitflags::bitflags; use bitflags::bitflags;
use bytes::{BufMut, BytesMut}; use bytes::{BufMut, BytesMut};
use log::{error, trace}; use log::{error, trace};
use tokio_timer::{delay, Delay};
use crate::body::{Body, BodySize, MessageBody, ResponseBody}; use crate::body::{Body, BodySize, MessageBody, ResponseBody};
use crate::cloneable::CloneableService; use crate::cloneable::CloneableService;
@ -893,10 +893,9 @@ mod tests {
use crate::h1::{ExpectHandler, UpgradeHandler}; use crate::h1::{ExpectHandler, UpgradeHandler};
use crate::test::TestBuffer; use crate::test::TestBuffer;
#[test] #[actix_rt::test]
fn test_req_parse_err() { async fn test_req_parse_err() {
let mut sys = actix_rt::System::new("test"); lazy(|cx| {
let _ = sys.block_on(lazy(|cx| {
let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n"); let buf = TestBuffer::new("GET /test HTTP/1\r\n\r\n");
let mut h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new( let mut h1 = Dispatcher::<_, _, _, _, UpgradeHandler<TestBuffer>>::new(
@ -918,7 +917,7 @@ mod tests {
assert!(inner.flags.contains(Flags::READ_DISCONNECT)); assert!(inner.flags.contains(Flags::READ_DISCONNECT));
assert_eq!(&inner.io.write_buf[..26], b"HTTP/1.1 400 Bad Request\r\n"); assert_eq!(&inner.io.write_buf[..26], b"HTTP/1.1 400 Bad Request\r\n");
} }
ok::<_, ()>(()) })
})); .await;
} }
} }

View File

@ -1,5 +1,3 @@
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;

View File

@ -1,7 +1,6 @@
//! Payload stream //! Payload stream
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@ -227,24 +226,19 @@ impl Inner {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use actix_rt::Runtime; use futures::future::poll_fn;
use futures::future::{poll_fn, ready};
#[test] #[actix_rt::test]
fn test_unread_data() { async fn test_unread_data() {
Runtime::new().unwrap().block_on(async { let (_, mut payload) = Payload::create(false);
let (_, mut payload) = Payload::create(false);
payload.unread_data(Bytes::from("data")); payload.unread_data(Bytes::from("data"));
assert!(!payload.is_empty()); assert!(!payload.is_empty());
assert_eq!(payload.len(), 4); assert_eq!(payload.len(), 4);
assert_eq!( assert_eq!(
Bytes::from("data"), Bytes::from("data"),
poll_fn(|cx| payload.readany(cx)).await.unwrap().unwrap() poll_fn(|cx| payload.readany(cx)).await.unwrap().unwrap()
); );
ready(())
});
} }
} }

View File

@ -9,7 +9,7 @@ use actix_codec::Framed;
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
use actix_service::{IntoServiceFactory, Service, ServiceFactory}; use actix_service::{IntoServiceFactory, Service, ServiceFactory};
use futures::future::{ok, Ready}; use futures::future::{ok, Ready};
use futures::{ready, Stream}; use futures::ready;
use crate::body::MessageBody; use crate::body::MessageBody;
use crate::cloneable::CloneableService; use crate::cloneable::CloneableService;

View File

@ -1,6 +1,4 @@
use std::future::Future;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_codec::Framed; use actix_codec::Framed;

View File

@ -3,7 +3,6 @@ use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed};
use futures::Sink;
use crate::body::{BodySize, MessageBody, ResponseBody}; use crate::body::{BodySize, MessageBody, ResponseBody};
use crate::error::Error; use crate::error::Error;

View File

@ -7,6 +7,7 @@ use std::time::Instant;
use std::{fmt, mem, net}; use std::{fmt, mem, net};
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_rt::time::Delay;
use actix_server_config::IoStream; use actix_server_config::IoStream;
use actix_service::Service; use actix_service::Service;
use bitflags::bitflags; use bitflags::bitflags;
@ -19,7 +20,6 @@ use http::header::{
}; };
use http::HttpTryFrom; use http::HttpTryFrom;
use log::{debug, error, trace}; use log::{debug, error, trace};
use tokio_timer::Delay;
use crate::body::{Body, BodySize, MessageBody, ResponseBody}; use crate::body::{Body, BodySize, MessageBody, ResponseBody};
use crate::cloneable::CloneableService; use crate::cloneable::CloneableService;
@ -139,7 +139,7 @@ where
on_connect.set(&mut req.extensions_mut()); on_connect.set(&mut req.extensions_mut());
} }
tokio_executor::current_thread::spawn(ServiceResponse::< actix_rt::spawn(ServiceResponse::<
S::Future, S::Future,
S::Response, S::Response,
S::Error, S::Error,

View File

@ -4,8 +4,7 @@
clippy::too_many_arguments, clippy::too_many_arguments,
clippy::new_without_default, clippy::new_without_default,
clippy::borrow_interior_mutable_const, clippy::borrow_interior_mutable_const,
clippy::write_with_newline, clippy::write_with_newline
unused_imports
)] )]
#[macro_use] #[macro_use]

View File

@ -1,4 +1,3 @@
use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};

View File

@ -7,7 +7,6 @@ use std::task::{Context, Poll};
use std::{fmt, str}; use std::{fmt, str};
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use futures::future::{ok, Ready};
use futures::stream::Stream; use futures::stream::Stream;
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;

View File

@ -8,7 +8,7 @@ use actix_server_config::{
Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig, Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig,
}; };
use actix_service::{IntoServiceFactory, Service, ServiceFactory}; use actix_service::{IntoServiceFactory, Service, ServiceFactory};
use bytes::{Buf, BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use futures::{ready, Future}; use futures::{ready, Future};
use h2::server::{self, Handshake}; use h2::server::{self, Handshake};
use pin_project::{pin_project, project}; use pin_project::{pin_project, project};
@ -659,7 +659,7 @@ impl<T: AsyncRead> AsyncRead for Io<T> {
// } // }
} }
impl<T: AsyncWrite> tokio_io::AsyncWrite for Io<T> { impl<T: AsyncWrite> actix_codec::AsyncWrite for Io<T> {
fn poll_write( fn poll_write(
self: Pin<&mut Self>, self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,

View File

@ -7,7 +7,7 @@ use std::task::{Context, Poll};
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_server_config::IoStream; use actix_server_config::IoStream;
use bytes::{Buf, Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use http::header::{self, HeaderName, HeaderValue}; use http::header::{self, HeaderName, HeaderValue};
use http::{HttpTryFrom, Method, Uri, Version}; use http::{HttpTryFrom, Method, Uri, Version};
use percent_encoding::percent_encode; use percent_encoding::percent_encode;

View File

@ -3,7 +3,7 @@ use bytes::Bytes;
use futures::future::{self, ok}; use futures::future::{self, ok};
use actix_http::{http, HttpService, Request, Response}; use actix_http::{http, HttpService, Request, Response};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \
@ -27,65 +27,58 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World"; Hello World Hello World Hello World Hello World Hello World";
#[test] #[actix_rt::test]
fn test_h1_v2() { async fn test_h1_v2() {
block_on(async { let srv = TestServer::start(move || {
let srv = TestServer::start(move || { HttpService::build().finish(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
HttpService::build() });
.finish(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
});
let response = srv.get("/").send().await.unwrap(); let response = srv.get("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.get("/").header("x-test", "111").send(); let request = srv.get("/").header("x-test", "111").send();
let mut response = request.await.unwrap(); let mut response = request.await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = response.body().await.unwrap(); let bytes = response.body().await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
let mut response = srv.post("/").send().await.unwrap(); let mut response = srv.post("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = response.body().await.unwrap(); let bytes = response.body().await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
} }
#[test] #[actix_rt::test]
fn test_connection_close() { async fn test_connection_close() {
block_on(async { let srv = TestServer::start(move || {
let srv = TestServer::start(move || { HttpService::build()
HttpService::build() .finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
.finish(|_| ok::<_, ()>(Response::Ok().body(STR))) .map(|_| ())
.map(|_| ()) });
});
let response = srv.get("/").force_close().send().await.unwrap(); let response = srv.get("/").force_close().send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
})
} }
#[test] #[actix_rt::test]
fn test_with_query_parameter() { async fn test_with_query_parameter() {
block_on(async { let srv = TestServer::start(move || {
let srv = TestServer::start(move || { HttpService::build()
HttpService::build() .finish(|req: Request| {
.finish(|req: Request| { if req.uri().query().unwrap().contains("qp=") {
if req.uri().query().unwrap().contains("qp=") { ok::<_, ()>(Response::Ok().finish())
ok::<_, ()>(Response::Ok().finish()) } else {
} else { ok::<_, ()>(Response::BadRequest().finish())
ok::<_, ()>(Response::BadRequest().finish()) }
} })
}) .map(|_| ())
.map(|_| ()) });
});
let request = srv.request(http::Method::GET, srv.url("/?qp=5")); let request = srv.request(http::Method::GET, srv.url("/?qp=5"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
})
} }

View File

@ -2,7 +2,7 @@
use std::io; use std::io;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_server::ssl::OpensslAcceptor; use actix_server::ssl::OpensslAcceptor;
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory}; use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory};
@ -57,156 +57,147 @@ fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> io::Result<OpensslAcceptor<T, ()
Ok(OpensslAcceptor::new(builder.build())) Ok(OpensslAcceptor::new(builder.build()))
} }
#[test] #[actix_rt::test]
fn test_h2() -> io::Result<()> { async fn test_h2() -> io::Result<()> {
block_on(async { let openssl = ssl_acceptor()?;
let openssl = ssl_acceptor()?; let srv = TestServer::start(move || {
let srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| ok::<_, Error>(Response::Ok().finish()))
.h2(|_| ok::<_, Error>(Response::Ok().finish())) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_1() -> io::Result<()> { async fn test_h2_1() -> io::Result<()> {
block_on(async { let openssl = ssl_acceptor()?;
let openssl = ssl_acceptor()?; let srv = TestServer::start(move || {
let srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .finish(|req: Request| {
.finish(|req: Request| { assert!(req.peer_addr().is_some());
assert!(req.peer_addr().is_some()); assert_eq!(req.version(), Version::HTTP_2);
assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::Ok().finish())
ok::<_, Error>(Response::Ok().finish()) })
}) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_body() -> io::Result<()> { async fn test_h2_body() -> io::Result<()> {
block_on(async { let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
let data = "HELLOWORLD".to_owned().repeat(64 * 1024); let openssl = ssl_acceptor()?;
let openssl = ssl_acceptor()?; let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|mut req: Request<_>| {
.h2(|mut req: Request<_>| { async move {
async move { let body = load_body(req.take_payload()).await?;
let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::Ok().body(body))
Ok::<_, Error>(Response::Ok().body(body)) }
} })
}) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send_body(data.clone()).await.unwrap(); let response = srv.sget("/").send_body(data.clone()).await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let body = srv.load_body(response).await.unwrap(); let body = srv.load_body(response).await.unwrap();
assert_eq!(&body, data.as_bytes()); assert_eq!(&body, data.as_bytes());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_content_length() { async fn test_h2_content_length() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap();
let srv = TestServer::start(move || { let srv = TestServer::start(move || {
pipeline_factory( pipeline_factory(
openssl openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e)), .map_err(|e| println!("Openssl error: {}", e)),
) )
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(|req: Request| { .h2(|req: Request| {
let indx: usize = req.uri().path()[1..].parse().unwrap(); let indx: usize = req.uri().path()[1..].parse().unwrap();
let statuses = [ let statuses = [
StatusCode::NO_CONTENT, StatusCode::NO_CONTENT,
StatusCode::CONTINUE, StatusCode::CONTINUE,
StatusCode::SWITCHING_PROTOCOLS, StatusCode::SWITCHING_PROTOCOLS,
StatusCode::PROCESSING, StatusCode::PROCESSING,
StatusCode::OK, StatusCode::OK,
StatusCode::NOT_FOUND, StatusCode::NOT_FOUND,
]; ];
ok::<_, ()>(Response::new(statuses[indx])) ok::<_, ()>(Response::new(statuses[indx]))
}) })
.map_err(|_| ()), .map_err(|_| ()),
) )
}); });
let header = HeaderName::from_static("content-length"); let header = HeaderName::from_static("content-length");
let value = HeaderValue::from_static("0"); let value = HeaderValue::from_static("0");
{ {
for i in 0..4 { for i in 0..4 {
let req = srv let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i))) .request(Method::GET, srv.surl(&format!("/{}", i)))
.send(); .send();
let response = req.await.unwrap(); let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), None); assert_eq!(response.headers().get(&header), None);
let req = srv let req = srv
.request(Method::HEAD, srv.surl(&format!("/{}", i))) .request(Method::HEAD, srv.surl(&format!("/{}", i)))
.send(); .send();
let response = req.await.unwrap(); let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), None); assert_eq!(response.headers().get(&header), None);
}
for i in 4..6 {
let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i)))
.send();
let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), Some(&value));
}
} }
})
for i in 4..6 {
let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i)))
.send();
let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), Some(&value));
}
}
} }
#[test] #[actix_rt::test]
fn test_h2_headers() { async fn test_h2_headers() {
block_on(async { let data = STR.repeat(10);
let data = STR.repeat(10); let data2 = data.clone();
let data2 = data.clone(); let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || { let mut srv = TestServer::start(move || {
let data = data.clone(); let data = data.clone();
pipeline_factory(openssl pipeline_factory(openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e))) .map_err(|e| println!("Openssl error: {}", e)))
.and_then( .and_then(
@ -232,15 +223,14 @@ fn test_h2_headers() {
} }
ok::<_, ()>(builder.body(data.clone())) ok::<_, ()>(builder.body(data.clone()))
}).map_err(|_| ())) }).map_err(|_| ()))
}); });
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from(data2)); assert_eq!(bytes, Bytes::from(data2));
})
} }
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
@ -265,281 +255,262 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World"; Hello World Hello World Hello World Hello World Hello World";
#[test] #[actix_rt::test]
fn test_h2_body2() { async fn test_h2_body2() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
.h2(|_| ok::<_, ()>(Response::Ok().body(STR))) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
} }
#[test] #[actix_rt::test]
fn test_h2_head_empty() { async fn test_h2_head_empty() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
.finish(|_| ok::<_, ()>(Response::Ok().body(STR))) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.shead("/").send().await.unwrap(); let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.version(), Version::HTTP_2); assert_eq!(response.version(), Version::HTTP_2);
{ {
let len = response.headers().get(header::CONTENT_LENGTH).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
} }
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert!(bytes.is_empty()); assert!(bytes.is_empty());
})
} }
#[test] #[actix_rt::test]
fn test_h2_head_binary() { async fn test_h2_head_binary() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| {
.h2(|_| { ok::<_, ()>(
ok::<_, ()>( Response::Ok().content_length(STR.len() as u64).body(STR),
Response::Ok().content_length(STR.len() as u64).body(STR), )
) })
}) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.shead("/").send().await.unwrap(); let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
{ {
let len = response.headers().get(header::CONTENT_LENGTH).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
} }
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert!(bytes.is_empty()); assert!(bytes.is_empty());
})
} }
#[test] #[actix_rt::test]
fn test_h2_head_binary2() { async fn test_h2_head_binary2() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let srv = TestServer::start(move || {
let srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
.h2(|_| ok::<_, ()>(Response::Ok().body(STR))) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.shead("/").send().await.unwrap(); let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
{ {
let len = response.headers().get(header::CONTENT_LENGTH).unwrap(); let len = response.headers().get(header::CONTENT_LENGTH).unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
} }
})
} }
#[test] #[actix_rt::test]
fn test_h2_body_length() { async fn test_h2_body_length() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(
pipeline_factory( openssl
openssl .clone()
.clone() .map_err(|e| println!("Openssl error: {}", e)),
.map_err(|e| println!("Openssl error: {}", e)), )
) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| {
.h2(|_| { let body = once(ok(Bytes::from_static(STR.as_ref())));
let body = once(ok(Bytes::from_static(STR.as_ref()))); ok::<_, ()>(
Response::Ok()
.body(body::SizedStream::new(STR.len() as u64, body)),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
}
#[actix_rt::test]
async fn test_h2_body_chunked_explicit() {
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(
openssl
.clone()
.map_err(|e| println!("Openssl error: {}", e)),
)
.and_then(
HttpService::build()
.h2(|_| {
let body = once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok()
.header(header::TRANSFER_ENCODING, "chunked")
.streaming(body),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
// read response
let bytes = srv.load_body(response).await.unwrap();
// decode
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
}
#[actix_rt::test]
async fn test_h2_response_http_error_handling() {
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(
openssl
.clone()
.map_err(|e| println!("Openssl error: {}", e)),
)
.and_then(
HttpService::build()
.h2(factory_fn_cfg(|_: &ServerConfig| {
ok::<_, ()>(service_fn2(|_| {
let broken_header = Bytes::from_static(b"\0\0\0");
ok::<_, ()>( ok::<_, ()>(
Response::Ok() Response::Ok()
.body(body::SizedStream::new(STR.len() as u64, body)), .header(header::CONTENT_TYPE, broken_header)
.body(STR),
) )
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
}
#[test]
fn test_h2_body_chunked_explicit() {
block_on(async {
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(
openssl
.clone()
.map_err(|e| println!("Openssl error: {}", e)),
)
.and_then(
HttpService::build()
.h2(|_| {
let body =
once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok()
.header(header::TRANSFER_ENCODING, "chunked")
.streaming(body),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
// read response
let bytes = srv.load_body(response).await.unwrap();
// decode
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
}
#[test]
fn test_h2_response_http_error_handling() {
block_on(async {
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(
openssl
.clone()
.map_err(|e| println!("Openssl error: {}", e)),
)
.and_then(
HttpService::build()
.h2(factory_fn_cfg(|_: &ServerConfig| {
ok::<_, ()>(service_fn2(|_| {
let broken_header = Bytes::from_static(b"\0\0\0");
ok::<_, ()>(
Response::Ok()
.header(header::CONTENT_TYPE, broken_header)
.body(STR),
)
}))
})) }))
.map_err(|_| ()), }))
) .map_err(|_| ()),
}); )
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value")); assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
})
} }
#[test] #[actix_rt::test]
fn test_h2_service_error() { async fn test_h2_service_error() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || { let mut srv = TestServer::start(move || {
pipeline_factory( pipeline_factory(
openssl openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e)), .map_err(|e| println!("Openssl error: {}", e)),
) )
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(|_| err::<Response, Error>(ErrorBadRequest("error"))) .h2(|_| err::<Response, Error>(ErrorBadRequest("error")))
.map_err(|_| ()), .map_err(|_| ()),
) )
}); });
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert_eq!(response.status(), StatusCode::BAD_REQUEST); assert_eq!(response.status(), StatusCode::BAD_REQUEST);
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(b"error")); assert_eq!(bytes, Bytes::from_static(b"error"));
})
} }
#[test] #[actix_rt::test]
fn test_h2_on_connect() { async fn test_h2_on_connect() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap();
let srv = TestServer::start(move || { let srv = TestServer::start(move || {
pipeline_factory( pipeline_factory(
openssl openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e)), .map_err(|e| println!("Openssl error: {}", e)),
) )
.and_then( .and_then(
HttpService::build() HttpService::build()
.on_connect(|_| 10usize) .on_connect(|_| 10usize)
.h2(|req: Request| { .h2(|req: Request| {
assert!(req.extensions().contains::<usize>()); assert!(req.extensions().contains::<usize>());
ok::<_, ()>(Response::Ok().finish()) ok::<_, ()>(Response::Ok().finish())
}) })
.map_err(|_| ()), .map_err(|_| ()),
) )
}); });
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
})
} }

View File

@ -4,7 +4,7 @@ use actix_http::error::PayloadError;
use actix_http::http::header::{self, HeaderName, HeaderValue}; use actix_http::http::header::{self, HeaderName, HeaderValue};
use actix_http::http::{Method, StatusCode, Version}; use actix_http::http::{Method, StatusCode, Version};
use actix_http::{body, error, Error, HttpService, Request, Response}; use actix_http::{body, error, Error, HttpService, Request, Response};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_server::ssl::RustlsAcceptor; use actix_server::ssl::RustlsAcceptor;
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory}; use actix_service::{factory_fn_cfg, pipeline_factory, service_fn2, ServiceFactory};
@ -45,140 +45,131 @@ fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> io::Result<RustlsAcceptor<T, ()>
Ok(RustlsAcceptor::new(config)) Ok(RustlsAcceptor::new(config))
} }
#[test] #[actix_rt::test]
fn test_h2() -> io::Result<()> { async fn test_h2() -> io::Result<()> {
block_on(async { let rustls = ssl_acceptor()?;
let rustls = ssl_acceptor()?; let srv = TestServer::start(move || {
let srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| future::ok::<_, Error>(Response::Ok().finish()))
.h2(|_| future::ok::<_, Error>(Response::Ok().finish())) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_1() -> io::Result<()> { async fn test_h2_1() -> io::Result<()> {
block_on(async { let rustls = ssl_acceptor()?;
let rustls = ssl_acceptor()?; let srv = TestServer::start(move || {
let srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .finish(|req: Request| {
.finish(|req: Request| { assert!(req.peer_addr().is_some());
assert!(req.peer_addr().is_some()); assert_eq!(req.version(), Version::HTTP_2);
assert_eq!(req.version(), Version::HTTP_2); future::ok::<_, Error>(Response::Ok().finish())
future::ok::<_, Error>(Response::Ok().finish()) })
}) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_body1() -> io::Result<()> { async fn test_h2_body1() -> io::Result<()> {
block_on(async { let data = "HELLOWORLD".to_owned().repeat(64 * 1024);
let data = "HELLOWORLD".to_owned().repeat(64 * 1024); let rustls = ssl_acceptor()?;
let rustls = ssl_acceptor()?; let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|mut req: Request<_>| {
.h2(|mut req: Request<_>| { async move {
async move { let body = load_body(req.take_payload()).await?;
let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::Ok().body(body))
Ok::<_, Error>(Response::Ok().body(body)) }
} })
}) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send_body(data.clone()).await.unwrap(); let response = srv.sget("/").send_body(data.clone()).await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let body = srv.load_body(response).await.unwrap(); let body = srv.load_body(response).await.unwrap();
assert_eq!(&body, data.as_bytes()); assert_eq!(&body, data.as_bytes());
Ok(()) Ok(())
})
} }
#[test] #[actix_rt::test]
fn test_h2_content_length() { async fn test_h2_content_length() {
block_on(async { let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap();
let srv = TestServer::start(move || { let srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(|req: Request| { .h2(|req: Request| {
let indx: usize = req.uri().path()[1..].parse().unwrap(); let indx: usize = req.uri().path()[1..].parse().unwrap();
let statuses = [ let statuses = [
StatusCode::NO_CONTENT, StatusCode::NO_CONTENT,
StatusCode::CONTINUE, StatusCode::CONTINUE,
StatusCode::SWITCHING_PROTOCOLS, StatusCode::SWITCHING_PROTOCOLS,
StatusCode::PROCESSING, StatusCode::PROCESSING,
StatusCode::OK, StatusCode::OK,
StatusCode::NOT_FOUND, StatusCode::NOT_FOUND,
]; ];
future::ok::<_, ()>(Response::new(statuses[indx])) future::ok::<_, ()>(Response::new(statuses[indx]))
}) })
.map_err(|_| ()), .map_err(|_| ()),
) )
}); });
let header = HeaderName::from_static("content-length"); let header = HeaderName::from_static("content-length");
let value = HeaderValue::from_static("0"); let value = HeaderValue::from_static("0");
{ {
for i in 0..4 { for i in 0..4 {
let req = srv let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i))) .request(Method::GET, srv.surl(&format!("/{}", i)))
.send(); .send();
let response = req.await.unwrap(); let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), None); assert_eq!(response.headers().get(&header), None);
let req = srv let req = srv
.request(Method::HEAD, srv.surl(&format!("/{}", i))) .request(Method::HEAD, srv.surl(&format!("/{}", i)))
.send(); .send();
let response = req.await.unwrap(); let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), None); assert_eq!(response.headers().get(&header), None);
}
for i in 4..6 {
let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i)))
.send();
let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), Some(&value));
}
} }
})
for i in 4..6 {
let req = srv
.request(Method::GET, srv.surl(&format!("/{}", i)))
.send();
let response = req.await.unwrap();
assert_eq!(response.headers().get(&header), Some(&value));
}
}
} }
#[test] #[actix_rt::test]
fn test_h2_headers() { async fn test_h2_headers() {
block_on(async { let data = STR.repeat(10);
let data = STR.repeat(10); let data2 = data.clone();
let data2 = data.clone(); let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || { let mut srv = TestServer::start(move || {
let data = data.clone(); let data = data.clone();
pipeline_factory(rustls pipeline_factory(rustls
.clone() .clone()
.map_err(|e| println!("Rustls error: {}", e))) .map_err(|e| println!("Rustls error: {}", e)))
.and_then( .and_then(
@ -204,15 +195,14 @@ fn test_h2_headers() {
} }
future::ok::<_, ()>(config.body(data.clone())) future::ok::<_, ()>(config.body(data.clone()))
}).map_err(|_| ())) }).map_err(|_| ()))
}); });
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from(data2)); assert_eq!(bytes, Bytes::from(data2));
})
} }
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
@ -237,238 +227,215 @@ const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \ Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World"; Hello World Hello World Hello World Hello World Hello World";
#[test] #[actix_rt::test]
fn test_h2_body2() { async fn test_h2_body2() {
block_on(async { let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| future::ok::<_, ()>(Response::Ok().body(STR)))
.h2(|_| future::ok::<_, ()>(Response::Ok().body(STR))) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref())); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
} }
#[test] #[actix_rt::test]
fn test_h2_head_empty() { async fn test_h2_head_empty() {
block_on(async { let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .finish(|_| ok::<_, ()>(Response::Ok().body(STR)))
.finish(|_| ok::<_, ()>(Response::Ok().body(STR))) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
let response = srv.shead("/").send().await.unwrap(); let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.version(), Version::HTTP_2); assert_eq!(response.version(), Version::HTTP_2);
{ {
let len = response let len = response
.headers() .headers()
.get(http::header::CONTENT_LENGTH) .get(http::header::CONTENT_LENGTH)
.unwrap(); .unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap()); assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
} }
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert!(bytes.is_empty()); assert!(bytes.is_empty());
})
} }
#[test] #[actix_rt::test]
fn test_h2_head_binary() { async fn test_h2_head_binary() {
block_on(async { let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap(); let mut srv = TestServer::start(move || {
let mut srv = TestServer::start(move || { pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) .and_then(
.and_then( HttpService::build()
HttpService::build() .h2(|_| {
.h2(|_| { ok::<_, ()>(
Response::Ok().content_length(STR.len() as u64).body(STR),
)
})
.map_err(|_| ()),
)
});
let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success());
{
let len = response
.headers()
.get(http::header::CONTENT_LENGTH)
.unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
}
// read response
let bytes = srv.load_body(response).await.unwrap();
assert!(bytes.is_empty());
}
#[actix_rt::test]
async fn test_h2_head_binary2() {
let rustls = ssl_acceptor().unwrap();
let srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
.map_err(|_| ()),
)
});
let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success());
{
let len = response
.headers()
.get(http::header::CONTENT_LENGTH)
.unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
}
}
#[actix_rt::test]
async fn test_h2_body_length() {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| {
let body = once(ok(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok()
.body(body::SizedStream::new(STR.len() as u64, body)),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
}
#[actix_rt::test]
async fn test_h2_body_chunked_explicit() {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| {
let body =
once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok()
.header(header::TRANSFER_ENCODING, "chunked")
.streaming(body),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
// read response
let bytes = srv.load_body(response).await.unwrap();
// decode
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
}
#[actix_rt::test]
async fn test_h2_response_http_error_handling() {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(factory_fn_cfg(|_: &ServerConfig| {
ok::<_, ()>(service_fn2(|_| {
let broken_header = Bytes::from_static(b"\0\0\0");
ok::<_, ()>( ok::<_, ()>(
Response::Ok() Response::Ok()
.content_length(STR.len() as u64) .header(http::header::CONTENT_TYPE, broken_header)
.body(STR), .body(STR),
) )
})
.map_err(|_| ()),
)
});
let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success());
{
let len = response
.headers()
.get(http::header::CONTENT_LENGTH)
.unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
}
// read response
let bytes = srv.load_body(response).await.unwrap();
assert!(bytes.is_empty());
})
}
#[test]
fn test_h2_head_binary2() {
block_on(async {
let rustls = ssl_acceptor().unwrap();
let srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| ok::<_, ()>(Response::Ok().body(STR)))
.map_err(|_| ()),
)
});
let response = srv.shead("/").send().await.unwrap();
assert!(response.status().is_success());
{
let len = response
.headers()
.get(http::header::CONTENT_LENGTH)
.unwrap();
assert_eq!(format!("{}", STR.len()), len.to_str().unwrap());
}
})
}
#[test]
fn test_h2_body_length() {
block_on(async {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| {
let body = once(ok(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok().body(body::SizedStream::new(
STR.len() as u64,
body,
)),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
// read response
let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
}
#[test]
fn test_h2_body_chunked_explicit() {
block_on(async {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(|_| {
let body =
once(ok::<_, Error>(Bytes::from_static(STR.as_ref())));
ok::<_, ()>(
Response::Ok()
.header(header::TRANSFER_ENCODING, "chunked")
.streaming(body),
)
})
.map_err(|_| ()),
)
});
let response = srv.sget("/").send().await.unwrap();
assert!(response.status().is_success());
assert!(!response.headers().contains_key(header::TRANSFER_ENCODING));
// read response
let bytes = srv.load_body(response).await.unwrap();
// decode
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
})
}
#[test]
fn test_h2_response_http_error_handling() {
block_on(async {
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then(
HttpService::build()
.h2(factory_fn_cfg(|_: &ServerConfig| {
ok::<_, ()>(service_fn2(|_| {
let broken_header = Bytes::from_static(b"\0\0\0");
ok::<_, ()>(
Response::Ok()
.header(
http::header::CONTENT_TYPE,
broken_header,
)
.body(STR),
)
}))
})) }))
.map_err(|_| ()), }))
) .map_err(|_| ()),
}); )
});
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(response.status(), http::StatusCode::INTERNAL_SERVER_ERROR);
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(b"failed to parse header value")); assert_eq!(bytes, Bytes::from_static(b"failed to parse header value"));
})
} }
#[test] #[actix_rt::test]
fn test_h2_service_error() { async fn test_h2_service_error() {
block_on(async { let rustls = ssl_acceptor().unwrap();
let rustls = ssl_acceptor().unwrap();
let mut srv = TestServer::start(move || { let mut srv = TestServer::start(move || {
pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e))) pipeline_factory(rustls.clone().map_err(|e| println!("Rustls error: {}", e)))
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(|_| err::<Response, Error>(error::ErrorBadRequest("error"))) .h2(|_| err::<Response, Error>(error::ErrorBadRequest("error")))
.map_err(|_| ()), .map_err(|_| ()),
) )
}); });
let response = srv.sget("/").send().await.unwrap(); let response = srv.sget("/").send().await.unwrap();
assert_eq!(response.status(), http::StatusCode::BAD_REQUEST); assert_eq!(response.status(), http::StatusCode::BAD_REQUEST);
// read response // read response
let bytes = srv.load_body(response).await.unwrap(); let bytes = srv.load_body(response).await.unwrap();
assert_eq!(bytes, Bytes::from_static(b"error")); assert_eq!(bytes, Bytes::from_static(b"error"));
})
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_codec::{AsyncRead, AsyncWrite, Framed};
use actix_http::{body, h1, ws, Error, HttpService, Request, Response}; use actix_http::{body, h1, ws, Error, HttpService, Request, Response};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_utils::framed::FramedTransport; use actix_utils::framed::FramedTransport;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::future; use futures::future;
@ -34,53 +34,51 @@ async fn service(msg: ws::Frame) -> Result<ws::Message, Error> {
Ok(msg) Ok(msg)
} }
#[test] #[actix_rt::test]
fn test_simple() { async fn test_simple() {
block_on(async { let mut srv = TestServer::start(|| {
let mut srv = TestServer::start(|| { HttpService::build()
HttpService::build() .upgrade(actix_service::service_fn(ws_service))
.upgrade(actix_service::service_fn(ws_service)) .finish(|_| future::ok::<_, ()>(Response::NotFound()))
.finish(|_| future::ok::<_, ()>(Response::NotFound())) });
});
// client service // client service
let mut framed = srv.ws().await.unwrap(); let mut framed = srv.ws().await.unwrap();
framed framed
.send(ws::Message::Text("text".to_string())) .send(ws::Message::Text("text".to_string()))
.await .await
.unwrap(); .unwrap();
let (item, mut framed) = framed.into_future().await; let (item, mut framed) = framed.into_future().await;
assert_eq!( assert_eq!(
item.unwrap().unwrap(), item.unwrap().unwrap(),
ws::Frame::Text(Some(BytesMut::from("text"))) ws::Frame::Text(Some(BytesMut::from("text")))
); );
framed framed
.send(ws::Message::Binary("text".into())) .send(ws::Message::Binary("text".into()))
.await .await
.unwrap(); .unwrap();
let (item, mut framed) = framed.into_future().await; let (item, mut framed) = framed.into_future().await;
assert_eq!( assert_eq!(
item.unwrap().unwrap(), item.unwrap().unwrap(),
ws::Frame::Binary(Some(Bytes::from_static(b"text").into())) ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
); );
framed.send(ws::Message::Ping("text".into())).await.unwrap(); framed.send(ws::Message::Ping("text".into())).await.unwrap();
let (item, mut framed) = framed.into_future().await; let (item, mut framed) = framed.into_future().await;
assert_eq!( assert_eq!(
item.unwrap().unwrap(), item.unwrap().unwrap(),
ws::Frame::Pong("text".to_string().into()) ws::Frame::Pong("text".to_string().into())
); );
framed framed
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into()))) .send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
.await .await
.unwrap(); .unwrap();
let (item, _framed) = framed.into_future().await; let (item, _framed) = framed.into_future().await;
assert_eq!( assert_eq!(
item.unwrap().unwrap(), item.unwrap().unwrap(),
ws::Frame::Close(Some(ws::CloseCode::Normal.into())) ws::Frame::Close(Some(ws::CloseCode::Normal.into()))
); );
})
} }

View File

@ -607,144 +607,130 @@ mod tests {
use super::*; use super::*;
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
use actix_web::test::{self, block_on, TestRequest}; use actix_web::test::{self, TestRequest};
use actix_web::{web, App, Error, HttpResponse}; use actix_web::{web, App, Error, HttpResponse};
const COOKIE_KEY_MASTER: [u8; 32] = [0; 32]; const COOKIE_KEY_MASTER: [u8; 32] = [0; 32];
const COOKIE_NAME: &'static str = "actix_auth"; const COOKIE_NAME: &'static str = "actix_auth";
const COOKIE_LOGIN: &'static str = "test"; const COOKIE_LOGIN: &'static str = "test";
#[test] #[actix_rt::test]
fn test_identity() { async fn test_identity() {
block_on(async { let mut srv = test::init_service(
let mut srv = test::init_service( App::new()
App::new() .wrap(IdentityService::new(
.wrap(IdentityService::new( CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .domain("www.rust-lang.org")
.domain("www.rust-lang.org") .name(COOKIE_NAME)
.name(COOKIE_NAME) .path("/")
.path("/") .secure(true),
.secure(true), ))
)) .service(web::resource("/index").to(|id: Identity| {
.service(web::resource("/index").to(|id: Identity| { if id.identity().is_some() {
if id.identity().is_some() { HttpResponse::Created()
HttpResponse::Created() } else {
} else {
HttpResponse::Ok()
}
}))
.service(web::resource("/login").to(|id: Identity| {
id.remember(COOKIE_LOGIN.to_string());
HttpResponse::Ok() HttpResponse::Ok()
})) }
.service(web::resource("/logout").to(|id: Identity| { }))
if id.identity().is_some() { .service(web::resource("/login").to(|id: Identity| {
id.forget(); id.remember(COOKIE_LOGIN.to_string());
HttpResponse::Ok() HttpResponse::Ok()
} else { }))
HttpResponse::BadRequest() .service(web::resource("/logout").to(|id: Identity| {
} if id.identity().is_some() {
})), id.forget();
) HttpResponse::Ok()
.await; } else {
let resp = test::call_service( HttpResponse::BadRequest()
&mut srv, }
TestRequest::with_uri("/index").to_request(), })),
) )
.await; .await;
assert_eq!(resp.status(), StatusCode::OK); let resp =
test::call_service(&mut srv, TestRequest::with_uri("/index").to_request())
.await;
assert_eq!(resp.status(), StatusCode::OK);
let resp = test::call_service( let resp =
&mut srv, test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
TestRequest::with_uri("/login").to_request(), .await;
) assert_eq!(resp.status(), StatusCode::OK);
.await; let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(resp.status(), StatusCode::OK);
let c = resp.response().cookies().next().unwrap().to_owned();
let resp = test::call_service( let resp = test::call_service(
&mut srv, &mut srv,
TestRequest::with_uri("/index") TestRequest::with_uri("/index")
.cookie(c.clone()) .cookie(c.clone())
.to_request(), .to_request(),
) )
.await; .await;
assert_eq!(resp.status(), StatusCode::CREATED); assert_eq!(resp.status(), StatusCode::CREATED);
let resp = test::call_service( let resp = test::call_service(
&mut srv, &mut srv,
TestRequest::with_uri("/logout") TestRequest::with_uri("/logout")
.cookie(c.clone()) .cookie(c.clone())
.to_request(), .to_request(),
) )
.await; .await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert!(resp.headers().contains_key(header::SET_COOKIE)) assert!(resp.headers().contains_key(header::SET_COOKIE))
})
} }
#[test] #[actix_rt::test]
fn test_identity_max_age_time() { async fn test_identity_max_age_time() {
block_on(async { let duration = Duration::days(1);
let duration = Duration::days(1); let mut srv = test::init_service(
let mut srv = test::init_service( App::new()
App::new() .wrap(IdentityService::new(
.wrap(IdentityService::new( CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .domain("www.rust-lang.org")
.domain("www.rust-lang.org") .name(COOKIE_NAME)
.name(COOKIE_NAME) .path("/")
.path("/") .max_age_time(duration)
.max_age_time(duration) .secure(true),
.secure(true), ))
)) .service(web::resource("/login").to(|id: Identity| {
.service(web::resource("/login").to(|id: Identity| { id.remember("test".to_string());
id.remember("test".to_string()); HttpResponse::Ok()
HttpResponse::Ok() })),
})), )
) .await;
.await; let resp =
let resp = test::call_service( test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
&mut srv, .await;
TestRequest::with_uri("/login").to_request(), assert_eq!(resp.status(), StatusCode::OK);
) assert!(resp.headers().contains_key(header::SET_COOKIE));
.await; let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(duration, c.max_age().unwrap());
assert!(resp.headers().contains_key(header::SET_COOKIE));
let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(duration, c.max_age().unwrap());
})
} }
#[test] #[actix_rt::test]
fn test_identity_max_age() { async fn test_identity_max_age() {
block_on(async { let seconds = 60;
let seconds = 60; let mut srv = test::init_service(
let mut srv = test::init_service( App::new()
App::new() .wrap(IdentityService::new(
.wrap(IdentityService::new( CookieIdentityPolicy::new(&COOKIE_KEY_MASTER)
CookieIdentityPolicy::new(&COOKIE_KEY_MASTER) .domain("www.rust-lang.org")
.domain("www.rust-lang.org") .name(COOKIE_NAME)
.name(COOKIE_NAME) .path("/")
.path("/") .max_age(seconds)
.max_age(seconds) .secure(true),
.secure(true), ))
)) .service(web::resource("/login").to(|id: Identity| {
.service(web::resource("/login").to(|id: Identity| { id.remember("test".to_string());
id.remember("test".to_string()); HttpResponse::Ok()
HttpResponse::Ok() })),
})), )
) .await;
.await; let resp =
let resp = test::call_service( test::call_service(&mut srv, TestRequest::with_uri("/login").to_request())
&mut srv, .await;
TestRequest::with_uri("/login").to_request(), assert_eq!(resp.status(), StatusCode::OK);
) assert!(resp.headers().contains_key(header::SET_COOKIE));
.await; let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(Duration::seconds(seconds as i64), c.max_age().unwrap());
assert!(resp.headers().contains_key(header::SET_COOKIE));
let c = resp.response().cookies().next().unwrap().to_owned();
assert_eq!(Duration::seconds(seconds as i64), c.max_age().unwrap());
})
} }
async fn create_identity_server< async fn create_identity_server<
@ -885,223 +871,202 @@ mod tests {
assert!(cookies.get(COOKIE_NAME).is_none()); assert!(cookies.get(COOKIE_NAME).is_none());
} }
#[test] #[actix_rt::test]
fn test_identity_legacy_cookie_is_set() { async fn test_identity_legacy_cookie_is_set() {
block_on(async { let mut srv = create_identity_server(|c| c).await;
let mut srv = create_identity_server(|c| c).await; let mut resp =
let mut resp = test::call_service(&mut srv, TestRequest::with_uri("/").to_request()).await;
test::call_service(&mut srv, TestRequest::with_uri("/").to_request()) assert_legacy_login_cookie(&mut resp, COOKIE_LOGIN);
.await; assert_logged_in(resp, None).await;
assert_legacy_login_cookie(&mut resp, COOKIE_LOGIN);
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_legacy_cookie_works() { async fn test_identity_legacy_cookie_works() {
block_on(async { let mut srv = create_identity_server(|c| c).await;
let mut srv = create_identity_server(|c| c).await; let cookie = legacy_login_cookie(COOKIE_LOGIN);
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_no_login_cookie(&mut resp);
assert_no_login_cookie(&mut resp); assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_legacy_cookie_rejected_if_visit_timestamp_needed() { async fn test_identity_legacy_cookie_rejected_if_visit_timestamp_needed() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await; let cookie = legacy_login_cookie(COOKIE_LOGIN);
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NoTimestamp,
LoginTimestampCheck::NoTimestamp, VisitTimeStampCheck::NewTimestamp,
VisitTimeStampCheck::NewTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_legacy_cookie_rejected_if_login_timestamp_needed() { async fn test_identity_legacy_cookie_rejected_if_login_timestamp_needed() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
create_identity_server(|c| c.login_deadline(Duration::days(90))).await; let cookie = legacy_login_cookie(COOKIE_LOGIN);
let cookie = legacy_login_cookie(COOKIE_LOGIN); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NewTimestamp,
LoginTimestampCheck::NewTimestamp, VisitTimeStampCheck::NoTimestamp,
VisitTimeStampCheck::NoTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_rejected_if_login_timestamp_needed() { async fn test_identity_cookie_rejected_if_login_timestamp_needed() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
create_identity_server(|c| c.login_deadline(Duration::days(90))).await; let cookie = login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now()));
let cookie = login_cookie(COOKIE_LOGIN, None, Some(SystemTime::now())); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NewTimestamp,
LoginTimestampCheck::NewTimestamp, VisitTimeStampCheck::NoTimestamp,
VisitTimeStampCheck::NoTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_rejected_if_visit_timestamp_needed() { async fn test_identity_cookie_rejected_if_visit_timestamp_needed() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await; let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NoTimestamp,
LoginTimestampCheck::NoTimestamp, VisitTimeStampCheck::NewTimestamp,
VisitTimeStampCheck::NewTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_rejected_if_login_timestamp_too_old() { async fn test_identity_cookie_rejected_if_login_timestamp_too_old() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
create_identity_server(|c| c.login_deadline(Duration::days(90))).await; let cookie = login_cookie(
let cookie = login_cookie( COOKIE_LOGIN,
COOKIE_LOGIN, Some(SystemTime::now() - Duration::days(180).to_std().unwrap()),
Some(SystemTime::now() - Duration::days(180).to_std().unwrap()), None,
None, );
); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NewTimestamp,
LoginTimestampCheck::NewTimestamp, VisitTimeStampCheck::NoTimestamp,
VisitTimeStampCheck::NoTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_rejected_if_visit_timestamp_too_old() { async fn test_identity_cookie_rejected_if_visit_timestamp_too_old() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.visit_deadline(Duration::days(90))).await;
create_identity_server(|c| c.visit_deadline(Duration::days(90))).await; let cookie = login_cookie(
let cookie = login_cookie( COOKIE_LOGIN,
COOKIE_LOGIN, None,
None, Some(SystemTime::now() - Duration::days(180).to_std().unwrap()),
Some(SystemTime::now() - Duration::days(180).to_std().unwrap()), );
); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_login_cookie(
assert_login_cookie( &mut resp,
&mut resp, COOKIE_LOGIN,
COOKIE_LOGIN, LoginTimestampCheck::NoTimestamp,
LoginTimestampCheck::NoTimestamp, VisitTimeStampCheck::NewTimestamp,
VisitTimeStampCheck::NewTimestamp, );
); assert_logged_in(resp, None).await;
assert_logged_in(resp, None).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_not_updated_on_login_deadline() { async fn test_identity_cookie_not_updated_on_login_deadline() {
block_on(async { let mut srv =
let mut srv = create_identity_server(|c| c.login_deadline(Duration::days(90))).await;
create_identity_server(|c| c.login_deadline(Duration::days(90))).await; let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None);
let cookie = login_cookie(COOKIE_LOGIN, Some(SystemTime::now()), None); let mut resp = test::call_service(
let mut resp = test::call_service( &mut srv,
&mut srv, TestRequest::with_uri("/")
TestRequest::with_uri("/") .cookie(cookie.clone())
.cookie(cookie.clone()) .to_request(),
.to_request(), )
) .await;
.await; assert_no_login_cookie(&mut resp);
assert_no_login_cookie(&mut resp); assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
})
} }
#[test] #[actix_rt::test]
fn test_identity_cookie_updated_on_visit_deadline() { async fn test_identity_cookie_updated_on_visit_deadline() {
block_on(async { let mut srv = create_identity_server(|c| {
let mut srv = create_identity_server(|c| { c.visit_deadline(Duration::days(90))
c.visit_deadline(Duration::days(90)) .login_deadline(Duration::days(90))
.login_deadline(Duration::days(90))
})
.await;
let timestamp = SystemTime::now() - Duration::days(1).to_std().unwrap();
let cookie = login_cookie(COOKIE_LOGIN, Some(timestamp), Some(timestamp));
let mut resp = test::call_service(
&mut srv,
TestRequest::with_uri("/")
.cookie(cookie.clone())
.to_request(),
)
.await;
assert_login_cookie(
&mut resp,
COOKIE_LOGIN,
LoginTimestampCheck::OldTimestamp(timestamp),
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
}) })
.await;
let timestamp = SystemTime::now() - Duration::days(1).to_std().unwrap();
let cookie = login_cookie(COOKIE_LOGIN, Some(timestamp), Some(timestamp));
let mut resp = test::call_service(
&mut srv,
TestRequest::with_uri("/")
.cookie(cookie.clone())
.to_request(),
)
.await;
assert_login_cookie(
&mut resp,
COOKIE_LOGIN,
LoginTimestampCheck::OldTimestamp(timestamp),
VisitTimeStampCheck::NewTimestamp,
);
assert_logged_in(resp, Some(COOKIE_LOGIN)).await;
} }
} }

View File

@ -813,12 +813,11 @@ mod tests {
use actix_http::h1::Payload; use actix_http::h1::Payload;
use actix_utils::mpsc; use actix_utils::mpsc;
use actix_web::http::header::{DispositionParam, DispositionType}; use actix_web::http::header::{DispositionParam, DispositionType};
use actix_web::test::block_on;
use bytes::Bytes; use bytes::Bytes;
use futures::future::lazy; use futures::future::lazy;
#[test] #[actix_rt::test]
fn test_boundary() { async fn test_boundary() {
let headers = HeaderMap::new(); let headers = HeaderMap::new();
match Multipart::boundary(&headers) { match Multipart::boundary(&headers) {
Err(MultipartError::NoContentType) => (), Err(MultipartError::NoContentType) => (),
@ -891,246 +890,228 @@ mod tests {
(bytes, headers) (bytes, headers)
} }
#[test] #[actix_rt::test]
fn test_multipart_no_end_crlf() { async fn test_multipart_no_end_crlf() {
block_on(async { let (sender, payload) = create_stream();
let (sender, payload) = create_stream(); let (bytes, headers) = create_simple_request_with_header();
let (bytes, headers) = create_simple_request_with_header(); let bytes_stripped = bytes.slice_to(bytes.len()); // strip crlf
let bytes_stripped = bytes.slice_to(bytes.len()); // strip crlf
sender.send(Ok(bytes_stripped)).unwrap(); sender.send(Ok(bytes_stripped)).unwrap();
drop(sender); // eof drop(sender); // eof
let mut multipart = Multipart::new(&headers, payload); let mut multipart = Multipart::new(&headers, payload);
match multipart.next().await.unwrap() { match multipart.next().await.unwrap() {
Ok(_) => (), Ok(_) => (),
_ => unreachable!(), _ => unreachable!(),
} }
match multipart.next().await.unwrap() { match multipart.next().await.unwrap() {
Ok(_) => (), Ok(_) => (),
_ => unreachable!(), _ => unreachable!(),
} }
match multipart.next().await { match multipart.next().await {
None => (), None => (),
_ => unreachable!(), _ => unreachable!(),
} }
})
} }
#[test] #[actix_rt::test]
fn test_multipart() { async fn test_multipart() {
block_on(async { let (sender, payload) = create_stream();
let (sender, payload) = create_stream(); let (bytes, headers) = create_simple_request_with_header();
let (bytes, headers) = create_simple_request_with_header();
sender.send(Ok(bytes)).unwrap(); sender.send(Ok(bytes)).unwrap();
let mut multipart = Multipart::new(&headers, payload); let mut multipart = Multipart::new(&headers, payload);
match multipart.next().await { match multipart.next().await {
Some(Ok(mut field)) => { Some(Ok(mut field)) => {
let cd = field.content_disposition().unwrap(); let cd = field.content_disposition().unwrap();
assert_eq!(cd.disposition, DispositionType::FormData); assert_eq!(cd.disposition, DispositionType::FormData);
assert_eq!(cd.parameters[0], DispositionParam::Name("file".into())); assert_eq!(cd.parameters[0], DispositionParam::Name("file".into()));
assert_eq!(field.content_type().type_(), mime::TEXT); assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN); assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await.unwrap() { match field.next().await.unwrap() {
Ok(chunk) => assert_eq!(chunk, "test"), Ok(chunk) => assert_eq!(chunk, "test"),
_ => unreachable!(), _ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(), match field.next().await {
} None => (),
_ => unreachable!(),
match multipart.next().await.unwrap() {
Ok(mut field) => {
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await {
Some(Ok(chunk)) => assert_eq!(chunk, "data"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(),
} }
_ => unreachable!(),
}
match multipart.next().await { match multipart.next().await.unwrap() {
None => (), Ok(mut field) => {
_ => unreachable!(), assert_eq!(field.content_type().type_(), mime::TEXT);
} assert_eq!(field.content_type().subtype(), mime::PLAIN);
});
}
#[test] match field.next().await {
fn test_stream() { Some(Ok(chunk)) => assert_eq!(chunk, "data"),
block_on(async { _ => unreachable!(),
let (sender, payload) = create_stream();
let (bytes, headers) = create_simple_request_with_header();
sender.send(Ok(bytes)).unwrap();
let mut multipart = Multipart::new(&headers, payload);
match multipart.next().await.unwrap() {
Ok(mut field) => {
let cd = field.content_disposition().unwrap();
assert_eq!(cd.disposition, DispositionType::FormData);
assert_eq!(cd.parameters[0], DispositionParam::Name("file".into()));
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await.unwrap() {
Ok(chunk) => assert_eq!(chunk, "test"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(), match field.next().await {
} None => (),
_ => unreachable!(),
match multipart.next().await {
Some(Ok(mut field)) => {
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await {
Some(Ok(chunk)) => assert_eq!(chunk, "data"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
_ => unreachable!(),
} }
_ => unreachable!(),
}
match multipart.next().await { match multipart.next().await {
None => (), None => (),
_ => unreachable!(), _ => unreachable!(),
}
}
#[actix_rt::test]
async fn test_stream() {
let (sender, payload) = create_stream();
let (bytes, headers) = create_simple_request_with_header();
sender.send(Ok(bytes)).unwrap();
let mut multipart = Multipart::new(&headers, payload);
match multipart.next().await.unwrap() {
Ok(mut field) => {
let cd = field.content_disposition().unwrap();
assert_eq!(cd.disposition, DispositionType::FormData);
assert_eq!(cd.parameters[0], DispositionParam::Name("file".into()));
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await.unwrap() {
Ok(chunk) => assert_eq!(chunk, "test"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
} }
}); _ => unreachable!(),
}
match multipart.next().await {
Some(Ok(mut field)) => {
assert_eq!(field.content_type().type_(), mime::TEXT);
assert_eq!(field.content_type().subtype(), mime::PLAIN);
match field.next().await {
Some(Ok(chunk)) => assert_eq!(chunk, "data"),
_ => unreachable!(),
}
match field.next().await {
None => (),
_ => unreachable!(),
}
}
_ => unreachable!(),
}
match multipart.next().await {
None => (),
_ => unreachable!(),
}
} }
#[test] #[actix_rt::test]
fn test_basic() { async fn test_basic() {
block_on(async { let (_, payload) = Payload::create(false);
let (_, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload);
assert_eq!(payload.buf.len(), 0); assert_eq!(payload.buf.len(), 0);
lazy(|cx| payload.poll_stream(cx)).await.unwrap(); lazy(|cx| payload.poll_stream(cx)).await.unwrap();
assert_eq!(None, payload.read_max(1).unwrap()); assert_eq!(None, payload.read_max(1).unwrap());
})
} }
#[test] #[actix_rt::test]
fn test_eof() { async fn test_eof() {
block_on(async { let (mut sender, payload) = Payload::create(false);
let (mut sender, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload);
assert_eq!(None, payload.read_max(4).unwrap()); assert_eq!(None, payload.read_max(4).unwrap());
sender.feed_data(Bytes::from("data")); sender.feed_data(Bytes::from("data"));
sender.feed_eof(); sender.feed_eof();
lazy(|cx| payload.poll_stream(cx)).await.unwrap(); lazy(|cx| payload.poll_stream(cx)).await.unwrap();
assert_eq!(Some(Bytes::from("data")), payload.read_max(4).unwrap()); assert_eq!(Some(Bytes::from("data")), payload.read_max(4).unwrap());
assert_eq!(payload.buf.len(), 0); assert_eq!(payload.buf.len(), 0);
assert!(payload.read_max(1).is_err()); assert!(payload.read_max(1).is_err());
assert!(payload.eof); assert!(payload.eof);
})
} }
#[test] #[actix_rt::test]
fn test_err() { async fn test_err() {
block_on(async { let (mut sender, payload) = Payload::create(false);
let (mut sender, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload); assert_eq!(None, payload.read_max(1).unwrap());
assert_eq!(None, payload.read_max(1).unwrap()); sender.set_error(PayloadError::Incomplete(None));
sender.set_error(PayloadError::Incomplete(None)); lazy(|cx| payload.poll_stream(cx)).await.err().unwrap();
lazy(|cx| payload.poll_stream(cx)).await.err().unwrap();
})
} }
#[test] #[actix_rt::test]
fn test_readmax() { async fn test_readmax() {
block_on(async { let (mut sender, payload) = Payload::create(false);
let (mut sender, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload);
sender.feed_data(Bytes::from("line1")); sender.feed_data(Bytes::from("line1"));
sender.feed_data(Bytes::from("line2")); sender.feed_data(Bytes::from("line2"));
lazy(|cx| payload.poll_stream(cx)).await.unwrap(); lazy(|cx| payload.poll_stream(cx)).await.unwrap();
assert_eq!(payload.buf.len(), 10); assert_eq!(payload.buf.len(), 10);
assert_eq!(Some(Bytes::from("line1")), payload.read_max(5).unwrap()); assert_eq!(Some(Bytes::from("line1")), payload.read_max(5).unwrap());
assert_eq!(payload.buf.len(), 5); assert_eq!(payload.buf.len(), 5);
assert_eq!(Some(Bytes::from("line2")), payload.read_max(5).unwrap()); assert_eq!(Some(Bytes::from("line2")), payload.read_max(5).unwrap());
assert_eq!(payload.buf.len(), 0); assert_eq!(payload.buf.len(), 0);
})
} }
#[test] #[actix_rt::test]
fn test_readexactly() { async fn test_readexactly() {
block_on(async { let (mut sender, payload) = Payload::create(false);
let (mut sender, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload);
assert_eq!(None, payload.read_exact(2)); assert_eq!(None, payload.read_exact(2));
sender.feed_data(Bytes::from("line1")); sender.feed_data(Bytes::from("line1"));
sender.feed_data(Bytes::from("line2")); sender.feed_data(Bytes::from("line2"));
lazy(|cx| payload.poll_stream(cx)).await.unwrap(); lazy(|cx| payload.poll_stream(cx)).await.unwrap();
assert_eq!(Some(Bytes::from_static(b"li")), payload.read_exact(2)); assert_eq!(Some(Bytes::from_static(b"li")), payload.read_exact(2));
assert_eq!(payload.buf.len(), 8); assert_eq!(payload.buf.len(), 8);
assert_eq!(Some(Bytes::from_static(b"ne1l")), payload.read_exact(4)); assert_eq!(Some(Bytes::from_static(b"ne1l")), payload.read_exact(4));
assert_eq!(payload.buf.len(), 4); assert_eq!(payload.buf.len(), 4);
})
} }
#[test] #[actix_rt::test]
fn test_readuntil() { async fn test_readuntil() {
block_on(async { let (mut sender, payload) = Payload::create(false);
let (mut sender, payload) = Payload::create(false); let mut payload = PayloadBuffer::new(payload);
let mut payload = PayloadBuffer::new(payload);
assert_eq!(None, payload.read_until(b"ne").unwrap()); assert_eq!(None, payload.read_until(b"ne").unwrap());
sender.feed_data(Bytes::from("line1")); sender.feed_data(Bytes::from("line1"));
sender.feed_data(Bytes::from("line2")); sender.feed_data(Bytes::from("line2"));
lazy(|cx| payload.poll_stream(cx)).await.unwrap(); lazy(|cx| payload.poll_stream(cx)).await.unwrap();
assert_eq!( assert_eq!(
Some(Bytes::from("line")), Some(Bytes::from("line")),
payload.read_until(b"ne").unwrap() payload.read_until(b"ne").unwrap()
); );
assert_eq!(payload.buf.len(), 6); assert_eq!(payload.buf.len(), 6);
assert_eq!( assert_eq!(
Some(Bytes::from("1line2")), Some(Bytes::from("1line2")),
payload.read_until(b"2").unwrap() payload.read_until(b"2").unwrap()
); );
assert_eq!(payload.buf.len(), 0); assert_eq!(payload.buf.len(), 0);
})
} }
} }

View File

@ -364,125 +364,117 @@ mod tests {
use actix_web::{test, web, App}; use actix_web::{test, web, App};
use bytes::Bytes; use bytes::Bytes;
#[test] #[actix_rt::test]
fn cookie_session() { async fn cookie_session() {
test::block_on(async { let mut app = test::init_service(
let mut app = test::init_service( App::new()
App::new() .wrap(CookieSession::signed(&[0; 32]).secure(false))
.wrap(CookieSession::signed(&[0; 32]).secure(false)) .service(web::resource("/").to(|ses: Session| {
.service(web::resource("/").to(|ses: Session| { async move {
async move { let _ = ses.set("counter", 100);
let _ = ses.set("counter", 100); "test"
"test" }
} })),
})), )
) .await;
.await;
let request = test::TestRequest::get().to_request(); let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap(); let response = app.call(request).await.unwrap();
assert!(response assert!(response
.response() .response()
.cookies() .cookies()
.find(|c| c.name() == "actix-session") .find(|c| c.name() == "actix-session")
.is_some()); .is_some());
})
} }
#[test] #[actix_rt::test]
fn private_cookie() { async fn private_cookie() {
test::block_on(async { let mut app = test::init_service(
let mut app = test::init_service( App::new()
App::new() .wrap(CookieSession::private(&[0; 32]).secure(false))
.wrap(CookieSession::private(&[0; 32]).secure(false)) .service(web::resource("/").to(|ses: Session| {
.service(web::resource("/").to(|ses: Session| { async move {
async move { let _ = ses.set("counter", 100);
let _ = ses.set("counter", 100); "test"
"test" }
} })),
})), )
) .await;
.await;
let request = test::TestRequest::get().to_request(); let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap(); let response = app.call(request).await.unwrap();
assert!(response assert!(response
.response() .response()
.cookies() .cookies()
.find(|c| c.name() == "actix-session") .find(|c| c.name() == "actix-session")
.is_some()); .is_some());
})
} }
#[test] #[actix_rt::test]
fn cookie_session_extractor() { async fn cookie_session_extractor() {
test::block_on(async { let mut app = test::init_service(
let mut app = test::init_service( App::new()
App::new() .wrap(CookieSession::signed(&[0; 32]).secure(false))
.wrap(CookieSession::signed(&[0; 32]).secure(false)) .service(web::resource("/").to(|ses: Session| {
.service(web::resource("/").to(|ses: Session| { async move {
async move { let _ = ses.set("counter", 100);
let _ = ses.set("counter", 100); "test"
"test" }
} })),
})), )
) .await;
.await;
let request = test::TestRequest::get().to_request(); let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap(); let response = app.call(request).await.unwrap();
assert!(response assert!(response
.response() .response()
.cookies() .cookies()
.find(|c| c.name() == "actix-session") .find(|c| c.name() == "actix-session")
.is_some()); .is_some());
})
} }
#[test] #[actix_rt::test]
fn basics() { async fn basics() {
test::block_on(async { let mut app = test::init_service(
let mut app = test::init_service( App::new()
App::new() .wrap(
.wrap( CookieSession::signed(&[0; 32])
CookieSession::signed(&[0; 32]) .path("/test/")
.path("/test/") .name("actix-test")
.name("actix-test") .domain("localhost")
.domain("localhost") .http_only(true)
.http_only(true) .same_site(SameSite::Lax)
.same_site(SameSite::Lax) .max_age(100),
.max_age(100), )
) .service(web::resource("/").to(|ses: Session| {
.service(web::resource("/").to(|ses: Session| { async move {
async move { let _ = ses.set("counter", 100);
let _ = ses.set("counter", 100); "test"
"test" }
} }))
})) .service(web::resource("/test/").to(|ses: Session| {
.service(web::resource("/test/").to(|ses: Session| { async move {
async move { let val: usize = ses.get("counter").unwrap().unwrap();
let val: usize = ses.get("counter").unwrap().unwrap(); format!("counter: {}", val)
format!("counter: {}", val) }
} })),
})), )
) .await;
.await;
let request = test::TestRequest::get().to_request(); let request = test::TestRequest::get().to_request();
let response = app.call(request).await.unwrap(); let response = app.call(request).await.unwrap();
let cookie = response let cookie = response
.response() .response()
.cookies() .cookies()
.find(|c| c.name() == "actix-test") .find(|c| c.name() == "actix-test")
.unwrap() .unwrap()
.clone(); .clone();
assert_eq!(cookie.path().unwrap(), "/test/"); assert_eq!(cookie.path().unwrap(), "/test/");
let request = test::TestRequest::with_uri("/test/") let request = test::TestRequest::with_uri("/test/")
.cookie(cookie) .cookie(cookie)
.to_request(); .to_request();
let body = test::read_response(&mut app, request).await; let body = test::read_response(&mut app, request).await;
assert_eq!(body, Bytes::from_static(b"counter: 100")); assert_eq!(body, Bytes::from_static(b"counter: 100"));
})
} }
} }

View File

@ -17,6 +17,7 @@ syn = { version = "^1", features = ["full", "parsing"] }
proc-macro2 = "^1" proc-macro2 = "^1"
[dev-dependencies] [dev-dependencies]
actix-rt = { version = "1.0.0-alpha.1" }
actix-web = { version = "2.0.0-alpha.1" } actix-web = { version = "2.0.0-alpha.1" }
actix-http = { version = "0.3.0-alpha.1", features=["openssl"] } actix-http = { version = "0.3.0-alpha.1", features=["openssl"] }
actix-http-test = { version = "0.3.0-alpha.1", features=["openssl"] } actix-http-test = { version = "0.3.0-alpha.1", features=["openssl"] }

View File

@ -1,5 +1,5 @@
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_web::{http, web::Path, App, HttpResponse, Responder}; use actix_web::{http, web::Path, App, HttpResponse, Responder};
use actix_web_codegen::{connect, delete, get, head, options, patch, post, put, trace}; use actix_web_codegen::{connect, delete, get, head, options, patch, post, put, trace};
use futures::{future, Future}; use futures::{future, Future};
@ -69,95 +69,89 @@ async fn get_param_test(_: Path<String>) -> impl Responder {
HttpResponse::Ok() HttpResponse::Ok()
} }
#[test] #[actix_rt::test]
fn test_params() { async fn test_params() {
block_on(async { let srv = TestServer::start(|| {
let srv = TestServer::start(|| { HttpService::new(
HttpService::new( App::new()
App::new() .service(get_param_test)
.service(get_param_test) .service(put_param_test)
.service(put_param_test) .service(delete_param_test),
.service(delete_param_test), )
) });
});
let request = srv.request(http::Method::GET, srv.url("/test/it")); let request = srv.request(http::Method::GET, srv.url("/test/it"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert_eq!(response.status(), http::StatusCode::OK); assert_eq!(response.status(), http::StatusCode::OK);
let request = srv.request(http::Method::PUT, srv.url("/test/it")); let request = srv.request(http::Method::PUT, srv.url("/test/it"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert_eq!(response.status(), http::StatusCode::CREATED); assert_eq!(response.status(), http::StatusCode::CREATED);
let request = srv.request(http::Method::DELETE, srv.url("/test/it")); let request = srv.request(http::Method::DELETE, srv.url("/test/it"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert_eq!(response.status(), http::StatusCode::NO_CONTENT); assert_eq!(response.status(), http::StatusCode::NO_CONTENT);
})
} }
#[test] #[actix_rt::test]
fn test_body() { async fn test_body() {
block_on(async { let srv = TestServer::start(|| {
let srv = TestServer::start(|| { HttpService::new(
HttpService::new( App::new()
App::new() .service(post_test)
.service(post_test) .service(put_test)
.service(put_test) .service(head_test)
.service(head_test) .service(connect_test)
.service(connect_test) .service(options_test)
.service(options_test) .service(trace_test)
.service(trace_test) .service(patch_test)
.service(patch_test) .service(test),
.service(test), )
) });
}); let request = srv.request(http::Method::GET, srv.url("/test"));
let request = srv.request(http::Method::GET, srv.url("/test")); let response = request.send().await.unwrap();
let response = request.send().await.unwrap(); assert!(response.status().is_success());
assert!(response.status().is_success());
let request = srv.request(http::Method::HEAD, srv.url("/test")); let request = srv.request(http::Method::HEAD, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.request(http::Method::CONNECT, srv.url("/test")); let request = srv.request(http::Method::CONNECT, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.request(http::Method::OPTIONS, srv.url("/test")); let request = srv.request(http::Method::OPTIONS, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.request(http::Method::TRACE, srv.url("/test")); let request = srv.request(http::Method::TRACE, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.request(http::Method::PATCH, srv.url("/test")); let request = srv.request(http::Method::PATCH, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
let request = srv.request(http::Method::PUT, srv.url("/test")); let request = srv.request(http::Method::PUT, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.status(), http::StatusCode::CREATED); assert_eq!(response.status(), http::StatusCode::CREATED);
let request = srv.request(http::Method::POST, srv.url("/test")); let request = srv.request(http::Method::POST, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.status(), http::StatusCode::NO_CONTENT); assert_eq!(response.status(), http::StatusCode::NO_CONTENT);
let request = srv.request(http::Method::GET, srv.url("/test")); let request = srv.request(http::Method::GET, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
})
} }
#[test] #[actix_rt::test]
fn test_auto_async() { async fn test_auto_async() {
block_on(async { let srv = TestServer::start(|| HttpService::new(App::new().service(auto_async)));
let srv = TestServer::start(|| HttpService::new(App::new().service(auto_async)));
let request = srv.request(http::Method::GET, srv.url("/test")); let request = srv.request(http::Method::GET, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
})
} }

View File

@ -30,7 +30,7 @@ default = ["brotli", "flate2-zlib"]
openssl = ["open-ssl", "actix-http/openssl"] openssl = ["open-ssl", "actix-http/openssl"]
# rustls # rustls
# rustls = ["rust-tls", "actix-http/rustls"] rustls = ["rust-tls", "actix-http/rustls"]
# brotli encoding, requires c compiler # brotli encoding, requires c compiler
brotli = ["actix-http/brotli"] brotli = ["actix-http/brotli"]
@ -45,6 +45,7 @@ flate2-rust = ["actix-http/flate2-rust"]
actix-codec = "0.2.0-alpha.1" actix-codec = "0.2.0-alpha.1"
actix-service = "1.0.0-alpha.1" actix-service = "1.0.0-alpha.1"
actix-http = "0.3.0-alpha.1" actix-http = "0.3.0-alpha.1"
actix-rt = "1.0.0-alpha.1"
base64 = "0.10.1" base64 = "0.10.1"
bytes = "0.4" bytes = "0.4"
@ -57,12 +58,10 @@ rand = "0.7"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_urlencoded = "0.6.1" serde_urlencoded = "0.6.1"
tokio-timer = "0.3.0-alpha.6"
open-ssl = { version="0.10", package="openssl", optional = true } open-ssl = { version="0.10", package="openssl", optional = true }
rust-tls = { version = "0.16.0", package="rustls", optional = true, features = ["dangerous_configuration"] } rust-tls = { version = "0.16.0", package="rustls", optional = true, features = ["dangerous_configuration"] }
[dev-dependencies] [dev-dependencies]
actix-rt = "1.0.0-alpha.1"
actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] } actix-connect = { version = "1.0.0-alpha.1", features=["openssl"] }
actix-web = { version = "2.0.0-alpha.1", features=["openssl"] } actix-web = { version = "2.0.0-alpha.1", features=["openssl"] }
actix-http = { version = "0.3.0-alpha.1", features=["openssl"] } actix-http = { version = "0.3.0-alpha.1", features=["openssl"] }
@ -73,5 +72,4 @@ brotli2 = { version="0.3.2" }
flate2 = { version="1.0.2" } flate2 = { version="1.0.2" }
env_logger = "0.6" env_logger = "0.6"
rand = "0.7" rand = "0.7"
tokio-tcp = "0.1"
webpki = { version = "0.21" } webpki = { version = "0.21" }

View File

@ -6,19 +6,16 @@
//! use actix_rt::System; //! use actix_rt::System;
//! use awc::Client; //! use awc::Client;
//! //!
//! fn main() { //! #[actix_rt::main]
//! System::new("test").block_on(async { //! async fn main() {
//! let mut client = Client::default(); //! let mut client = Client::default();
//! //!
//! client.get("http://www.rust-lang.org") // <- Create request builder //! let response = client.get("http://www.rust-lang.org") // <- Create request builder
//! .header("User-Agent", "Actix-web") //! .header("User-Agent", "Actix-web")
//! .send() // <- Send http request //! .send() // <- Send http request
//! .await //! .await;
//! .and_then(|response| { // <- server http response //!
//! println!("Response: {:?}", response); //! println!("Response: {:?}", response);
//! Ok(())
//! })
//! });
//! } //! }
//! ``` //! ```
use std::cell::RefCell; use std::cell::RefCell;

View File

@ -39,19 +39,18 @@ const HTTPS_ENCODING: &str = "gzip, deflate";
/// ```rust /// ```rust
/// use actix_rt::System; /// use actix_rt::System;
/// ///
/// fn main() { /// #[actix_rt::main]
/// System::new("test").block_on(async { /// async fn main() {
/// let response = awc::Client::new() /// let response = awc::Client::new()
/// .get("http://www.rust-lang.org") // <- Create request builder /// .get("http://www.rust-lang.org") // <- Create request builder
/// .header("User-Agent", "Actix-web") /// .header("User-Agent", "Actix-web")
/// .send() // <- Send http request /// .send() // <- Send http request
/// .await; /// .await;
/// ///
/// response.and_then(|response| { // <- server http response /// response.and_then(|response| { // <- server http response
/// println!("Response: {:?}", response); /// println!("Response: {:?}", response);
/// Ok(()) /// Ok(())
/// }) /// });
/// });
/// } /// }
/// ``` /// ```
pub struct ClientRequest { pub struct ClientRequest {
@ -308,25 +307,21 @@ impl ClientRequest {
/// Set a cookie /// Set a cookie
/// ///
/// ```rust /// ```rust
/// # use actix_rt::System; /// #[actix_rt::main]
/// fn main() { /// async fn main() {
/// System::new("test").block_on(async { /// let resp = awc::Client::new().get("https://www.rust-lang.org")
/// awc::Client::new().get("https://www.rust-lang.org") /// .cookie(
/// .cookie( /// awc::http::Cookie::build("name", "value")
/// awc::http::Cookie::build("name", "value") /// .domain("www.rust-lang.org")
/// .domain("www.rust-lang.org") /// .path("/")
/// .path("/") /// .secure(true)
/// .secure(true) /// .http_only(true)
/// .http_only(true) /// .finish(),
/// .finish(), /// )
/// ) /// .send()
/// .send() /// .await;
/// .await ///
/// .and_then(|response| { /// println!("Response: {:?}", resp);
/// println!("Response: {:?}", response);
/// Ok(())
/// })
/// });
/// } /// }
/// ``` /// ```
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {

View File

@ -358,41 +358,37 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use actix_http_test::block_on;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{http::header, test::TestResponse}; use crate::{http::header, test::TestResponse};
#[test] #[actix_rt::test]
fn test_body() { async fn test_body() {
block_on(async { let mut req = TestResponse::with_header(header::CONTENT_LENGTH, "xxxx").finish();
let mut req = match req.body().await.err().unwrap() {
TestResponse::with_header(header::CONTENT_LENGTH, "xxxx").finish(); PayloadError::UnknownLength => (),
match req.body().await.err().unwrap() { _ => unreachable!("error"),
PayloadError::UnknownLength => (), }
_ => unreachable!("error"),
}
let mut req = let mut req =
TestResponse::with_header(header::CONTENT_LENGTH, "1000000").finish(); TestResponse::with_header(header::CONTENT_LENGTH, "1000000").finish();
match req.body().await.err().unwrap() { match req.body().await.err().unwrap() {
PayloadError::Overflow => (), PayloadError::Overflow => (),
_ => unreachable!("error"), _ => unreachable!("error"),
} }
let mut req = TestResponse::default() let mut req = TestResponse::default()
.set_payload(Bytes::from_static(b"test")) .set_payload(Bytes::from_static(b"test"))
.finish(); .finish();
assert_eq!(req.body().await.ok().unwrap(), Bytes::from_static(b"test")); assert_eq!(req.body().await.ok().unwrap(), Bytes::from_static(b"test"));
let mut req = TestResponse::default() let mut req = TestResponse::default()
.set_payload(Bytes::from_static(b"11111111111111")) .set_payload(Bytes::from_static(b"11111111111111"))
.finish(); .finish();
match req.body().limit(5).await.err().unwrap() { match req.body().limit(5).await.err().unwrap() {
PayloadError::Overflow => (), PayloadError::Overflow => (),
_ => unreachable!("error"), _ => unreachable!("error"),
} }
})
} }
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
@ -414,58 +410,56 @@ mod tests {
} }
} }
#[test] #[actix_rt::test]
fn test_json_body() { async fn test_json_body() {
block_on(async { let mut req = TestResponse::default().finish();
let mut req = TestResponse::default().finish(); let json = JsonBody::<_, MyObject>::new(&mut req).await;
let json = JsonBody::<_, MyObject>::new(&mut req).await; assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let mut req = TestResponse::default() let mut req = TestResponse::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/text"), header::HeaderValue::from_static("application/text"),
) )
.finish(); .finish();
let json = JsonBody::<_, MyObject>::new(&mut req).await; let json = JsonBody::<_, MyObject>::new(&mut req).await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType)); assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let mut req = TestResponse::default() let mut req = TestResponse::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"), header::HeaderValue::from_static("application/json"),
) )
.header( .header(
header::CONTENT_LENGTH, header::CONTENT_LENGTH,
header::HeaderValue::from_static("10000"), header::HeaderValue::from_static("10000"),
) )
.finish(); .finish();
let json = JsonBody::<_, MyObject>::new(&mut req).limit(100).await; let json = JsonBody::<_, MyObject>::new(&mut req).limit(100).await;
assert!(json_eq( assert!(json_eq(
json.err().unwrap(), json.err().unwrap(),
JsonPayloadError::Payload(PayloadError::Overflow) JsonPayloadError::Payload(PayloadError::Overflow)
)); ));
let mut req = TestResponse::default() let mut req = TestResponse::default()
.header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"), header::HeaderValue::from_static("application/json"),
) )
.header( .header(
header::CONTENT_LENGTH, header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"), header::HeaderValue::from_static("16"),
) )
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.finish(); .finish();
let json = JsonBody::<_, MyObject>::new(&mut req).await; let json = JsonBody::<_, MyObject>::new(&mut req).await;
assert_eq!( assert_eq!(
json.ok().unwrap(), json.ok().unwrap(),
MyObject { MyObject {
name: "test".to_owned() name: "test".to_owned()
} }
); );
})
} }
} }

View File

@ -4,12 +4,12 @@ use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use std::time::Duration; use std::time::Duration;
use actix_rt::time::{delay_for, Delay};
use bytes::Bytes; use bytes::Bytes;
use derive_more::From; use derive_more::From;
use futures::{future::LocalBoxFuture, ready, Future, Stream}; use futures::{future::LocalBoxFuture, ready, Future, Stream};
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;
use tokio_timer::{delay_for, Delay};
use actix_http::body::{Body, BodyStream}; use actix_http::body::{Body, BodyStream};
use actix_http::encoding::Decoder; use actix_http::encoding::Decoder;

View File

@ -7,8 +7,8 @@ use std::{fmt, str};
use actix_codec::Framed; use actix_codec::Framed;
use actix_http::cookie::{Cookie, CookieJar}; use actix_http::cookie::{Cookie, CookieJar};
use actix_http::{ws, Payload, RequestHead}; use actix_http::{ws, Payload, RequestHead};
use actix_rt::time::Timeout;
use percent_encoding::percent_encode; use percent_encoding::percent_encode;
use tokio_timer::Timeout;
use actix_http::cookie::USERINFO; use actix_http::cookie::USERINFO;
pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message}; pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message};
@ -389,21 +389,19 @@ impl fmt::Debug for WebsocketsRequest {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use actix_web::test::block_on;
use super::*; use super::*;
use crate::Client; use crate::Client;
#[test] #[actix_rt::test]
fn test_debug() { async fn test_debug() {
let request = Client::new().ws("/").header("x-test", "111"); let request = Client::new().ws("/").header("x-test", "111");
let repr = format!("{:?}", request); let repr = format!("{:?}", request);
assert!(repr.contains("WebsocketsRequest")); assert!(repr.contains("WebsocketsRequest"));
assert!(repr.contains("x-test")); assert!(repr.contains("x-test"));
} }
#[test] #[actix_rt::test]
fn test_header_override() { async fn test_header_override() {
let req = Client::build() let req = Client::build()
.header(header::CONTENT_TYPE, "111") .header(header::CONTENT_TYPE, "111")
.finish() .finish()
@ -421,8 +419,8 @@ mod tests {
); );
} }
#[test] #[actix_rt::test]
fn basic_auth() { async fn basic_auth() {
let req = Client::new() let req = Client::new()
.ws("/") .ws("/")
.basic_auth("username", Some("password")); .basic_auth("username", Some("password"));
@ -448,8 +446,8 @@ mod tests {
); );
} }
#[test] #[actix_rt::test]
fn bearer_auth() { async fn bearer_auth() {
let req = Client::new().ws("/").bearer_auth("someS3cr3tAutht0k3n"); let req = Client::new().ws("/").bearer_auth("someS3cr3tAutht0k3n");
assert_eq!( assert_eq!(
req.head req.head
@ -463,35 +461,33 @@ mod tests {
let _ = req.connect(); let _ = req.connect();
} }
#[test] #[actix_rt::test]
fn basics() { async fn basics() {
block_on(async { let req = Client::new()
let req = Client::new() .ws("http://localhost/")
.ws("http://localhost/") .origin("test-origin")
.origin("test-origin") .max_frame_size(100)
.max_frame_size(100) .server_mode()
.server_mode() .protocols(&["v1", "v2"])
.protocols(&["v1", "v2"]) .set_header_if_none(header::CONTENT_TYPE, "json")
.set_header_if_none(header::CONTENT_TYPE, "json") .set_header_if_none(header::CONTENT_TYPE, "text")
.set_header_if_none(header::CONTENT_TYPE, "text") .cookie(Cookie::build("cookie1", "value1").finish());
.cookie(Cookie::build("cookie1", "value1").finish()); assert_eq!(
assert_eq!( req.origin.as_ref().unwrap().to_str().unwrap(),
req.origin.as_ref().unwrap().to_str().unwrap(), "test-origin"
"test-origin" );
); assert_eq!(req.max_size, 100);
assert_eq!(req.max_size, 100); assert_eq!(req.server_mode, true);
assert_eq!(req.server_mode, true); assert_eq!(req.protocols, Some("v1,v2".to_string()));
assert_eq!(req.protocols, Some("v1,v2".to_string())); assert_eq!(
assert_eq!( req.head.headers.get(header::CONTENT_TYPE).unwrap(),
req.head.headers.get(header::CONTENT_TYPE).unwrap(), header::HeaderValue::from_static("json")
header::HeaderValue::from_static("json") );
);
let _ = req.connect().await; let _ = req.connect().await;
assert!(Client::new().ws("/").connect().await.is_err()); assert!(Client::new().ws("/").connect().await.is_err());
assert!(Client::new().ws("http:///test").connect().await.is_err()); assert!(Client::new().ws("http:///test").connect().await.is_err());
assert!(Client::new().ws("hmm://test.com/").connect().await.is_err()); assert!(Client::new().ws("hmm://test.com/").connect().await.is_err());
})
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_server::ssl::OpensslAcceptor; use actix_server::ssl::OpensslAcceptor;
use actix_service::{pipeline_factory, ServiceFactory}; use actix_service::{pipeline_factory, ServiceFactory};
use actix_web::http::Version; use actix_web::http::Version;
@ -53,57 +53,54 @@ mod danger {
} }
} }
// #[test] // #[actix_rt::test]
fn _test_connection_reuse_h2() { async fn _test_connection_reuse_h2() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let num = Arc::new(AtomicUsize::new(0));
let num = Arc::new(AtomicUsize::new(0)); let num2 = num.clone();
let num2 = num.clone();
let srv = TestServer::start(move || { let srv = TestServer::start(move || {
let num2 = num2.clone(); let num2 = num2.clone();
pipeline_factory(move |io| { pipeline_factory(move |io| {
num2.fetch_add(1, Ordering::Relaxed); num2.fetch_add(1, Ordering::Relaxed);
ok(io) ok(io)
}) })
.and_then( .and_then(
openssl openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e)), .map_err(|e| println!("Openssl error: {}", e)),
) )
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(App::new().service( .h2(App::new()
web::resource("/").route(web::to(|| HttpResponse::Ok())), .service(web::resource("/").route(web::to(|| HttpResponse::Ok()))))
)) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
// disable ssl verification // disable ssl verification
let mut config = ClientConfig::new(); let mut config = ClientConfig::new();
let protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; let protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
config.set_protocols(&protos); config.set_protocols(&protos);
config config
.dangerous() .dangerous()
.set_certificate_verifier(Arc::new(danger::NoCertificateVerification {})); .set_certificate_verifier(Arc::new(danger::NoCertificateVerification {}));
let client = awc::Client::build() let client = awc::Client::build()
.connector(awc::Connector::new().rustls(Arc::new(config)).finish()) .connector(awc::Connector::new().rustls(Arc::new(config)).finish())
.finish(); .finish();
// req 1 // req 1
let request = client.get(srv.surl("/")).send(); let request = client.get(srv.surl("/")).send();
let response = request.await.unwrap(); let response = request.await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// req 2 // req 2
let req = client.post(srv.surl("/")); let req = client.post(srv.surl("/"));
let response = req.send().await.unwrap(); let response = req.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.version(), Version::HTTP_2); assert_eq!(response.version(), Version::HTTP_2);
// one connection // one connection
assert_eq!(num.load(Ordering::Relaxed), 1); assert_eq!(num.load(Ordering::Relaxed), 1);
})
} }

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_codec::{AsyncRead, AsyncWrite};
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use actix_server::ssl::OpensslAcceptor; use actix_server::ssl::OpensslAcceptor;
use actix_service::{pipeline_factory, ServiceFactory}; use actix_service::{pipeline_factory, ServiceFactory};
use actix_web::http::Version; use actix_web::http::Version;
@ -35,56 +35,53 @@ fn ssl_acceptor<T: AsyncRead + AsyncWrite>() -> Result<OpensslAcceptor<T, ()>> {
Ok(actix_server::ssl::OpensslAcceptor::new(builder.build())) Ok(actix_server::ssl::OpensslAcceptor::new(builder.build()))
} }
#[test] #[actix_rt::test]
fn test_connection_reuse_h2() { async fn test_connection_reuse_h2() {
block_on(async { let openssl = ssl_acceptor().unwrap();
let openssl = ssl_acceptor().unwrap(); let num = Arc::new(AtomicUsize::new(0));
let num = Arc::new(AtomicUsize::new(0)); let num2 = num.clone();
let num2 = num.clone();
let srv = TestServer::start(move || { let srv = TestServer::start(move || {
let num2 = num2.clone(); let num2 = num2.clone();
pipeline_factory(move |io| { pipeline_factory(move |io| {
num2.fetch_add(1, Ordering::Relaxed); num2.fetch_add(1, Ordering::Relaxed);
ok(io) ok(io)
}) })
.and_then( .and_then(
openssl openssl
.clone() .clone()
.map_err(|e| println!("Openssl error: {}", e)), .map_err(|e| println!("Openssl error: {}", e)),
) )
.and_then( .and_then(
HttpService::build() HttpService::build()
.h2(App::new().service( .h2(App::new()
web::resource("/").route(web::to(|| HttpResponse::Ok())), .service(web::resource("/").route(web::to(|| HttpResponse::Ok()))))
)) .map_err(|_| ()),
.map_err(|_| ()), )
) });
});
// disable ssl verification // disable ssl verification
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap(); let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE); builder.set_verify(SslVerifyMode::NONE);
let _ = builder let _ = builder
.set_alpn_protos(b"\x02h2\x08http/1.1") .set_alpn_protos(b"\x02h2\x08http/1.1")
.map_err(|e| log::error!("Can not set alpn protocol: {:?}", e)); .map_err(|e| log::error!("Can not set alpn protocol: {:?}", e));
let client = awc::Client::build() let client = awc::Client::build()
.connector(awc::Connector::new().ssl(builder.build()).finish()) .connector(awc::Connector::new().ssl(builder.build()).finish())
.finish(); .finish();
// req 1 // req 1
let request = client.get(srv.surl("/")).send(); let request = client.get(srv.surl("/")).send();
let response = request.await.unwrap(); let response = request.await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
// req 2 // req 2
let req = client.post(srv.surl("/")); let req = client.post(srv.surl("/"));
let response = req.send().await.unwrap(); let response = req.send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
assert_eq!(response.version(), Version::HTTP_2); assert_eq!(response.version(), Version::HTTP_2);
// one connection // one connection
assert_eq!(num.load(Ordering::Relaxed), 1); assert_eq!(num.load(Ordering::Relaxed), 1);
})
} }

View File

@ -2,7 +2,7 @@ use std::io;
use actix_codec::Framed; use actix_codec::Framed;
use actix_http::{body::BodySize, h1, ws, Error, HttpService, Request, Response}; use actix_http::{body::BodySize, h1, ws, Error, HttpService, Request, Response};
use actix_http_test::{block_on, TestServer}; use actix_http_test::TestServer;
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::future::ok; use futures::future::ok;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
@ -28,56 +28,54 @@ async fn ws_service(req: ws::Frame) -> Result<ws::Message, io::Error> {
} }
} }
#[test] #[actix_rt::test]
fn test_simple() { async fn test_simple() {
block_on(async { let mut srv = TestServer::start(|| {
let mut srv = TestServer::start(|| { HttpService::build()
HttpService::build() .upgrade(|(req, mut framed): (Request, Framed<_, _>)| {
.upgrade(|(req, mut framed): (Request, Framed<_, _>)| { async move {
async move { let res = ws::handshake_response(req.head()).finish();
let res = ws::handshake_response(req.head()).finish(); // send handshake response
// send handshake response framed
framed .send(h1::Message::Item((res.drop_body(), BodySize::None)))
.send(h1::Message::Item((res.drop_body(), BodySize::None))) .await?;
.await?;
// start websocket service // start websocket service
let framed = framed.into_framed(ws::Codec::new()); let framed = framed.into_framed(ws::Codec::new());
ws::Transport::with(framed, ws_service).await ws::Transport::with(framed, ws_service).await
} }
}) })
.finish(|_| ok::<_, Error>(Response::NotFound())) .finish(|_| ok::<_, Error>(Response::NotFound()))
}); });
// client service // client service
let mut framed = srv.ws().await.unwrap(); let mut framed = srv.ws().await.unwrap();
framed framed
.send(ws::Message::Text("text".to_string())) .send(ws::Message::Text("text".to_string()))
.await .await
.unwrap(); .unwrap();
let item = framed.next().await.unwrap().unwrap(); let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, ws::Frame::Text(Some(BytesMut::from("text")))); assert_eq!(item, ws::Frame::Text(Some(BytesMut::from("text"))));
framed framed
.send(ws::Message::Binary("text".into())) .send(ws::Message::Binary("text".into()))
.await .await
.unwrap(); .unwrap();
let item = framed.next().await.unwrap().unwrap(); let item = framed.next().await.unwrap().unwrap();
assert_eq!( assert_eq!(
item, item,
ws::Frame::Binary(Some(Bytes::from_static(b"text").into())) ws::Frame::Binary(Some(Bytes::from_static(b"text").into()))
); );
framed.send(ws::Message::Ping("text".into())).await.unwrap(); framed.send(ws::Message::Ping("text".into())).await.unwrap();
let item = framed.next().await.unwrap().unwrap(); let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, ws::Frame::Pong("text".to_string().into())); assert_eq!(item, ws::Frame::Pong("text".to_string().into()));
framed framed
.send(ws::Message::Close(Some(ws::CloseCode::Normal.into()))) .send(ws::Message::Close(Some(ws::CloseCode::Normal.into())))
.await .await
.unwrap(); .unwrap();
let item = framed.next().await.unwrap().unwrap(); let item = framed.next().await.unwrap().unwrap();
assert_eq!(item, ws::Frame::Close(Some(ws::CloseCode::Normal.into()))); assert_eq!(item, ws::Frame::Close(Some(ws::CloseCode::Normal.into())));
})
} }

View File

@ -2,12 +2,10 @@ use std::cell::RefCell;
use std::fmt; use std::fmt;
use std::future::Future; use std::future::Future;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll};
use actix_http::body::{Body, MessageBody}; use actix_http::body::{Body, MessageBody};
use actix_service::boxed::{self, BoxedNewService}; use actix_service::boxed::{self, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, IntoServiceFactory, ServiceFactory, Transform, apply, apply_fn_factory, IntoServiceFactory, ServiceFactory, Transform,
}; };
@ -25,7 +23,7 @@ use crate::service::{
ServiceResponse, ServiceResponse,
}; };
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>;
type FnDataFactory = type FnDataFactory =
Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>; Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;
@ -485,231 +483,195 @@ where
mod tests { mod tests {
use actix_service::Service; use actix_service::Service;
use bytes::Bytes; use bytes::Bytes;
use futures::future::{ok, Future}; use futures::future::ok;
use super::*; use super::*;
use crate::http::{header, HeaderValue, Method, StatusCode}; use crate::http::{header, HeaderValue, Method, StatusCode};
use crate::middleware::DefaultHeaders; use crate::middleware::DefaultHeaders;
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::ServiceRequest;
use crate::test::{block_on, call_service, init_service, read_body, TestRequest}; use crate::test::{call_service, init_service, read_body, TestRequest};
use crate::{web, Error, HttpRequest, HttpResponse}; use crate::{web, HttpRequest, HttpResponse};
#[test] #[actix_rt::test]
fn test_default_resource() { async fn test_default_resource() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new().service(web::resource("/test").to(|| HttpResponse::Ok())),
App::new().service(web::resource("/test").to(|| HttpResponse::Ok())), )
) .await;
let req = TestRequest::with_uri("/test").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/blah").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let mut srv = init_service(
App::new()
.service(web::resource("/test").to(|| HttpResponse::Ok()))
.service(
web::resource("/test2")
.default_service(|r: ServiceRequest| {
ok(r.into_response(HttpResponse::Created()))
})
.route(web::get().to(|| HttpResponse::Ok())),
)
.default_service(|r: ServiceRequest| {
ok(r.into_response(HttpResponse::MethodNotAllowed()))
}),
)
.await;
let req = TestRequest::with_uri("/blah").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let req = TestRequest::with_uri("/test2").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test2")
.method(Method::POST)
.to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
}
#[actix_rt::test]
async fn test_data_factory() {
let mut srv =
init_service(App::new().data_factory(|| ok::<_, ()>(10usize)).service(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
))
.await; .await;
let req = TestRequest::with_uri("/test").to_request(); let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/blah").to_request(); let mut srv =
let resp = srv.call(req).await.unwrap(); init_service(App::new().data_factory(|| ok::<_, ()>(10u32)).service(
assert_eq!(resp.status(), StatusCode::NOT_FOUND); web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
))
let mut srv = init_service(
App::new()
.service(web::resource("/test").to(|| HttpResponse::Ok()))
.service(
web::resource("/test2")
.default_service(|r: ServiceRequest| {
ok(r.into_response(HttpResponse::Created()))
})
.route(web::get().to(|| HttpResponse::Ok())),
)
.default_service(|r: ServiceRequest| {
ok(r.into_response(HttpResponse::MethodNotAllowed()))
}),
)
.await; .await;
let req = TestRequest::default().to_request();
let req = TestRequest::with_uri("/blah").to_request(); let resp = srv.call(req).await.unwrap();
let resp = srv.call(req).await.unwrap(); assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let req = TestRequest::with_uri("/test2").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test2")
.method(Method::POST)
.to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::CREATED);
})
} }
#[test] #[actix_rt::test]
fn test_data_factory() { async fn test_wrap() {
block_on(async { let mut srv = init_service(
let mut srv = App::new()
init_service(App::new().data_factory(|| ok::<_, ()>(10usize)).service( .wrap(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), DefaultHeaders::new()
)) .header(header::CONTENT_TYPE, HeaderValue::from_static("0001")),
.await; )
let req = TestRequest::default().to_request(); .route("/test", web::get().to(|| HttpResponse::Ok())),
let resp = srv.call(req).await.unwrap(); )
assert_eq!(resp.status(), StatusCode::OK); .await;
let req = TestRequest::with_uri("/test").to_request();
let mut srv = let resp = call_service(&mut srv, req).await;
init_service(App::new().data_factory(|| ok::<_, ()>(10u32)).service( assert_eq!(resp.status(), StatusCode::OK);
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), assert_eq!(
)) resp.headers().get(header::CONTENT_TYPE).unwrap(),
.await; HeaderValue::from_static("0001")
let req = TestRequest::default().to_request(); );
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
})
} }
fn md<S, B>( #[actix_rt::test]
req: ServiceRequest, async fn test_router_wrap() {
srv: &mut S, let mut srv = init_service(
) -> impl Future<Output = Result<ServiceResponse<B>, Error>> App::new()
where .route("/test", web::get().to(|| HttpResponse::Ok()))
S: Service< .wrap(
Request = ServiceRequest, DefaultHeaders::new()
Response = ServiceResponse<B>, .header(header::CONTENT_TYPE, HeaderValue::from_static("0001")),
Error = Error, ),
>, )
{ .await;
let fut = srv.call(req); let req = TestRequest::with_uri("/test").to_request();
async move { let resp = call_service(&mut srv, req).await;
let mut res = fut.await?; assert_eq!(resp.status(), StatusCode::OK);
res.headers_mut() assert_eq!(
.insert(header::CONTENT_TYPE, HeaderValue::from_static("0001")); resp.headers().get(header::CONTENT_TYPE).unwrap(),
Ok(res) HeaderValue::from_static("0001")
} );
} }
#[test] #[actix_rt::test]
fn test_wrap() { async fn test_wrap_fn() {
block_on(async { let mut srv = init_service(
let mut srv = App::new()
init_service( .wrap_fn(|req, srv| {
App::new() let fut = srv.call(req);
.wrap(DefaultHeaders::new().header( async move {
let mut res = fut.await?;
res.headers_mut().insert(
header::CONTENT_TYPE, header::CONTENT_TYPE,
HeaderValue::from_static("0001"), HeaderValue::from_static("0001"),
);
Ok(res)
}
})
.service(web::resource("/test").to(|| HttpResponse::Ok())),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
}
#[actix_rt::test]
async fn test_router_wrap_fn() {
let mut srv = init_service(
App::new()
.route("/test", web::get().to(|| HttpResponse::Ok()))
.wrap_fn(|req, srv| {
let fut = srv.call(req);
async {
let mut res = fut.await?;
res.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("0001"),
);
Ok(res)
}
}),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
}
#[actix_rt::test]
async fn test_external_resource() {
let mut srv = init_service(
App::new()
.external_resource("youtube", "https://youtube.com/watch/{video_id}")
.route(
"/test",
web::get().to(|req: HttpRequest| {
HttpResponse::Ok().body(format!(
"{}",
req.url_for("youtube", &["12345"]).unwrap()
)) ))
.route("/test", web::get().to(|| HttpResponse::Ok())),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
})
}
#[test]
fn test_router_wrap() {
block_on(async {
let mut srv =
init_service(
App::new()
.route("/test", web::get().to(|| HttpResponse::Ok()))
.wrap(DefaultHeaders::new().header(
header::CONTENT_TYPE,
HeaderValue::from_static("0001"),
)),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
})
}
#[test]
fn test_wrap_fn() {
block_on(async {
let mut srv = init_service(
App::new()
.wrap_fn(|req, srv| {
let fut = srv.call(req);
async move {
let mut res = fut.await?;
res.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("0001"),
);
Ok(res)
}
})
.service(web::resource("/test").to(|| HttpResponse::Ok())),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
})
}
#[test]
fn test_router_wrap_fn() {
block_on(async {
let mut srv = init_service(
App::new()
.route("/test", web::get().to(|| HttpResponse::Ok()))
.wrap_fn(|req, srv| {
let fut = srv.call(req);
async {
let mut res = fut.await?;
res.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("0001"),
);
Ok(res)
}
}), }),
) ),
.await; )
let req = TestRequest::with_uri("/test").to_request(); .await;
let resp = call_service(&mut srv, req).await; let req = TestRequest::with_uri("/test").to_request();
assert_eq!(resp.status(), StatusCode::OK); let resp = call_service(&mut srv, req).await;
assert_eq!( assert_eq!(resp.status(), StatusCode::OK);
resp.headers().get(header::CONTENT_TYPE).unwrap(), let body = read_body(resp).await;
HeaderValue::from_static("0001") assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
);
})
}
#[test]
fn test_external_resource() {
block_on(async {
let mut srv = init_service(
App::new()
.external_resource("youtube", "https://youtube.com/watch/{video_id}")
.route(
"/test",
web::get().to(|req: HttpRequest| {
HttpResponse::Ok().body(format!(
"{}",
req.url_for("youtube", &["12345"]).unwrap()
))
}),
),
)
.await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let body = read_body(resp).await;
assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
})
} }
} }

View File

@ -8,9 +8,9 @@ use std::task::{Context, Poll};
use actix_http::{Extensions, Request, Response}; use actix_http::{Extensions, Request, Response};
use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url}; use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::boxed::{self, BoxedNewService, BoxedService}; use actix_service::boxed::{self, BoxService, BoxServiceFactory};
use actix_service::{service_fn, Service, ServiceFactory}; use actix_service::{service_fn, Service, ServiceFactory};
use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready}; use futures::future::{ok, FutureExt, LocalBoxFuture};
use crate::config::{AppConfig, AppService}; use crate::config::{AppConfig, AppService};
use crate::data::DataFactory; use crate::data::DataFactory;
@ -21,9 +21,9 @@ use crate::rmap::ResourceMap;
use crate::service::{AppServiceFactory, ServiceRequest, ServiceResponse}; use crate::service::{AppServiceFactory, ServiceRequest, ServiceResponse};
type Guards = Vec<Box<dyn Guard>>; type Guards = Vec<Box<dyn Guard>>;
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>; type HttpService = BoxService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>;
type BoxedResponse = LocalBoxFuture<'static, Result<ServiceResponse, Error>>; type BoxResponse = LocalBoxFuture<'static, Result<ServiceResponse, Error>>;
type FnDataFactory = type FnDataFactory =
Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>; Box<dyn Fn() -> LocalBoxFuture<'static, Result<Box<dyn DataFactory>, ()>>>;
@ -387,7 +387,7 @@ impl Service for AppRouting {
type Request = ServiceRequest; type Request = ServiceRequest;
type Response = ServiceResponse; type Response = ServiceResponse;
type Error = Error; type Error = Error;
type Future = BoxedResponse; type Future = BoxResponse;
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> { fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
if self.ready.is_none() { if self.ready.is_none() {
@ -447,13 +447,12 @@ impl ServiceFactory for AppEntry {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use actix_service::Service; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{ use std::sync::Arc;
atomic::{AtomicBool, Ordering},
Arc,
};
use crate::{test, web, App, HttpResponse}; use crate::test::{init_service, TestRequest};
use crate::{web, App, HttpResponse};
use actix_service::Service;
struct DropData(Arc<AtomicBool>); struct DropData(Arc<AtomicBool>);
@ -463,19 +462,20 @@ mod tests {
} }
} }
#[test] #[actix_rt::test]
fn drop_data() { async fn test_drop_data() {
let data = Arc::new(AtomicBool::new(false)); let data = Arc::new(AtomicBool::new(false));
test::block_on(async {
let mut app = test::init_service( {
let mut app = init_service(
App::new() App::new()
.data(DropData(data.clone())) .data(DropData(data.clone()))
.service(web::resource("/test").to(|| HttpResponse::Ok())), .service(web::resource("/test").to(|| HttpResponse::Ok())),
) )
.await; .await;
let req = test::TestRequest::with_uri("/test").to_request(); let req = TestRequest::with_uri("/test").to_request();
let _ = app.call(req).await.unwrap(); let _ = app.call(req).await.unwrap();
}); }
assert!(data.load(Ordering::Relaxed)); assert!(data.load(Ordering::Relaxed));
} }
} }

View File

@ -18,7 +18,7 @@ use crate::service::{
type Guards = Vec<Box<dyn Guard>>; type Guards = Vec<Box<dyn Guard>>;
type HttpNewService = type HttpNewService =
boxed::BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; boxed::BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>;
/// Application configuration /// Application configuration
pub struct AppService { pub struct AppService {
@ -246,28 +246,27 @@ mod tests {
use super::*; use super::*;
use crate::http::{Method, StatusCode}; use crate::http::{Method, StatusCode};
use crate::test::{block_on, call_service, init_service, read_body, TestRequest}; use crate::test::{call_service, init_service, read_body, TestRequest};
use crate::{web, App, HttpRequest, HttpResponse}; use crate::{web, App, HttpRequest, HttpResponse};
#[test] #[actix_rt::test]
fn test_data() { async fn test_data() {
block_on(async { let cfg = |cfg: &mut ServiceConfig| {
let cfg = |cfg: &mut ServiceConfig| { cfg.data(10usize);
cfg.data(10usize); };
};
let mut srv = init_service(App::new().configure(cfg).service( let mut srv =
init_service(App::new().configure(cfg).service(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)) ))
.await; .await;
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
})
} }
// #[test] // #[actix_rt::test]
// fn test_data_factory() { // async fn test_data_factory() {
// let cfg = |cfg: &mut ServiceConfig| { // let cfg = |cfg: &mut ServiceConfig| {
// cfg.data_factory(|| { // cfg.data_factory(|| {
// sleep(std::time::Duration::from_millis(50)).then(|_| { // sleep(std::time::Duration::from_millis(50)).then(|_| {
@ -282,7 +281,7 @@ mod tests {
// web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), // web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
// )); // ));
// let req = TestRequest::default().to_request(); // let req = TestRequest::default().to_request();
// let resp = block_on(srv.call(req)).unwrap(); // let resp = srv.call(req).await.unwrap();
// assert_eq!(resp.status(), StatusCode::OK); // assert_eq!(resp.status(), StatusCode::OK);
// let cfg2 = |cfg: &mut ServiceConfig| { // let cfg2 = |cfg: &mut ServiceConfig| {
@ -294,63 +293,58 @@ mod tests {
// .configure(cfg2), // .configure(cfg2),
// ); // );
// let req = TestRequest::default().to_request(); // let req = TestRequest::default().to_request();
// let resp = block_on(srv.call(req)).unwrap(); // let resp = srv.call(req).await.unwrap();
// assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); // assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
// } // }
#[test] #[actix_rt::test]
fn test_external_resource() { async fn test_external_resource() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new()
App::new() .configure(|cfg| {
.configure(|cfg| { cfg.external_resource(
cfg.external_resource( "youtube",
"youtube", "https://youtube.com/watch/{video_id}",
"https://youtube.com/watch/{video_id}", );
); })
}) .route(
.route( "/test",
"/test", web::get().to(|req: HttpRequest| {
web::get().to(|req: HttpRequest| { HttpResponse::Ok().body(format!(
HttpResponse::Ok().body(format!( "{}",
"{}", req.url_for("youtube", &["12345"]).unwrap()
req.url_for("youtube", &["12345"]).unwrap() ))
)) }),
}), ),
), )
) .await;
.await; let req = TestRequest::with_uri("/test").to_request();
let req = TestRequest::with_uri("/test").to_request(); let resp = call_service(&mut srv, req).await;
let resp = call_service(&mut srv, req).await; assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.status(), StatusCode::OK); let body = read_body(resp).await;
let body = read_body(resp).await; assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
})
} }
#[test] #[actix_rt::test]
fn test_service() { async fn test_service() {
block_on(async { let mut srv = init_service(App::new().configure(|cfg| {
let mut srv = init_service(App::new().configure(|cfg| { cfg.service(
cfg.service( web::resource("/test").route(web::get().to(|| HttpResponse::Created())),
web::resource("/test") )
.route(web::get().to(|| HttpResponse::Created())), .route("/index.html", web::get().to(|| HttpResponse::Ok()));
) }))
.route("/index.html", web::get().to(|| HttpResponse::Ok())); .await;
}))
.await;
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::GET) .method(Method::GET)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::CREATED); assert_eq!(resp.status(), StatusCode::CREATED);
let req = TestRequest::with_uri("/index.html") let req = TestRequest::with_uri("/index.html")
.method(Method::GET) .method(Method::GET)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
})
} }
} }

View File

@ -139,104 +139,97 @@ mod tests {
use super::*; use super::*;
use crate::http::StatusCode; use crate::http::StatusCode;
use crate::test::{block_on, init_service, TestRequest}; use crate::test::{init_service, TestRequest};
use crate::{web, App, HttpResponse}; use crate::{web, App, HttpResponse};
#[test] #[actix_rt::test]
fn test_data_extractor() { async fn test_data_extractor() {
block_on(async { let mut srv =
let mut srv = init_service(App::new().data(10usize).service( init_service(App::new().data(10usize).service(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)) ))
.await; .await;
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let mut srv = init_service(App::new().data(10u32).service( let mut srv =
init_service(App::new().data(10u32).service(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()), web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
)) ))
.await; .await;
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
})
} }
#[test] #[actix_rt::test]
fn test_register_data_extractor() { async fn test_register_data_extractor() {
block_on(async { let mut srv =
let mut srv = init_service(App::new().register_data(Data::new(10usize)).service(
init_service(App::new().register_data(Data::new(10usize)).service( web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
))
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let mut srv =
init_service(App::new().register_data(Data::new(10u32)).service(
web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
))
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
})
}
#[test]
fn test_route_data_extractor() {
block_on(async {
let mut srv = init_service(App::new().service(
web::resource("/").data(10usize).route(web::get().to(
|data: web::Data<usize>| {
let _ = data.clone();
HttpResponse::Ok()
},
)),
)) ))
.await; .await;
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
// different type let mut srv =
let mut srv = init_service( init_service(App::new().register_data(Data::new(10u32)).service(
App::new().service( web::resource("/").to(|_: web::Data<usize>| HttpResponse::Ok()),
web::resource("/")
.data(10u32)
.route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())),
),
)
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
})
}
#[test]
fn test_override_data() {
block_on(async {
let mut srv = init_service(App::new().data(1usize).service(
web::resource("/").data(10usize).route(web::get().to(
|data: web::Data<usize>| {
assert_eq!(*data, 10);
let _ = data.clone();
HttpResponse::Ok()
},
)),
)) ))
.await; .await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
let req = TestRequest::default().to_request(); #[actix_rt::test]
let resp = srv.call(req).await.unwrap(); async fn test_route_data_extractor() {
assert_eq!(resp.status(), StatusCode::OK); let mut srv =
}) init_service(App::new().service(web::resource("/").data(10usize).route(
web::get().to(|data: web::Data<usize>| {
let _ = data.clone();
HttpResponse::Ok()
}),
)))
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
// different type
let mut srv = init_service(
App::new().service(
web::resource("/")
.data(10u32)
.route(web::get().to(|_: web::Data<usize>| HttpResponse::Ok())),
),
)
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
}
#[actix_rt::test]
async fn test_override_data() {
let mut srv = init_service(App::new().data(1usize).service(
web::resource("/").data(10usize).route(web::get().to(
|data: web::Data<usize>| {
assert_eq!(*data, 10);
let _ = data.clone();
HttpResponse::Ok()
},
)),
))
.await;
let req = TestRequest::default().to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
} }
} }

View File

@ -270,7 +270,7 @@ mod tests {
use serde_derive::Deserialize; use serde_derive::Deserialize;
use super::*; use super::*;
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
use crate::types::{Form, FormConfig}; use crate::types::{Form, FormConfig};
#[derive(Deserialize, Debug, PartialEq)] #[derive(Deserialize, Debug, PartialEq)]
@ -278,8 +278,8 @@ mod tests {
hello: String, hello: String,
} }
#[test] #[actix_rt::test]
fn test_option() { async fn test_option() {
let (req, mut pl) = TestRequest::with_header( let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
@ -287,7 +287,9 @@ mod tests {
.data(FormConfig::default().limit(4096)) .data(FormConfig::default().limit(4096))
.to_http_parts(); .to_http_parts();
let r = block_on(Option::<Form<Info>>::from_request(&req, &mut pl)).unwrap(); let r = Option::<Form<Info>>::from_request(&req, &mut pl)
.await
.unwrap();
assert_eq!(r, None); assert_eq!(r, None);
let (req, mut pl) = TestRequest::with_header( let (req, mut pl) = TestRequest::with_header(
@ -298,7 +300,9 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world")) .set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts(); .to_http_parts();
let r = block_on(Option::<Form<Info>>::from_request(&req, &mut pl)).unwrap(); let r = Option::<Form<Info>>::from_request(&req, &mut pl)
.await
.unwrap();
assert_eq!( assert_eq!(
r, r,
Some(Form(Info { Some(Form(Info {
@ -314,12 +318,14 @@ mod tests {
.set_payload(Bytes::from_static(b"bye=world")) .set_payload(Bytes::from_static(b"bye=world"))
.to_http_parts(); .to_http_parts();
let r = block_on(Option::<Form<Info>>::from_request(&req, &mut pl)).unwrap(); let r = Option::<Form<Info>>::from_request(&req, &mut pl)
.await
.unwrap();
assert_eq!(r, None); assert_eq!(r, None);
} }
#[test] #[actix_rt::test]
fn test_result() { async fn test_result() {
let (req, mut pl) = TestRequest::with_header( let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
"application/x-www-form-urlencoded", "application/x-www-form-urlencoded",
@ -328,7 +334,8 @@ mod tests {
.set_payload(Bytes::from_static(b"hello=world")) .set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts(); .to_http_parts();
let r = block_on(Result::<Form<Info>, Error>::from_request(&req, &mut pl)) let r = Result::<Form<Info>, Error>::from_request(&req, &mut pl)
.await
.unwrap() .unwrap()
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
@ -346,8 +353,9 @@ mod tests {
.set_payload(Bytes::from_static(b"bye=world")) .set_payload(Bytes::from_static(b"bye=world"))
.to_http_parts(); .to_http_parts();
let r = let r = Result::<Form<Info>, Error>::from_request(&req, &mut pl)
block_on(Result::<Form<Info>, Error>::from_request(&req, &mut pl)).unwrap(); .await
.unwrap();
assert!(r.is_err()); assert!(r.is_err());
} }
} }

View File

@ -1,4 +1,4 @@
#![allow(clippy::borrow_interior_mutable_const, unused_imports, dead_code)] #![allow(clippy::borrow_interior_mutable_const)]
//! Actix web is a small, pragmatic, and extremely fast web framework //! Actix web is a small, pragmatic, and extremely fast web framework
//! for Rust. //! for Rust.
//! //!
@ -143,9 +143,9 @@ pub mod dev {
HttpServiceFactory, ServiceRequest, ServiceResponse, WebService, HttpServiceFactory, ServiceRequest, ServiceResponse, WebService,
}; };
//pub use crate::types::form::UrlEncoded; pub use crate::types::form::UrlEncoded;
//pub use crate::types::json::JsonBody; pub use crate::types::json::JsonBody;
//pub use crate::types::readlines::Readlines; pub use crate::types::readlines::Readlines;
pub use actix_http::body::{Body, BodySize, MessageBody, ResponseBody, SizedStream}; pub use actix_http::body::{Body, BodySize, MessageBody, ResponseBody, SizedStream};
pub use actix_http::encoding::Decoder as Decompress; pub use actix_http::encoding::Decoder as Decompress;
@ -174,17 +174,16 @@ pub mod client {
//! use actix_rt::System; //! use actix_rt::System;
//! use actix_web::client::Client; //! use actix_web::client::Client;
//! //!
//! fn main() { //! #[actix_rt::main]
//! System::new("test").block_on(async { //! async fn main() {
//! let mut client = Client::default(); //! let mut client = Client::default();
//! //!
//! // Create request builder and send request //! // Create request builder and send request
//! let response = client.get("http://www.rust-lang.org") //! let response = client.get("http://www.rust-lang.org")
//! .header("User-Agent", "Actix-web") //! .header("User-Agent", "Actix-web")
//! .send().await; // <- Send http request //! .send().await; // <- Send http request
//! //!
//! println!("Response: {:?}", response); //! println!("Response: {:?}", response);
//! });
//! } //! }
//! ``` //! ```
pub use awc::error::{ pub use awc::error::{

View File

@ -2,7 +2,7 @@
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures::future::{ok, Either, FutureExt, LocalBoxFuture, Ready}; use futures::future::{ok, Either, FutureExt, LocalBoxFuture};
/// `Middleware` for conditionally enables another middleware. /// `Middleware` for conditionally enables another middleware.
/// The controled middleware must not change the `Service` interfaces. /// The controled middleware must not change the `Service` interfaces.
@ -102,7 +102,7 @@ mod tests {
use crate::error::Result; use crate::error::Result;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode}; use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::middleware::errhandlers::*; use crate::middleware::errhandlers::*;
use crate::test::{self, block_on, TestRequest}; use crate::test::{self, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
@ -112,46 +112,40 @@ mod tests {
Ok(ErrorHandlerResponse::Response(res)) Ok(ErrorHandlerResponse::Response(res))
} }
#[test] #[actix_rt::test]
fn test_handler_enabled() { async fn test_handler_enabled() {
block_on(async { let srv = |req: ServiceRequest| {
let srv = |req: ServiceRequest| { ok(req.into_response(HttpResponse::InternalServerError().finish()))
ok(req.into_response(HttpResponse::InternalServerError().finish())) };
};
let mw = ErrorHandlers::new() let mw =
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500); ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mut mw = Condition::new(true, mw) let mut mw = Condition::new(true, mw)
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let resp = let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request()) test::call_service(&mut mw, TestRequest::default().to_srv_request()).await;
.await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
} }
#[test] #[actix_rt::test]
fn test_handler_disabled() { async fn test_handler_disabled() {
block_on(async { let srv = |req: ServiceRequest| {
let srv = |req: ServiceRequest| { ok(req.into_response(HttpResponse::InternalServerError().finish()))
ok(req.into_response(HttpResponse::InternalServerError().finish())) };
};
let mw = ErrorHandlers::new() let mw =
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500); ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
let mut mw = Condition::new(false, mw) let mut mw = Condition::new(false, mw)
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let resp = let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request()) test::call_service(&mut mw, TestRequest::default().to_srv_request()).await;
.await; assert_eq!(resp.headers().get(CONTENT_TYPE), None);
assert_eq!(resp.headers().get(CONTENT_TYPE), None);
})
} }
} }

View File

@ -1,6 +1,4 @@
//! Middleware for setting default response headers //! Middleware for setting default response headers
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc; use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@ -161,55 +159,50 @@ mod tests {
use super::*; use super::*;
use crate::dev::ServiceRequest; use crate::dev::ServiceRequest;
use crate::http::header::CONTENT_TYPE; use crate::http::header::CONTENT_TYPE;
use crate::test::{block_on, ok_service, TestRequest}; use crate::test::{ok_service, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
#[test] #[actix_rt::test]
fn test_default_headers() { async fn test_default_headers() {
block_on(async { let mut mw = DefaultHeaders::new()
let mut mw = DefaultHeaders::new() .header(CONTENT_TYPE, "0001")
.header(CONTENT_TYPE, "0001") .new_transform(ok_service())
.new_transform(ok_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::default().to_srv_request(); let req = TestRequest::default().to_srv_request();
let resp = mw.call(req).await.unwrap(); let resp = mw.call(req).await.unwrap();
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
let req = TestRequest::default().to_srv_request(); let req = TestRequest::default().to_srv_request();
let srv = |req: ServiceRequest| { let srv = |req: ServiceRequest| {
ok(req.into_response( ok(req
HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish(), .into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish()))
)) };
}; let mut mw = DefaultHeaders::new()
let mut mw = DefaultHeaders::new() .header(CONTENT_TYPE, "0001")
.header(CONTENT_TYPE, "0001") .new_transform(srv.into_service())
.new_transform(srv.into_service()) .await
.await .unwrap();
.unwrap(); let resp = mw.call(req).await.unwrap();
let resp = mw.call(req).await.unwrap(); assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002");
})
} }
#[test] #[actix_rt::test]
fn test_content_type() { async fn test_content_type() {
block_on(async { let srv =
let srv = |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish()));
|req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())); let mut mw = DefaultHeaders::new()
let mut mw = DefaultHeaders::new() .content_type()
.content_type() .new_transform(srv.into_service())
.new_transform(srv.into_service()) .await
.await .unwrap();
.unwrap();
let req = TestRequest::default().to_srv_request(); let req = TestRequest::default().to_srv_request();
let resp = mw.call(req).await.unwrap(); let resp = mw.call(req).await.unwrap();
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
"application/octet-stream" "application/octet-stream"
); );
})
} }
} }

View File

@ -3,7 +3,7 @@ use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures::future::{err, ok, Either, Future, FutureExt, LocalBoxFuture, Ready}; use futures::future::{ok, FutureExt, LocalBoxFuture, Ready};
use hashbrown::HashMap; use hashbrown::HashMap;
use crate::dev::{ServiceRequest, ServiceResponse}; use crate::dev::{ServiceRequest, ServiceResponse};
@ -151,7 +151,7 @@ mod tests {
use super::*; use super::*;
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode}; use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::test::{self, block_on, TestRequest}; use crate::test::{self, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { fn render_500<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
@ -161,24 +161,21 @@ mod tests {
Ok(ErrorHandlerResponse::Response(res)) Ok(ErrorHandlerResponse::Response(res))
} }
#[test] #[actix_rt::test]
fn test_handler() { async fn test_handler() {
block_on(async { let srv = |req: ServiceRequest| {
let srv = |req: ServiceRequest| { ok(req.into_response(HttpResponse::InternalServerError().finish()))
ok(req.into_response(HttpResponse::InternalServerError().finish())) };
};
let mut mw = ErrorHandlers::new() let mut mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500) .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500)
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let resp = let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request()) test::call_service(&mut mw, TestRequest::default().to_srv_request()).await;
.await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
} }
fn render_500_async<B: 'static>( fn render_500_async<B: 'static>(
@ -190,23 +187,20 @@ mod tests {
Ok(ErrorHandlerResponse::Future(ok(res).boxed_local())) Ok(ErrorHandlerResponse::Future(ok(res).boxed_local()))
} }
#[test] #[actix_rt::test]
fn test_handler_async() { async fn test_handler_async() {
block_on(async { let srv = |req: ServiceRequest| {
let srv = |req: ServiceRequest| { ok(req.into_response(HttpResponse::InternalServerError().finish()))
ok(req.into_response(HttpResponse::InternalServerError().finish())) };
};
let mut mw = ErrorHandlers::new() let mut mw = ErrorHandlers::new()
.handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async) .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async)
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let resp = let resp =
test::call_service(&mut mw, TestRequest::default().to_srv_request()) test::call_service(&mut mw, TestRequest::default().to_srv_request()).await;
.await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
})
} }
} }

View File

@ -479,10 +479,10 @@ mod tests {
use super::*; use super::*;
use crate::http::{header, StatusCode}; use crate::http::{header, StatusCode};
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
#[test] #[actix_rt::test]
fn test_logger() { async fn test_logger() {
let srv = |req: ServiceRequest| { let srv = |req: ServiceRequest| {
ok(req.into_response( ok(req.into_response(
HttpResponse::build(StatusCode::OK) HttpResponse::build(StatusCode::OK)
@ -492,18 +492,18 @@ mod tests {
}; };
let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test"); let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test");
let mut srv = block_on(logger.new_transform(srv.into_service())).unwrap(); let mut srv = logger.new_transform(srv.into_service()).await.unwrap();
let req = TestRequest::with_header( let req = TestRequest::with_header(
header::USER_AGENT, header::USER_AGENT,
header::HeaderValue::from_static("ACTIX-WEB"), header::HeaderValue::from_static("ACTIX-WEB"),
) )
.to_srv_request(); .to_srv_request();
let _res = block_on(srv.call(req)); let _res = srv.call(req).await;
} }
#[test] #[actix_rt::test]
fn test_url_path() { async fn test_url_path() {
let mut format = Format::new("%T %U"); let mut format = Format::new("%T %U");
let req = TestRequest::with_header( let req = TestRequest::with_header(
header::USER_AGENT, header::USER_AGENT,
@ -533,8 +533,8 @@ mod tests {
assert!(s.contains("/test/route/yeah")); assert!(s.contains("/test/route/yeah"));
} }
#[test] #[actix_rt::test]
fn test_default_format() { async fn test_default_format() {
let mut format = Format::default(); let mut format = Format::default();
let req = TestRequest::with_header( let req = TestRequest::with_header(
@ -566,8 +566,8 @@ mod tests {
assert!(s.contains("ACTIX-WEB")); assert!(s.contains("ACTIX-WEB"));
} }
#[test] #[actix_rt::test]
fn test_request_time_format() { async fn test_request_time_format() {
let mut format = Format::new("%t"); let mut format = Format::new("%t");
let req = TestRequest::default().to_srv_request(); let req = TestRequest::default().to_srv_request();

View File

@ -105,62 +105,56 @@ mod tests {
use super::*; use super::*;
use crate::dev::ServiceRequest; use crate::dev::ServiceRequest;
use crate::test::{block_on, call_service, init_service, TestRequest}; use crate::test::{call_service, init_service, TestRequest};
use crate::{web, App, HttpResponse}; use crate::{web, App, HttpResponse};
#[test] #[actix_rt::test]
fn test_wrap() { async fn test_wrap() {
block_on(async { let mut app = init_service(
let mut app = init_service( App::new()
App::new() .wrap(NormalizePath::default())
.wrap(NormalizePath::default()) .service(web::resource("/v1/something/").to(|| HttpResponse::Ok())),
.service(web::resource("/v1/something/").to(|| HttpResponse::Ok())), )
) .await;
.await;
let req = TestRequest::with_uri("/v1//something////").to_request(); let req = TestRequest::with_uri("/v1//something////").to_request();
let res = call_service(&mut app, req).await; let res = call_service(&mut app, req).await;
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
#[test] #[actix_rt::test]
fn test_in_place_normalization() { async fn test_in_place_normalization() {
block_on(async { let srv = |req: ServiceRequest| {
let srv = |req: ServiceRequest| { assert_eq!("/v1/something/", req.path());
assert_eq!("/v1/something/", req.path()); ok(req.into_response(HttpResponse::Ok().finish()))
ok(req.into_response(HttpResponse::Ok().finish())) };
};
let mut normalize = NormalizePath let mut normalize = NormalizePath
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let req = TestRequest::with_uri("/v1//something////").to_srv_request(); let req = TestRequest::with_uri("/v1//something////").to_srv_request();
let res = normalize.call(req).await.unwrap(); let res = normalize.call(req).await.unwrap();
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
#[test] #[actix_rt::test]
fn should_normalize_nothing() { async fn should_normalize_nothing() {
block_on(async { const URI: &str = "/v1/something/";
const URI: &str = "/v1/something/";
let srv = |req: ServiceRequest| { let srv = |req: ServiceRequest| {
assert_eq!(URI, req.path()); assert_eq!(URI, req.path());
ok(req.into_response(HttpResponse::Ok().finish())) ok(req.into_response(HttpResponse::Ok().finish()))
}; };
let mut normalize = NormalizePath let mut normalize = NormalizePath
.new_transform(srv.into_service()) .new_transform(srv.into_service())
.await .await
.unwrap(); .unwrap();
let req = TestRequest::with_uri(URI).to_srv_request(); let req = TestRequest::with_uri(URI).to_srv_request();
let res = normalize.call(req).await.unwrap(); let res = normalize.call(req).await.unwrap();
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
} }

View File

@ -350,7 +350,7 @@ mod tests {
use super::*; use super::*;
use crate::dev::{ResourceDef, ResourceMap}; use crate::dev::{ResourceDef, ResourceMap};
use crate::http::{header, StatusCode}; use crate::http::{header, StatusCode};
use crate::test::{block_on, call_service, init_service, TestRequest}; use crate::test::{call_service, init_service, TestRequest};
use crate::{web, App, HttpResponse}; use crate::{web, App, HttpResponse};
#[test] #[test]
@ -466,16 +466,62 @@ mod tests {
); );
} }
#[test] #[actix_rt::test]
fn test_app_data() { async fn test_app_data() {
block_on(async { let mut srv = init_service(App::new().data(10usize).service(
let mut srv = init_service(App::new().data(10usize).service( web::resource("/").to(|req: HttpRequest| {
web::resource("/").to(|req: HttpRequest| { if req.app_data::<usize>().is_some() {
if req.app_data::<usize>().is_some() { HttpResponse::Ok()
HttpResponse::Ok() } else {
} else { HttpResponse::BadRequest()
HttpResponse::BadRequest() }
} }),
))
.await;
let req = TestRequest::default().to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let mut srv = init_service(App::new().data(10u32).service(
web::resource("/").to(|req: HttpRequest| {
if req.app_data::<usize>().is_some() {
HttpResponse::Ok()
} else {
HttpResponse::BadRequest()
}
}),
))
.await;
let req = TestRequest::default().to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
#[actix_rt::test]
async fn test_extensions_dropped() {
struct Tracker {
pub dropped: bool,
}
struct Foo {
tracker: Rc<RefCell<Tracker>>,
}
impl Drop for Foo {
fn drop(&mut self) {
self.tracker.borrow_mut().dropped = true;
}
}
let tracker = Rc::new(RefCell::new(Tracker { dropped: false }));
{
let tracker2 = Rc::clone(&tracker);
let mut srv = init_service(App::new().data(10u32).service(
web::resource("/").to(move |req: HttpRequest| {
req.extensions_mut().insert(Foo {
tracker: Rc::clone(&tracker2),
});
HttpResponse::Ok()
}), }),
)) ))
.await; .await;
@ -483,58 +529,8 @@ mod tests {
let req = TestRequest::default().to_request(); let req = TestRequest::default().to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
}
let mut srv = init_service(App::new().data(10u32).service( assert!(tracker.borrow().dropped);
web::resource("/").to(|req: HttpRequest| {
if req.app_data::<usize>().is_some() {
HttpResponse::Ok()
} else {
HttpResponse::BadRequest()
}
}),
))
.await;
let req = TestRequest::default().to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
})
}
#[test]
fn test_extensions_dropped() {
block_on(async {
struct Tracker {
pub dropped: bool,
}
struct Foo {
tracker: Rc<RefCell<Tracker>>,
}
impl Drop for Foo {
fn drop(&mut self) {
self.tracker.borrow_mut().dropped = true;
}
}
let tracker = Rc::new(RefCell::new(Tracker { dropped: false }));
{
let tracker2 = Rc::clone(&tracker);
let mut srv = init_service(App::new().data(10u32).service(
web::resource("/").to(move |req: HttpRequest| {
req.extensions_mut().insert(Foo {
tracker: Rc::clone(&tracker2),
});
HttpResponse::Ok()
}),
))
.await;
let req = TestRequest::default().to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
}
assert!(tracker.borrow().dropped);
})
} }
} }

View File

@ -6,12 +6,11 @@ use std::rc::Rc;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_http::{Error, Extensions, Response}; use actix_http::{Error, Extensions, Response};
use actix_service::boxed::{self, BoxedNewService, BoxedService}; use actix_service::boxed::{self, BoxService, BoxServiceFactory};
use actix_service::{ use actix_service::{
apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory, Transform, apply, apply_fn_factory, IntoServiceFactory, Service, ServiceFactory, Transform,
}; };
use futures::future::{ok, Either, LocalBoxFuture, Ready}; use futures::future::{ok, Either, LocalBoxFuture, Ready};
use pin_project::pin_project;
use crate::data::Data; use crate::data::Data;
use crate::dev::{insert_slash, AppService, HttpServiceFactory, ResourceDef}; use crate::dev::{insert_slash, AppService, HttpServiceFactory, ResourceDef};
@ -22,8 +21,8 @@ use crate::responder::Responder;
use crate::route::{CreateRouteService, Route, RouteService}; use crate::route::{CreateRouteService, Route, RouteService};
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::{ServiceRequest, ServiceResponse};
type HttpService = BoxedService<ServiceRequest, ServiceResponse, Error>; type HttpService = BoxService<ServiceRequest, ServiceResponse, Error>;
type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>;
/// *Resource* is an entry in resources table which corresponds to requested URL. /// *Resource* is an entry in resources table which corresponds to requested URL.
/// ///
@ -585,40 +584,20 @@ impl ServiceFactory for ResourceEndpoint {
mod tests { mod tests {
use std::time::Duration; use std::time::Duration;
use actix_rt::time::delay_for;
use actix_service::Service; use actix_service::Service;
use futures::future::{ok, Future}; use futures::future::ok;
use tokio_timer::delay_for;
use crate::http::{header, HeaderValue, Method, StatusCode}; use crate::http::{header, HeaderValue, Method, StatusCode};
use crate::middleware::DefaultHeaders; use crate::middleware::DefaultHeaders;
use crate::service::{ServiceRequest, ServiceResponse}; use crate::service::ServiceRequest;
use crate::test::{block_on, call_service, init_service, TestRequest}; use crate::test::{call_service, init_service, TestRequest};
use crate::{guard, web, App, Error, HttpResponse}; use crate::{guard, web, App, Error, HttpResponse};
fn md<S, B>( #[actix_rt::test]
req: ServiceRequest, async fn test_middleware() {
srv: &mut S, let mut srv =
) -> impl Future<Output = Result<ServiceResponse<B>, Error>> init_service(
where
S: Service<
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = Error,
>,
{
let fut = srv.call(req);
async move {
let mut res = fut.await?;
res.headers_mut()
.insert(header::CONTENT_TYPE, HeaderValue::from_static("0001"));
Ok(res)
}
}
#[test]
fn test_middleware() {
block_on(async {
let mut srv = init_service(
App::new().service( App::new().service(
web::resource("/test") web::resource("/test")
.name("test") .name("test")
@ -630,185 +609,173 @@ mod tests {
), ),
) )
.await; .await;
let req = TestRequest::with_uri("/test").to_request(); let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!( assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(), resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001") HeaderValue::from_static("0001")
); );
})
} }
#[test] #[actix_rt::test]
fn test_middleware_fn() { async fn test_middleware_fn() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new().service(
App::new().service( web::resource("/test")
web::resource("/test") .wrap_fn(|req, srv| {
.wrap_fn(|req, srv| { let fut = srv.call(req);
let fut = srv.call(req); async {
async { fut.await.map(|mut res| {
fut.await.map(|mut res| { res.headers_mut().insert(
res.headers_mut().insert( header::CONTENT_TYPE,
header::CONTENT_TYPE, HeaderValue::from_static("0001"),
HeaderValue::from_static("0001"), );
); res
res })
}) }
} })
}) .route(web::get().to(|| HttpResponse::Ok())),
.route(web::get().to(|| HttpResponse::Ok())), ),
), )
) .await;
let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
}
#[actix_rt::test]
async fn test_to() {
let mut srv =
init_service(App::new().service(web::resource("/test").to(|| {
async {
delay_for(Duration::from_millis(100)).await;
Ok::<_, Error>(HttpResponse::Ok())
}
})))
.await; .await;
let req = TestRequest::with_uri("/test").to_request(); let req = TestRequest::with_uri("/test").to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(),
HeaderValue::from_static("0001")
);
})
} }
#[test] #[actix_rt::test]
fn test_to() { async fn test_default_resource() {
block_on(async { let mut srv = init_service(
let mut srv = App::new()
init_service(App::new().service(web::resource("/test").to(|| { .service(
async { web::resource("/test").route(web::get().to(|| HttpResponse::Ok())),
delay_for(Duration::from_millis(100)).await; )
Ok::<_, Error>(HttpResponse::Ok()) .default_service(|r: ServiceRequest| {
} ok(r.into_response(HttpResponse::BadRequest()))
}))) }),
.await; )
let req = TestRequest::with_uri("/test").to_request(); .await;
let resp = call_service(&mut srv, req).await; let req = TestRequest::with_uri("/test").to_request();
assert_eq!(resp.status(), StatusCode::OK); let resp = call_service(&mut srv, req).await;
}) assert_eq!(resp.status(), StatusCode::OK);
}
#[test] let req = TestRequest::with_uri("/test")
fn test_default_resource() { .method(Method::POST)
block_on(async { .to_request();
let mut srv = init_service( let resp = call_service(&mut srv, req).await;
App::new() assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
.service(
web::resource("/test") let mut srv = init_service(
.route(web::get().to(|| HttpResponse::Ok())), App::new().service(
) web::resource("/test")
.route(web::get().to(|| HttpResponse::Ok()))
.default_service(|r: ServiceRequest| { .default_service(|r: ServiceRequest| {
ok(r.into_response(HttpResponse::BadRequest())) ok(r.into_response(HttpResponse::BadRequest()))
}), }),
) ),
.await; )
let req = TestRequest::with_uri("/test").to_request(); .await;
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test").to_request();
.method(Method::POST) let resp = call_service(&mut srv, req).await;
.to_request(); assert_eq!(resp.status(), StatusCode::OK);
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let mut srv = init_service( let req = TestRequest::with_uri("/test")
App::new().service( .method(Method::POST)
web::resource("/test") .to_request();
.route(web::get().to(|| HttpResponse::Ok())) let resp = call_service(&mut srv, req).await;
.default_service(|r: ServiceRequest| { assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
ok(r.into_response(HttpResponse::BadRequest())) }
}),
#[actix_rt::test]
async fn test_resource_guards() {
let mut srv = init_service(
App::new()
.service(
web::resource("/test/{p}")
.guard(guard::Get())
.to(|| HttpResponse::Ok()),
)
.service(
web::resource("/test/{p}")
.guard(guard::Put())
.to(|| HttpResponse::Created()),
)
.service(
web::resource("/test/{p}")
.guard(guard::Delete())
.to(|| HttpResponse::NoContent()),
), ),
) )
.await; .await;
let req = TestRequest::with_uri("/test").to_request(); let req = TestRequest::with_uri("/test/it")
let resp = call_service(&mut srv, req).await; .method(Method::GET)
assert_eq!(resp.status(), StatusCode::OK); .to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test/it")
.method(Method::POST) .method(Method::PUT)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST); assert_eq!(resp.status(), StatusCode::CREATED);
})
let req = TestRequest::with_uri("/test/it")
.method(Method::DELETE)
.to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
} }
#[test] #[actix_rt::test]
fn test_resource_guards() { async fn test_data() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new()
App::new() .data(1.0f64)
.service( .data(1usize)
web::resource("/test/{p}") .register_data(web::Data::new('-'))
.guard(guard::Get()) .service(
.to(|| HttpResponse::Ok()), web::resource("/test")
) .data(10usize)
.service( .register_data(web::Data::new('*'))
web::resource("/test/{p}") .guard(guard::Get())
.guard(guard::Put()) .to(
.to(|| HttpResponse::Created()), |data1: web::Data<usize>,
) data2: web::Data<char>,
.service( data3: web::Data<f64>| {
web::resource("/test/{p}") assert_eq!(*data1, 10);
.guard(guard::Delete()) assert_eq!(*data2, '*');
.to(|| HttpResponse::NoContent()), assert_eq!(*data3, 1.0);
), HttpResponse::Ok()
) },
.await; ),
),
)
.await;
let req = TestRequest::with_uri("/test/it") let req = TestRequest::get().uri("/test").to_request();
.method(Method::GET) let resp = call_service(&mut srv, req).await;
.to_request(); assert_eq!(resp.status(), StatusCode::OK);
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test/it")
.method(Method::PUT)
.to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::CREATED);
let req = TestRequest::with_uri("/test/it")
.method(Method::DELETE)
.to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::NO_CONTENT);
})
}
#[test]
fn test_data() {
block_on(async {
let mut srv = init_service(
App::new()
.data(1.0f64)
.data(1usize)
.register_data(web::Data::new('-'))
.service(
web::resource("/test")
.data(10usize)
.register_data(web::Data::new('*'))
.guard(guard::Get())
.to(
|data1: web::Data<usize>,
data2: web::Data<char>,
data3: web::Data<f64>| {
assert_eq!(*data1, 10);
assert_eq!(*data2, '*');
assert_eq!(*data3, 1.0);
HttpResponse::Ok()
},
),
),
)
.await;
let req = TestRequest::get().uri("/test").to_request();
let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK);
})
} }
} }

View File

@ -10,7 +10,7 @@ use actix_http::http::{
}; };
use actix_http::{Error, Response, ResponseBuilder}; use actix_http::{Error, Response, ResponseBuilder};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::future::{err, ok, Either as EitherFuture, LocalBoxFuture, Ready}; use futures::future::{err, ok, Either as EitherFuture, Ready};
use futures::ready; use futures::ready;
use pin_project::{pin_project, project}; use pin_project::{pin_project, project};
@ -457,37 +457,34 @@ pub(crate) mod tests {
use super::*; use super::*;
use crate::dev::{Body, ResponseBody}; use crate::dev::{Body, ResponseBody};
use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode}; use crate::http::{header::CONTENT_TYPE, HeaderValue, StatusCode};
use crate::test::{block_on, init_service, TestRequest}; use crate::test::{init_service, TestRequest};
use crate::{error, web, App, HttpResponse}; use crate::{error, web, App, HttpResponse};
#[test] #[actix_rt::test]
fn test_option_responder() { async fn test_option_responder() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new()
App::new() .service(
.service( web::resource("/none").to(|| async { Option::<&'static str>::None }),
web::resource("/none") )
.to(|| async { Option::<&'static str>::None }), .service(web::resource("/some").to(|| async { Some("some") })),
) )
.service(web::resource("/some").to(|| async { Some("some") })), .await;
)
.await;
let req = TestRequest::with_uri("/none").to_request(); let req = TestRequest::with_uri("/none").to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::NOT_FOUND); assert_eq!(resp.status(), StatusCode::NOT_FOUND);
let req = TestRequest::with_uri("/some").to_request(); let req = TestRequest::with_uri("/some").to_request();
let resp = srv.call(req).await.unwrap(); let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
match resp.response().body() { match resp.response().body() {
ResponseBody::Body(Body::Bytes(ref b)) => { ResponseBody::Body(Body::Bytes(ref b)) => {
let bytes: Bytes = b.clone().into(); let bytes: Bytes = b.clone().into();
assert_eq!(bytes, Bytes::from_static(b"some")); assert_eq!(bytes, Bytes::from_static(b"some"));
}
_ => panic!(),
} }
}) _ => panic!(),
}
} }
pub(crate) trait BodyTest { pub(crate) trait BodyTest {
@ -516,153 +513,142 @@ pub(crate) mod tests {
} }
} }
#[test] #[actix_rt::test]
fn test_responder() { async fn test_responder() {
block_on(async { let req = TestRequest::default().to_http_request();
let req = TestRequest::default().to_http_request();
let resp: HttpResponse = "test".respond_to(&req).await.unwrap(); let resp: HttpResponse = "test".respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test"); assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("text/plain; charset=utf-8") HeaderValue::from_static("text/plain; charset=utf-8")
); );
let resp: HttpResponse = b"test".respond_to(&req).await.unwrap(); let resp: HttpResponse = b"test".respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test"); assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("application/octet-stream") HeaderValue::from_static("application/octet-stream")
); );
let resp: HttpResponse = "test".to_string().respond_to(&req).await.unwrap(); let resp: HttpResponse = "test".to_string().respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test"); assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("text/plain; charset=utf-8") HeaderValue::from_static("text/plain; charset=utf-8")
); );
let resp: HttpResponse = let resp: HttpResponse = (&"test".to_string()).respond_to(&req).await.unwrap();
(&"test".to_string()).respond_to(&req).await.unwrap(); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!(resp.body().bin_ref(), b"test"); assert_eq!(
assert_eq!( resp.headers().get(CONTENT_TYPE).unwrap(),
resp.headers().get(CONTENT_TYPE).unwrap(), HeaderValue::from_static("text/plain; charset=utf-8")
HeaderValue::from_static("text/plain; charset=utf-8") );
);
let resp: HttpResponse = let resp: HttpResponse =
Bytes::from_static(b"test").respond_to(&req).await.unwrap(); Bytes::from_static(b"test").respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test"); assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("application/octet-stream") HeaderValue::from_static("application/octet-stream")
); );
let resp: HttpResponse = BytesMut::from(b"test".as_ref()) let resp: HttpResponse = BytesMut::from(b"test".as_ref())
.respond_to(&req)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("application/octet-stream")
);
// InternalError
let resp: HttpResponse =
error::InternalError::new("err", StatusCode::BAD_REQUEST)
.respond_to(&req)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
})
}
#[test]
fn test_result_responder() {
block_on(async {
let req = TestRequest::default().to_http_request();
// Result<I, E>
let resp: HttpResponse = Ok::<_, Error>("test".to_string())
.respond_to(&req)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("text/plain; charset=utf-8")
);
let res = Err::<String, _>(error::InternalError::new(
"err",
StatusCode::BAD_REQUEST,
))
.respond_to(&req) .respond_to(&req)
.await; .await
assert!(res.is_err()); .unwrap();
}) assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("application/octet-stream")
);
// InternalError
let resp: HttpResponse =
error::InternalError::new("err", StatusCode::BAD_REQUEST)
.respond_to(&req)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
} }
#[test] #[actix_rt::test]
fn test_custom_responder() { async fn test_result_responder() {
block_on(async { let req = TestRequest::default().to_http_request();
let req = TestRequest::default().to_http_request();
let res = "test"
.to_string()
.with_status(StatusCode::BAD_REQUEST)
.respond_to(&req)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
assert_eq!(res.body().bin_ref(), b"test");
let res = "test" // Result<I, E>
.to_string() let resp: HttpResponse = Ok::<_, Error>("test".to_string())
.with_header("content-type", "json") .respond_to(&req)
.respond_to(&req) .await
.await .unwrap();
.unwrap(); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(resp.body().bin_ref(), b"test");
assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("text/plain; charset=utf-8")
);
assert_eq!(res.status(), StatusCode::OK); let res =
assert_eq!(res.body().bin_ref(), b"test"); Err::<String, _>(error::InternalError::new("err", StatusCode::BAD_REQUEST))
assert_eq!( .respond_to(&req)
res.headers().get(CONTENT_TYPE).unwrap(), .await;
HeaderValue::from_static("json") assert!(res.is_err());
);
})
} }
#[test] #[actix_rt::test]
fn test_tuple_responder_with_status_code() { async fn test_custom_responder() {
block_on(async { let req = TestRequest::default().to_http_request();
let req = TestRequest::default().to_http_request(); let res = "test"
let res = ("test".to_string(), StatusCode::BAD_REQUEST) .to_string()
.respond_to(&req) .with_status(StatusCode::BAD_REQUEST)
.await .respond_to(&req)
.unwrap(); .await
assert_eq!(res.status(), StatusCode::BAD_REQUEST); .unwrap();
assert_eq!(res.body().bin_ref(), b"test"); assert_eq!(res.status(), StatusCode::BAD_REQUEST);
assert_eq!(res.body().bin_ref(), b"test");
let req = TestRequest::default().to_http_request(); let res = "test"
let res = ("test".to_string(), StatusCode::OK) .to_string()
.with_header("content-type", "json") .with_header("content-type", "json")
.respond_to(&req) .respond_to(&req)
.await .await
.unwrap(); .unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.body().bin_ref(), b"test"); assert_eq!(res.status(), StatusCode::OK);
assert_eq!( assert_eq!(res.body().bin_ref(), b"test");
res.headers().get(CONTENT_TYPE).unwrap(), assert_eq!(
HeaderValue::from_static("json") res.headers().get(CONTENT_TYPE).unwrap(),
); HeaderValue::from_static("json")
}) );
}
#[actix_rt::test]
async fn test_tuple_responder_with_status_code() {
let req = TestRequest::default().to_http_request();
let res = ("test".to_string(), StatusCode::BAD_REQUEST)
.respond_to(&req)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
assert_eq!(res.body().bin_ref(), b"test");
let req = TestRequest::default().to_http_request();
let res = ("test".to_string(), StatusCode::OK)
.with_header("content-type", "json")
.respond_to(&req)
.await
.unwrap();
assert_eq!(res.status(), StatusCode::OK);
assert_eq!(res.body().bin_ref(), b"test");
assert_eq!(
res.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("json")
);
} }
} }

View File

@ -5,7 +5,7 @@ use std::task::{Context, Poll};
use actix_http::{http::Method, Error}; use actix_http::{http::Method, Error};
use actix_service::{Service, ServiceFactory}; use actix_service::{Service, ServiceFactory};
use futures::future::{ok, ready, Either, FutureExt, LocalBoxFuture, Ready}; use futures::future::{ready, FutureExt, LocalBoxFuture};
use crate::extract::FromRequest; use crate::extract::FromRequest;
use crate::guard::{self, Guard}; use crate::guard::{self, Guard};
@ -342,93 +342,90 @@ where
mod tests { mod tests {
use std::time::Duration; use std::time::Duration;
use actix_rt::time::delay_for;
use bytes::Bytes; use bytes::Bytes;
use futures::Future;
use serde_derive::Serialize; use serde_derive::Serialize;
use tokio_timer::delay_for;
use crate::http::{Method, StatusCode}; use crate::http::{Method, StatusCode};
use crate::test::{block_on, call_service, init_service, read_body, TestRequest}; use crate::test::{call_service, init_service, read_body, TestRequest};
use crate::{error, web, App, Error, HttpResponse}; use crate::{error, web, App, HttpResponse};
#[derive(Serialize, PartialEq, Debug)] #[derive(Serialize, PartialEq, Debug)]
struct MyObject { struct MyObject {
name: String, name: String,
} }
#[test] #[actix_rt::test]
fn test_route() { async fn test_route() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new()
App::new() .service(
.service( web::resource("/test")
web::resource("/test") .route(web::get().to(|| HttpResponse::Ok()))
.route(web::get().to(|| HttpResponse::Ok())) .route(web::put().to(|| {
.route(web::put().to(|| { async {
async { Err::<HttpResponse, _>(error::ErrorBadRequest("err"))
Err::<HttpResponse, _>(error::ErrorBadRequest("err")) }
} }))
})) .route(web::post().to(|| {
.route(web::post().to(|| { async {
async { delay_for(Duration::from_millis(100)).await;
delay_for(Duration::from_millis(100)).await; HttpResponse::Created()
HttpResponse::Created() }
} }))
})) .route(web::delete().to(|| {
.route(web::delete().to(|| { async {
async { delay_for(Duration::from_millis(100)).await;
delay_for(Duration::from_millis(100)).await; Err::<HttpResponse, _>(error::ErrorBadRequest("err"))
Err::<HttpResponse, _>(error::ErrorBadRequest("err")) }
} })),
})), )
) .service(web::resource("/json").route(web::get().to(|| {
.service(web::resource("/json").route(web::get().to(|| { async {
async { delay_for(Duration::from_millis(25)).await;
delay_for(Duration::from_millis(25)).await; web::Json(MyObject {
web::Json(MyObject { name: "test".to_string(),
name: "test".to_string(), })
}) }
} }))),
}))), )
) .await;
.await;
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::GET) .method(Method::GET)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::POST) .method(Method::POST)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::CREATED); assert_eq!(resp.status(), StatusCode::CREATED);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::PUT) .method(Method::PUT)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST); assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::DELETE) .method(Method::DELETE)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST); assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let req = TestRequest::with_uri("/test") let req = TestRequest::with_uri("/test")
.method(Method::HEAD) .method(Method::HEAD)
.to_request(); .to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED); assert_eq!(resp.status(), StatusCode::METHOD_NOT_ALLOWED);
let req = TestRequest::with_uri("/json").to_request(); let req = TestRequest::with_uri("/json").to_request();
let resp = call_service(&mut srv, req).await; let resp = call_service(&mut srv, req).await;
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
let body = read_body(resp).await; let body = read_body(resp).await;
assert_eq!(body, Bytes::from_static(b"{\"name\":\"test\"}")); assert_eq!(body, Bytes::from_static(b"{\"name\":\"test\"}"));
})
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,6 @@ use actix_http::{
}; };
use actix_router::{Path, Resource, ResourceDef, Url}; use actix_router::{Path, Resource, ResourceDef, Url};
use actix_service::{IntoServiceFactory, ServiceFactory}; use actix_service::{IntoServiceFactory, ServiceFactory};
use futures::future::{ok, Ready};
use crate::config::{AppConfig, AppService}; use crate::config::{AppConfig, AppService};
use crate::data::Data; use crate::data::Data;
@ -529,9 +528,10 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::test::{block_on, init_service, TestRequest}; use crate::test::{init_service, TestRequest};
use crate::{guard, http, web, App, HttpResponse}; use crate::{guard, http, web, App, HttpResponse};
use actix_service::Service; use actix_service::Service;
use futures::future::ok;
#[test] #[test]
fn test_service_request() { fn test_service_request() {
@ -554,35 +554,29 @@ mod tests {
assert!(ServiceRequest::from_request(r).is_err()); assert!(ServiceRequest::from_request(r).is_err());
} }
#[test] #[actix_rt::test]
fn test_service() { async fn test_service() {
block_on(async { let mut srv = init_service(
let mut srv = init_service( App::new().service(web::service("/test").name("test").finish(
App::new().service(web::service("/test").name("test").finish( |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
|req: ServiceRequest| { )),
ok(req.into_response(HttpResponse::Ok().finish())) )
}, .await;
)), let req = TestRequest::with_uri("/test").to_request();
) let resp = srv.call(req).await.unwrap();
.await; assert_eq!(resp.status(), http::StatusCode::OK);
let req = TestRequest::with_uri("/test").to_request();
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), http::StatusCode::OK);
let mut srv = init_service(App::new().service( let mut srv = init_service(
web::service("/test").guard(guard::Get()).finish( App::new().service(web::service("/test").guard(guard::Get()).finish(
|req: ServiceRequest| { |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
ok(req.into_response(HttpResponse::Ok().finish())) )),
}, )
), .await;
)) let req = TestRequest::with_uri("/test")
.await; .method(http::Method::PUT)
let req = TestRequest::with_uri("/test") .to_request();
.method(http::Method::PUT) let resp = srv.call(req).await.unwrap();
.to_request(); assert_eq!(resp.status(), http::StatusCode::NOT_FOUND);
let resp = srv.call(req).await.unwrap();
assert_eq!(resp.status(), http::StatusCode::NOT_FOUND);
})
} }
#[test] #[test]

View File

@ -9,14 +9,13 @@ use actix_router::{Path, ResourceDef, Url};
use actix_server_config::ServerConfig; use actix_server_config::ServerConfig;
use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory}; use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures::future::{ok, Future, FutureExt}; use futures::future::ok;
use futures::stream::{Stream, StreamExt}; use futures::stream::{Stream, StreamExt};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;
pub use actix_http::test::TestBuffer; pub use actix_http::test::TestBuffer;
pub use actix_testing::{block_fn, block_on, run_on};
use crate::config::{AppConfig, AppConfigInner}; use crate::config::{AppConfig, AppConfigInner};
use crate::data::Data; use crate::data::Data;
@ -51,8 +50,8 @@ pub fn default_service(
/// use actix_service::Service; /// use actix_service::Service;
/// use actix_web::{test, web, App, HttpResponse, http::StatusCode}; /// use actix_web::{test, web, App, HttpResponse, http::StatusCode};
/// ///
/// #[test] /// #[actix_rt::test]
/// fn test_init_service() { /// async fn test_init_service() {
/// let mut app = test::init_service( /// let mut app = test::init_service(
/// App::new() /// App::new()
/// .service(web::resource("/test").to(|| async { HttpResponse::Ok() })) /// .service(web::resource("/test").to(|| async { HttpResponse::Ok() }))
@ -62,7 +61,7 @@ pub fn default_service(
/// let req = test::TestRequest::with_uri("/test").to_request(); /// let req = test::TestRequest::with_uri("/test").to_request();
/// ///
/// // Execute application /// // Execute application
/// let resp = test::block_on(app.call(req)).unwrap(); /// let resp = app.call(req).await.unwrap();
/// assert_eq!(resp.status(), StatusCode::OK); /// assert_eq!(resp.status(), StatusCode::OK);
/// } /// }
/// ``` /// ```
@ -116,14 +115,13 @@ where
} }
/// Helper function that returns a response body of a TestRequest /// Helper function that returns a response body of a TestRequest
/// This function blocks the current thread until futures complete.
/// ///
/// ```rust /// ```rust
/// use actix_web::{test, web, App, HttpResponse, http::header}; /// use actix_web::{test, web, App, HttpResponse, http::header};
/// use bytes::Bytes; /// use bytes::Bytes;
/// ///
/// #[test] /// #[actix_rt::test]
/// fn test_index() { /// async fn test_index() {
/// let mut app = test::init_service( /// let mut app = test::init_service(
/// App::new().service( /// App::new().service(
/// web::resource("/index.html") /// web::resource("/index.html")
@ -149,7 +147,7 @@ where
let mut resp = app let mut resp = app
.call(req) .call(req)
.await .await
.unwrap_or_else(|_| panic!("read_response failed at block_on unwrap")); .unwrap_or_else(|_| panic!("read_response failed at application call"));
let mut body = resp.take_body(); let mut body = resp.take_body();
let mut bytes = BytesMut::new(); let mut bytes = BytesMut::new();
@ -160,14 +158,13 @@ where
} }
/// Helper function that returns a response body of a ServiceResponse. /// Helper function that returns a response body of a ServiceResponse.
/// This function blocks the current thread until futures complete.
/// ///
/// ```rust /// ```rust
/// use actix_web::{test, web, App, HttpResponse, http::header}; /// use actix_web::{test, web, App, HttpResponse, http::header};
/// use bytes::Bytes; /// use bytes::Bytes;
/// ///
/// #[test] /// #[actix_rt::test]
/// fn test_index() { /// async fn test_index() {
/// let mut app = test::init_service( /// let mut app = test::init_service(
/// App::new().service( /// App::new().service(
/// web::resource("/index.html") /// web::resource("/index.html")
@ -210,7 +207,6 @@ where
} }
/// Helper function that returns a deserialized response body of a TestRequest /// Helper function that returns a deserialized response body of a TestRequest
/// This function blocks the current thread until futures complete.
/// ///
/// ```rust /// ```rust
/// use actix_web::{App, test, web, HttpResponse, http::header}; /// use actix_web::{App, test, web, HttpResponse, http::header};
@ -222,8 +218,8 @@ where
/// name: String /// name: String
/// } /// }
/// ///
/// #[test] /// #[actix_rt::test]
/// fn test_add_person() { /// async fn test_add_person() {
/// let mut app = test::init_service( /// let mut app = test::init_service(
/// App::new().service( /// App::new().service(
/// web::resource("/people") /// web::resource("/people")
@ -512,90 +508,81 @@ mod tests {
use super::*; use super::*;
use crate::{http::header, web, App, HttpResponse}; use crate::{http::header, web, App, HttpResponse};
#[test] #[actix_rt::test]
fn test_basics() { async fn test_basics() {
block_on(async { let req = TestRequest::with_hdr(header::ContentType::json())
let req = TestRequest::with_hdr(header::ContentType::json()) .version(Version::HTTP_2)
.version(Version::HTTP_2) .set(header::Date(SystemTime::now().into()))
.set(header::Date(SystemTime::now().into())) .param("test", "123")
.param("test", "123") .data(10u32)
.data(10u32) .to_http_request();
.to_http_request(); assert!(req.headers().contains_key(header::CONTENT_TYPE));
assert!(req.headers().contains_key(header::CONTENT_TYPE)); assert!(req.headers().contains_key(header::DATE));
assert!(req.headers().contains_key(header::DATE)); assert_eq!(&req.match_info()["test"], "123");
assert_eq!(&req.match_info()["test"], "123"); assert_eq!(req.version(), Version::HTTP_2);
assert_eq!(req.version(), Version::HTTP_2); let data = req.get_app_data::<u32>().unwrap();
let data = req.get_app_data::<u32>().unwrap(); assert!(req.get_app_data::<u64>().is_none());
assert!(req.get_app_data::<u64>().is_none()); assert_eq!(*data, 10);
assert_eq!(*data, 10); assert_eq!(*data.get_ref(), 10);
assert_eq!(*data.get_ref(), 10);
assert!(req.app_data::<u64>().is_none()); assert!(req.app_data::<u64>().is_none());
let data = req.app_data::<u32>().unwrap(); let data = req.app_data::<u32>().unwrap();
assert_eq!(*data, 10); assert_eq!(*data, 10);
})
} }
#[test] #[actix_rt::test]
fn test_request_methods() { async fn test_request_methods() {
block_on(async { let mut app = init_service(
let mut app = init_service( App::new().service(
App::new().service( web::resource("/index.html")
web::resource("/index.html") .route(web::put().to(|| async { HttpResponse::Ok().body("put!") }))
.route( .route(
web::put().to(|| async { HttpResponse::Ok().body("put!") }), web::patch().to(|| async { HttpResponse::Ok().body("patch!") }),
) )
.route( .route(
web::patch() web::delete()
.to(|| async { HttpResponse::Ok().body("patch!") }), .to(|| async { HttpResponse::Ok().body("delete!") }),
) ),
.route( ),
web::delete() )
.to(|| async { HttpResponse::Ok().body("delete!") }), .await;
),
), let put_req = TestRequest::put()
) .uri("/index.html")
.header(header::CONTENT_TYPE, "application/json")
.to_request();
let result = read_response(&mut app, put_req).await;
assert_eq!(result, Bytes::from_static(b"put!"));
let patch_req = TestRequest::patch()
.uri("/index.html")
.header(header::CONTENT_TYPE, "application/json")
.to_request();
let result = read_response(&mut app, patch_req).await;
assert_eq!(result, Bytes::from_static(b"patch!"));
let delete_req = TestRequest::delete().uri("/index.html").to_request();
let result = read_response(&mut app, delete_req).await;
assert_eq!(result, Bytes::from_static(b"delete!"));
}
#[actix_rt::test]
async fn test_response() {
let mut app =
init_service(App::new().service(web::resource("/index.html").route(
web::post().to(|| async { HttpResponse::Ok().body("welcome!") }),
)))
.await; .await;
let put_req = TestRequest::put() let req = TestRequest::post()
.uri("/index.html") .uri("/index.html")
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, "application/json")
.to_request(); .to_request();
let result = read_response(&mut app, put_req).await; let result = read_response(&mut app, req).await;
assert_eq!(result, Bytes::from_static(b"put!")); assert_eq!(result, Bytes::from_static(b"welcome!"));
let patch_req = TestRequest::patch()
.uri("/index.html")
.header(header::CONTENT_TYPE, "application/json")
.to_request();
let result = read_response(&mut app, patch_req).await;
assert_eq!(result, Bytes::from_static(b"patch!"));
let delete_req = TestRequest::delete().uri("/index.html").to_request();
let result = read_response(&mut app, delete_req).await;
assert_eq!(result, Bytes::from_static(b"delete!"));
})
}
#[test]
fn test_response() {
block_on(async {
let mut app =
init_service(App::new().service(web::resource("/index.html").route(
web::post().to(|| async { HttpResponse::Ok().body("welcome!") }),
)))
.await;
let req = TestRequest::post()
.uri("/index.html")
.header(header::CONTENT_TYPE, "application/json")
.to_request();
let result = read_response(&mut app, req).await;
assert_eq!(result, Bytes::from_static(b"welcome!"));
})
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -604,114 +591,103 @@ mod tests {
name: String, name: String,
} }
#[test] #[actix_rt::test]
fn test_response_json() { async fn test_response_json() {
block_on(async { let mut app = init_service(App::new().service(web::resource("/people").route(
let mut app = web::post().to(|person: web::Json<Person>| {
init_service(App::new().service(web::resource("/people").route( async { HttpResponse::Ok().json(person.into_inner()) }
web::post().to(|person: web::Json<Person>| { }),
async { HttpResponse::Ok().json(person.into_inner()) } )))
}), .await;
)))
.await;
let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes(); let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes();
let req = TestRequest::post() let req = TestRequest::post()
.uri("/people") .uri("/people")
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, "application/json")
.set_payload(payload) .set_payload(payload)
.to_request(); .to_request();
let result: Person = read_response_json(&mut app, req).await; let result: Person = read_response_json(&mut app, req).await;
assert_eq!(&result.id, "12345"); assert_eq!(&result.id, "12345");
})
} }
#[test] #[actix_rt::test]
fn test_request_response_form() { async fn test_request_response_form() {
block_on(async { let mut app = init_service(App::new().service(web::resource("/people").route(
let mut app = web::post().to(|person: web::Form<Person>| {
init_service(App::new().service(web::resource("/people").route( async { HttpResponse::Ok().json(person.into_inner()) }
web::post().to(|person: web::Form<Person>| { }),
async { HttpResponse::Ok().json(person.into_inner()) } )))
}), .await;
)))
.await;
let payload = Person { let payload = Person {
id: "12345".to_string(), id: "12345".to_string(),
name: "User name".to_string(), name: "User name".to_string(),
}; };
let req = TestRequest::post() let req = TestRequest::post()
.uri("/people") .uri("/people")
.set_form(&payload) .set_form(&payload)
.to_request(); .to_request();
assert_eq!(req.content_type(), "application/x-www-form-urlencoded"); assert_eq!(req.content_type(), "application/x-www-form-urlencoded");
let result: Person = read_response_json(&mut app, req).await; let result: Person = read_response_json(&mut app, req).await;
assert_eq!(&result.id, "12345"); assert_eq!(&result.id, "12345");
assert_eq!(&result.name, "User name"); assert_eq!(&result.name, "User name");
})
} }
#[test] #[actix_rt::test]
fn test_request_response_json() { async fn test_request_response_json() {
block_on(async { let mut app = init_service(App::new().service(web::resource("/people").route(
let mut app = web::post().to(|person: web::Json<Person>| {
init_service(App::new().service(web::resource("/people").route( async { HttpResponse::Ok().json(person.into_inner()) }
web::post().to(|person: web::Json<Person>| { }),
async { HttpResponse::Ok().json(person.into_inner()) } )))
}), .await;
)))
.await;
let payload = Person { let payload = Person {
id: "12345".to_string(), id: "12345".to_string(),
name: "User name".to_string(), name: "User name".to_string(),
}; };
let req = TestRequest::post() let req = TestRequest::post()
.uri("/people") .uri("/people")
.set_json(&payload) .set_json(&payload)
.to_request(); .to_request();
assert_eq!(req.content_type(), "application/json"); assert_eq!(req.content_type(), "application/json");
let result: Person = read_response_json(&mut app, req).await; let result: Person = read_response_json(&mut app, req).await;
assert_eq!(&result.id, "12345"); assert_eq!(&result.id, "12345");
assert_eq!(&result.name, "User name"); assert_eq!(&result.name, "User name");
})
} }
#[test] #[actix_rt::test]
fn test_async_with_block() { async fn test_async_with_block() {
block_on(async { async fn async_with_block() -> Result<HttpResponse, Error> {
async fn async_with_block() -> Result<HttpResponse, Error> { let res = web::block(move || Some(4usize).ok_or("wrong")).await;
let res = web::block(move || Some(4usize).ok_or("wrong")).await;
match res? { match res? {
Ok(value) => Ok(HttpResponse::Ok() Ok(value) => Ok(HttpResponse::Ok()
.content_type("text/plain") .content_type("text/plain")
.body(format!("Async with block value: {}", value))), .body(format!("Async with block value: {}", value))),
Err(_) => panic!("Unexpected"), Err(_) => panic!("Unexpected"),
}
} }
}
let mut app = init_service( let mut app = init_service(
App::new().service(web::resource("/index.html").to(async_with_block)), App::new().service(web::resource("/index.html").to(async_with_block)),
) )
.await; .await;
let req = TestRequest::post().uri("/index.html").to_request(); let req = TestRequest::post().uri("/index.html").to_request();
let res = app.call(req).await.unwrap(); let res = app.call(req).await.unwrap();
assert!(res.status().is_success()); assert!(res.status().is_success());
})
} }
// #[test] // #[actix_rt::test]
// fn test_actor() { // fn test_actor() {
// use actix::Actor; // use actix::Actor;

View File

@ -10,7 +10,7 @@ use actix_http::{Error, HttpMessage, Payload, Response};
use bytes::BytesMut; use bytes::BytesMut;
use encoding_rs::{Encoding, UTF_8}; use encoding_rs::{Encoding, UTF_8};
use futures::future::{err, ok, FutureExt, LocalBoxFuture, Ready}; use futures::future::{err, ok, FutureExt, LocalBoxFuture, Ready};
use futures::{Stream, StreamExt}; use futures::StreamExt;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
@ -370,7 +370,7 @@ mod tests {
use super::*; use super::*;
use crate::http::header::{HeaderValue, CONTENT_TYPE}; use crate::http::header::{HeaderValue, CONTENT_TYPE};
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
#[derive(Deserialize, Serialize, Debug, PartialEq)] #[derive(Deserialize, Serialize, Debug, PartialEq)]
struct Info { struct Info {
@ -378,26 +378,22 @@ mod tests {
counter: i64, counter: i64,
} }
#[test] #[actix_rt::test]
fn test_form() { async fn test_form() {
block_on(async { let (req, mut pl) =
let (req, mut pl) = TestRequest::with_header( TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
CONTENT_TYPE, .header(CONTENT_LENGTH, "11")
"application/x-www-form-urlencoded", .set_payload(Bytes::from_static(b"hello=world&counter=123"))
) .to_http_parts();
.header(CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world&counter=123"))
.to_http_parts();
let Form(s) = Form::<Info>::from_request(&req, &mut pl).await.unwrap(); let Form(s) = Form::<Info>::from_request(&req, &mut pl).await.unwrap();
assert_eq!( assert_eq!(
s, s,
Info { Info {
hello: "world".into(), hello: "world".into(),
counter: 123 counter: 123
} }
); );
})
} }
fn eq(err: UrlencodedError, other: UrlencodedError) -> bool { fn eq(err: UrlencodedError, other: UrlencodedError) -> bool {
@ -418,95 +414,83 @@ mod tests {
} }
} }
#[test] #[actix_rt::test]
fn test_urlencoded_error() { async fn test_urlencoded_error() {
block_on(async { let (req, mut pl) =
let (req, mut pl) = TestRequest::with_header( TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
CONTENT_TYPE, .header(CONTENT_LENGTH, "xxxx")
"application/x-www-form-urlencoded",
)
.header(CONTENT_LENGTH, "xxxx")
.to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await;
assert!(eq(info.err().unwrap(), UrlencodedError::UnknownLength));
let (req, mut pl) = TestRequest::with_header(
CONTENT_TYPE,
"application/x-www-form-urlencoded",
)
.header(CONTENT_LENGTH, "1000000")
.to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await;
assert!(eq(
info.err().unwrap(),
UrlencodedError::Overflow { size: 0, limit: 0 }
));
let (req, mut pl) = TestRequest::with_header(CONTENT_TYPE, "text/plain")
.header(CONTENT_LENGTH, "10")
.to_http_parts(); .to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await; let info = UrlEncoded::<Info>::new(&req, &mut pl).await;
assert!(eq(info.err().unwrap(), UrlencodedError::ContentType)); assert!(eq(info.err().unwrap(), UrlencodedError::UnknownLength));
})
let (req, mut pl) =
TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
.header(CONTENT_LENGTH, "1000000")
.to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await;
assert!(eq(
info.err().unwrap(),
UrlencodedError::Overflow { size: 0, limit: 0 }
));
let (req, mut pl) = TestRequest::with_header(CONTENT_TYPE, "text/plain")
.header(CONTENT_LENGTH, "10")
.to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await;
assert!(eq(info.err().unwrap(), UrlencodedError::ContentType));
} }
#[test] #[actix_rt::test]
fn test_urlencoded() { async fn test_urlencoded() {
block_on(async { let (req, mut pl) =
let (req, mut pl) = TestRequest::with_header( TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded")
CONTENT_TYPE, .header(CONTENT_LENGTH, "11")
"application/x-www-form-urlencoded", .set_payload(Bytes::from_static(b"hello=world&counter=123"))
) .to_http_parts();
.header(CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world&counter=123"))
.to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await.unwrap(); let info = UrlEncoded::<Info>::new(&req, &mut pl).await.unwrap();
assert_eq!( assert_eq!(
info, info,
Info { Info {
hello: "world".to_owned(), hello: "world".to_owned(),
counter: 123 counter: 123
} }
); );
let (req, mut pl) = TestRequest::with_header( let (req, mut pl) = TestRequest::with_header(
CONTENT_TYPE, CONTENT_TYPE,
"application/x-www-form-urlencoded; charset=utf-8", "application/x-www-form-urlencoded; charset=utf-8",
) )
.header(CONTENT_LENGTH, "11") .header(CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world&counter=123")) .set_payload(Bytes::from_static(b"hello=world&counter=123"))
.to_http_parts(); .to_http_parts();
let info = UrlEncoded::<Info>::new(&req, &mut pl).await.unwrap(); let info = UrlEncoded::<Info>::new(&req, &mut pl).await.unwrap();
assert_eq!( assert_eq!(
info, info,
Info { Info {
hello: "world".to_owned(), hello: "world".to_owned(),
counter: 123 counter: 123
} }
); );
})
} }
#[test] #[actix_rt::test]
fn test_responder() { async fn test_responder() {
block_on(async { let req = TestRequest::default().to_http_request();
let req = TestRequest::default().to_http_request();
let form = Form(Info { let form = Form(Info {
hello: "world".to_string(), hello: "world".to_string(),
counter: 123, counter: 123,
}); });
let resp = form.respond_to(&req).await.unwrap(); let resp = form.respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!( assert_eq!(
resp.headers().get(CONTENT_TYPE).unwrap(), resp.headers().get(CONTENT_TYPE).unwrap(),
HeaderValue::from_static("application/x-www-form-urlencoded") HeaderValue::from_static("application/x-www-form-urlencoded")
); );
use crate::responder::tests::BodyTest; use crate::responder::tests::BodyTest;
assert_eq!(resp.body().bin_ref(), b"hello=world&counter=123"); assert_eq!(resp.body().bin_ref(), b"hello=world&counter=123");
})
} }
} }

View File

@ -8,7 +8,7 @@ use std::{fmt, ops};
use bytes::BytesMut; use bytes::BytesMut;
use futures::future::{err, ok, FutureExt, LocalBoxFuture, Ready}; use futures::future::{err, ok, FutureExt, LocalBoxFuture, Ready};
use futures::{Stream, StreamExt}; use futures::StreamExt;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use serde_json; use serde_json;
@ -402,7 +402,7 @@ mod tests {
use super::*; use super::*;
use crate::error::InternalError; use crate::error::InternalError;
use crate::http::header; use crate::http::header;
use crate::test::{block_on, load_stream, TestRequest}; use crate::test::{load_stream, TestRequest};
use crate::HttpResponse; use crate::HttpResponse;
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
@ -424,236 +424,222 @@ mod tests {
} }
} }
#[test] #[actix_rt::test]
fn test_responder() { async fn test_responder() {
block_on(async { let req = TestRequest::default().to_http_request();
let req = TestRequest::default().to_http_request();
let j = Json(MyObject { let j = Json(MyObject {
name: "test".to_string(), name: "test".to_string(),
}); });
let resp = j.respond_to(&req).await.unwrap(); let resp = j.respond_to(&req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK); assert_eq!(resp.status(), StatusCode::OK);
assert_eq!( assert_eq!(
resp.headers().get(header::CONTENT_TYPE).unwrap(), resp.headers().get(header::CONTENT_TYPE).unwrap(),
header::HeaderValue::from_static("application/json") header::HeaderValue::from_static("application/json")
); );
use crate::responder::tests::BodyTest; use crate::responder::tests::BodyTest;
assert_eq!(resp.body().bin_ref(), b"{\"name\":\"test\"}"); assert_eq!(resp.body().bin_ref(), b"{\"name\":\"test\"}");
})
} }
#[test] #[actix_rt::test]
fn test_custom_error_responder() { async fn test_custom_error_responder() {
block_on(async { let (req, mut pl) = TestRequest::default()
let (req, mut pl) = TestRequest::default() .header(
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(10).error_handler(|err, _| {
let msg = MyObject {
name: "invalid request".to_string(),
};
let resp = HttpResponse::BadRequest()
.body(serde_json::to_string(&msg).unwrap());
InternalError::from_response(err, resp).into()
}))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
let mut resp = Response::from_error(s.err().unwrap().into());
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let body = load_stream(resp.take_body()).await.unwrap();
let msg: MyObject = serde_json::from_slice(&body).unwrap();
assert_eq!(msg.name, "invalid request");
})
}
#[test]
fn test_extract() {
block_on(async {
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s.name, "test");
assert_eq!(
s.into_inner(),
MyObject {
name: "test".to_string()
}
);
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(10))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(format!("{}", s.err().unwrap())
.contains("Json payload size is bigger than allowed"));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(
JsonConfig::default()
.limit(10)
.error_handler(|_, _| JsonPayloadError::ContentType.into()),
)
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(format!("{}", s.err().unwrap()).contains("Content type error"));
})
}
#[test]
fn test_json_body() {
block_on(async {
let (req, mut pl) = TestRequest::default().to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/text"),
)
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("10000"),
)
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None)
.limit(100)
.await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert_eq!(
json.ok().unwrap(),
MyObject {
name: "test".to_owned()
}
);
})
}
#[test]
fn test_with_json_and_bad_content_type() {
block_on(async {
let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"), header::HeaderValue::from_static("application/json"),
) )
.header( .header(
header::CONTENT_LENGTH, header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"), header::HeaderValue::from_static("16"),
) )
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(4096)) .data(JsonConfig::default().limit(10).error_handler(|err, _| {
.to_http_parts(); let msg = MyObject {
name: "invalid request".to_string(),
let s = Json::<MyObject>::from_request(&req, &mut pl).await; };
assert!(s.is_err()) let resp = HttpResponse::BadRequest()
}) .body(serde_json::to_string(&msg).unwrap());
} InternalError::from_response(err, resp).into()
#[test]
fn test_with_json_and_good_custom_content_type() {
block_on(async {
let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
})) }))
.to_http_parts(); .to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await; let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(s.is_ok()) let mut resp = Response::from_error(s.err().unwrap().into());
}) assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
let body = load_stream(resp.take_body()).await.unwrap();
let msg: MyObject = serde_json::from_slice(&body).unwrap();
assert_eq!(msg.name, "invalid request");
} }
#[test] #[actix_rt::test]
fn test_with_json_and_bad_custom_content_type() { async fn test_extract() {
block_on(async { let (req, mut pl) = TestRequest::default()
let (req, mut pl) = TestRequest::with_header( .header(
header::CONTENT_TYPE, header::CONTENT_TYPE,
header::HeaderValue::from_static("text/html"), header::HeaderValue::from_static("application/json"),
) )
.header( .header(
header::CONTENT_LENGTH, header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"), header::HeaderValue::from_static("16"),
) )
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
}))
.to_http_parts(); .to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await; let s = Json::<MyObject>::from_request(&req, &mut pl).await.unwrap();
assert!(s.is_err()) assert_eq!(s.name, "test");
}) assert_eq!(
s.into_inner(),
MyObject {
name: "test".to_string()
}
);
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(10))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(format!("{}", s.err().unwrap())
.contains("Json payload size is bigger than allowed"));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(
JsonConfig::default()
.limit(10)
.error_handler(|_, _| JsonPayloadError::ContentType.into()),
)
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(format!("{}", s.err().unwrap()).contains("Content type error"));
}
#[actix_rt::test]
async fn test_json_body() {
let (req, mut pl) = TestRequest::default().to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/text"),
)
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("10000"),
)
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None)
.limit(100)
.await;
assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow));
let (req, mut pl) = TestRequest::default()
.header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.to_http_parts();
let json = JsonBody::<MyObject>::new(&req, &mut pl, None).await;
assert_eq!(
json.ok().unwrap(),
MyObject {
name: "test".to_owned()
}
);
}
#[actix_rt::test]
async fn test_with_json_and_bad_content_type() {
let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().limit(4096))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(s.is_err())
}
#[actix_rt::test]
async fn test_with_json_and_good_custom_content_type() {
let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/plain"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
}))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(s.is_ok())
}
#[actix_rt::test]
async fn test_with_json_and_bad_custom_content_type() {
let (req, mut pl) = TestRequest::with_header(
header::CONTENT_TYPE,
header::HeaderValue::from_static("text/html"),
)
.header(
header::CONTENT_LENGTH,
header::HeaderValue::from_static("16"),
)
.set_payload(Bytes::from_static(b"{\"name\": \"test\"}"))
.data(JsonConfig::default().content_type(|mime: mime::Mime| {
mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN
}))
.to_http_parts();
let s = Json::<MyObject>::from_request(&req, &mut pl).await;
assert!(s.is_err())
} }
} }

View File

@ -12,3 +12,4 @@ pub use self::json::{Json, JsonConfig};
pub use self::path::{Path, PathConfig}; pub use self::path::{Path, PathConfig};
pub use self::payload::{Payload, PayloadConfig}; pub use self::payload::{Payload, PayloadConfig};
pub use self::query::{Query, QueryConfig}; pub use self::query::{Query, QueryConfig};
pub use self::readlines::Readlines;

View File

@ -1,5 +1,4 @@
//! Path extractor //! Path extractor
use std::sync::Arc; use std::sync::Arc;
use std::{fmt, ops}; use std::{fmt, ops};
@ -253,7 +252,7 @@ mod tests {
use serde_derive::Deserialize; use serde_derive::Deserialize;
use super::*; use super::*;
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
use crate::{error, http, HttpResponse}; use crate::{error, http, HttpResponse};
#[derive(Deserialize, Debug, Display)] #[derive(Deserialize, Debug, Display)]
@ -269,118 +268,110 @@ mod tests {
value: u32, value: u32,
} }
#[test] #[actix_rt::test]
fn test_extract_path_single() { async fn test_extract_path_single() {
block_on(async { let resource = ResourceDef::new("/{value}/");
let resource = ResourceDef::new("/{value}/");
let mut req = TestRequest::with_uri("/32/").to_srv_request(); let mut req = TestRequest::with_uri("/32/").to_srv_request();
resource.match_path(req.match_info_mut()); resource.match_path(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
assert_eq!(*Path::<i8>::from_request(&req, &mut pl).await.unwrap(), 32); assert_eq!(*Path::<i8>::from_request(&req, &mut pl).await.unwrap(), 32);
assert!(Path::<MyStruct>::from_request(&req, &mut pl).await.is_err()); assert!(Path::<MyStruct>::from_request(&req, &mut pl).await.is_err());
})
} }
#[test] #[actix_rt::test]
fn test_tuple_extract() { async fn test_tuple_extract() {
block_on(async { let resource = ResourceDef::new("/{key}/{value}/");
let resource = ResourceDef::new("/{key}/{value}/");
let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
resource.match_path(req.match_info_mut()); resource.match_path(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let res = <(Path<(String, String)>,)>::from_request(&req, &mut pl) let res = <(Path<(String, String)>,)>::from_request(&req, &mut pl)
.await
.unwrap();
assert_eq!((res.0).0, "name");
assert_eq!((res.0).1, "user1");
let res = <(Path<(String, String)>, Path<(String, String)>)>::from_request(
&req, &mut pl,
)
.await .await
.unwrap(); .unwrap();
assert_eq!((res.0).0, "name"); assert_eq!((res.0).0, "name");
assert_eq!((res.0).1, "user1"); assert_eq!((res.0).1, "user1");
assert_eq!((res.1).0, "name");
assert_eq!((res.1).1, "user1");
let () = <()>::from_request(&req, &mut pl).await.unwrap(); let res = <(Path<(String, String)>, Path<(String, String)>)>::from_request(
}) &req, &mut pl,
)
.await
.unwrap();
assert_eq!((res.0).0, "name");
assert_eq!((res.0).1, "user1");
assert_eq!((res.1).0, "name");
assert_eq!((res.1).1, "user1");
let () = <()>::from_request(&req, &mut pl).await.unwrap();
} }
#[test] #[actix_rt::test]
fn test_request_extract() { async fn test_request_extract() {
block_on(async { let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
let mut req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
let resource = ResourceDef::new("/{key}/{value}/"); let resource = ResourceDef::new("/{key}/{value}/");
resource.match_path(req.match_info_mut()); resource.match_path(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let mut s = Path::<MyStruct>::from_request(&req, &mut pl).await.unwrap(); let mut s = Path::<MyStruct>::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s.key, "name"); assert_eq!(s.key, "name");
assert_eq!(s.value, "user1"); assert_eq!(s.value, "user1");
s.value = "user2".to_string(); s.value = "user2".to_string();
assert_eq!(s.value, "user2"); assert_eq!(s.value, "user2");
assert_eq!( assert_eq!(
format!("{}, {:?}", s, s), format!("{}, {:?}", s, s),
"MyStruct(name, user2), MyStruct { key: \"name\", value: \"user2\" }" "MyStruct(name, user2), MyStruct { key: \"name\", value: \"user2\" }"
); );
let s = s.into_inner(); let s = s.into_inner();
assert_eq!(s.value, "user2"); assert_eq!(s.value, "user2");
let s = Path::<(String, String)>::from_request(&req, &mut pl) let s = Path::<(String, String)>::from_request(&req, &mut pl)
.await .await
.unwrap(); .unwrap();
assert_eq!(s.0, "name"); assert_eq!(s.0, "name");
assert_eq!(s.1, "user1"); assert_eq!(s.1, "user1");
let mut req = TestRequest::with_uri("/name/32/").to_srv_request(); let mut req = TestRequest::with_uri("/name/32/").to_srv_request();
let resource = ResourceDef::new("/{key}/{value}/"); let resource = ResourceDef::new("/{key}/{value}/");
resource.match_path(req.match_info_mut()); resource.match_path(req.match_info_mut());
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let s = Path::<Test2>::from_request(&req, &mut pl).await.unwrap(); let s = Path::<Test2>::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s.as_ref().key, "name"); assert_eq!(s.as_ref().key, "name");
assert_eq!(s.value, 32); assert_eq!(s.value, 32);
let s = Path::<(String, u8)>::from_request(&req, &mut pl) let s = Path::<(String, u8)>::from_request(&req, &mut pl)
.await .await
.unwrap(); .unwrap();
assert_eq!(s.0, "name"); assert_eq!(s.0, "name");
assert_eq!(s.1, 32); assert_eq!(s.1, 32);
let res = Path::<Vec<String>>::from_request(&req, &mut pl) let res = Path::<Vec<String>>::from_request(&req, &mut pl)
.await .await
.unwrap(); .unwrap();
assert_eq!(res[0], "name".to_owned()); assert_eq!(res[0], "name".to_owned());
assert_eq!(res[1], "32".to_owned()); assert_eq!(res[1], "32".to_owned());
})
} }
#[test] #[actix_rt::test]
fn test_custom_err_handler() { async fn test_custom_err_handler() {
block_on(async { let (req, mut pl) = TestRequest::with_uri("/name/user1/")
let (req, mut pl) = TestRequest::with_uri("/name/user1/") .data(PathConfig::default().error_handler(|err, _| {
.data(PathConfig::default().error_handler(|err, _| { error::InternalError::from_response(
error::InternalError::from_response( err,
err, HttpResponse::Conflict().finish(),
HttpResponse::Conflict().finish(), )
) .into()
.into() }))
})) .to_http_parts();
.to_http_parts();
let s = Path::<(usize,)>::from_request(&req, &mut pl) let s = Path::<(usize,)>::from_request(&req, &mut pl)
.await .await
.unwrap_err(); .unwrap_err();
let res: HttpResponse = s.into(); let res: HttpResponse = s.into();
assert_eq!(res.status(), http::StatusCode::CONFLICT); assert_eq!(res.status(), http::StatusCode::CONFLICT);
})
} }
} }

View File

@ -395,10 +395,10 @@ mod tests {
use super::*; use super::*;
use crate::http::header; use crate::http::header;
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
#[test] #[actix_rt::test]
fn test_payload_config() { async fn test_payload_config() {
let req = TestRequest::default().to_http_request(); let req = TestRequest::default().to_http_request();
let cfg = PayloadConfig::default().mimetype(mime::APPLICATION_JSON); let cfg = PayloadConfig::default().mimetype(mime::APPLICATION_JSON);
assert!(cfg.check_mimetype(&req).is_err()); assert!(cfg.check_mimetype(&req).is_err());
@ -415,32 +415,32 @@ mod tests {
assert!(cfg.check_mimetype(&req).is_ok()); assert!(cfg.check_mimetype(&req).is_ok());
} }
#[test] #[actix_rt::test]
fn test_bytes() { async fn test_bytes() {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11") let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world")) .set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts(); .to_http_parts();
let s = block_on(Bytes::from_request(&req, &mut pl)).unwrap(); let s = Bytes::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s, Bytes::from_static(b"hello=world")); assert_eq!(s, Bytes::from_static(b"hello=world"));
} }
#[test] #[actix_rt::test]
fn test_string() { async fn test_string() {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11") let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11")
.set_payload(Bytes::from_static(b"hello=world")) .set_payload(Bytes::from_static(b"hello=world"))
.to_http_parts(); .to_http_parts();
let s = block_on(String::from_request(&req, &mut pl)).unwrap(); let s = String::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s, "hello=world"); assert_eq!(s, "hello=world");
} }
#[test] #[actix_rt::test]
fn test_message_body() { async fn test_message_body() {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx") let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx")
.to_srv_request() .to_srv_request()
.into_parts(); .into_parts();
let res = block_on(HttpMessageBody::new(&req, &mut pl)); let res = HttpMessageBody::new(&req, &mut pl).await;
match res.err().unwrap() { match res.err().unwrap() {
PayloadError::UnknownLength => (), PayloadError::UnknownLength => (),
_ => unreachable!("error"), _ => unreachable!("error"),
@ -449,7 +449,7 @@ mod tests {
let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "1000000") let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "1000000")
.to_srv_request() .to_srv_request()
.into_parts(); .into_parts();
let res = block_on(HttpMessageBody::new(&req, &mut pl)); let res = HttpMessageBody::new(&req, &mut pl).await;
match res.err().unwrap() { match res.err().unwrap() {
PayloadError::Overflow => (), PayloadError::Overflow => (),
_ => unreachable!("error"), _ => unreachable!("error"),
@ -458,13 +458,13 @@ mod tests {
let (req, mut pl) = TestRequest::default() let (req, mut pl) = TestRequest::default()
.set_payload(Bytes::from_static(b"test")) .set_payload(Bytes::from_static(b"test"))
.to_http_parts(); .to_http_parts();
let res = block_on(HttpMessageBody::new(&req, &mut pl)); let res = HttpMessageBody::new(&req, &mut pl).await;
assert_eq!(res.ok().unwrap(), Bytes::from_static(b"test")); assert_eq!(res.ok().unwrap(), Bytes::from_static(b"test"));
let (req, mut pl) = TestRequest::default() let (req, mut pl) = TestRequest::default()
.set_payload(Bytes::from_static(b"11111111111111")) .set_payload(Bytes::from_static(b"11111111111111"))
.to_http_parts(); .to_http_parts();
let res = block_on(HttpMessageBody::new(&req, &mut pl).limit(5)); let res = HttpMessageBody::new(&req, &mut pl).limit(5).await;
match res.err().unwrap() { match res.err().unwrap() {
PayloadError::Overflow => (), PayloadError::Overflow => (),
_ => unreachable!("error"), _ => unreachable!("error"),

View File

@ -228,7 +228,7 @@ mod tests {
use super::*; use super::*;
use crate::error::InternalError; use crate::error::InternalError;
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
use crate::HttpResponse; use crate::HttpResponse;
#[derive(Deserialize, Debug, Display)] #[derive(Deserialize, Debug, Display)]
@ -236,8 +236,8 @@ mod tests {
id: String, id: String,
} }
#[test] #[actix_rt::test]
fn test_service_request_extract() { async fn test_service_request_extract() {
let req = TestRequest::with_uri("/name/user1/").to_srv_request(); let req = TestRequest::with_uri("/name/user1/").to_srv_request();
assert!(Query::<Id>::from_query(&req.query_string()).is_err()); assert!(Query::<Id>::from_query(&req.query_string()).is_err());
@ -252,48 +252,44 @@ mod tests {
assert_eq!(s.id, "test1"); assert_eq!(s.id, "test1");
} }
#[test] #[actix_rt::test]
fn test_request_extract() { async fn test_request_extract() {
block_on(async { let req = TestRequest::with_uri("/name/user1/").to_srv_request();
let req = TestRequest::with_uri("/name/user1/").to_srv_request(); let (req, mut pl) = req.into_parts();
let (req, mut pl) = req.into_parts(); assert!(Query::<Id>::from_request(&req, &mut pl).await.is_err());
assert!(Query::<Id>::from_request(&req, &mut pl).await.is_err());
let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request(); let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let mut s = Query::<Id>::from_request(&req, &mut pl).await.unwrap(); let mut s = Query::<Id>::from_request(&req, &mut pl).await.unwrap();
assert_eq!(s.id, "test"); assert_eq!(s.id, "test");
assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }"); assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");
s.id = "test1".to_string(); s.id = "test1".to_string();
let s = s.into_inner(); let s = s.into_inner();
assert_eq!(s.id, "test1"); assert_eq!(s.id, "test1");
})
} }
#[test] #[actix_rt::test]
fn test_custom_error_responder() { async fn test_custom_error_responder() {
block_on(async { let req = TestRequest::with_uri("/name/user1/")
let req = TestRequest::with_uri("/name/user1/") .data(QueryConfig::default().error_handler(|e, _| {
.data(QueryConfig::default().error_handler(|e, _| { let resp = HttpResponse::UnprocessableEntity().finish();
let resp = HttpResponse::UnprocessableEntity().finish(); InternalError::from_response(e, resp).into()
InternalError::from_response(e, resp).into() }))
})) .to_srv_request();
.to_srv_request();
let (req, mut pl) = req.into_parts(); let (req, mut pl) = req.into_parts();
let query = Query::<Id>::from_request(&req, &mut pl).await; let query = Query::<Id>::from_request(&req, &mut pl).await;
assert!(query.is_err()); assert!(query.is_err());
assert_eq!( assert_eq!(
query query
.unwrap_err() .unwrap_err()
.as_response_error() .as_response_error()
.error_response() .error_response()
.status(), .status(),
StatusCode::UNPROCESSABLE_ENTITY StatusCode::UNPROCESSABLE_ENTITY
); );
})
} }
} }

View File

@ -1,5 +1,4 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::future::Future;
use std::pin::Pin; use std::pin::Pin;
use std::str; use std::str;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@ -7,7 +6,6 @@ use std::task::{Context, Poll};
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use encoding_rs::{Encoding, UTF_8}; use encoding_rs::{Encoding, UTF_8};
use futures::Stream; use futures::Stream;
use pin_project::pin_project;
use crate::dev::Payload; use crate::dev::Payload;
use crate::error::{PayloadError, ReadlinesError}; use crate::error::{PayloadError, ReadlinesError};
@ -174,12 +172,11 @@ mod tests {
use futures::stream::StreamExt; use futures::stream::StreamExt;
use super::*; use super::*;
use crate::test::{block_on, TestRequest}; use crate::test::TestRequest;
#[test] #[actix_rt::test]
fn test_readlines() { async fn test_readlines() {
block_on(async { let mut req = TestRequest::default()
let mut req = TestRequest::default()
.set_payload(Bytes::from_static( .set_payload(Bytes::from_static(
b"Lorem Ipsum is simply dummy text of the printing and typesetting\n\ b"Lorem Ipsum is simply dummy text of the printing and typesetting\n\
industry. Lorem Ipsum has been the industry's standard dummy\n\ industry. Lorem Ipsum has been the industry's standard dummy\n\
@ -187,21 +184,20 @@ mod tests {
)) ))
.to_request(); .to_request();
let mut stream = Readlines::new(&mut req); let mut stream = Readlines::new(&mut req);
assert_eq!( assert_eq!(
stream.next().await.unwrap().unwrap(), stream.next().await.unwrap().unwrap(),
"Lorem Ipsum is simply dummy text of the printing and typesetting\n" "Lorem Ipsum is simply dummy text of the printing and typesetting\n"
); );
assert_eq!( assert_eq!(
stream.next().await.unwrap().unwrap(), stream.next().await.unwrap().unwrap(),
"industry. Lorem Ipsum has been the industry's standard dummy\n" "industry. Lorem Ipsum has been the industry's standard dummy\n"
); );
assert_eq!( assert_eq!(
stream.next().await.unwrap().unwrap(), stream.next().await.unwrap().unwrap(),
"Contrary to popular belief, Lorem Ipsum is not simply random text." "Contrary to popular belief, Lorem Ipsum is not simply random text."
); );
})
} }
} }

View File

@ -6,7 +6,6 @@ pub use actix_http::Response as HttpResponse;
pub use bytes::{Bytes, BytesMut}; pub use bytes::{Bytes, BytesMut};
pub use futures::channel::oneshot::Canceled; pub use futures::channel::oneshot::Canceled;
use crate::error::Error;
use crate::extract::FromRequest; use crate::extract::FromRequest;
use crate::handler::Factory; use crate::handler::Factory;
use crate::resource::Resource; use crate::resource::Resource;

View File

@ -54,8 +54,6 @@ slab = "0.4"
serde_urlencoded = "0.6.1" serde_urlencoded = "0.6.1"
time = "0.1" time = "0.1"
tokio-net = "0.2.0-alpha.6" tokio-net = "0.2.0-alpha.6"
tokio-timer = "0.3.0-alpha.6"
open-ssl = { version="0.10", package="openssl", optional = true } open-ssl = { version="0.10", package="openssl", optional = true }
[dev-dependencies] [dev-dependencies]

View File

@ -23,26 +23,25 @@ pub use actix_testing::*;
/// ///
/// ```rust /// ```rust
/// use actix_http::HttpService; /// use actix_http::HttpService;
/// use actix_http_test::{block_on, TestServer}; /// use actix_http_test::TestServer;
/// use actix_web::{web, App, HttpResponse, Error}; /// use actix_web::{web, App, HttpResponse, Error};
/// ///
/// async fn my_handler() -> Result<HttpResponse, Error> { /// async fn my_handler() -> Result<HttpResponse, Error> {
/// Ok(HttpResponse::Ok().into()) /// Ok(HttpResponse::Ok().into())
/// } /// }
/// ///
/// fn main() { /// #[actix_rt::test]
/// block_on( async { /// async fn test_example() {
/// let mut srv = TestServer::start( /// let mut srv = TestServer::start(
/// || HttpService::new( /// || HttpService::new(
/// App::new().service( /// App::new().service(
/// web::resource("/").to(my_handler)) /// web::resource("/").to(my_handler))
/// ) /// )
/// ); /// );
/// ///
/// let req = srv.get("/"); /// let req = srv.get("/");
/// let response = req.send().await.unwrap(); /// let response = req.send().await.unwrap();
/// assert!(response.status().is_success()); /// assert!(response.status().is_success());
/// })
/// } /// }
/// ``` /// ```
pub struct TestServer; pub struct TestServer;

View File

@ -6,7 +6,7 @@ use std::{net, thread, time::Duration};
use open_ssl::ssl::SslAcceptorBuilder; use open_ssl::ssl::SslAcceptorBuilder;
use actix_http::Response; use actix_http::Response;
use actix_web::{test, web, App, HttpServer}; use actix_web::{web, App, HttpServer};
fn unused_addr() -> net::SocketAddr { fn unused_addr() -> net::SocketAddr {
let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap(); let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
@ -17,9 +17,9 @@ fn unused_addr() -> net::SocketAddr {
tcp.local_addr().unwrap() tcp.local_addr().unwrap()
} }
#[test]
#[cfg(unix)] #[cfg(unix)]
fn test_start() { #[actix_rt::test]
async fn test_start() {
let addr = unused_addr(); let addr = unused_addr();
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
@ -53,21 +53,18 @@ fn test_start() {
#[cfg(feature = "client")] #[cfg(feature = "client")]
{ {
use actix_http::client; use actix_http::client;
use actix_web::test;
test::block_on(async { let client = awc::Client::build()
let client = awc::Client::build() .connector(
.connector( client::Connector::new()
client::Connector::new() .timeout(Duration::from_millis(100))
.timeout(Duration::from_millis(100)) .finish(),
.finish(), )
) .finish();
.finish();
let host = format!("http://{}", addr); let host = format!("http://{}", addr);
let response = client.get(host.clone()).send().await.unwrap(); let response = client.get(host.clone()).send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
});
} }
// stop // stop
@ -91,9 +88,9 @@ fn ssl_acceptor() -> std::io::Result<SslAcceptorBuilder> {
Ok(builder) Ok(builder)
} }
#[test] #[actix_rt::test]
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
fn test_start_ssl() { async fn test_start_ssl() {
let addr = unused_addr(); let addr = unused_addr();
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
@ -119,27 +116,25 @@ fn test_start_ssl() {
}); });
let (srv, sys) = rx.recv().unwrap(); let (srv, sys) = rx.recv().unwrap();
test::block_on(async move { use open_ssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
use open_ssl::ssl::{SslConnector, SslMethod, SslVerifyMode}; let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap(); builder.set_verify(SslVerifyMode::NONE);
builder.set_verify(SslVerifyMode::NONE); let _ = builder
let _ = builder .set_alpn_protos(b"\x02h2\x08http/1.1")
.set_alpn_protos(b"\x02h2\x08http/1.1") .map_err(|e| log::error!("Can not set alpn protocol: {:?}", e));
.map_err(|e| log::error!("Can not set alpn protocol: {:?}", e));
let client = awc::Client::build() let client = awc::Client::build()
.connector( .connector(
awc::Connector::new() awc::Connector::new()
.ssl(builder.build()) .ssl(builder.build())
.timeout(Duration::from_millis(100)) .timeout(Duration::from_millis(100))
.finish(), .finish(),
) )
.finish(); .finish();
let host = format!("https://{}", addr); let host = format!("https://{}", addr);
let response = client.get(host.clone()).send().await.unwrap(); let response = client.get(host.clone()).send().await.unwrap();
assert!(response.status().is_success()); assert!(response.status().is_success());
});
// stop // stop
let _ = srv.stop(false); let _ = srv.stop(false);

File diff suppressed because it is too large Load Diff