1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-01-31 11:02:08 +01:00

revive commented out tests (#1912)

This commit is contained in:
Rob Ede 2021-01-17 05:19:32 +00:00 committed by GitHub
parent 1c95fc2654
commit ee10148444
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 243 additions and 222 deletions

View File

@ -6,6 +6,7 @@
* `ResponseBuilder::insert_header` method which allows using typed headers. [#1869] * `ResponseBuilder::insert_header` method which allows using typed headers. [#1869]
* `ResponseBuilder::append_header` method which allows using typed headers. [#1869] * `ResponseBuilder::append_header` method which allows using typed headers. [#1869]
* `TestRequest::insert_header` method which allows using typed headers. [#1869] * `TestRequest::insert_header` method which allows using typed headers. [#1869]
* `ContentEncoding` implements all necessary header traits. [#1912]
### Changed ### Changed
* `ResponseBuilder::content_type` now takes an `impl IntoHeaderValue` to support using typed * `ResponseBuilder::content_type` now takes an `impl IntoHeaderValue` to support using typed
@ -24,6 +25,7 @@
[#1869]: https://github.com/actix/actix-web/pull/1869 [#1869]: https://github.com/actix/actix-web/pull/1869
[#1894]: https://github.com/actix/actix-web/pull/1894 [#1894]: https://github.com/actix/actix-web/pull/1894
[#1904]: https://github.com/actix/actix-web/pull/1904 [#1904]: https://github.com/actix/actix-web/pull/1904
[#1912]: https://github.com/actix/actix-web/pull/1912
## 3.0.0-beta.1 - 2021-01-07 ## 3.0.0-beta.1 - 2021-01-07

View File

@ -1,3 +1,13 @@
use std::{convert::Infallible, str::FromStr};
use http::header::InvalidHeaderValue;
use crate::{
error::ParseError,
header::{self, from_one_raw_str, Header, HeaderName, HeaderValue, IntoHeaderValue},
HttpMessage,
};
/// Represents a supported content encoding. /// Represents a supported content encoding.
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
pub enum ContentEncoding { pub enum ContentEncoding {
@ -47,6 +57,20 @@ impl ContentEncoding {
} }
} }
impl Default for ContentEncoding {
fn default() -> Self {
Self::Identity
}
}
impl FromStr for ContentEncoding {
type Err = Infallible;
fn from_str(val: &str) -> Result<Self, Self::Err> {
Ok(Self::from(val))
}
}
impl From<&str> for ContentEncoding { impl From<&str> for ContentEncoding {
fn from(val: &str) -> ContentEncoding { fn from(val: &str) -> ContentEncoding {
let val = val.trim(); let val = val.trim();
@ -58,7 +82,25 @@ impl From<&str> for ContentEncoding {
} else if val.eq_ignore_ascii_case("deflate") { } else if val.eq_ignore_ascii_case("deflate") {
ContentEncoding::Deflate ContentEncoding::Deflate
} else { } else {
ContentEncoding::Identity ContentEncoding::default()
} }
} }
} }
impl IntoHeaderValue for ContentEncoding {
type Error = InvalidHeaderValue;
fn try_into_value(self) -> Result<http::HeaderValue, Self::Error> {
Ok(HeaderValue::from_static(self.as_str()))
}
}
impl Header for ContentEncoding {
fn name() -> HeaderName {
header::CONTENT_ENCODING
}
fn parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError> {
from_one_raw_str(msg.headers().get(Self::name()))
}
}

View File

@ -67,8 +67,10 @@ actix-http-test = { version = "3.0.0-beta.1", features = ["openssl"] }
actix-utils = "3.0.0-beta.1" actix-utils = "3.0.0-beta.1"
actix-server = "2.0.0-beta.2" actix-server = "2.0.0-beta.2"
actix-tls = { version = "3.0.0-beta.2", features = ["openssl", "rustls"] } actix-tls = { version = "3.0.0-beta.2", features = ["openssl", "rustls"] }
brotli2 = "0.3.2" brotli2 = "0.3.2"
flate2 = "1.0.13" flate2 = "1.0.13"
futures-util = { version = "0.3.7", default-features = false } futures-util = { version = "0.3.7", default-features = false }
env_logger = "0.7" env_logger = "0.7"
rcgen = "0.8"
webpki = "0.21" webpki = "0.21"

View File

@ -9,17 +9,20 @@ use bytes::Bytes;
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use flate2::write::GzEncoder; use flate2::write::GzEncoder;
use flate2::Compression; use flate2::Compression;
use futures_util::future::ok; use futures_util::{future::ok, stream};
use rand::Rng; use rand::Rng;
use actix_http::HttpService; use actix_http::{
http::{self, StatusCode},
HttpService,
};
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory}; use actix_service::{map_config, pipeline_factory};
use actix_web::dev::{AppConfig, BodyEncoding};
use actix_web::http::Cookie;
use actix_web::middleware::Compress;
use actix_web::{ use actix_web::{
http::header, test, web, App, Error, HttpMessage, HttpRequest, HttpResponse, dev::{AppConfig, BodyEncoding},
http::{header, Cookie},
middleware::Compress,
test, web, App, Error, HttpMessage, HttpRequest, HttpResponse,
}; };
use awc::error::SendRequestError; use awc::error::SendRequestError;
@ -557,117 +560,94 @@ async fn test_client_brotli_encoding_large_random() {
assert_eq!(bytes, Bytes::from(data)); assert_eq!(bytes, Bytes::from(data));
} }
// TODO: why is test ignored #[actix_rt::test]
// #[actix_rt::test] async fn test_client_deflate_encoding() {
// async fn test_client_deflate_encoding() { let srv = test::start(|| {
// let srv = test::TestServer::start(|app| { App::new().default_service(web::to(|body: Bytes| {
// app.handler(|req: &HttpRequest| { HttpResponse::Ok()
// req.body() .encoding(http::ContentEncoding::Br)
// .and_then(|bytes: Bytes| { .body(body)
// Ok(HttpResponse::Ok() }))
// .content_encoding(http::ContentEncoding::Br) });
// .body(bytes))
// })
// .responder()
// })
// });
// // client request let req = srv.post("/").send_body(STR);
// let request = srv
// .post()
// .content_encoding(http::ContentEncoding::Deflate)
// .body(STR)
// .unwrap();
// let response = srv.execute(request.send()).unwrap();
// assert!(response.status().is_success());
// // read response let mut res = req.await.unwrap();
// let bytes = srv.execute(response.body()).unwrap(); assert_eq!(res.status(), StatusCode::OK);
// assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
// }
// TODO: why is test ignored let bytes = res.body().await.unwrap();
// #[actix_rt::test] assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
// async fn test_client_deflate_encoding_large_random() { }
// let data = rand::thread_rng()
// .sample_iter(&rand::distributions::Alphanumeric)
// .take(70_000)
// .collect::<String>();
// let srv = test::TestServer::start(|app| { #[actix_rt::test]
// app.handler(|req: &HttpRequest| { async fn test_client_deflate_encoding_large_random() {
// req.body() let data = rand::thread_rng()
// .and_then(|bytes: Bytes| { .sample_iter(rand::distributions::Alphanumeric)
// Ok(HttpResponse::Ok() .map(char::from)
// .content_encoding(http::ContentEncoding::Br) .take(70_000)
// .body(bytes)) .collect::<String>();
// })
// .responder()
// })
// });
// // client request let srv = test::start(|| {
// let request = srv App::new().default_service(web::to(|body: Bytes| {
// .post() HttpResponse::Ok()
// .content_encoding(http::ContentEncoding::Deflate) .encoding(http::ContentEncoding::Br)
// .body(data.clone()) .body(body)
// .unwrap(); }))
// let response = srv.execute(request.send()).unwrap(); });
// assert!(response.status().is_success());
// // read response let req = srv.post("/").send_body(data.clone());
// let bytes = srv.execute(response.body()).unwrap();
// assert_eq!(bytes, Bytes::from(data));
// }
// TODO: why is test ignored let mut res = req.await.unwrap();
// #[actix_rt::test] let bytes = res.body().await.unwrap();
// async fn test_client_streaming_explicit() {
// let srv = test::TestServer::start(|app| {
// app.handler(|req: &HttpRequest| {
// req.body()
// .map_err(Error::from)
// .and_then(|body| {
// Ok(HttpResponse::Ok()
// .chunked()
// .content_encoding(http::ContentEncoding::Identity)
// .body(body))
// })
// .responder()
// })
// });
// let body = once(Ok(Bytes::from_static(STR.as_ref()))); assert_eq!(res.status(), StatusCode::OK);
assert_eq!(bytes, Bytes::from(data));
}
// let request = srv.get("/").body(Body::Streaming(Box::new(body))).unwrap(); #[actix_rt::test]
// let response = srv.execute(request.send()).unwrap(); async fn test_client_streaming_explicit() {
// assert!(response.status().is_success()); let srv = test::start(|| {
App::new().default_service(web::to(|body: web::Payload| {
HttpResponse::Ok()
.encoding(http::ContentEncoding::Identity)
.streaming(body)
}))
});
// // read response let body = stream::once(async {
// let bytes = srv.execute(response.body()).unwrap(); Ok::<_, actix_http::Error>(Bytes::from_static(STR.as_bytes()))
// assert_eq!(bytes, Bytes::from_static(STR.as_ref())); });
// } let req = srv.post("/").send_stream(Box::pin(body));
// TODO: why is test ignored let mut res = req.await.unwrap();
// #[actix_rt::test] assert!(res.status().is_success());
// async fn test_body_streaming_implicit() {
// let srv = test::TestServer::start(|app| {
// app.handler(|_| {
// let body = once(Ok(Bytes::from_static(STR.as_ref())));
// HttpResponse::Ok()
// .content_encoding(http::ContentEncoding::Gzip)
// .body(Body::Streaming(Box::new(body)))
// })
// });
// let request = srv.get("/").finish().unwrap(); let bytes = res.body().await.unwrap();
// let response = srv.execute(request.send()).unwrap(); assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
// assert!(response.status().is_success()); }
// // read response #[actix_rt::test]
// let bytes = srv.execute(response.body()).unwrap(); async fn test_body_streaming_implicit() {
// assert_eq!(bytes, Bytes::from_static(STR.as_ref())); let srv = test::start(|| {
// } App::new().default_service(web::to(|| {
let body = stream::once(async {
Ok::<_, actix_http::Error>(Bytes::from_static(STR.as_bytes()))
});
HttpResponse::Ok()
.encoding(http::ContentEncoding::Gzip)
.streaming(Box::pin(body))
}))
});
let req = srv.get("/").send();
let mut res = req.await.unwrap();
assert!(res.status().is_success());
let bytes = res.body().await.unwrap();
assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
}
#[actix_rt::test] #[actix_rt::test]
async fn test_client_cookie_handling() { async fn test_client_cookie_handling() {
@ -738,36 +718,35 @@ async fn test_client_cookie_handling() {
assert_eq!(c2, cookie2); assert_eq!(c2, cookie2);
} }
// TODO: why is test ignored #[actix_rt::test]
// #[actix_rt::test] async fn client_unread_response() {
// fn client_read_until_eof() { let addr = test::unused_addr();
// let addr = test::TestServer::unused_addr();
// thread::spawn(move || { std::thread::spawn(move || {
// let lst = net::TcpListener::bind(addr).unwrap(); let lst = std::net::TcpListener::bind(addr).unwrap();
// for stream in lst.incoming() { for stream in lst.incoming() {
// let mut stream = stream.unwrap(); let mut stream = stream.unwrap();
// let mut b = [0; 1000]; let mut b = [0; 1000];
// let _ = stream.read(&mut b).unwrap(); let _ = stream.read(&mut b).unwrap();
// let _ = stream let _ = stream.write_all(
// .write_all(b"HTTP/1.1 200 OK\r\nconnection: close\r\n\r\nwelcome!"); b"HTTP/1.1 200 OK\r\n\
// } connection: close\r\n\
// }); \r\n\
welcome!",
);
}
});
// let mut sys = actix::System::new("test"); // client request
let req = awc::Client::new().get(format!("http://{}/", addr).as_str());
let mut res = req.send().await.unwrap();
assert!(res.status().is_success());
// // client request // awc does not read all bytes unless content-length is specified
// let req = client::ClientRequest::get(format!("http://{}/", addr).as_str()) let bytes = res.body().await.unwrap();
// .finish() assert_eq!(bytes, Bytes::from_static(b""));
// .unwrap(); }
// let response = req.send().await.unwrap();
// assert!(response.status().is_success());
// // read response
// let bytes = response.body().await.unwrap();
// assert_eq!(bytes, Bytes::from_static(b"welcome!"));
// }
#[actix_rt::test] #[actix_rt::test]
async fn client_basic_auth() { async fn client_basic_auth() {

View File

@ -1,58 +1,57 @@
#![cfg(feature = "rustls")] #![cfg(feature = "rustls")]
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc; extern crate rust_tls as rustls;
use std::{
io::BufReader,
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
};
use actix_http::HttpService; use actix_http::HttpService;
use actix_http_test::test_server; use actix_http_test::test_server;
use actix_service::{map_config, pipeline_factory, ServiceFactoryExt}; use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_web::http::Version; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse};
use actix_web::{dev::AppConfig, web, App, HttpResponse};
use futures_util::future::ok; use futures_util::future::ok;
use open_ssl::ssl::{SslAcceptor, SslFiletype, SslMethod, SslVerifyMode}; use rustls::internal::pemfile::{certs, pkcs8_private_keys};
use rust_tls::ClientConfig; use rustls::{ClientConfig, NoClientAuth, ServerConfig};
#[allow(unused)] fn tls_config() -> ServerConfig {
fn ssl_acceptor() -> SslAcceptor { let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
// load ssl keys let cert_file = cert.serialize_pem().unwrap();
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); let key_file = cert.serialize_private_key_pem();
builder.set_verify_callback(SslVerifyMode::NONE, |_, _| true);
builder let mut config = ServerConfig::new(NoClientAuth::new());
.set_private_key_file("../tests/key.pem", SslFiletype::PEM) let cert_file = &mut BufReader::new(cert_file.as_bytes());
.unwrap(); let key_file = &mut BufReader::new(key_file.as_bytes());
builder
.set_certificate_chain_file("../tests/cert.pem") let cert_chain = certs(cert_file).unwrap();
.unwrap(); let mut keys = pkcs8_private_keys(key_file).unwrap();
builder.set_alpn_select_callback(|_, protos| { config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
const H2: &[u8] = b"\x02h2";
if protos.windows(3).any(|window| window == H2) { config
Ok(b"h2")
} else {
Err(open_ssl::ssl::AlpnError::NOACK)
}
});
builder.set_alpn_protos(b"\x02h2").unwrap();
builder.build()
} }
mod danger { mod danger {
pub struct NoCertificateVerification {} pub struct NoCertificateVerification;
impl rust_tls::ServerCertVerifier for NoCertificateVerification { impl rustls::ServerCertVerifier for NoCertificateVerification {
fn verify_server_cert( fn verify_server_cert(
&self, &self,
_roots: &rust_tls::RootCertStore, _roots: &rustls::RootCertStore,
_presented_certs: &[rust_tls::Certificate], _presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef<'_>, _dns_name: webpki::DNSNameRef<'_>,
_ocsp: &[u8], _ocsp: &[u8],
) -> Result<rust_tls::ServerCertVerified, rust_tls::TLSError> { ) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
Ok(rust_tls::ServerCertVerified::assertion()) Ok(rustls::ServerCertVerified::assertion())
} }
} }
} }
// TODO: why is test ignored #[actix_rt::test]
// #[actix_rt::test] async fn test_connection_reuse_h2() {
async fn _test_connection_reuse_h2() {
let num = Arc::new(AtomicUsize::new(0)); let num = Arc::new(AtomicUsize::new(0));
let num2 = num.clone(); let num2 = num.clone();
@ -69,19 +68,19 @@ async fn _test_connection_reuse_h2() {
.service(web::resource("/").route(web::to(HttpResponse::Ok))), .service(web::resource("/").route(web::to(HttpResponse::Ok))),
|_| AppConfig::default(), |_| AppConfig::default(),
)) ))
.openssl(ssl_acceptor()) .rustls(tls_config())
.map_err(|_| ()), .map_err(|_| ()),
) )
}) })
.await; .await;
// disable ssl verification // disable TLS 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::builder() let client = awc::Client::builder()
.connector(awc::Connector::new().rustls(Arc::new(config)).finish()) .connector(awc::Connector::new().rustls(Arc::new(config)).finish())

