From a77b0b054a00f24bf1f3cc3637d919702ddc1602 Mon Sep 17 00:00:00 2001 From: Nikolai Vazquez Date: Fri, 10 May 2019 23:44:49 +0200 Subject: [PATCH 01/17] Make `App::configure` take an `FnOnce` (#825) --- src/app.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.rs b/src/app.rs index bac71250f..eb14d46fa 100644 --- a/src/app.rs +++ b/src/app.rs @@ -128,7 +128,7 @@ where /// ``` pub fn configure(mut self, f: F) -> Self where - F: Fn(&mut ServiceConfig), + F: FnOnce(&mut ServiceConfig), { let mut cfg = ServiceConfig::new(); f(&mut cfg); From 4066375737c5c7669c4a441bbc4aeb48f46097af Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 10 May 2019 14:45:30 -0700 Subject: [PATCH 02/17] Update CHANGES.md --- CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index cfd7a6df8..ce7da6d28 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # Changes +### Changes + +* `App::configure` take an `FnOnce` instead of `Fn` + + ## [1.0.0-beta.3] - 2019-05-04 ### Added From df08baf67f166d2d75118b859f1049b01944daf4 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 08:34:51 -0700 Subject: [PATCH 03/17] update actix-net dependencies --- Cargo.toml | 13 +++--- actix-files/Cargo.toml | 4 +- actix-files/src/lib.rs | 2 + actix-framed/Cargo.toml | 5 ++- actix-framed/src/app.rs | 7 +++- actix-framed/src/helpers.rs | 4 +- actix-framed/src/route.rs | 1 + actix-framed/src/service.rs | 24 ++++++----- actix-http/CHANGES.md | 9 ++++ actix-http/Cargo.toml | 10 ++--- actix-http/src/builder.rs | 26 ++++++++---- actix-http/src/h1/expect.rs | 4 +- actix-http/src/h1/service.rs | 35 +++++++++------- actix-http/src/h1/upgrade.rs | 4 +- actix-http/src/h2/service.rs | 18 ++++---- actix-http/src/service.rs | 46 +++++++++++---------- actix-http/tests/test_server.rs | 10 ++--- actix-multipart/Cargo.toml | 2 +- actix-session/Cargo.toml | 2 +- awc/Cargo.toml | 4 +- awc/src/builder.rs | 71 +++++++++++++++----------------- awc/src/response.rs | 3 +- awc/src/test.rs | 29 ------------- awc/src/ws.rs | 49 +++++++++++----------- awc/tests/test_client.rs | 14 +++---- awc/tests/test_ws.rs | 70 +++++++------------------------ src/app.rs | 8 +++- src/app_service.rs | 12 ++++-- src/config.rs | 1 + src/handler.rs | 32 +++++++++----- src/middleware/cors.rs | 12 +++--- src/middleware/defaultheaders.rs | 20 +++++---- src/middleware/errhandlers.rs | 14 +++---- src/middleware/logger.rs | 8 ++-- src/middleware/normalize.rs | 16 +++---- src/resource.rs | 8 ++++ src/route.rs | 5 +++ src/scope.rs | 11 ++++- src/server.rs | 12 +++--- src/service.rs | 2 + src/test.rs | 9 ++-- test-server/Cargo.toml | 6 +-- test-server/src/lib.rs | 40 +++++++++++++----- 43 files changed, 361 insertions(+), 321 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a87148462..f4e2f79ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,13 +66,13 @@ rust-tls = ["rustls", "actix-server/rust-tls"] [dependencies] actix-codec = "0.1.2" -actix-service = "0.3.6" -actix-utils = "0.3.4" +actix-service = "0.4.0" +actix-utils = "0.4.0" actix-router = "0.1.3" actix-rt = "0.2.2" actix-web-codegen = "0.1.0-beta.1" actix-http = { version = "0.1.5", features=["fail"] } -actix-server = "0.4.3" +actix-server = "0.5.0" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" actix = { version = "0.8.1", features=["http"], optional = true } @@ -101,7 +101,7 @@ rustls = { version = "^0.15", optional = true } [dev-dependencies] actix-http = { version = "0.1.5", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.1.1", features=["ssl"] } -actix-files = { version = "0.1.0-beta.1" } +actix-files = { version = "0.1.0-betsa.1" } rand = "0.6" env_logger = "0.6" serde_derive = "1.0" @@ -121,5 +121,8 @@ actix-http-test = { path = "test-server" } actix-web-codegen = { path = "actix-web-codegen" } actix-web-actors = { path = "actix-web-actors" } actix-session = { path = "actix-session" } -actix-files = { path = "actix-files" } awc = { path = "awc" } + +actix-files = { path = "actix-files" } +actix-framed = { path = "actix-framed" } +actix-multipart = { path = "actix-multipart" } diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 5e37fc090..a0cbba366 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.1.0-beta.1" +version = "0.1.0-betsa.1" authors = ["Nikolay Kim "] description = "Static files support for actix web." readme = "README.md" @@ -19,7 +19,7 @@ path = "src/lib.rs" [dependencies] actix-web = "1.0.0-beta.1" -actix-service = "0.3.4" +actix-service = "0.4.0" bitflags = "1" bytes = "0.4" futures = "0.1.25" diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 4038a5487..301d9d81d 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -334,6 +334,7 @@ impl Files { where F: IntoNewService, U: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -363,6 +364,7 @@ impl HttpServiceFactory for Files { } impl NewService for Files { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index f0622fd90..985515367 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -21,11 +21,12 @@ path = "src/lib.rs" [dependencies] actix-codec = "0.1.2" -actix-service = "0.3.6" -actix-utils = "0.3.4" +actix-service = "0.4.0" +actix-utils = "0.4.0" actix-router = "0.1.2" actix-rt = "0.2.2" actix-http = "0.1.0" +actix-server-config = "0.1.1" bytes = "0.4" futures = "0.1.25" diff --git a/actix-framed/src/app.rs b/actix-framed/src/app.rs index 20bc2f771..297796bd1 100644 --- a/actix-framed/src/app.rs +++ b/actix-framed/src/app.rs @@ -4,6 +4,7 @@ use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_http::h1::{Codec, SendResponse}; use actix_http::{Error, Request, Response}; use actix_router::{Path, Router, Url}; +use actix_server_config::ServerConfig; use actix_service::{IntoNewService, NewService, Service}; use actix_utils::cloneable::CloneableService; use futures::{Async, Future, Poll}; @@ -49,6 +50,7 @@ impl FramedApp { where U: HttpServiceFactory, U::Factory: NewService< + Config = (), Request = FramedRequest, Response = (), Error = Error, @@ -88,11 +90,12 @@ pub struct FramedAppFactory { services: Rc>)>>, } -impl NewService for FramedAppFactory +impl NewService for FramedAppFactory where T: AsyncRead + AsyncWrite + 'static, S: 'static, { + type Config = ServerConfig; type Request = (Request, Framed); type Response = (); type Error = Error; @@ -100,7 +103,7 @@ where type Service = CloneableService>; type Future = CreateService; - fn new_service(&self, _: &C) -> Self::Future { + fn new_service(&self, _: &ServerConfig) -> Self::Future { CreateService { fut: self .services diff --git a/actix-framed/src/helpers.rs b/actix-framed/src/helpers.rs index c2c7dbd8b..944b729d4 100644 --- a/actix-framed/src/helpers.rs +++ b/actix-framed/src/helpers.rs @@ -13,6 +13,7 @@ pub(crate) type BoxedHttpService = Box< pub(crate) type BoxedHttpNewService = Box< NewService< + Config = (), Request = Req, Response = (), Error = Error, @@ -39,12 +40,13 @@ where impl NewService for HttpNewService where - T: NewService, + T: NewService, T::Request: 'static, T::Future: 'static, T::Service: Service>> + 'static, ::Future: 'static, { + type Config = (); type Request = T::Request; type Response = (); type Error = Error; diff --git a/actix-framed/src/route.rs b/actix-framed/src/route.rs index c8d9d4326..c50401d6d 100644 --- a/actix-framed/src/route.rs +++ b/actix-framed/src/route.rs @@ -106,6 +106,7 @@ where R::Future: 'static, R::Error: fmt::Display, { + type Config = (); type Request = FramedRequest; type Response = (); type Error = Error; diff --git a/actix-framed/src/service.rs b/actix-framed/src/service.rs index 6e5c7a543..fbbc9fbef 100644 --- a/actix-framed/src/service.rs +++ b/actix-framed/src/service.rs @@ -12,22 +12,23 @@ use futures::{Async, Future, IntoFuture, Poll, Sink}; /// Service that verifies incoming request if it is valid websocket /// upgrade request. In case of error returns `HandshakeError` -pub struct VerifyWebSockets { - _t: PhantomData, +pub struct VerifyWebSockets { + _t: PhantomData<(T, C)>, } -impl Default for VerifyWebSockets { +impl Default for VerifyWebSockets { fn default() -> Self { VerifyWebSockets { _t: PhantomData } } } -impl NewService for VerifyWebSockets { +impl NewService for VerifyWebSockets { + type Config = C; type Request = (Request, Framed); type Response = (Request, Framed); type Error = (HandshakeError, Framed); type InitError = (); - type Service = VerifyWebSockets; + type Service = VerifyWebSockets; type Future = FutureResult; fn new_service(&self, _: &C) -> Self::Future { @@ -35,7 +36,7 @@ impl NewService for VerifyWebSockets { } } -impl Service for VerifyWebSockets { +impl Service for VerifyWebSockets { type Request = (Request, Framed); type Response = (Request, Framed); type Error = (HandshakeError, Framed); @@ -54,9 +55,9 @@ impl Service for VerifyWebSockets { } /// Send http/1 error response -pub struct SendError(PhantomData<(T, R, E)>); +pub struct SendError(PhantomData<(T, R, E, C)>); -impl Default for SendError +impl Default for SendError where T: AsyncRead + AsyncWrite, E: ResponseError, @@ -66,17 +67,18 @@ where } } -impl NewService for SendError +impl NewService for SendError where T: AsyncRead + AsyncWrite + 'static, R: 'static, E: ResponseError + 'static, { + type Config = C; type Request = Result)>; type Response = R; type Error = (E, Framed); type InitError = (); - type Service = SendError; + type Service = SendError; type Future = FutureResult; fn new_service(&self, _: &C) -> Self::Future { @@ -84,7 +86,7 @@ where } } -impl Service for SendError +impl Service for SendError where T: AsyncRead + AsyncWrite + 'static, R: 'static, diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 872a481d8..f1c119d57 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,5 +1,14 @@ # Changes +## [0.2.0] - 2019-xx-xx + +### Changed + +* Update actix-service to 0.4 + +* Expect and upgrade services accept `ServerConfig` config. + + ## [0.1.5] - 2019-05-04 ### Fixed diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index bcc9b456b..eaac7c090 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -44,10 +44,10 @@ fail = ["failure"] secure-cookies = ["ring"] [dependencies] -actix-service = "0.3.6" +actix-service = "0.4.0" actix-codec = "0.1.2" -actix-connect = "0.1.5" -actix-utils = "0.3.5" +actix-connect = "0.2.0" +actix-utils = "0.4.0" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" @@ -97,8 +97,8 @@ chrono = "0.4.6" [dev-dependencies] actix-rt = "0.2.2" -actix-server = { version = "0.4.3", features=["ssl"] } -actix-connect = { version = "0.1.4", features=["ssl"] } +actix-server = { version = "0.5.0", features=["ssl"] } +actix-connect = { version = "0.2.0", features=["ssl"] } actix-http-test = { version = "0.1.0", features=["ssl"] } env_logger = "0.6" serde_derive = "1.0" diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index 56f144bd8..b1b193a9e 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -29,7 +29,7 @@ pub struct HttpServiceBuilder> { impl HttpServiceBuilder> where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, { @@ -48,13 +48,17 @@ where impl HttpServiceBuilder where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, - X: NewService, + X: NewService, X::Error: Into, X::InitError: fmt::Debug, - U: NewService), Response = ()>, + U: NewService< + Config = SrvConfig, + Request = (Request, Framed), + Response = (), + >, U::Error: fmt::Display, U::InitError: fmt::Debug, { @@ -101,7 +105,7 @@ where pub fn expect(self, expect: F) -> HttpServiceBuilder where F: IntoNewService, - X1: NewService, + X1: NewService, X1::Error: Into, X1::InitError: fmt::Debug, { @@ -122,7 +126,11 @@ where pub fn upgrade(self, upgrade: F) -> HttpServiceBuilder where F: IntoNewService, - U1: NewService), Response = ()>, + U1: NewService< + Config = SrvConfig, + Request = (Request, Framed), + Response = (), + >, U1::Error: fmt::Display, U1::InitError: fmt::Debug, { @@ -140,7 +148,7 @@ where pub fn h1(self, service: F) -> H1Service where B: MessageBody + 'static, - F: IntoNewService, + F: IntoNewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -159,7 +167,7 @@ where pub fn h2(self, service: F) -> H2Service where B: MessageBody + 'static, - F: IntoNewService, + F: IntoNewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -177,7 +185,7 @@ where pub fn finish(self, service: F) -> HttpService where B: MessageBody + 'static, - F: IntoNewService, + F: IntoNewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, diff --git a/actix-http/src/h1/expect.rs b/actix-http/src/h1/expect.rs index 86fcb2cc3..32b6bd9c4 100644 --- a/actix-http/src/h1/expect.rs +++ b/actix-http/src/h1/expect.rs @@ -1,3 +1,4 @@ +use actix_server_config::ServerConfig; use actix_service::{NewService, Service}; use futures::future::{ok, FutureResult}; use futures::{Async, Poll}; @@ -8,6 +9,7 @@ use crate::request::Request; pub struct ExpectHandler; impl NewService for ExpectHandler { + type Config = ServerConfig; type Request = Request; type Response = Request; type Error = Error; @@ -15,7 +17,7 @@ impl NewService for ExpectHandler { type InitError = Error; type Future = FutureResult; - fn new_service(&self, _: &()) -> Self::Future { + fn new_service(&self, _: &ServerConfig) -> Self::Future { ok(ExpectHandler) } } diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index ecf6c8b93..2c0a48eba 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -29,14 +29,14 @@ pub struct H1Service> { impl H1Service where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, B: MessageBody, { /// Create new `HttpService` instance with default config. - pub fn new>(service: F) -> Self { + pub fn new>(service: F) -> Self { let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0); H1Service { @@ -49,10 +49,7 @@ where } /// Create new `HttpService` instance with config. - pub fn with_config>( - cfg: ServiceConfig, - service: F, - ) -> Self { + pub fn with_config>(cfg: ServiceConfig, service: F) -> Self { H1Service { cfg, srv: service.into_new_service(), @@ -65,7 +62,7 @@ where impl H1Service where - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, S::InitError: fmt::Debug, @@ -102,21 +99,26 @@ where } } -impl NewService for H1Service +impl NewService for H1Service where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, S::InitError: fmt::Debug, B: MessageBody, - X: NewService, + X: NewService, X::Error: Into, X::InitError: fmt::Debug, - U: NewService), Response = ()>, + U: NewService< + Config = SrvConfig, + Request = (Request, Framed), + Response = (), + >, U::Error: fmt::Display, U::InitError: fmt::Debug, { + type Config = SrvConfig; type Request = Io; type Response = (); type Error = DispatchError; @@ -127,8 +129,8 @@ where fn new_service(&self, cfg: &SrvConfig) -> Self::Future { H1ServiceResponse { fut: self.srv.new_service(cfg).into_future(), - fut_ex: Some(self.expect.new_service(&())), - fut_upg: self.upgrade.as_ref().map(|f| f.new_service(&())), + fut_ex: Some(self.expect.new_service(cfg)), + fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)), expect: None, upgrade: None, cfg: Some(self.cfg.clone()), @@ -140,7 +142,7 @@ where #[doc(hidden)] pub struct H1ServiceResponse where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, X: NewService, @@ -162,7 +164,7 @@ where impl Future for H1ServiceResponse where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, S::InitError: fmt::Debug, @@ -320,10 +322,11 @@ where } } -impl NewService for OneRequest +impl NewService for OneRequest where T: IoStream, { + type Config = SrvConfig; type Request = Io; type Response = (Request, Framed); type Error = ParseError; diff --git a/actix-http/src/h1/upgrade.rs b/actix-http/src/h1/upgrade.rs index 0d0164fe6..0278f23e5 100644 --- a/actix-http/src/h1/upgrade.rs +++ b/actix-http/src/h1/upgrade.rs @@ -1,6 +1,7 @@ use std::marker::PhantomData; use actix_codec::Framed; +use actix_server_config::ServerConfig; use actix_service::{NewService, Service}; use futures::future::FutureResult; use futures::{Async, Poll}; @@ -12,6 +13,7 @@ use crate::request::Request; pub struct UpgradeHandler(PhantomData); impl NewService for UpgradeHandler { + type Config = ServerConfig; type Request = (Request, Framed); type Response = (); type Error = Error; @@ -19,7 +21,7 @@ impl NewService for UpgradeHandler { type InitError = Error; type Future = FutureResult; - fn new_service(&self, _: &()) -> Self::Future { + fn new_service(&self, _: &ServerConfig) -> Self::Future { unimplemented!() } } diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 42b8d8d82..b4191f03a 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -31,14 +31,14 @@ pub struct H2Service { impl H2Service where - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, ::Future: 'static, B: MessageBody + 'static, { /// Create new `HttpService` instance. - pub fn new>(service: F) -> Self { + pub fn new>(service: F) -> Self { let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0); H2Service { @@ -49,10 +49,7 @@ where } /// Create new `HttpService` instance with config. - pub fn with_config>( - cfg: ServiceConfig, - service: F, - ) -> Self { + pub fn with_config>(cfg: ServiceConfig, service: F) -> Self { H2Service { cfg, srv: service.into_new_service(), @@ -61,15 +58,16 @@ where } } -impl NewService for H2Service +impl NewService for H2Service where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, ::Future: 'static, B: MessageBody + 'static, { + type Config = SrvConfig; type Request = Io; type Response = (); type Error = DispatchError; @@ -87,7 +85,7 @@ where } #[doc(hidden)] -pub struct H2ServiceResponse, B> { +pub struct H2ServiceResponse { fut: ::Future, cfg: Option, _t: PhantomData<(T, P, B)>, @@ -96,7 +94,7 @@ pub struct H2ServiceResponse, impl Future for H2ServiceResponse where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::Response: Into>, ::Future: 'static, diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index dd3af1db0..b762f3cb9 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -30,7 +30,7 @@ pub struct HttpService HttpService where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -45,7 +45,7 @@ where impl HttpService where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -53,7 +53,7 @@ where B: MessageBody + 'static, { /// Create new `HttpService` instance. - pub fn new>(service: F) -> Self { + pub fn new>(service: F) -> Self { let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0); HttpService { @@ -66,7 +66,7 @@ where } /// Create new `HttpService` instance with config. - pub(crate) fn with_config>( + pub(crate) fn with_config>( cfg: ServiceConfig, service: F, ) -> Self { @@ -82,7 +82,7 @@ where impl HttpService where - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -95,7 +95,7 @@ where /// request will be forwarded to main service. pub fn expect(self, expect: X1) -> HttpService where - X1: NewService, + X1: NewService, X1::Error: Into, X1::InitError: fmt::Debug, { @@ -114,7 +114,11 @@ where /// and this service get called with original request and framed object. pub fn upgrade(self, upgrade: Option) -> HttpService where - U1: NewService), Response = ()>, + U1: NewService< + Config = SrvConfig, + Request = (Request, Framed), + Response = (), + >, U1::Error: fmt::Display, U1::InitError: fmt::Debug, { @@ -128,22 +132,27 @@ where } } -impl NewService for HttpService +impl NewService for HttpService where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, ::Future: 'static, B: MessageBody + 'static, - X: NewService, + X: NewService, X::Error: Into, X::InitError: fmt::Debug, - U: NewService), Response = ()>, + U: NewService< + Config = SrvConfig, + Request = (Request, Framed), + Response = (), + >, U::Error: fmt::Display, U::InitError: fmt::Debug, { + type Config = SrvConfig; type Request = ServerIo; type Response = (); type Error = DispatchError; @@ -154,8 +163,8 @@ where fn new_service(&self, cfg: &SrvConfig) -> Self::Future { HttpServiceResponse { fut: self.srv.new_service(cfg).into_future(), - fut_ex: Some(self.expect.new_service(&())), - fut_upg: self.upgrade.as_ref().map(|f| f.new_service(&())), + fut_ex: Some(self.expect.new_service(cfg)), + fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)), expect: None, upgrade: None, cfg: Some(self.cfg.clone()), @@ -165,14 +174,7 @@ where } #[doc(hidden)] -pub struct HttpServiceResponse< - T, - P, - S: NewService, - B, - X: NewService, - U: NewService, -> { +pub struct HttpServiceResponse { fut: S::Future, fut_ex: Option, fut_upg: Option, @@ -185,7 +187,7 @@ pub struct HttpServiceResponse< impl Future for HttpServiceResponse where T: IoStream, - S: NewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index 4b56e4b2c..d0c5e3526 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -5,7 +5,7 @@ use std::{net, thread}; use actix_codec::{AsyncRead, AsyncWrite}; use actix_http_test::TestServer; use actix_server_config::ServerConfig; -use actix_service::{fn_cfg_factory, fn_service, NewService}; +use actix_service::{new_service_cfg, service_fn, NewService}; use bytes::{Bytes, BytesMut}; use futures::future::{self, ok, Future}; use futures::stream::{once, Stream}; @@ -163,7 +163,7 @@ fn test_h2_body() -> std::io::Result<()> { fn test_expect_continue() { let srv = TestServer::new(|| { HttpService::build() - .expect(fn_service(|req: Request| { + .expect(service_fn(|req: Request| { if req.head().uri.query() == Some("yes=") { Ok(req) } else { @@ -190,7 +190,7 @@ fn test_expect_continue() { fn test_expect_continue_h1() { let srv = TestServer::new(|| { HttpService::build() - .expect(fn_service(|req: Request| { + .expect(service_fn(|req: Request| { sleep(Duration::from_millis(20)).then(move |_| { if req.head().uri.query() == Some("yes=") { Ok(req) @@ -912,7 +912,7 @@ fn test_h1_body_chunked_implicit() { #[test] fn test_h1_response_http_error_handling() { let mut srv = TestServer::new(|| { - HttpService::build().h1(fn_cfg_factory(|_: &ServerConfig| { + HttpService::build().h1(new_service_cfg(|_: &ServerConfig| { Ok::<_, ()>(|_| { let broken_header = Bytes::from_static(b"\0\0\0"); ok::<_, ()>( @@ -943,7 +943,7 @@ fn test_h2_response_http_error_handling() { .map_err(|e| println!("Openssl error: {}", e)) .and_then( HttpService::build() - .h2(fn_cfg_factory(|_: &ServerConfig| { + .h2(new_service_cfg(|_: &ServerConfig| { Ok::<_, ()>(|_| { let broken_header = Bytes::from_static(b"\0\0\0"); ok::<_, ()>( diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 8e1714e7d..5d0b6fad4 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" [dependencies] actix-web = "1.0.0-beta.1" -actix-service = "0.3.6" +actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" httparse = "1.3" diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index e13ff5c62..fe2054c91 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -25,7 +25,7 @@ cookie-session = ["actix-web/secure-cookies"] [dependencies] actix-web = "1.0.0-beta.2" -actix-service = "0.3.4" +actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" futures = "0.1.25" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index f061351dd..2b51a7525 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -40,7 +40,7 @@ flate2-rust = ["actix-http/flate2-rust"] [dependencies] actix-codec = "0.1.2" -actix-service = "0.3.6" +actix-service = "0.4.0" actix-http = "0.1.4" base64 = "0.10.1" bytes = "0.4" @@ -62,7 +62,7 @@ actix-web = { version = "1.0.0-beta.1", features=["ssl"] } actix-http = { version = "0.1.4", features=["ssl"] } actix-http-test = { version = "0.1.1", features=["ssl"] } actix-utils = "0.3.4" -actix-server = { version = "0.4.3", features=["ssl"] } +actix-server = { version = "0.5.0", features=["ssl"] } brotli2 = { version="0.3.2" } flate2 = { version="1.0.2" } env_logger = "0.6" diff --git a/awc/src/builder.rs b/awc/src/builder.rs index c460f1357..2bc52a431 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -140,51 +140,46 @@ impl ClientBuilder { #[cfg(test)] mod tests { use super::*; - use crate::test; #[test] fn client_basic_auth() { - test::run_on(|| { - let client = ClientBuilder::new().basic_auth("username", Some("password")); - assert_eq!( - client - .config - .headers - .get(header::AUTHORIZATION) - .unwrap() - .to_str() - .unwrap(), - "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" - ); + let client = ClientBuilder::new().basic_auth("username", Some("password")); + assert_eq!( + client + .config + .headers + .get(header::AUTHORIZATION) + .unwrap() + .to_str() + .unwrap(), + "Basic dXNlcm5hbWU6cGFzc3dvcmQ=" + ); - let client = ClientBuilder::new().basic_auth("username", None); - assert_eq!( - client - .config - .headers - .get(header::AUTHORIZATION) - .unwrap() - .to_str() - .unwrap(), - "Basic dXNlcm5hbWU=" - ); - }); + let client = ClientBuilder::new().basic_auth("username", None); + assert_eq!( + client + .config + .headers + .get(header::AUTHORIZATION) + .unwrap() + .to_str() + .unwrap(), + "Basic dXNlcm5hbWU=" + ); } #[test] fn client_bearer_auth() { - test::run_on(|| { - let client = ClientBuilder::new().bearer_auth("someS3cr3tAutht0k3n"); - assert_eq!( - client - .config - .headers - .get(header::AUTHORIZATION) - .unwrap() - .to_str() - .unwrap(), - "Bearer someS3cr3tAutht0k3n" - ); - }) + let client = ClientBuilder::new().bearer_auth("someS3cr3tAutht0k3n"); + assert_eq!( + client + .config + .headers + .get(header::AUTHORIZATION) + .unwrap() + .to_str() + .unwrap(), + "Bearer someS3cr3tAutht0k3n" + ); } } diff --git a/awc/src/response.rs b/awc/src/response.rs index b9b007b87..d186526de 100644 --- a/awc/src/response.rs +++ b/awc/src/response.rs @@ -347,10 +347,11 @@ where #[cfg(test)] mod tests { use super::*; + use actix_http_test::block_on; use futures::Async; use serde::{Deserialize, Serialize}; - use crate::{http::header, test::block_on, test::TestResponse}; + use crate::{http::header, test::TestResponse}; #[test] fn test_body() { diff --git a/awc/src/test.rs b/awc/src/test.rs index 8df21e8f9..f2c513bab 100644 --- a/awc/src/test.rs +++ b/awc/src/test.rs @@ -6,39 +6,10 @@ use actix_http::http::header::{self, Header, HeaderValue, IntoHeaderValue}; use actix_http::http::{HeaderName, HttpTryFrom, StatusCode, Version}; use actix_http::{h1, Payload, ResponseHead}; use bytes::Bytes; -#[cfg(test)] -use futures::Future; use percent_encoding::{percent_encode, USERINFO_ENCODE_SET}; use crate::ClientResponse; -#[cfg(test)] -thread_local! { - static RT: std::cell::RefCell = { - std::cell::RefCell::new(actix_rt::Runtime::new().unwrap()) - }; -} - -#[cfg(test)] -pub(crate) fn run_on(f: F) -> R -where - F: Fn() -> R, -{ - RT.with(move |rt| { - rt.borrow_mut() - .block_on(futures::future::lazy(|| Ok::<_, ()>(f()))) - }) - .unwrap() -} - -#[cfg(test)] -pub(crate) fn block_on(f: F) -> Result -where - F: Future, -{ - RT.with(move |rt| rt.borrow_mut().block_on(f)) -} - /// Test `ClientResponse` builder pub struct TestResponse { head: ResponseHead, diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 94a90535b..d3e06d3d5 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -318,7 +318,9 @@ impl WebsocketsRequest { } } else { log::trace!("Invalid connection header: {:?}", conn); - return Err(WsClientError::InvalidConnectionHeader(conn.clone())); + return Err(WsClientError::InvalidConnectionHeader( + conn.clone(), + )); } } else { log::trace!("Missing connection header"); @@ -462,29 +464,28 @@ mod tests { #[test] fn basics() { - actix_http_test::run_on(|| { - let req = Client::new() - .ws("http://localhost/") - .origin("test-origin") - .max_frame_size(100) - .server_mode() - .protocols(&["v1", "v2"]) - .set_header_if_none(header::CONTENT_TYPE, "json") - .set_header_if_none(header::CONTENT_TYPE, "text") - .cookie(Cookie::build("cookie1", "value1").finish()); - assert_eq!( - req.origin.as_ref().unwrap().to_str().unwrap(), - "test-origin" - ); - assert_eq!(req.max_size, 100); - assert_eq!(req.server_mode, true); - assert_eq!(req.protocols, Some("v1,v2".to_string())); - assert_eq!( - req.head.headers.get(header::CONTENT_TYPE).unwrap(), - header::HeaderValue::from_static("json") - ); - let _ = req.connect(); - }); + let req = Client::new() + .ws("http://localhost/") + .origin("test-origin") + .max_frame_size(100) + .server_mode() + .protocols(&["v1", "v2"]) + .set_header_if_none(header::CONTENT_TYPE, "json") + .set_header_if_none(header::CONTENT_TYPE, "text") + .cookie(Cookie::build("cookie1", "value1").finish()); + assert_eq!( + req.origin.as_ref().unwrap().to_str().unwrap(), + "test-origin" + ); + assert_eq!(req.max_size, 100); + assert_eq!(req.server_mode, true); + assert_eq!(req.protocols, Some("v1,v2".to_string())); + assert_eq!( + req.head.headers.get(header::CONTENT_TYPE).unwrap(), + header::HeaderValue::from_static("json") + ); + + let _ = actix_http_test::block_fn(move || req.connect()); assert!(Client::new().ws("/").connect().poll().is_err()); assert!(Client::new().ws("http:///test").connect().poll().is_err()); diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index 94684dd97..698481e37 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -15,7 +15,7 @@ use rand::Rng; use actix_codec::{AsyncRead, AsyncWrite}; use actix_http::HttpService; use actix_http_test::TestServer; -use actix_service::{fn_service, NewService}; +use actix_service::{service_fn, NewService}; use actix_web::http::{Cookie, Version}; use actix_web::middleware::{BodyEncoding, Compress}; use actix_web::{http::header, web, App, Error, HttpMessage, HttpRequest, HttpResponse}; @@ -182,7 +182,7 @@ fn test_connection_reuse() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) @@ -216,7 +216,7 @@ fn test_connection_reuse_h2() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) @@ -268,7 +268,7 @@ fn test_connection_force_close() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) @@ -300,7 +300,7 @@ fn test_connection_server_close() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) @@ -335,7 +335,7 @@ fn test_connection_wait_queue() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) @@ -380,7 +380,7 @@ fn test_connection_wait_queue_force_close() { let mut srv = TestServer::new(move || { let num2 = num2.clone(); - fn_service(move |io| { + service_fn(move |io| { num2.fetch_add(1, Ordering::Relaxed); Ok(io) }) diff --git a/awc/tests/test_ws.rs b/awc/tests/test_ws.rs index 4fc9f4bdc..5abf96355 100644 --- a/awc/tests/test_ws.rs +++ b/awc/tests/test_ws.rs @@ -1,17 +1,11 @@ use std::io; use actix_codec::Framed; +use actix_http::{body::BodySize, h1, ws, Error, HttpService, Request, Response}; use actix_http_test::TestServer; -use actix_server::Io; -use actix_service::{fn_service, NewService}; -use actix_utils::framed::IntoFramed; -use actix_utils::stream::TakeItem; use bytes::{Bytes, BytesMut}; -use futures::future::{ok, Either}; +use futures::future::ok; use futures::{Future, Sink, Stream}; -use tokio_tcp::TcpStream; - -use actix_http::{body::BodySize, h1, ws, Request, ResponseError, ServiceConfig}; fn ws_service(req: ws::Frame) -> impl Future { match req { @@ -37,52 +31,20 @@ fn ws_service(req: ws::Frame) -> impl Future| Ok(io.into_parts().0)) - .and_then(IntoFramed::new(|| h1::Codec::new(ServiceConfig::default()))) - .and_then(TakeItem::new().map_err(|_| ())) - .and_then( - |(req, framed): (Option>, Framed<_, _>)| { - // validate request - if let Some(h1::Message::Item(req)) = req { - match ws::verify_handshake(req.head()) { - Err(e) => { - // validation failed - let res = e.error_response(); - Either::A( - framed - .send(h1::Message::Item(( - res.drop_body(), - BodySize::Empty, - ))) - .map_err(|_| ()) - .map(|_| ()), - ) - } - Ok(_) => { - let res = ws::handshake_response(req.head()).finish(); - Either::B( - // send handshake response - framed - .send(h1::Message::Item(( - res.drop_body(), - BodySize::None, - ))) - .map_err(|_| ()) - .and_then(|framed| { - // start websocket service - let framed = - framed.into_framed(ws::Codec::new()); - ws::Transport::with(framed, ws_service) - .map_err(|_| ()) - }), - ) - } - } - } else { - panic!() - } - }, - ) + HttpService::build() + .upgrade(|(req, framed): (Request, Framed<_, _>)| { + let res = ws::handshake_response(req.head()).finish(); + // send handshake response + framed + .send(h1::Message::Item((res.drop_body(), BodySize::None))) + .map_err(|e: io::Error| e.into()) + .and_then(|framed| { + // start websocket service + let framed = framed.into_framed(ws::Codec::new()); + ws::Transport::with(framed, ws_service) + }) + }) + .finish(|_| ok::<_, Error>(Response::NotFound())) }); // client service diff --git a/src/app.rs b/src/app.rs index eb14d46fa..cc04630a3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -4,7 +4,6 @@ use std::marker::PhantomData; use std::rc::Rc; use actix_http::body::{Body, MessageBody}; -use actix_server_config::ServerConfig; use actix_service::boxed::{self, BoxedNewService}; use actix_service::{ apply_transform, IntoNewService, IntoTransform, NewService, Transform, @@ -59,6 +58,7 @@ impl App where B: MessageBody, T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -234,6 +234,7 @@ where where F: IntoNewService, U: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -319,6 +320,7 @@ where mw: F, ) -> App< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -384,6 +386,7 @@ where mw: F, ) -> App< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -400,10 +403,11 @@ where } } -impl IntoNewService, ServerConfig> for App +impl IntoNewService> for App where B: MessageBody, T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, diff --git a/src/app_service.rs b/src/app_service.rs index e2f918428..f34389840 100644 --- a/src/app_service.rs +++ b/src/app_service.rs @@ -6,7 +6,7 @@ use actix_http::{Extensions, Request, Response}; use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url}; use actix_server_config::ServerConfig; use actix_service::boxed::{self, BoxedNewService, BoxedService}; -use actix_service::{fn_service, NewService, Service}; +use actix_service::{service_fn, NewService, Service}; use futures::future::{ok, Either, FutureResult}; use futures::{Async, Future, Poll}; @@ -31,6 +31,7 @@ type BoxedResponse = Either< pub struct AppInit where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -46,15 +47,17 @@ where pub(crate) external: RefCell>, } -impl NewService for AppInit +impl NewService for AppInit where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, InitError = (), >, { + type Config = ServerConfig; type Request = Request; type Response = ServiceResponse; type Error = T::Error; @@ -65,7 +68,7 @@ where fn new_service(&self, cfg: &ServerConfig) -> Self::Future { // update resource default service let default = self.default.clone().unwrap_or_else(|| { - Rc::new(boxed::new_service(fn_service(|req: ServiceRequest| { + Rc::new(boxed::new_service(service_fn(|req: ServiceRequest| { Ok(req.into_response(Response::NotFound().finish())) }))) }); @@ -148,6 +151,7 @@ where impl Future for AppInitResult where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -233,6 +237,7 @@ pub struct AppRoutingFactory { } impl NewService for AppRoutingFactory { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; @@ -391,6 +396,7 @@ impl AppEntry { } impl NewService for AppEntry { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; diff --git a/src/config.rs b/src/config.rs index e4e390b15..62fd01be6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -107,6 +107,7 @@ impl AppService { ) where F: IntoNewService, S: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, diff --git a/src/handler.rs b/src/handler.rs index 245aba9d1..b53d16389 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,7 +1,8 @@ +use std::convert::Infallible; use std::marker::PhantomData; use actix_http::{Error, Payload, Response}; -use actix_service::{NewService, Service, Void}; +use actix_service::{NewService, Service}; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll}; @@ -71,7 +72,7 @@ where { type Request = (T, HttpRequest); type Response = ServiceResponse; - type Error = Void; + type Error = Infallible; type Future = HandlerServiceResponse<::Future>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { @@ -98,7 +99,7 @@ where T::Error: Into, { type Item = ServiceResponse; - type Error = Void; + type Error = Infallible; fn poll(&mut self) -> Poll { match self.fut.poll() { @@ -191,7 +192,7 @@ where { type Request = (T, HttpRequest); type Response = ServiceResponse; - type Error = Void; + type Error = Infallible; type Future = AsyncHandlerServiceResponse; fn poll_ready(&mut self) -> Poll<(), Self::Error> { @@ -225,7 +226,7 @@ where T::Error: Into, { type Item = ServiceResponse; - type Error = Void; + type Error = Infallible; fn poll(&mut self) -> Poll { if let Some(ref mut fut) = self.fut2 { @@ -280,9 +281,13 @@ impl Extract { impl NewService for Extract where - S: Service - + Clone, + S: Service< + Request = (T, HttpRequest), + Response = ServiceResponse, + Error = Infallible, + > + Clone, { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = (Error, ServiceRequest); @@ -305,8 +310,11 @@ pub struct ExtractService { impl Service for ExtractService where - S: Service - + Clone, + S: Service< + Request = (T, HttpRequest), + Response = ServiceResponse, + Error = Infallible, + > + Clone, { type Request = ServiceRequest; type Response = ServiceResponse; @@ -339,7 +347,11 @@ pub struct ExtractResponse { impl Future for ExtractResponse where - S: Service, + S: Service< + Request = (T, HttpRequest), + Response = ServiceResponse, + Error = Infallible, + >, { type Item = ServiceResponse; type Error = (Error, ServiceRequest); diff --git a/src/middleware/cors.rs b/src/middleware/cors.rs index bb4fd567f..f731f49bd 100644 --- a/src/middleware/cors.rs +++ b/src/middleware/cors.rs @@ -805,14 +805,15 @@ where #[cfg(test)] mod tests { - use actix_service::{FnService, Transform}; + use actix_service::{IntoService, Transform}; use super::*; use crate::test::{self, block_on, TestRequest}; impl Cors { - fn finish(self, srv: S) -> CorsMiddleware + fn finish(self, srv: F) -> CorsMiddleware where + F: IntoService, S: Service< Request = ServiceRequest, Response = ServiceResponse, @@ -822,7 +823,8 @@ mod tests { B: 'static, { block_on( - IntoTransform::::into_transform(self).new_transform(srv), + IntoTransform::::into_transform(self) + .new_transform(srv.into_service()), ) .unwrap() } @@ -1063,11 +1065,11 @@ mod tests { .allowed_headers(exposed_headers.clone()) .expose_headers(exposed_headers.clone()) .allowed_header(header::CONTENT_TYPE) - .finish(FnService::new(move |req: ServiceRequest| { + .finish(|req: ServiceRequest| { req.into_response( HttpResponse::Ok().header(header::VARY, "Accept").finish(), ) - })); + }); let req = TestRequest::with_header("Origin", "https://www.example.com") .method(Method::OPTIONS) .to_srv_request(); diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index 8b92b530d..bddcdd552 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -150,7 +150,7 @@ where #[cfg(test)] mod tests { - use actix_service::FnService; + use actix_service::IntoService; use super::*; use crate::dev::ServiceRequest; @@ -172,13 +172,13 @@ mod tests { assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); let req = TestRequest::default().to_srv_request(); - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { req.into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish()) - }); + }; let mut mw = block_on( DefaultHeaders::new() .header(CONTENT_TYPE, "0001") - .new_transform(srv), + .new_transform(srv.into_service()), ) .unwrap(); let resp = block_on(mw.call(req)).unwrap(); @@ -187,11 +187,13 @@ mod tests { #[test] fn test_content_type() { - let srv = FnService::new(|req: ServiceRequest| { - req.into_response(HttpResponse::Ok().finish()) - }); - let mut mw = - block_on(DefaultHeaders::new().content_type().new_transform(srv)).unwrap(); + let srv = |req: ServiceRequest| req.into_response(HttpResponse::Ok().finish()); + let mut mw = block_on( + DefaultHeaders::new() + .content_type() + .new_transform(srv.into_service()), + ) + .unwrap(); let req = TestRequest::default().to_srv_request(); let resp = block_on(mw.call(req)).unwrap(); diff --git a/src/middleware/errhandlers.rs b/src/middleware/errhandlers.rs index acc6783f8..ac166e0eb 100644 --- a/src/middleware/errhandlers.rs +++ b/src/middleware/errhandlers.rs @@ -142,7 +142,7 @@ where #[cfg(test)] mod tests { - use actix_service::FnService; + use actix_service::IntoService; use futures::future::ok; use super::*; @@ -159,14 +159,14 @@ mod tests { #[test] fn test_handler() { - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { req.into_response(HttpResponse::InternalServerError().finish()) - }); + }; let mut mw = test::block_on( ErrorHandlers::new() .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500) - .new_transform(srv), + .new_transform(srv.into_service()), ) .unwrap(); @@ -185,14 +185,14 @@ mod tests { #[test] fn test_handler_async() { - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { req.into_response(HttpResponse::InternalServerError().finish()) - }); + }; let mut mw = test::block_on( ErrorHandlers::new() .handler(StatusCode::INTERNAL_SERVER_ERROR, render_500_async) - .new_transform(srv), + .new_transform(srv.into_service()), ) .unwrap(); diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 3e3fb05fa..5d0b615e1 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -457,7 +457,7 @@ impl<'a> fmt::Display for FormatDisplay<'a> { #[cfg(test)] mod tests { - use actix_service::{FnService, Service, Transform}; + use actix_service::{IntoService, Service, Transform}; use super::*; use crate::http::{header, StatusCode}; @@ -465,16 +465,16 @@ mod tests { #[test] fn test_logger() { - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { req.into_response( HttpResponse::build(StatusCode::OK) .header("X-Test", "ttt") .finish(), ) - }); + }; let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test"); - let mut srv = block_on(logger.new_transform(srv)).unwrap(); + let mut srv = block_on(logger.new_transform(srv.into_service())).unwrap(); let req = TestRequest::with_header( header::USER_AGENT, diff --git a/src/middleware/normalize.rs b/src/middleware/normalize.rs index a86e2b9c7..427f954fe 100644 --- a/src/middleware/normalize.rs +++ b/src/middleware/normalize.rs @@ -100,7 +100,7 @@ where #[cfg(test)] mod tests { - use actix_service::FnService; + use actix_service::IntoService; use super::*; use crate::dev::ServiceRequest; @@ -122,12 +122,13 @@ mod tests { #[test] fn test_in_place_normalization() { - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { assert_eq!("/v1/something/", req.path()); req.into_response(HttpResponse::Ok().finish()) - }); + }; - let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap(); + let mut normalize = + block_on(NormalizePath.new_transform(srv.into_service())).unwrap(); let req = TestRequest::with_uri("/v1//something////").to_srv_request(); let res = block_on(normalize.call(req)).unwrap(); @@ -138,12 +139,13 @@ mod tests { fn should_normalize_nothing() { const URI: &str = "/v1/something/"; - let srv = FnService::new(|req: ServiceRequest| { + let srv = |req: ServiceRequest| { assert_eq!(URI, req.path()); req.into_response(HttpResponse::Ok().finish()) - }); + }; - let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap(); + let mut normalize = + block_on(NormalizePath.new_transform(srv.into_service())).unwrap(); let req = TestRequest::with_uri(URI).to_srv_request(); let res = block_on(normalize.call(req)).unwrap(); diff --git a/src/resource.rs b/src/resource.rs index 8bafc0fcd..2040a1bbe 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -75,6 +75,7 @@ impl Resource { impl Resource where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -274,6 +275,7 @@ where mw: F, ) -> Resource< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -340,6 +342,7 @@ where mw: F, ) -> Resource< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -360,6 +363,7 @@ where where F: IntoNewService, U: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -380,6 +384,7 @@ where impl HttpServiceFactory for Resource where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -411,6 +416,7 @@ where impl IntoNewService for Resource where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -435,6 +441,7 @@ pub struct ResourceFactory { } impl NewService for ResourceFactory { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; @@ -575,6 +582,7 @@ impl ResourceEndpoint { } impl NewService for ResourceEndpoint { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; diff --git a/src/route.rs b/src/route.rs index 62f030c79..660b82002 100644 --- a/src/route.rs +++ b/src/route.rs @@ -26,6 +26,7 @@ type BoxedRouteService = Box< type BoxedRouteNewService = Box< NewService< + Config = (), Request = Req, Response = Res, Error = Error, @@ -61,6 +62,7 @@ impl Route { } impl NewService for Route { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; @@ -283,6 +285,7 @@ where impl RouteNewService where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = (Error, ServiceRequest), @@ -299,6 +302,7 @@ where impl NewService for RouteNewService where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = (Error, ServiceRequest), @@ -307,6 +311,7 @@ where T::Service: 'static, ::Future: 'static, { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; diff --git a/src/scope.rs b/src/scope.rs index ada533341..59d3c6738 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -6,7 +6,7 @@ use actix_http::Response; use actix_router::{ResourceDef, ResourceInfo, Router}; use actix_service::boxed::{self, BoxedNewService, BoxedService}; use actix_service::{ - ApplyTransform, IntoNewService, IntoTransform, NewService, Service, Transform, + apply_transform, IntoNewService, IntoTransform, NewService, Service, Transform, }; use futures::future::{ok, Either, Future, FutureResult}; use futures::{Async, IntoFuture, Poll}; @@ -85,6 +85,7 @@ impl Scope { impl Scope where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -188,6 +189,7 @@ where where F: IntoNewService, U: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -218,6 +220,7 @@ where mw: F, ) -> Scope< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -234,7 +237,7 @@ where >, F: IntoTransform, { - let endpoint = ApplyTransform::new(mw, self.endpoint); + let endpoint = apply_transform(mw, self.endpoint); Scope { endpoint, rdef: self.rdef, @@ -280,6 +283,7 @@ where mw: F, ) -> Scope< impl NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -297,6 +301,7 @@ where impl HttpServiceFactory for Scope where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -355,6 +360,7 @@ pub struct ScopeFactory { } impl NewService for ScopeFactory { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; @@ -515,6 +521,7 @@ impl ScopeEndpoint { } impl NewService for ScopeEndpoint { + type Config = (); type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; diff --git a/src/server.rs b/src/server.rs index efc70773f..3cb139976 100644 --- a/src/server.rs +++ b/src/server.rs @@ -51,8 +51,8 @@ struct Config { pub struct HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -71,8 +71,8 @@ where impl HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, @@ -442,8 +442,8 @@ where impl HttpServer where F: Fn() -> I + Send + Clone + 'static, - I: IntoNewService, - S: NewService, + I: IntoNewService, + S: NewService, S::Error: Into, S::InitError: fmt::Debug, S::Response: Into>, diff --git a/src/service.rs b/src/service.rs index f35ea89f2..eee8b0adb 100644 --- a/src/service.rs +++ b/src/service.rs @@ -442,6 +442,7 @@ impl WebService { where F: IntoNewService, T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, @@ -467,6 +468,7 @@ struct WebServiceImpl { impl HttpServiceFactory for WebServiceImpl where T: NewService< + Config = (), Request = ServiceRequest, Response = ServiceResponse, Error = Error, diff --git a/src/test.rs b/src/test.rs index 66b380e83..3b3aac67d 100644 --- a/src/test.rs +++ b/src/test.rs @@ -9,7 +9,7 @@ use actix_http::{cookie::Cookie, Extensions, Request}; use actix_router::{Path, ResourceDef, Url}; use actix_rt::Runtime; use actix_server_config::ServerConfig; -use actix_service::{FnService, IntoNewService, NewService, Service}; +use actix_service::{IntoNewService, IntoService, NewService, Service}; use bytes::{Bytes, BytesMut}; use futures::future::{lazy, ok, Future, IntoFuture}; use futures::Stream; @@ -110,9 +110,10 @@ pub fn default_service( status_code: StatusCode, ) -> impl Service, Error = Error> { - FnService::new(move |req: ServiceRequest| { + (move |req: ServiceRequest| { req.into_response(HttpResponse::build(status_code).finish()) }) + .into_service() } /// This method accepts application builder instance, and constructs @@ -141,9 +142,9 @@ pub fn init_service( app: R, ) -> impl Service, Error = E> where - R: IntoNewService, + R: IntoNewService, S: NewService< - ServerConfig, + Config = ServerConfig, Request = Request, Response = ServiceResponse, Error = E, diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 906c9d389..cd5cc5057 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -32,9 +32,9 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] [dependencies] actix-codec = "0.1.2" actix-rt = "0.2.2" -actix-service = "0.3.6" -actix-server = "0.4.3" -actix-utils = "0.3.5" +actix-service = "0.4.0" +actix-server = "0.5.0" +actix-utils = "0.4.0" awc = "0.1.1" base64 = "0.10" diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 42d07549d..b8f5934ae 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -9,16 +9,30 @@ use actix_server::{Server, StreamServiceFactory}; use awc::{error::PayloadError, ws, Client, ClientRequest, ClientResponse, Connector}; use bytes::Bytes; use futures::future::lazy; -use futures::{Future, Stream}; +use futures::{Future, IntoFuture, Stream}; use http::Method; use net2::TcpBuilder; thread_local! { - static RT: RefCell = { - RefCell::new(Runtime::new().unwrap()) + static RT: RefCell = { + RefCell::new(Inner(Some(Runtime::new().unwrap()))) }; } +struct Inner(Option); + +impl Inner { + fn get_mut(&mut self) -> &mut Runtime { + self.0.as_mut().unwrap() + } +} + +impl Drop for Inner { + fn drop(&mut self) { + std::mem::forget(self.0.take().unwrap()) + } +} + /// Runs the provided future, blocking the current thread until the future /// completes. /// @@ -31,21 +45,27 @@ thread_local! { /// This function panics on nested call. pub fn block_on(f: F) -> Result where - F: Future, + F: IntoFuture, { - RT.with(move |rt| rt.borrow_mut().block_on(f)) + RT.with(move |rt| rt.borrow_mut().get_mut().block_on(f.into_future())) } -/// Runs the provided function, with runtime enabled. +/// Runs the provided function, blocking the current thread until the resul +/// future completes. +/// +/// This function can be used to synchronously block the current thread +/// until the provided `future` has resolved either successfully or with an +/// error. The result of the future is then returned from this function +/// call. /// /// Note that this function is intended to be used only for testing purpose. /// This function panics on nested call. -pub fn run_on(f: F) -> R +pub fn block_fn(f: F) -> Result where - F: Fn() -> R, + F: FnOnce() -> R, + R: IntoFuture, { - RT.with(move |rt| rt.borrow_mut().block_on(lazy(|| Ok::<_, ()>(f())))) - .unwrap() + RT.with(move |rt| rt.borrow_mut().get_mut().block_on(lazy(|| f()))) } /// The `TestServer` type. From 45c05978b0c2fdbe1f8b60708f54d472ba25b41b Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 09:42:05 -0700 Subject: [PATCH 04/17] Allow to set/override app data on scope level --- CHANGES.md | 6 ++++ src/app.rs | 4 +-- src/config.rs | 18 ++++++------ src/data.rs | 7 +---- src/resource.rs | 2 +- src/scope.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 90 insertions(+), 20 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ce7da6d28..aa42900d0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [1.0.0-beta.4] - 2019-05-xx + +### Add + +* Allow to set/override app data on scope level + ### Changes * `App::configure` take an `FnOnce` instead of `Fn` diff --git a/src/app.rs b/src/app.rs index cc04630a3..1568d5fca 100644 --- a/src/app.rs +++ b/src/app.rs @@ -95,8 +95,8 @@ where /// web::get().to(index))); /// } /// ``` - pub fn data> + 'static>(mut self, data: U) -> Self { - self.data.push(Box::new(data.into())); + pub fn data(mut self, data: U) -> Self { + self.data.push(Box::new(Data::new(data))); self } diff --git a/src/config.rs b/src/config.rs index 62fd01be6..bc33da9df 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,7 +31,7 @@ pub struct AppService { Option, Option>, )>, - route_data: Rc>>, + service_data: Rc>>, } impl AppService { @@ -39,12 +39,12 @@ impl AppService { pub(crate) fn new( config: AppConfig, default: Rc, - route_data: Rc>>, + service_data: Rc>>, ) -> Self { AppService { config, default, - route_data, + service_data, root: true, services: Vec::new(), } @@ -75,7 +75,7 @@ impl AppService { default: self.default.clone(), services: Vec::new(), root: false, - route_data: self.route_data.clone(), + service_data: self.service_data.clone(), } } @@ -90,11 +90,11 @@ impl AppService { } /// Set global route data - pub fn set_route_data(&self, extensions: &mut Extensions) -> bool { - for f in self.route_data.iter() { + pub fn set_service_data(&self, extensions: &mut Extensions) -> bool { + for f in self.service_data.iter() { f.create(extensions); } - !self.route_data.is_empty() + !self.service_data.is_empty() } /// Register http service @@ -192,8 +192,8 @@ impl ServiceConfig { /// by using `Data` extractor where `T` is data type. /// /// This is same as `App::data()` method. - pub fn data> + 'static>(&mut self, data: S) -> &mut Self { - self.data.push(Box::new(data.into())); + pub fn data(&mut self, data: S) -> &mut Self { + self.data.push(Box::new(Data::new(data))); self } diff --git a/src/data.rs b/src/data.rs index f23bfff7f..5cb636f6a 100644 --- a/src/data.rs +++ b/src/data.rs @@ -93,12 +93,6 @@ impl Clone for Data { } } -impl From for Data { - fn from(data: T) -> Self { - Data::new(data) - } -} - impl FromRequest for Data { type Config = (); type Error = Error; @@ -135,6 +129,7 @@ impl DataFactory for Data { #[cfg(test)] mod tests { use actix_service::Service; + use std::sync::Mutex; use crate::http::StatusCode; use crate::test::{block_on, init_service, TestRequest}; diff --git a/src/resource.rs b/src/resource.rs index 2040a1bbe..7f76e0f5c 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -407,7 +407,7 @@ where } // custom app data storage if let Some(ref mut ext) = self.data { - config.set_route_data(ext); + config.set_service_data(ext); } config.register_service(rdef, guards, self, None) } diff --git a/src/scope.rs b/src/scope.rs index 59d3c6738..84f34dae6 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::fmt; use std::rc::Rc; -use actix_http::Response; +use actix_http::{Extensions, Response}; use actix_router::{ResourceDef, ResourceInfo, Router}; use actix_service::boxed::{self, BoxedNewService, BoxedService}; use actix_service::{ @@ -11,6 +11,7 @@ use actix_service::{ use futures::future::{ok, Either, Future, FutureResult}; use futures::{Async, IntoFuture, Poll}; +use crate::data::Data; use crate::dev::{AppService, HttpServiceFactory}; use crate::error::Error; use crate::guard::Guard; @@ -61,6 +62,7 @@ type BoxedResponse = Either< pub struct Scope { endpoint: T, rdef: String, + data: Option, services: Vec>, guards: Vec>, default: Rc>>>, @@ -74,6 +76,7 @@ impl Scope { Scope { endpoint: ScopeEndpoint::new(fref.clone()), rdef: path.to_string(), + data: None, guards: Vec::new(), services: Vec::new(), default: Rc::new(RefCell::new(None)), @@ -117,6 +120,39 @@ where self } + /// Set or override application data. Application data could be accessed + /// by using `Data` extractor where `T` is data type. + /// + /// ```rust + /// use std::cell::Cell; + /// use actix_web::{web, App}; + /// + /// struct MyData { + /// counter: Cell, + /// } + /// + /// fn index(data: web::Data) { + /// data.counter.set(data.counter.get() + 1); + /// } + /// + /// fn main() { + /// let app = App::new().service( + /// web::scope("/app") + /// .data(MyData{ counter: Cell::new(0) }) + /// .service( + /// web::resource("/index.html").route( + /// web::get().to(index))) + /// ); + /// } + /// ``` + pub fn data(mut self, data: U) -> Self { + if self.data.is_none() { + self.data = Some(Extensions::new()); + } + self.data.as_mut().unwrap().insert(Data::new(data)); + self + } + /// Register http service. /// /// This is similar to `App's` service registration. @@ -241,6 +277,7 @@ where Scope { endpoint, rdef: self.rdef, + data: self.data, guards: self.guards, services: self.services, default: self.default, @@ -308,7 +345,7 @@ where InitError = (), > + 'static, { - fn register(self, config: &mut AppService) { + fn register(mut self, config: &mut AppService) { // update default resource if needed if self.default.borrow().is_none() { *self.default.borrow_mut() = Some(config.default_service()); @@ -322,8 +359,14 @@ where let mut rmap = ResourceMap::new(ResourceDef::root_prefix(&self.rdef)); + // custom app data storage + if let Some(ref mut ext) = self.data { + config.set_service_data(ext); + } + // complete scope pipeline creation *self.factory_ref.borrow_mut() = Some(ScopeFactory { + data: self.data.take().map(|data| Rc::new(data)), default: self.default.clone(), services: Rc::new( cfg.into_services() @@ -355,6 +398,7 @@ where } pub struct ScopeFactory { + data: Option>, services: Rc>)>>, default: Rc>>>, } @@ -388,6 +432,7 @@ impl NewService for ScopeFactory { }) .collect(), default: None, + data: self.data.clone(), default_fut, } } @@ -397,6 +442,7 @@ impl NewService for ScopeFactory { #[doc(hidden)] pub struct ScopeFactoryResponse { fut: Vec, + data: Option>, default: Option, default_fut: Option>>, } @@ -460,6 +506,7 @@ impl Future for ScopeFactoryResponse { router }); Ok(Async::Ready(ScopeService { + data: self.data.clone(), router: router.finish(), default: self.default.take(), _ready: None, @@ -471,6 +518,7 @@ impl Future for ScopeFactoryResponse { } pub struct ScopeService { + data: Option>, router: Router>>, default: Option, _ready: Option<(ServiceRequest, ResourceInfo)>, @@ -499,6 +547,9 @@ impl Service for ScopeService { }); if let Some((srv, _info)) = res { + if let Some(ref data) = self.data { + req.set_data_container(data.clone()); + } Either::A(srv.call(req)) } else if let Some(ref mut default) = self.default { Either::A(default.call(req)) @@ -953,4 +1004,22 @@ mod tests { HeaderValue::from_static("0001") ); } + + #[test] + fn test_override_data() { + let mut srv = init_service(App::new().data(1usize).service( + web::scope("app").data(10usize).route( + "/t", + web::get().to(|data: web::Data| { + assert_eq!(*data, 10); + let _ = data.clone(); + HttpResponse::Ok() + }), + ), + )); + + let req = TestRequest::with_uri("/app/t").to_request(); + let resp = call_service(&mut srv, req); + assert_eq!(resp.status(), StatusCode::OK); + } } From 07b9707ca100df7730d20572163a668f833da284 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 09:56:55 -0700 Subject: [PATCH 05/17] prepare actix-http release --- Cargo.toml | 2 +- actix-http/CHANGES.md | 6 +++++- actix-http/Cargo.toml | 6 +++--- actix-session/Cargo.toml | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f4e2f79ea..1bd47e439 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,7 +82,7 @@ bytes = "0.4" derive_more = "0.14" encoding = "0.2" futures = "0.1" -hashbrown = "0.2.2" +hashbrown = "0.3.0" log = "0.4" mime = "0.3" net2 = "0.2.33" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index f1c119d57..a6653f621 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [0.2.0] - 2019-xx-xx +## [0.2.0] - 2019-05-xx ### Changed @@ -8,6 +8,10 @@ * Expect and upgrade services accept `ServerConfig` config. +### Deleted + +* `OneRequest` service + ## [0.1.5] - 2019-05-04 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index eaac7c090..1f0e1268c 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.1.5" +version = "0.2.0" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" @@ -59,8 +59,8 @@ copyless = "0.1.2" derive_more = "0.14" either = "1.5.2" encoding = "0.2" -futures = "0.1" -hashbrown = "0.2.2" +futures = "0.1.25" +hashbrown = "0.3.0" h2 = "0.1.16" http = "0.1.17" httparse = "1.3" diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index fe2054c91..4af0fc29a 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -29,7 +29,7 @@ actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" futures = "0.1.25" -hashbrown = "0.2.2" +hashbrown = "0.3.0" serde = "1.0" serde_json = "1.0" time = "0.1.42" From beae9ca0f77a7ff381df0cb831b62fcc601127be Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 09:57:16 -0700 Subject: [PATCH 06/17] update changes --- actix-http/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index a6653f621..61c211b26 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [0.2.0] - 2019-05-xx +## [0.2.0] - 2019-05-12 ### Changed From 07c9eec8039547e97df91d424e376b299002cbb5 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 10:04:38 -0700 Subject: [PATCH 07/17] prepare awc release --- Cargo.toml | 4 ++-- awc/CHANGES.md | 6 ++++++ awc/Cargo.toml | 8 ++++---- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1bd47e439..6c0433d5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ actix-utils = "0.4.0" actix-router = "0.1.3" actix-rt = "0.2.2" actix-web-codegen = "0.1.0-beta.1" -actix-http = { version = "0.1.5", features=["fail"] } +actix-http = { version = "0.2.0", features=["fail"] } actix-server = "0.5.0" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" @@ -99,7 +99,7 @@ openssl = { version="0.10", optional = true } rustls = { version = "^0.15", optional = true } [dev-dependencies] -actix-http = { version = "0.1.5", features=["ssl", "brotli", "flate2-zlib"] } +actix-http = { version = "0.2.0", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.1.1", features=["ssl"] } actix-files = { version = "0.1.0-betsa.1" } rand = "0.6" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 124efc36a..f36b0bb3a 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,9 +1,15 @@ # Changes +## [0.2.0] - 2019-05-12 + ### Added * Allow to send headers in `Camel-Case` form. +### Changed + +* Upgrade actix-http dependency. + ## [0.1.1] - 2019-04-19 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 2b51a7525..b92d62f06 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "0.1.1" +version = "0.2.0" authors = ["Nikolay Kim "] description = "Actix http client." readme = "README.md" @@ -41,7 +41,7 @@ flate2-rust = ["actix-http/flate2-rust"] [dependencies] actix-codec = "0.1.2" actix-service = "0.4.0" -actix-http = "0.1.4" +actix-http = "0.2.0" base64 = "0.10.1" bytes = "0.4" derive_more = "0.14" @@ -59,9 +59,9 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.2.2" actix-web = { version = "1.0.0-beta.1", features=["ssl"] } -actix-http = { version = "0.1.4", features=["ssl"] } +actix-http = { version = "0.2.0", features=["ssl"] } actix-http-test = { version = "0.1.1", features=["ssl"] } -actix-utils = "0.3.4" +actix-utils = "0.4.0" actix-server = { version = "0.5.0", features=["ssl"] } brotli2 = { version="0.3.2" } flate2 = { version="1.0.2" } From e9cbcbaf03128b9932a58f5ed00441efad669701 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 10:18:02 -0700 Subject: [PATCH 08/17] update dependencies --- Cargo.toml | 5 ++--- actix-framed/Cargo.toml | 10 +++++----- actix-framed/changes.md | 5 +++++ actix-http/Cargo.toml | 2 +- actix-multipart/Cargo.toml | 2 +- actix-web-actors/Cargo.toml | 4 ++-- actix-web-codegen/Cargo.toml | 4 ++-- awc/Cargo.toml | 2 +- src/data.rs | 1 - test-server/CHANGES.md | 4 ++++ test-server/Cargo.toml | 6 +++--- 11 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6c0433d5b..08e5d55a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,7 +76,7 @@ actix-server = "0.5.0" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" actix = { version = "0.8.1", features=["http"], optional = true } -awc = { version = "0.1.1", optional = true } +awc = { version = "0.2.0", optional = true } bytes = "0.4" derive_more = "0.14" @@ -100,7 +100,7 @@ rustls = { version = "^0.15", optional = true } [dev-dependencies] actix-http = { version = "0.2.0", features=["ssl", "brotli", "flate2-zlib"] } -actix-http-test = { version = "0.1.1", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } actix-files = { version = "0.1.0-betsa.1" } rand = "0.6" env_logger = "0.6" @@ -124,5 +124,4 @@ actix-session = { path = "actix-session" } awc = { path = "awc" } actix-files = { path = "actix-files" } -actix-framed = { path = "actix-framed" } actix-multipart = { path = "actix-multipart" } diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index 985515367..c2ab26fa2 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-framed" -version = "0.1.0" +version = "0.2.0" authors = ["Nikolay Kim "] description = "Actix framed app server" readme = "README.md" @@ -25,7 +25,7 @@ actix-service = "0.4.0" actix-utils = "0.4.0" actix-router = "0.1.2" actix-rt = "0.2.2" -actix-http = "0.1.0" +actix-http = "0.2.0" actix-server-config = "0.1.1" bytes = "0.4" @@ -33,6 +33,6 @@ futures = "0.1.25" log = "0.4" [dev-dependencies] -actix-server = { version = "0.4.3", features=["ssl"] } -actix-connect = { version = "0.1.4", features=["ssl"] } -actix-http-test = { version = "0.1.0", features=["ssl"] } +actix-server = { version = "0.5.0", features=["ssl"] } +actix-connect = { version = "0.2.0", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } diff --git a/actix-framed/changes.md b/actix-framed/changes.md index 9cef3c057..9f16c790a 100644 --- a/actix-framed/changes.md +++ b/actix-framed/changes.md @@ -1,5 +1,10 @@ # Changes +## [0.2.0] - 2019-05-12 + +* Update dependencies + + ## [0.1.0] - 2019-04-16 * Update tests diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 1f0e1268c..fabf7fe92 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -99,7 +99,7 @@ chrono = "0.4.6" actix-rt = "0.2.2" actix-server = { version = "0.5.0", features=["ssl"] } actix-connect = { version = "0.2.0", features=["ssl"] } -actix-http-test = { version = "0.1.0", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } env_logger = "0.6" serde_derive = "1.0" openssl = { version="0.10" } diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 5d0b6fad4..6e3f6dc76 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -31,4 +31,4 @@ twoway = "0.2" [dev-dependencies] actix-rt = "0.2.2" -actix-http = "0.1.1" \ No newline at end of file +actix-http = "0.2.0" \ No newline at end of file diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 22fdf613d..f2309d196 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -20,11 +20,11 @@ path = "src/lib.rs" [dependencies] actix = "0.8.0" actix-web = "1.0.0-beta.1" -actix-http = "0.1.1" +actix-http = "0.2.0" actix-codec = "0.1.2" bytes = "0.4" futures = "0.1.25" [dev-dependencies] env_logger = "0.6" -actix-http-test = { version = "0.1.0", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 4108d879a..696121834 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -17,6 +17,6 @@ syn = { version = "0.15", features = ["full", "parsing"] } [dev-dependencies] actix-web = { version = "1.0.0-alpha.6" } -actix-http = { version = "0.1.1", features=["ssl"] } -actix-http-test = { version = "0.1.0", features=["ssl"] } +actix-http = { version = "0.2.0", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } futures = { version = "0.1" } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index b92d62f06..20cee12ea 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -60,7 +60,7 @@ openssl = { version="0.10", optional = true } actix-rt = "0.2.2" actix-web = { version = "1.0.0-beta.1", features=["ssl"] } actix-http = { version = "0.2.0", features=["ssl"] } -actix-http-test = { version = "0.1.1", features=["ssl"] } +actix-http-test = { version = "0.2.0", features=["ssl"] } actix-utils = "0.4.0" actix-server = { version = "0.5.0", features=["ssl"] } brotli2 = { version="0.3.2" } diff --git a/src/data.rs b/src/data.rs index 5cb636f6a..1328c4ef6 100644 --- a/src/data.rs +++ b/src/data.rs @@ -129,7 +129,6 @@ impl DataFactory for Data { #[cfg(test)] mod tests { use actix_service::Service; - use std::sync::Mutex; use crate::http::StatusCode; use crate::test::{block_on, init_service, TestRequest}; diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index 700b3aa1f..8704a64c2 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.2.0] - 2019-05-12 + +* Update awc and actix-http deps + ## [0.1.1] - 2019-04-24 * Always make new connection for http client diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index cd5cc5057..13817d506 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "0.1.1" +version = "0.2.0" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -35,7 +35,7 @@ actix-rt = "0.2.2" actix-service = "0.4.0" actix-server = "0.5.0" actix-utils = "0.4.0" -awc = "0.1.1" +awc = "0.2.0" base64 = "0.10" bytes = "0.4" @@ -56,4 +56,4 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-web = "1.0.0-beta.1" -actix-http = "0.1.2" +actix-http = "0.2.0" From 1ca58e876b16db57757544af5f4b9fc209959da8 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 10:49:21 -0700 Subject: [PATCH 09/17] prepare beta4 release --- CHANGES.md | 4 +++- Cargo.toml | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index aa42900d0..dedf07585 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.0-beta.4] - 2019-05-xx +## [1.0.0-beta.4] - 2019-05-12 ### Add @@ -10,6 +10,8 @@ * `App::configure` take an `FnOnce` instead of `Fn` +* Upgrade actix-net crates + ## [1.0.0-beta.3] - 2019-05-04 diff --git a/Cargo.toml b/Cargo.toml index 08e5d55a6..23b388279 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.0-beta.3" +version = "1.0.0-beta.4" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -121,7 +121,6 @@ actix-http-test = { path = "test-server" } actix-web-codegen = { path = "actix-web-codegen" } actix-web-actors = { path = "actix-web-actors" } actix-session = { path = "actix-session" } -awc = { path = "awc" } - actix-files = { path = "actix-files" } actix-multipart = { path = "actix-multipart" } +awc = { path = "awc" } From 3bb081852ce9deae03b0ce62f056841a1cd83bbb Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 10:53:21 -0700 Subject: [PATCH 10/17] prep actix-session release --- actix-session/CHANGES.md | 4 ++++ actix-session/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/actix-session/CHANGES.md b/actix-session/CHANGES.md index 8e06a5624..5f2bdadd1 100644 --- a/actix-session/CHANGES.md +++ b/actix-session/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.1.0-beta.4] - 2019-05-12 + +* Use actix-web 1.0.0-beta.4 + ## [0.1.0-beta.2] - 2019-04-28 * Add helper trait `UserSession` which allows to get session for ServiceRequest and HttpRequest diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index 4af0fc29a..f74d23f02 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-session" -version = "0.1.0-beta.2" +version = "0.1.0-beta.4" authors = ["Nikolay Kim "] description = "Session for actix web framework." readme = "README.md" @@ -24,7 +24,7 @@ default = ["cookie-session"] cookie-session = ["actix-web/secure-cookies"] [dependencies] -actix-web = "1.0.0-beta.2" +actix-web = "1.0.0-beta.4" actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" From 36d017dcc6b27c1442a2d013b588d3119f692957 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 11:41:43 -0700 Subject: [PATCH 11/17] update deps --- Cargo.toml | 2 +- actix-files/CHANGES.md | 4 ++++ actix-files/Cargo.toml | 6 +++--- actix-web-actors/Cargo.toml | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 23b388279..513c9add4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,7 @@ rustls = { version = "^0.15", optional = true } [dev-dependencies] actix-http = { version = "0.2.0", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.0", features=["ssl"] } -actix-files = { version = "0.1.0-betsa.1" } +actix-files = { version = "0.1.0-beta.4" } rand = "0.6" env_logger = "0.6" serde_derive = "1.0" diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 05a5e5805..6b4ab57b8 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.1.0-beta.4] - 2019-05-12 + +* Update actix-web to beta.4 + ## [0.1.0-beta.1] - 2019-04-20 * Update actix-web to beta.1 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index a0cbba366..c75b3515d 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.1.0-betsa.1" +version = "0.1.0-beta.4" authors = ["Nikolay Kim "] description = "Static files support for actix web." readme = "README.md" @@ -18,7 +18,7 @@ name = "actix_files" path = "src/lib.rs" [dependencies] -actix-web = "1.0.0-beta.1" +actix-web = "1.0.0-beta.4" actix-service = "0.4.0" bitflags = "1" bytes = "0.4" @@ -31,4 +31,4 @@ percent-encoding = "1.0" v_htmlescape = "0.4" [dev-dependencies] -actix-web = { version = "1.0.0-beta.1", features=["ssl"] } +actix-web = { version = "1.0.0-beta.4", features=["ssl"] } diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index f2309d196..6d87b5ef7 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-actors" -version = "1.0.0-alpha.3" +version = "1.0.0-beta.4" authors = ["Nikolay Kim "] description = "Actix actors support for actix web framework." readme = "README.md" @@ -19,7 +19,7 @@ path = "src/lib.rs" [dependencies] actix = "0.8.0" -actix-web = "1.0.0-beta.1" +actix-web = "1.0.0-beta.4" actix-http = "0.2.0" actix-codec = "0.1.2" bytes = "0.4" From 2350a2dc68ad2093fa4b95ff26a47bab86d54868 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 11:43:05 -0700 Subject: [PATCH 12/17] Handle cancellation of uploads #834 #736 --- actix-multipart/CHANGES.md | 6 ++++++ actix-multipart/Cargo.toml | 4 ++-- actix-multipart/src/error.rs | 3 +++ actix-multipart/src/server.rs | 17 ++++++++++++++--- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 9f8fa052a..5ee1d6201 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [0.1.0-beta.4] - 2019-05-12 + +* Handle cancellation of uploads #834 #736 + +* Upgrade to actix-web 1.0.0-beta.4 + ## [0.1.0-beta.1] - 2019-04-21 * Do not support nested multipart diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 6e3f6dc76..e88c642bc 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.1.0-beta.1" +version = "0.1.0-beta.4" authors = ["Nikolay Kim "] description = "Multipart support for actix web framework." readme = "README.md" @@ -18,7 +18,7 @@ name = "actix_multipart" path = "src/lib.rs" [dependencies] -actix-web = "1.0.0-beta.1" +actix-web = "1.0.0-beta.4" actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" diff --git a/actix-multipart/src/error.rs b/actix-multipart/src/error.rs index 995585850..32c740a1a 100644 --- a/actix-multipart/src/error.rs +++ b/actix-multipart/src/error.rs @@ -28,6 +28,9 @@ pub enum MultipartError { /// Payload error #[display(fmt = "{}", _0)] Payload(PayloadError), + /// Not consumed + #[display(fmt = "Multipart stream is not consumed")] + NotConsumed, } /// Return `BadRequest` for `MultipartError` diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index 82b0b5ace..7d746ea2f 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -1,5 +1,5 @@ //! Multipart payload support -use std::cell::{RefCell, UnsafeCell}; +use std::cell::{Cell, RefCell, UnsafeCell}; use std::marker::PhantomData; use std::rc::Rc; use std::{cmp, fmt}; @@ -116,6 +116,8 @@ impl Stream for Multipart { payload.poll_stream()?; } inner.poll(&self.safety) + } else if !self.safety.is_clean() { + Err(MultipartError::NotConsumed) } else { Ok(Async::NotReady) } @@ -415,6 +417,8 @@ impl Stream for Field { } inner.poll(&self.safety) + } else if !self.safety.is_clean() { + return Err(MultipartError::NotConsumed); } else { Ok(Async::NotReady) } @@ -655,6 +659,7 @@ struct Safety { task: Option, level: usize, payload: Rc>, + clean: Rc>, } impl Safety { @@ -663,12 +668,17 @@ impl Safety { Safety { task: None, level: Rc::strong_count(&payload), + clean: Rc::new(Cell::new(true)), payload, } } fn current(&self) -> bool { - Rc::strong_count(&self.payload) == self.level + Rc::strong_count(&self.payload) == self.level && self.clean.get() + } + + fn is_clean(&self) -> bool { + self.clean.get() } } @@ -678,6 +688,7 @@ impl Clone for Safety { Safety { task: Some(current_task()), level: Rc::strong_count(&payload), + clean: self.clean.clone(), payload, } } @@ -687,7 +698,7 @@ impl Drop for Safety { fn drop(&mut self) { // parent task is dead if Rc::strong_count(&self.payload) != self.level { - panic!("Safety get dropped but it is not from top-most task"); + self.clean.set(true); } if let Some(task) = self.task.take() { task.notify() From 86b569e3206a39c29c15d10906669d39a1f9fb79 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 11:56:01 -0700 Subject: [PATCH 13/17] version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 513c9add4..9c670ab16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.0-beta.4" +version = "1.0.0-beta.5" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" From 5a90e33bcccd893de499ff73b4d53c8273570555 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 12 May 2019 12:01:24 -0700 Subject: [PATCH 14/17] update deps --- actix-files/Cargo.toml | 4 ++-- actix-multipart/Cargo.toml | 2 +- actix-session/Cargo.toml | 2 +- actix-web-actors/Cargo.toml | 2 +- actix-web-codegen/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- test-server/Cargo.toml | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index c75b3515d..6b065758d 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -18,7 +18,7 @@ name = "actix_files" path = "src/lib.rs" [dependencies] -actix-web = "1.0.0-beta.4" +actix-web = "1.0.0-beta.5" actix-service = "0.4.0" bitflags = "1" bytes = "0.4" @@ -31,4 +31,4 @@ percent-encoding = "1.0" v_htmlescape = "0.4" [dev-dependencies] -actix-web = { version = "1.0.0-beta.4", features=["ssl"] } +actix-web = { version = "1.0.0-beta.5", features=["ssl"] } diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index e88c642bc..7d19ef9fd 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -18,7 +18,7 @@ name = "actix_multipart" path = "src/lib.rs" [dependencies] -actix-web = "1.0.0-beta.4" +actix-web = "1.0.0-beta.5" actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index f74d23f02..5bebb9a19 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -24,7 +24,7 @@ default = ["cookie-session"] cookie-session = ["actix-web/secure-cookies"] [dependencies] -actix-web = "1.0.0-beta.4" +actix-web = "1.0.0-beta.5" actix-service = "0.4.0" bytes = "0.4" derive_more = "0.14" diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 6d87b5ef7..fe24d4c30 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -19,7 +19,7 @@ path = "src/lib.rs" [dependencies] actix = "0.8.0" -actix-web = "1.0.0-beta.4" +actix-web = "1.0.0-beta.5" actix-http = "0.2.0" actix-codec = "0.1.2" bytes = "0.4" diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 696121834..7ca7912fa 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -16,7 +16,7 @@ quote = "0.6" syn = { version = "0.15", features = ["full", "parsing"] } [dev-dependencies] -actix-web = { version = "1.0.0-alpha.6" } +actix-web = { version = "1.0.0-beta.5" } actix-http = { version = "0.2.0", features=["ssl"] } actix-http-test = { version = "0.2.0", features=["ssl"] } futures = { version = "0.1" } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 20cee12ea..2112185c8 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -58,7 +58,7 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.2.2" -actix-web = { version = "1.0.0-beta.1", features=["ssl"] } +actix-web = { version = "1.0.0-beta.4", features=["ssl"] } actix-http = { version = "0.2.0", features=["ssl"] } actix-http-test = { version = "0.2.0", features=["ssl"] } actix-utils = "0.4.0" diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 13817d506..8567b745e 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -55,5 +55,5 @@ tokio-timer = "0.2" openssl = { version="0.10", optional = true } [dev-dependencies] -actix-web = "1.0.0-beta.1" +actix-web = "1.0.0-beta.4" actix-http = "0.2.0" From 6c3d8b87384c1e375c4b1eb5dc4a27d839942a9d Mon Sep 17 00:00:00 2001 From: Davide Di Carlo Date: Mon, 13 May 2019 05:04:08 +0200 Subject: [PATCH 15/17] Make JsonConfig send (#830) * replace Rc with Arc * add Send trait requirement for Fn in JsonConfig error handler * add Sync trait requirement for Fn in JsonConfig error handler * use associated type inside JsonConfig * fix lint: members in the impl has the same order in the trait * Update CHANGES.md --- CHANGES.md | 6 ++++-- src/types/json.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dedf07585..67a97f143 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +### Changes + +* `JsonConfig` is now `Send + Sync`, this implies that `error_handler` must be `Send + Sync` too. + ## [1.0.0-beta.4] - 2019-05-12 ### Add @@ -9,10 +13,8 @@ ### Changes * `App::configure` take an `FnOnce` instead of `Fn` - * Upgrade actix-net crates - ## [1.0.0-beta.3] - 2019-05-04 ### Added diff --git a/src/types/json.rs b/src/types/json.rs index 73614d87e..4e827942f 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -1,6 +1,6 @@ //! Json extractor/responder -use std::rc::Rc; +use std::sync::Arc; use std::{fmt, ops}; use bytes::BytesMut; @@ -168,15 +168,15 @@ impl FromRequest for Json where T: DeserializeOwned + 'static, { - type Config = JsonConfig; type Error = Error; type Future = Box>; + type Config = JsonConfig; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let req2 = req.clone(); let (limit, err) = req - .app_data::() + .app_data::() .map(|c| (c.limit, c.ehandler.clone())) .unwrap_or((32768, None)); @@ -236,7 +236,7 @@ where #[derive(Clone)] pub struct JsonConfig { limit: usize, - ehandler: Option Error>>, + ehandler: Option Error + Send + Sync>>, } impl JsonConfig { @@ -249,9 +249,9 @@ impl JsonConfig { /// Set custom error handler pub fn error_handler(mut self, f: F) -> Self where - F: Fn(JsonPayloadError, &HttpRequest) -> Error + 'static, + F: Fn(JsonPayloadError, &HttpRequest) -> Error + Send + Sync + 'static, { - self.ehandler = Some(Rc::new(f)); + self.ehandler = Some(Arc::new(f)); self } } From f8af3b86e51796727efd28ad51c3f1f6dc9a51bd Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 14 May 2019 08:48:11 -0700 Subject: [PATCH 16/17] export set_date --- actix-http/src/config.rs | 3 ++- actix-http/src/h1/codec.rs | 7 ++++++- actix-http/src/h1/dispatcher.rs | 9 +++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/actix-http/src/config.rs b/actix-http/src/config.rs index f7d7f5f94..aba50a814 100644 --- a/actix-http/src/config.rs +++ b/actix-http/src/config.rs @@ -158,7 +158,8 @@ impl ServiceConfig { self.0.timer.now() } - pub(crate) fn set_date(&self, dst: &mut BytesMut) { + #[doc(hidden)] + pub fn set_date(&self, dst: &mut BytesMut) { let mut buf: [u8; 39] = [0; 39]; buf[..6].copy_from_slice(b"date: "); buf[6..35].copy_from_slice(&self.0.timer.date().bytes); diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index 1e1e1602f..22c7ed232 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -31,7 +31,7 @@ const AVERAGE_HEADER_SIZE: usize = 30; /// HTTP/1 Codec pub struct Codec { - pub(crate) config: ServiceConfig, + config: ServiceConfig, decoder: decoder::MessageDecoder, payload: Option, version: Version, @@ -104,6 +104,11 @@ impl Codec { MessageType::Payload } } + + #[inline] + pub fn config(&self) -> &ServiceConfig { + &self.config + } } impl Decoder for Codec { diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 758466837..ec717ae07 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -567,7 +567,7 @@ where } if updated && self.ka_timer.is_some() { - if let Some(expire) = self.codec.config.keep_alive_expire() { + if let Some(expire) = self.codec.config().keep_alive_expire() { self.ka_expire = expire; } } @@ -579,7 +579,7 @@ where if self.ka_timer.is_none() { // shutdown timeout if self.flags.contains(Flags::SHUTDOWN) { - if let Some(interval) = self.codec.config.client_disconnect_timer() { + if let Some(interval) = self.codec.config().client_disconnect_timer() { self.ka_timer = Some(Delay::new(interval)); } else { self.flags.insert(Flags::READ_DISCONNECT); @@ -607,7 +607,7 @@ where // start shutdown timer if let Some(deadline) = - self.codec.config.client_disconnect_timer() + self.codec.config().client_disconnect_timer() { if let Some(timer) = self.ka_timer.as_mut() { timer.reset(deadline); @@ -632,7 +632,8 @@ where self.flags.insert(Flags::STARTED | Flags::SHUTDOWN); self.state = State::None; } - } else if let Some(deadline) = self.codec.config.keep_alive_expire() + } else if let Some(deadline) = + self.codec.config().keep_alive_expire() { if let Some(timer) = self.ka_timer.as_mut() { timer.reset(deadline); From bba90d7f2276d0e636ccb04fd7a11ffde30dbe76 Mon Sep 17 00:00:00 2001 From: Davide Di Carlo Date: Tue, 14 May 2019 22:54:30 +0200 Subject: [PATCH 17/17] Query config (#839) * add QueryConfig * expose QueryConfig in web module * fmt * use associated type for QueryConfig * update CHANGES.md --- CHANGES.md | 4 ++ src/error.rs | 24 ++++++++++++ src/types/mod.rs | 2 +- src/types/query.rs | 94 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 120 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 67a97f143..2e4d23ba1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,9 @@ # Changes +### Add + +* `QueryConfig`, similar to `JsonConfig` for customizing error handling of query extractors. + ### Changes * `JsonConfig` is now `Send + Sync`, this implies that `error_handler` must be `Send + Sync` too. diff --git a/src/error.rs b/src/error.rs index e9e225f22..a3062b586 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,6 +6,7 @@ use url::ParseError as UrlParseError; use crate::http::StatusCode; use crate::HttpResponse; +use serde_urlencoded::de; /// Errors which can occur when attempting to generate resource uri. #[derive(Debug, PartialEq, Display, From)] @@ -91,6 +92,23 @@ impl ResponseError for JsonPayloadError { } } +/// A set of errors that can occur during parsing query strings +#[derive(Debug, Display, From)] +pub enum QueryPayloadError { + /// Deserialize error + #[display(fmt = "Query deserialize error: {}", _0)] + Deserialize(de::Error), +} + +/// Return `BadRequest` for `QueryPayloadError` +impl ResponseError for QueryPayloadError { + fn error_response(&self) -> HttpResponse { + match *self { + QueryPayloadError::Deserialize(_) => HttpResponse::new(StatusCode::BAD_REQUEST), + } + } +} + /// Error type returned when reading body as lines. #[derive(From, Display, Debug)] pub enum ReadlinesError { @@ -143,6 +161,12 @@ mod tests { assert_eq!(resp.status(), StatusCode::BAD_REQUEST); } + #[test] + fn test_query_payload_error() { + let resp: HttpResponse = QueryPayloadError::Deserialize(serde_urlencoded::from_str::("bad query").unwrap_err()).error_response(); + assert_eq!(resp.status(), StatusCode::BAD_REQUEST); + } + #[test] fn test_readlines_error() { let resp: HttpResponse = ReadlinesError::LimitOverflow.error_response(); diff --git a/src/types/mod.rs b/src/types/mod.rs index 30ee73091..d01d597b7 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -11,4 +11,4 @@ pub use self::form::{Form, FormConfig}; pub use self::json::{Json, JsonConfig}; pub use self::path::Path; pub use self::payload::{Payload, PayloadConfig}; -pub use self::query::Query; +pub use self::query::{Query, QueryConfig}; diff --git a/src/types/query.rs b/src/types/query.rs index f9f545d61..24225dad2 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -1,5 +1,6 @@ //! Query extractor +use std::sync::Arc; use std::{fmt, ops}; use actix_http::error::Error; @@ -9,6 +10,7 @@ use serde_urlencoded; use crate::dev::Payload; use crate::extract::FromRequest; use crate::request::HttpRequest; +use crate::error::QueryPayloadError; #[derive(PartialEq, Eq, PartialOrd, Ord)] /// Extract typed information from from the request's query. @@ -115,32 +117,103 @@ impl FromRequest for Query where T: de::DeserializeOwned, { - type Config = (); type Error = Error; type Future = Result; + type Config = QueryConfig; #[inline] fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let error_handler = req + .app_data::() + .map(|c| c.ehandler.clone()) + .unwrap_or(None); + serde_urlencoded::from_str::(req.query_string()) .map(|val| Ok(Query(val))) - .unwrap_or_else(|e| { + .unwrap_or_else(move |e| { + let e = QueryPayloadError::Deserialize(e); + log::debug!( "Failed during Query extractor deserialization. \ Request path: {:?}", req.path() ); - Err(e.into()) + + let e = if let Some(error_handler) = error_handler { + (error_handler)(e, req) + } else { + e.into() + }; + + Err(e) }) } } +/// Query extractor configuration +/// +/// ```rust +/// #[macro_use] extern crate serde_derive; +/// use actix_web::{error, web, App, FromRequest, HttpResponse}; +/// +/// #[derive(Deserialize)] +/// struct Info { +/// username: String, +/// } +/// +/// /// deserialize `Info` from request's querystring +/// fn index(info: web::Query) -> String { +/// format!("Welcome {}!", info.username) +/// } +/// +/// fn main() { +/// let app = App::new().service( +/// web::resource("/index.html").data( +/// // change query extractor configuration +/// web::Query::::configure(|cfg| { +/// cfg.error_handler(|err, req| { // <- create custom error response +/// error::InternalError::from_response( +/// err, HttpResponse::Conflict().finish()).into() +/// }) +/// })) +/// .route(web::post().to(index)) +/// ); +/// } +/// ``` +#[derive(Clone)] +pub struct QueryConfig { + ehandler: Option Error + Send + Sync>>, +} + +impl QueryConfig { + /// Set custom error handler + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(QueryPayloadError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.ehandler = Some(Arc::new(f)); + self + } +} + +impl Default for QueryConfig { + fn default() -> Self { + QueryConfig { + ehandler: None, + } + } +} + #[cfg(test)] mod tests { use derive_more::Display; use serde_derive::Deserialize; + use actix_http::http::StatusCode; use super::*; use crate::test::TestRequest; + use crate::error::InternalError; + use crate::HttpResponse; #[derive(Deserialize, Debug, Display)] struct Id { @@ -164,4 +237,19 @@ mod tests { let s = s.into_inner(); assert_eq!(s.id, "test1"); } + + #[test] + fn test_custom_error_responder() { + let req = TestRequest::with_uri("/name/user1/") + .data(QueryConfig::default().error_handler(|e, _| { + let resp = HttpResponse::UnprocessableEntity().finish(); + InternalError::from_response(e, resp).into() + })).to_srv_request(); + + let (req, mut pl) = req.into_parts(); + let query = Query::::from_request(&req, &mut pl); + + assert!(query.is_err()); + assert_eq!(query.unwrap_err().as_response_error().error_response().status(), StatusCode::UNPROCESSABLE_ENTITY); + } }