diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index c080dd8c3..94a2ddfbe 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -1,14 +1,12 @@ -name: Upload documentation +name: Upload Documentation on: push: - branches: - - master + branches: [master] jobs: build: runs-on: ubuntu-latest - if: github.repository == 'actix/actix-web' steps: - uses: actions/checkout@v2 @@ -20,14 +18,14 @@ jobs: profile: minimal override: true - - name: check build + - name: Build Docs uses: actions-rs/cargo@v1 with: command: doc args: --workspace --all-features --no-deps - name: Tweak HTML - run: echo "" > target/doc/index.html + run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@3.7.1 diff --git a/Cargo.toml b/Cargo.toml index 84fdddf5b..bd758ab10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ required-features = ["compress"] [[test]] name = "test_server" -required-features = ["compress"] +required-features = ["compress", "cookies"] [[example]] name = "on_connect" diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 2862fcdc9..96967e18a 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -61,12 +61,12 @@ derive_more = "0.99.5" encoding_rs = "0.8" futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.7", default-features = false, features = ["alloc", "sink"] } -h2 = "0.3.0" +h2 = "=0.3.0" http = "0.2.2" httparse = "1.3" itoa = "0.4" language-tags = "0.2" -lazy_static = "1.4" +once_cell = "1.5" log = "0.4" mime = "0.3" percent-encoding = "2.1" diff --git a/actix-http/src/header/common/content_disposition.rs b/actix-http/src/header/common/content_disposition.rs index ecc59aba3..6076d033c 100644 --- a/actix-http/src/header/common/content_disposition.rs +++ b/actix-http/src/header/common/content_disposition.rs @@ -6,7 +6,7 @@ //! Browser conformance tests at: http://greenbytes.de/tech/tc2231/ //! IANA assignment: http://www.iana.org/assignments/cont-disp/cont-disp.xhtml -use lazy_static::lazy_static; +use once_cell::sync::Lazy; use regex::Regex; use std::fmt::{self, Write}; @@ -520,9 +520,7 @@ impl fmt::Display for DispositionParam { // // // See also comments in test_from_raw_unnecessary_percent_decode. - lazy_static! { - static ref RE: Regex = Regex::new("[\x00-\x08\x10-\x1F\x7F\"\\\\]").unwrap(); - } + static RE: Lazy = Lazy::new(|| Regex::new("[\x00-\x08\x10-\x1F\x7F\"\\\\]").unwrap()); match self { DispositionParam::Name(ref value) => write!(f, "name={}", value), DispositionParam::Filename(ref value) => { diff --git a/src/route.rs b/src/route.rs index b6b2482cd..c157025b8 100644 --- a/src/route.rs +++ b/src/route.rs @@ -1,13 +1,13 @@ #![allow(clippy::rc_buffer)] // inner value is mutated before being shared (`Rc::get_mut`) -use std::future::Future; -use std::pin::Pin; -use std::rc::Rc; -use std::task::{Context, Poll}; +use std::{future::Future, rc::Rc}; use actix_http::{http::Method, Error}; -use actix_service::{Service, ServiceFactory}; -use futures_util::future::{ready, FutureExt, LocalBoxFuture}; +use actix_service::{ + boxed::{self, BoxService, BoxServiceFactory}, + Service, ServiceFactory, +}; +use futures_core::future::LocalBoxFuture; use crate::extract::FromRequest; use crate::guard::{self, Guard}; @@ -16,33 +16,12 @@ use crate::responder::Responder; use crate::service::{ServiceRequest, ServiceResponse}; use crate::HttpResponse; -type BoxedRouteService = Box< - dyn Service< - ServiceRequest, - Response = ServiceResponse, - Error = Error, - Future = LocalBoxFuture<'static, Result>, - >, ->; - -type BoxedRouteNewService = Box< - dyn ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - InitError = (), - Service = BoxedRouteService, - Future = LocalBoxFuture<'static, Result>, - >, ->; - /// Resource route definition /// /// Route uses builder-like pattern for configuration. /// If handler is not explicitly set, default *404 Not Found* handler is used. pub struct Route { - service: BoxedRouteNewService, + service: BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>, guards: Rc>>, } @@ -51,9 +30,7 @@ impl Route { #[allow(clippy::new_without_default)] pub fn new() -> Route { Route { - service: Box::new(RouteNewService::new(HandlerService::new(|| { - ready(HttpResponse::NotFound()) - }))), + service: boxed::factory(HandlerService::new(HttpResponse::NotFound)), guards: Rc::new(Vec::new()), } } @@ -64,44 +41,26 @@ impl Route { } impl ServiceFactory for Route { - type Config = (); type Response = ServiceResponse; type Error = Error; - type InitError = (); + type Config = (); type Service = RouteService; - type Future = CreateRouteService; + type InitError = (); + type Future = LocalBoxFuture<'static, Result>; fn new_service(&self, _: ()) -> Self::Future { - CreateRouteService { - fut: self.service.new_service(()), - guards: self.guards.clone(), - } - } -} + let fut = self.service.new_service(()); + let guards = self.guards.clone(); -pub struct CreateRouteService { - fut: LocalBoxFuture<'static, Result>, - guards: Rc>>, -} - -impl Future for CreateRouteService { - type Output = Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.get_mut(); - - match this.fut.as_mut().poll(cx)? { - Poll::Ready(service) => Poll::Ready(Ok(RouteService { - service, - guards: this.guards.clone(), - })), - Poll::Pending => Poll::Pending, - } + Box::pin(async move { + let service = fut.await?; + Ok(RouteService { service, guards }) + }) } } pub struct RouteService { - service: BoxedRouteService, + service: BoxService, guards: Rc>>, } @@ -121,9 +80,7 @@ impl Service for RouteService { type Error = Error; type Future = LocalBoxFuture<'static, Result>; - fn poll_ready(&self, cx: &mut Context<'_>) -> Poll> { - self.service.poll_ready(cx) - } + actix_service::forward_ready!(service); fn call(&self, req: ServiceRequest) -> Self::Future { self.service.call(req) @@ -224,80 +181,11 @@ impl Route { R: Future + 'static, R::Output: Responder + 'static, { - self.service = Box::new(RouteNewService::new(HandlerService::new(handler))); + self.service = boxed::factory(HandlerService::new(handler)); self } } -struct RouteNewService -where - T: ServiceFactory, -{ - service: T, -} - -impl RouteNewService -where - T: ServiceFactory, - T::Future: 'static, - T::Service: 'static, - >::Future: 'static, -{ - pub fn new(service: T) -> Self { - RouteNewService { service } - } -} - -impl ServiceFactory for RouteNewService -where - T: ServiceFactory, - T::Future: 'static, - T::Service: 'static, - >::Future: 'static, -{ - type Response = ServiceResponse; - type Error = Error; - type Config = (); - type Service = BoxedRouteService; - type InitError = (); - type Future = LocalBoxFuture<'static, Result>; - - fn new_service(&self, _: ()) -> Self::Future { - self.service - .new_service(()) - .map(|result| match result { - Ok(service) => { - let service = Box::new(RouteServiceWrapper { service }) as _; - Ok(service) - } - Err(_) => Err(()), - }) - .boxed_local() - } -} - -struct RouteServiceWrapper> { - service: T, -} - -impl Service for RouteServiceWrapper -where - T::Future: 'static, - T: Service, -{ - type Response = ServiceResponse; - type Error = Error; - type Future = LocalBoxFuture<'static, Result>; - - fn poll_ready(&self, cx: &mut Context<'_>) -> Poll> { - self.service.poll_ready(cx) - } - - fn call(&self, req: ServiceRequest) -> Self::Future { - Box::pin(self.service.call(req)) - } -} - #[cfg(test)] mod tests { use std::time::Duration; diff --git a/tests/test_server.rs b/tests/test_server.rs index 2466730f9..b35af657d 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -21,6 +21,7 @@ use flate2::{ Compression, }; use futures_util::ready; +#[cfg(feature = "openssl")] use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslMethod}, @@ -54,6 +55,7 @@ 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"; +#[cfg(feature = "openssl")] fn openssl_config() -> SslAcceptor { let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); let cert_file = cert.serialize_pem().unwrap(); @@ -786,11 +788,6 @@ mod plus_rustls { #[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 data = rand::thread_rng() .sample_iter(&Alphanumeric) .take(160_000)