View File

@ -16,6 +16,7 @@ use actix_http::{
Error, Error,
}; };
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use futures_core::ready;
use futures_util::future::{ok, Ready}; use futures_util::future::{ok, Ready};
use pin_project::pin_project; use pin_project::pin_project;
@ -131,7 +132,7 @@ where
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project(); let this = self.project();
match futures_util::ready!(this.fut.poll(cx)) { match ready!(this.fut.poll(cx)) {
Ok(resp) => { Ok(resp) => {
let enc = if let Some(enc) = resp.response().get_encoding() { let enc = if let Some(enc) = resp.response().get_encoding() {
enc enc

View File

@ -800,62 +800,58 @@ async fn test_reading_deflate_encoding_large_random_rustls() {
assert_eq!(bytes, Bytes::from(data)); assert_eq!(bytes, Bytes::from(data));
} }
// TODO: why is test ignored #[actix_rt::test]
// #[test] async fn test_server_cookies() {
// fn test_server_cookies() { use actix_web::{http, HttpMessage};
// use actix_web::http;
// let srv = test::TestServer::with_factory(|| { let srv = test::start(|| {
// App::new().resource("/", |r| { App::new().default_service(web::to(|| {
// r.f(|_| { HttpResponse::Ok()
// HttpResponse::Ok() .cookie(
// .cookie( http::CookieBuilder::new("first", "first_value")
// http::CookieBuilder::new("first", "first_value") .http_only(true)
// .http_only(true) .finish(),
// .finish(), )
// ) .cookie(http::Cookie::new("second", "first_value"))
// .cookie(http::Cookie::new("second", "first_value")) .cookie(http::Cookie::new("second", "second_value"))
// .cookie(http::Cookie::new("second", "second_value")) .finish()
// .finish() }))
// }) });
// })
// });
// let first_cookie = http::CookieBuilder::new("first", "first_value") let first_cookie = http::CookieBuilder::new("first", "first_value")
// .http_only(true) .http_only(true)
// .finish(); .finish();
// let second_cookie = http::Cookie::new("second", "second_value"); let second_cookie = http::Cookie::new("second", "second_value");
// let request = srv.get("/").finish().unwrap(); let req = srv.get("/");
// let response = srv.execute(request.send()).unwrap(); let res = req.send().await.unwrap();
// assert!(response.status().is_success()); assert!(res.status().is_success());
// let cookies = response.cookies().expect("To have cookies"); let cookies = res.cookies().expect("To have cookies");
// assert_eq!(cookies.len(), 2); assert_eq!(cookies.len(), 2);
// if cookies[0] == first_cookie { if cookies[0] == first_cookie {
// assert_eq!(cookies[1], second_cookie); assert_eq!(cookies[1], second_cookie);
// } else { } else {
// assert_eq!(cookies[0], second_cookie); assert_eq!(cookies[0], second_cookie);
// assert_eq!(cookies[1], first_cookie); assert_eq!(cookies[1], first_cookie);
// } }
// let first_cookie = first_cookie.to_string(); let first_cookie = first_cookie.to_string();
// let second_cookie = second_cookie.to_string(); let second_cookie = second_cookie.to_string();
// //Check that we have exactly two instances of raw cookie headers // Check that we have exactly two instances of raw cookie headers
// let cookies = response let cookies = res
// .headers() .headers()
// .get_all(http::header::SET_COOKIE) .get_all(http::header::SET_COOKIE)
// .iter() .map(|header| header.to_str().expect("To str").to_string())
// .map(|header| header.to_str().expect("To str").to_string()) .collect::<Vec<_>>();
// .collect::<Vec<_>>(); assert_eq!(cookies.len(), 2);
// assert_eq!(cookies.len(), 2); if cookies[0] == first_cookie {
// if cookies[0] == first_cookie { assert_eq!(cookies[1], second_cookie);
// assert_eq!(cookies[1], second_cookie); } else {
// } else { assert_eq!(cookies[0], second_cookie);
// assert_eq!(cookies[0], second_cookie); assert_eq!(cookies[1], first_cookie);
// assert_eq!(cookies[1], first_cookie); }
// } }
// }
#[actix_rt::test] #[actix_rt::test]
async fn test_slow_request() { async fn test_slow_request() {