From 1f1482b706035bd0c9a86db0315950f4662cdcbd Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 13 Feb 2021 16:28:26 +0000 Subject: [PATCH] use rcgen in tls acceptors --- actix-http/Cargo.toml | 1 + actix-http/tests/test_openssl.rs | 61 +++++++------- actix-http/tests/test_rustls.rs | 45 ++++++----- awc/tests/test_connector.rs | 27 ++++--- awc/tests/test_ssl_client.rs | 27 ++++--- src/lib.rs | 4 +- src/middleware/compat.rs | 11 ++- src/request.rs | 2 + src/test.rs | 5 +- tests/test_httpserver.rs | 23 ++++-- tests/test_server.rs | 132 +++++++++++++++++++------------ 11 files changed, 206 insertions(+), 132 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 0e6916a0b..69a344d4a 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -95,6 +95,7 @@ actix-http-test = { version = "3.0.0-beta.2", features = ["openssl"] } actix-tls = { version = "3.0.0-beta.2", features = ["openssl"] } criterion = "0.3" env_logger = "0.8" +rcgen = "0.8" serde_derive = "1.0" tls-openssl = { version = "0.10", package = "openssl" } tls-rustls = { version = "0.19", package = "rustls" } diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs index 188516f83..f44968baa 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -14,7 +14,11 @@ use actix_service::{fn_service, ServiceFactoryExt}; use bytes::{Bytes, BytesMut}; use futures_util::future::{err, ok, ready}; use futures_util::stream::{once, Stream, StreamExt}; -use openssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod}; +use openssl::{ + pkey::PKey, + ssl::{SslAcceptor, SslMethod}, + x509::X509, +}; async fn load_body(stream: S) -> Result where @@ -34,29 +38,26 @@ where Ok(body) } -fn ssl_acceptor() -> SslAcceptor { - // load ssl keys +fn tls_config() -> SslAcceptor { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); + let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("../tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("../tests/cert.pem") - .unwrap(); + builder.set_certificate(&cert).unwrap(); + builder.set_private_key(&key).unwrap(); + builder.set_alpn_select_callback(|_, protos| { const H2: &[u8] = b"\x02h2"; - const H11: &[u8] = b"\x08http/1.1"; if protos.windows(3).any(|window| window == H2) { Ok(b"h2") - } else if protos.windows(9).any(|window| window == H11) { - Ok(b"http/1.1") } else { - Err(AlpnError::NOACK) + Err(openssl::ssl::AlpnError::NOACK) } }); - builder - .set_alpn_protos(b"\x08http/1.1\x02h2") - .expect("Can not contrust SslAcceptor"); + builder.set_alpn_protos(b"\x02h2").unwrap(); builder.build() } @@ -66,7 +67,7 @@ async fn test_h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Error>(Response::Ok().finish())) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -85,7 +86,7 @@ async fn test_h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::Ok().finish()) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -104,7 +105,7 @@ async fn test_h2_body() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::Ok().body(body)) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -133,7 +134,7 @@ async fn test_h2_content_length() { ]; ok::<_, ()>(Response::new(statuses[indx])) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -195,7 +196,7 @@ async fn test_h2_headers() { } ok::<_, ()>(builder.body(data.clone())) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }).await; @@ -234,7 +235,7 @@ async fn test_h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR))) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -252,7 +253,7 @@ async fn test_h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, ()>(Response::Ok().body(STR))) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -276,7 +277,7 @@ async fn test_h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR))) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -299,7 +300,7 @@ async fn test_h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR))) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -323,7 +324,7 @@ async fn test_h2_body_length() { Response::Ok().body(body::SizedStream::new(STR.len() as u64, body)), ) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -348,7 +349,7 @@ async fn test_h2_body_chunked_explicit() { .streaming(body), ) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -376,7 +377,7 @@ async fn test_h2_response_http_error_handling() { .body(STR), ) })) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -394,7 +395,7 @@ async fn test_h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::(ErrorBadRequest("error"))) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; @@ -418,7 +419,7 @@ async fn test_h2_on_connect() { assert!(req.extensions().contains::()); ok::<_, ()>(Response::Ok().finish()) }) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index 59ffcfeb0..a36400910 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -31,14 +31,19 @@ where Ok(body) } -fn ssl_acceptor() -> RustlsServerConfig { - // load ssl keys +fn tls_config() -> RustlsServerConfig { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let mut config = RustlsServerConfig::new(NoClientAuth::new()); - let cert_file = &mut BufReader::new(File::open("../tests/cert.pem").unwrap()); - let key_file = &mut BufReader::new(File::open("../tests/key.pem").unwrap()); + let cert_file = &mut BufReader::new(cert_file.as_bytes()); + let key_file = &mut BufReader::new(key_file.as_bytes()); + let cert_chain = certs(cert_file).unwrap(); let mut keys = pkcs8_private_keys(key_file).unwrap(); config.set_single_cert(cert_chain, keys.remove(0)).unwrap(); + config } @@ -47,7 +52,7 @@ async fn test_h1() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h1(|_| future::ok::<_, Error>(Response::Ok().finish())) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -61,7 +66,7 @@ async fn test_h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| future::ok::<_, Error>(Response::Ok().finish())) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -79,7 +84,7 @@ async fn test_h1_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_11); future::ok::<_, Error>(Response::Ok().finish()) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -97,7 +102,7 @@ async fn test_h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); future::ok::<_, Error>(Response::Ok().finish()) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -115,7 +120,7 @@ async fn test_h2_body1() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::Ok().body(body)) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -143,7 +148,7 @@ async fn test_h2_content_length() { ]; future::ok::<_, ()>(Response::new(statuses[indx])) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -203,7 +208,7 @@ async fn test_h2_headers() { } future::ok::<_, ()>(config.body(data.clone())) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }).await; let response = srv.sget("/").send().await.unwrap(); @@ -241,7 +246,7 @@ async fn test_h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| future::ok::<_, ()>(Response::Ok().body(STR))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -258,7 +263,7 @@ async fn test_h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, ()>(Response::Ok().body(STR))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -284,7 +289,7 @@ async fn test_h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -309,7 +314,7 @@ async fn test_h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, ()>(Response::Ok().body(STR))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -335,7 +340,7 @@ async fn test_h2_body_length() { Response::Ok().body(body::SizedStream::new(STR.len() as u64, body)), ) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -359,7 +364,7 @@ async fn test_h2_body_chunked_explicit() { .streaming(body), ) }) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -388,7 +393,7 @@ async fn test_h2_response_http_error_handling() { ) })) })) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -405,7 +410,7 @@ async fn test_h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::(error::ErrorBadRequest("error"))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; @@ -422,7 +427,7 @@ async fn test_h1_service_error() { let mut srv = test_server(move || { HttpService::build() .h1(|_| err::(error::ErrorBadRequest("error"))) - .rustls(ssl_acceptor()) + .rustls(tls_config()) }) .await; diff --git a/awc/tests/test_connector.rs b/awc/tests/test_connector.rs index 4e4fa5833..fd725506d 100644 --- a/awc/tests/test_connector.rs +++ b/awc/tests/test_connector.rs @@ -7,17 +7,23 @@ use actix_http_test::test_server; use actix_service::{map_config, ServiceFactoryExt}; use actix_web::http::Version; use actix_web::{dev::AppConfig, web, App, HttpResponse}; -use openssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode}; +use openssl::{ + pkey::PKey, + ssl::{SslAcceptor, SslConnector, SslMethod, SslVerifyMode}, + x509::X509, +}; + +fn tls_config() -> SslAcceptor { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); + let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); -fn ssl_acceptor() -> SslAcceptor { - // load ssl keys let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("../tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("../tests/cert.pem") - .unwrap(); + builder.set_certificate(&cert).unwrap(); + builder.set_private_key(&key).unwrap(); + builder.set_alpn_select_callback(|_, protos| { const H2: &[u8] = b"\x02h2"; if protos.windows(3).any(|window| window == H2) { @@ -27,6 +33,7 @@ fn ssl_acceptor() -> SslAcceptor { } }); builder.set_alpn_protos(b"\x02h2").unwrap(); + builder.build() } @@ -38,7 +45,7 @@ async fn test_connection_window_size() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()) }) .await; diff --git a/awc/tests/test_ssl_client.rs b/awc/tests/test_ssl_client.rs index b93c729e5..08aa125cd 100644 --- a/awc/tests/test_ssl_client.rs +++ b/awc/tests/test_ssl_client.rs @@ -11,17 +11,23 @@ use actix_service::{map_config, pipeline_factory, ServiceFactoryExt}; use actix_web::http::Version; use actix_web::{dev::AppConfig, web, App, HttpResponse}; use futures_util::future::ok; -use openssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode}; +use openssl::{ + pkey::PKey, + ssl::{SslAcceptor, SslConnector, SslMethod, SslVerifyMode}, + x509::X509, +}; + +fn tls_config() -> SslAcceptor { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); + let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); -fn ssl_acceptor() -> SslAcceptor { - // load ssl keys let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("../tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("../tests/cert.pem") - .unwrap(); + builder.set_certificate(&cert).unwrap(); + builder.set_private_key(&key).unwrap(); + builder.set_alpn_select_callback(|_, protos| { const H2: &[u8] = b"\x02h2"; if protos.windows(3).any(|window| window == H2) { @@ -31,6 +37,7 @@ fn ssl_acceptor() -> SslAcceptor { } }); builder.set_alpn_protos(b"\x02h2").unwrap(); + builder.build() } @@ -51,7 +58,7 @@ async fn test_connection_reuse_h2() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .openssl(ssl_acceptor()) + .openssl(tls_config()) .map_err(|_| ()), ) }) diff --git a/src/lib.rs b/src/lib.rs index 73390a55e..16b2ab186 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,8 +99,10 @@ pub mod test; pub(crate) mod types; pub mod web; +#[cfg(feature = "cookies")] +pub use actix_http::cookie; pub use actix_http::Response as HttpResponse; -pub use actix_http::{body, cookie, http, Error, HttpMessage, ResponseError, Result}; +pub use actix_http::{body, http, Error, HttpMessage, ResponseError, Result}; pub use actix_rt as rt; pub use actix_web_codegen::*; diff --git a/src/middleware/compat.rs b/src/middleware/compat.rs index 97742e92c..6f60264b1 100644 --- a/src/middleware/compat.rs +++ b/src/middleware/compat.rs @@ -123,18 +123,24 @@ impl MapServiceResponseBody for ServiceRespons #[cfg(test)] mod tests { + // easier to code when cookies feature is disabled + #![allow(unused_imports)] + use super::*; use actix_service::IntoService; use crate::dev::ServiceRequest; use crate::http::StatusCode; - use crate::middleware::{Compress, Condition, Logger}; + use crate::middleware::{self, Condition, Logger}; use crate::test::{call_service, init_service, TestRequest}; use crate::{web, App, HttpResponse}; #[actix_rt::test] + #[cfg(feature = "cookies")] async fn test_scope_middleware() { + use crate::middleware::Compress; + let logger = Logger::default(); let compress = Compress::default(); @@ -154,7 +160,10 @@ mod tests { } #[actix_rt::test] + #[cfg(feature = "cookies")] async fn test_resource_scope_middleware() { + use crate::middleware::Compress; + let logger = Logger::default(); let compress = Compress::default(); diff --git a/src/request.rs b/src/request.rs index d62fca300..514b7466e 100644 --- a/src/request.rs +++ b/src/request.rs @@ -429,12 +429,14 @@ mod tests { } #[test] + #[cfg(feature = "cookies")] fn test_no_request_cookies() { let req = TestRequest::default().to_http_request(); assert!(req.cookies().unwrap().is_empty()); } #[test] + #[cfg(feature = "cookies")] fn test_request_cookies() { let req = TestRequest::default() .append_header((header::COOKIE, "cookie1=value1")) diff --git a/src/test.rs b/src/test.rs index d576838de..2ec4252b1 100644 --- a/src/test.rs +++ b/src/test.rs @@ -6,10 +6,12 @@ use std::sync::mpsc; use std::{fmt, net, thread, time}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; +#[cfg(feature = "cookies")] +use actix_http::cookie::Cookie; use actix_http::http::header::{ContentType, IntoHeaderPair}; use actix_http::http::{Method, StatusCode, Uri, Version}; use actix_http::test::TestRequest as HttpTestRequest; -use actix_http::{cookie::Cookie, ws, Extensions, HttpService, Request}; +use actix_http::{ws, Extensions, HttpService, Request}; use actix_router::{Path, ResourceDef, Url}; use actix_rt::{time::sleep, System}; use actix_service::{map_config, IntoService, IntoServiceFactory, Service, ServiceFactory}; @@ -438,6 +440,7 @@ impl TestRequest { } /// Set cookie for this request. + #[cfg(feature = "cookies")] pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { self.req.cookie(cookie); self diff --git a/tests/test_httpserver.rs b/tests/test_httpserver.rs index 34d57008d..3aa1d36b0 100644 --- a/tests/test_httpserver.rs +++ b/tests/test_httpserver.rs @@ -73,15 +73,22 @@ async fn test_start() { #[cfg(feature = "openssl")] fn ssl_acceptor() -> std::io::Result { - use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; - // load ssl keys + use openssl::{ + pkey::PKey, + ssl::{SslAcceptor, SslMethod}, + x509::X509, + }; + + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); + let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("tests/cert.pem") - .unwrap(); + builder.set_certificate(&cert).unwrap(); + builder.set_private_key(&key).unwrap(); + Ok(builder) } diff --git a/tests/test_server.rs b/tests/test_server.rs index c2e627a3f..a38939c59 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -21,6 +21,7 @@ use flate2::{ Compression, }; use futures_util::ready; +use openssl::{pkey::PKey, ssl::SslAcceptor, x509::X509}; use rand::{distributions::Alphanumeric, Rng}; use actix_web::dev::BodyEncoding; @@ -49,6 +50,30 @@ 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"; +fn openssl_config() -> SslAcceptor { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); + let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); + + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + builder.set_certificate(&cert).unwrap(); + builder.set_private_key(&key).unwrap(); + + builder.set_alpn_select_callback(|_, protos| { + const H2: &[u8] = b"\x02h2"; + if protos.windows(3).any(|window| window == H2) { + Ok(b"h2") + } else { + Err(openssl::ssl::AlpnError::NOACK) + } + }); + builder.set_alpn_protos(b"\x02h2").unwrap(); + + builder.build() +} + struct TestBody { data: Bytes, chunk_size: usize, @@ -700,18 +725,8 @@ async fn test_brotli_encoding_large() { #[cfg(feature = "openssl")] #[actix_rt::test] async fn test_brotli_encoding_large_openssl() { - // load ssl keys - use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; - let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder - .set_private_key_file("tests/key.pem", SslFiletype::PEM) - .unwrap(); - builder - .set_certificate_chain_file("tests/cert.pem") - .unwrap(); - let data = STR.repeat(10); - let srv = test::start_with(test::config().openssl(builder.build()), move || { + let srv = test::start_with(test::config().openssl(openssl_config()), move || { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| { HttpResponse::Ok() .encoding(actix_web::http::ContentEncoding::Identity) @@ -739,53 +754,68 @@ async fn test_brotli_encoding_large_openssl() { } #[cfg(all(feature = "rustls", feature = "openssl"))] -#[actix_rt::test] -async fn test_reading_deflate_encoding_large_random_rustls() { - use rustls::internal::pemfile::{certs, pkcs8_private_keys}; - use rustls::{NoClientAuth, ServerConfig}; - use std::fs::File; - use std::io::BufReader; +mod rustls { + use rustls::{ + internal::pemfile::{certs, pkcs8_private_keys}, + NoClientAuth, ServerConfig as RustlsServerConfig, + }; - let data = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(160_000) - .map(char::from) - .collect::(); + fn rustls_config() -> RustlsServerConfig { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); - // load ssl keys - let mut config = ServerConfig::new(NoClientAuth::new()); - let cert_file = &mut BufReader::new(File::open("tests/cert.pem").unwrap()); - let key_file = &mut BufReader::new(File::open("tests/key.pem").unwrap()); - let cert_chain = certs(cert_file).unwrap(); - let mut keys = pkcs8_private_keys(key_file).unwrap(); - config.set_single_cert(cert_chain, keys.remove(0)).unwrap(); + let mut config = ServerConfig::new(NoClientAuth::new()); + let cert_file = &mut BufReader::new(cert_file.as_bytes()); + let key_file = &mut BufReader::new(key_file.as_bytes()); - let srv = test::start_with(test::config().rustls(config), || { - App::new().service(web::resource("/").route(web::to(|bytes: Bytes| { - HttpResponse::Ok() - .encoding(actix_web::http::ContentEncoding::Identity) - .body(bytes) - }))) - }); + let cert_chain = certs(cert_file).unwrap(); + let mut keys = pkcs8_private_keys(key_file).unwrap(); + config.set_single_cert(cert_chain, keys.remove(0)).unwrap(); - // encode data - let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); - e.write_all(data.as_ref()).unwrap(); - let enc = e.finish().unwrap(); + config + } - // client request - let req = srv - .post("/") - .insert_header((actix_web::http::header::CONTENT_ENCODING, "deflate")) - .send_stream(TestBody::new(Bytes::from(enc), 1024)); + #[actix_rt::test] + async fn test_reading_deflate_encoding_large_random_rustls() { + use rustls::internal::pemfile::{certs, pkcs8_private_keys}; + use rustls::{NoClientAuth, ServerConfig}; + use std::fs::File; + use std::io::BufReader; - let mut response = req.await.unwrap(); - assert!(response.status().is_success()); + let data = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(160_000) + .map(char::from) + .collect::(); - // read response - let bytes = response.body().await.unwrap(); - assert_eq!(bytes.len(), data.len()); - assert_eq!(bytes, Bytes::from(data)); + let srv = test::start_with(test::config().rustls(rustls_config()), || { + App::new().service(web::resource("/").route(web::to(|bytes: Bytes| { + HttpResponse::Ok() + .encoding(actix_web::http::ContentEncoding::Identity) + .body(bytes) + }))) + }); + + // encode data + let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); + e.write_all(data.as_ref()).unwrap(); + let enc = e.finish().unwrap(); + + // client request + let req = srv + .post("/") + .insert_header((actix_web::http::header::CONTENT_ENCODING, "deflate")) + .send_stream(TestBody::new(Bytes::from(enc), 1024)); + + let mut response = req.await.unwrap(); + assert!(response.status().is_success()); + + // read response + let bytes = response.body().await.unwrap(); + assert_eq!(bytes.len(), data.len()); + assert_eq!(bytes, Bytes::from(data)); + } } #[actix_rt::test]