From ee769832cf5b8dfafbd2543bdb46c949c670f05c Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 12 Jun 2019 11:26:46 +0800 Subject: [PATCH 01/80] get_identity from HttpMessage (#908) * get_identity from HttpMessage * more doc for RequestIdentity --- CHANGES.md | 11 +++++++++++ src/middleware/identity.rs | 34 ++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 07991142e..3e9265258 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,16 @@ # Changes +## [1.0.x] - 2019-xx-xx + +### Add + +* Add `middleware::identity::RequestIdentity` trait to `get_identity` from `HttpMessage`. + +### Changes + +### Fixed + + ## [1.0.0] - 2019-06-05 ### Add diff --git a/src/middleware/identity.rs b/src/middleware/identity.rs index 82ae01542..304df9eb2 100644 --- a/src/middleware/identity.rs +++ b/src/middleware/identity.rs @@ -61,7 +61,10 @@ use crate::cookie::{Cookie, CookieJar, Key, SameSite}; use crate::error::{Error, Result}; use crate::http::header::{self, HeaderValue}; use crate::service::{ServiceRequest, ServiceResponse}; -use crate::{dev::Payload, FromRequest, HttpMessage, HttpRequest}; +use crate::{ + dev::{Extensions, Payload}, + FromRequest, HttpMessage, HttpRequest, +}; /// The extractor type to obtain your identity from a request. /// @@ -96,11 +99,7 @@ impl Identity { /// Return the claimed identity of the user associated request or /// ``None`` if no identity can be found associated with the request. pub fn identity(&self) -> Option { - if let Some(id) = self.0.extensions().get::() { - id.id.clone() - } else { - None - } + Identity::get_identity(&self.0.extensions()) } /// Remember identity. @@ -119,6 +118,14 @@ impl Identity { id.changed = true; } } + + fn get_identity(extensions: &Extensions) -> Option { + if let Some(id) = extensions.get::() { + id.id.clone() + } else { + None + } + } } struct IdentityItem { @@ -126,6 +133,21 @@ struct IdentityItem { changed: bool, } +/// Helper trait that allows to get Identity. +/// It could be used in middleware but identity policy must be set before any other middleware that needs identity +pub trait RequestIdentity { + fn get_identity(&self) -> Option; +} + +impl RequestIdentity for T +where + T: HttpMessage, +{ + fn get_identity(&self) -> Option { + Identity::get_identity(&self.extensions()) + } +} + /// Extractor implementation for Identity type. /// /// ```rust From ff724e239db50210a9913de6e214be214f41befa Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 12 Jun 2019 15:52:48 +0600 Subject: [PATCH 02/80] move identity service separate crate --- CHANGES.md | 6 ++- Cargo.toml | 5 ++- MIGRATION.md | 17 +++++++ actix-identity/CHANGES.md | 5 +++ actix-identity/Cargo.toml | 29 ++++++++++++ actix-identity/LICENSE-APACHE | 1 + actix-identity/LICENSE-MIT | 1 + actix-identity/README.md | 9 ++++ .../identity.rs => actix-identity/src/lib.rs | 45 +++++++++---------- awc/src/lib.rs | 1 + src/lib.rs | 2 +- src/middleware/mod.rs | 3 -- 12 files changed, 92 insertions(+), 32 deletions(-) create mode 100644 actix-identity/CHANGES.md create mode 100644 actix-identity/Cargo.toml create mode 120000 actix-identity/LICENSE-APACHE create mode 120000 actix-identity/LICENSE-MIT create mode 100644 actix-identity/README.md rename src/middleware/identity.rs => actix-identity/src/lib.rs (97%) diff --git a/CHANGES.md b/CHANGES.md index 3e9265258..231cb133f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.x] - 2019-xx-xx +## [1.0.1] - 2019-06-xx ### Add @@ -8,7 +8,9 @@ ### Changes -### Fixed +* Disable default feature `secure-cookies`. + +* Move identity middleware to `actix-identity` crate. ## [1.0.0] - 2019-06-05 diff --git a/Cargo.toml b/Cargo.toml index cd0e94589..08eb7cd9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ members = [ "actix-files", "actix-framed", "actix-session", + "actix-identity", "actix-multipart", "actix-web-actors", "actix-web-codegen", @@ -41,7 +42,7 @@ members = [ ] [features] -default = ["brotli", "flate2-zlib", "secure-cookies", "client", "fail"] +default = ["brotli", "flate2-zlib", "client", "fail"] # http client client = ["awc"] @@ -77,7 +78,7 @@ actix-http = "0.2.3" actix-server = "0.5.1" actix-server-config = "0.1.1" actix-threadpool = "0.1.1" -awc = { version = "0.2.0", optional = true } +awc = { version = "0.2.1", optional = true } bytes = "0.4" derive_more = "0.14" diff --git a/MIGRATION.md b/MIGRATION.md index 1736ee65d..8b5d7dd49 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,3 +1,20 @@ +## 1.0.1 + +* Identity middleware has been moved to `actix-identity` crate + + instead of + + ```rust + use actix_web::middleware::identity::{Identity, CookieIdentityPolicy, IdentityService}; + ``` + + use + + ```rust + use actix_identity::{Identity, CookieIdentityPolicy, IdentityService}; + ``` + + ## 1.0 * Resource registration. 1.0 version uses generalized resource diff --git a/actix-identity/CHANGES.md b/actix-identity/CHANGES.md new file mode 100644 index 000000000..74a204055 --- /dev/null +++ b/actix-identity/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## [0.1.0] - 2019-06-xx + +* Move identity middleware to separate crate diff --git a/actix-identity/Cargo.toml b/actix-identity/Cargo.toml new file mode 100644 index 000000000..3b1b90865 --- /dev/null +++ b/actix-identity/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "actix-identity" +version = "0.1.0" +authors = ["Nikolay Kim "] +description = "Identity service for actix web framework." +readme = "README.md" +keywords = ["http", "web", "framework", "async", "futures"] +homepage = "https://actix.rs" +repository = "https://github.com/actix/actix-web.git" +documentation = "https://docs.rs/actix-identity/" +license = "MIT/Apache-2.0" +edition = "2018" +workspace = ".." + +[lib] +name = "actix_identity" +path = "src/lib.rs" + +[dependencies] +actix-web = { version = "1.0.0", default-features = false, features = ["secure-cookies"] } +actix-service = "0.4.0" +futures = "0.1.25" +serde = "1.0" +serde_json = "1.0" +time = "0.1.42" + +[dev-dependencies] +actix-rt = "0.2.2" +actix-http = "0.2.3" diff --git a/actix-identity/LICENSE-APACHE b/actix-identity/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/actix-identity/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/actix-identity/LICENSE-MIT b/actix-identity/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/actix-identity/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/actix-identity/README.md b/actix-identity/README.md new file mode 100644 index 000000000..60b615c76 --- /dev/null +++ b/actix-identity/README.md @@ -0,0 +1,9 @@ +# Identity service for actix web framework [![Build Status](https://travis-ci.org/actix/actix-web.svg?branch=master)](https://travis-ci.org/actix/actix-web) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) [![crates.io](https://meritbadge.herokuapp.com/actix-identity)](https://crates.io/crates/actix-identity) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Documentation & community resources + +* [User Guide](https://actix.rs/docs/) +* [API Documentation](https://docs.rs/actix-identity/) +* [Chat on gitter](https://gitter.im/actix/actix) +* Cargo package: [actix-session](https://crates.io/crates/actix-identity) +* Minimum supported Rust version: 1.34 or later diff --git a/src/middleware/identity.rs b/actix-identity/src/lib.rs similarity index 97% rename from src/middleware/identity.rs rename to actix-identity/src/lib.rs index 304df9eb2..6664df676 100644 --- a/src/middleware/identity.rs +++ b/actix-identity/src/lib.rs @@ -10,12 +10,11 @@ //! uses cookies as identity storage. //! //! To access current request identity -//! [**Identity**](trait.Identity.html) extractor should be used. +//! [**Identity**](struct.Identity.html) extractor should be used. //! //! ```rust -//! use actix_web::middleware::identity::Identity; -//! use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; //! use actix_web::*; +//! use actix_identity::{Identity, CookieIdentityPolicy, IdentityService}; //! //! fn index(id: Identity) -> String { //! // access request identity @@ -39,7 +38,7 @@ //! fn main() { //! let app = App::new().wrap(IdentityService::new( //! // <- create identity middleware -//! CookieIdentityPolicy::new(&[0; 32]) // <- create cookie session backend +//! CookieIdentityPolicy::new(&[0; 32]) // <- create cookie identity policy //! .name("auth-cookie") //! .secure(false))) //! .service(web::resource("/index.html").to(index)) @@ -57,20 +56,17 @@ use futures::{Future, IntoFuture, Poll}; use serde::{Deserialize, Serialize}; use time::Duration; -use crate::cookie::{Cookie, CookieJar, Key, SameSite}; -use crate::error::{Error, Result}; -use crate::http::header::{self, HeaderValue}; -use crate::service::{ServiceRequest, ServiceResponse}; -use crate::{ - dev::{Extensions, Payload}, - FromRequest, HttpMessage, HttpRequest, -}; +use actix_web::cookie::{Cookie, CookieJar, Key, SameSite}; +use actix_web::dev::{Extensions, Payload, ServiceRequest, ServiceResponse}; +use actix_web::error::{Error, Result}; +use actix_web::http::header::{self, HeaderValue}; +use actix_web::{FromRequest, HttpMessage, HttpRequest}; /// The extractor type to obtain your identity from a request. /// /// ```rust /// use actix_web::*; -/// use actix_web::middleware::identity::Identity; +/// use actix_identity::Identity; /// /// fn index(id: Identity) -> Result { /// // access request identity @@ -134,7 +130,9 @@ struct IdentityItem { } /// Helper trait that allows to get Identity. +/// /// It could be used in middleware but identity policy must be set before any other middleware that needs identity +/// RequestIdentity is implemented both for `ServiceRequest` and `HttpRequest`. pub trait RequestIdentity { fn get_identity(&self) -> Option; } @@ -152,7 +150,7 @@ where /// /// ```rust /// # use actix_web::*; -/// use actix_web::middleware::identity::Identity; +/// use actix_identity::Identity; /// /// fn index(id: Identity) -> String { /// // access request identity @@ -199,7 +197,7 @@ pub trait IdentityPolicy: Sized + 'static { /// /// ```rust /// use actix_web::App; -/// use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; +/// use actix_identity::{CookieIdentityPolicy, IdentityService}; /// /// fn main() { /// let app = App::new().wrap(IdentityService::new( @@ -464,9 +462,8 @@ impl CookieIdentityInner { /// # Example /// /// ```rust -/// # extern crate actix_web; -/// use actix_web::middleware::identity::{CookieIdentityPolicy, IdentityService}; /// use actix_web::App; +/// use actix_identity::{CookieIdentityPolicy, IdentityService}; /// /// fn main() { /// let app = App::new().wrap(IdentityService::new( @@ -612,13 +609,13 @@ impl IdentityPolicy for CookieIdentityPolicy { #[cfg(test)] mod tests { - use super::*; - use crate::http::StatusCode; - use crate::test::{self, TestRequest}; - use crate::{web, App, HttpResponse}; - use std::borrow::Borrow; + use super::*; + use actix_web::http::StatusCode; + use actix_web::test::{self, TestRequest}; + use actix_web::{web, App, Error, HttpResponse}; + const COOKIE_KEY_MASTER: [u8; 32] = [0; 32]; const COOKIE_NAME: &'static str = "actix_auth"; const COOKIE_LOGIN: &'static str = "test"; @@ -739,8 +736,8 @@ mod tests { f: F, ) -> impl actix_service::Service< Request = actix_http::Request, - Response = ServiceResponse, - Error = actix_http::Error, + Response = ServiceResponse, + Error = Error, > { test::init_service( App::new() diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 8c1bc80b6..9fbda8aa8 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -38,6 +38,7 @@ pub mod test; pub mod ws; pub use self::builder::ClientBuilder; +pub use self::connect::BoxedSocket; pub use self::request::ClientRequest; pub use self::response::{ClientResponse, JsonBody, MessageBody}; diff --git a/src/lib.rs b/src/lib.rs index f0bf01bc9..fffbc2f5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,7 +70,7 @@ //! * `ssl` - enables ssl support via `openssl` crate, supports `http/2` //! * `rust-tls` - enables ssl support via `rustls` crate, supports `http/2` //! * `secure-cookies` - enables secure cookies support, includes `ring` crate as -//! dependency (default enabled) +//! dependency //! * `brotli` - enables `brotli` compression support, requires `c` //! compiler (default enabled) //! * `flate2-zlib` - enables `gzip`, `deflate` compression support, requires diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 5266f7c1a..99c6cb457 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -11,6 +11,3 @@ mod normalize; pub use self::defaultheaders::DefaultHeaders; pub use self::logger::Logger; pub use self::normalize::NormalizePath; - -#[cfg(feature = "secure-cookies")] -pub mod identity; From 2ffda29f9bf56cb357cca7480cd29e6e743e59d3 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 12 Jun 2019 16:15:06 +0600 Subject: [PATCH 03/80] Allow to test an app that uses async actors #897 --- CHANGES.md | 2 ++ Cargo.toml | 3 ++- MIGRATION.md | 2 +- src/test.rs | 46 ++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 231cb133f..14400add5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,8 @@ * Move identity middleware to `actix-identity` crate. +* Allow to test an app that uses async actors #897 + ## [1.0.0] - 2019-06-05 diff --git a/Cargo.toml b/Cargo.toml index 08eb7cd9f..871ed7451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,8 @@ rustls = { version = "0.15", optional = true } [dev-dependencies] actix-http = { version = "0.2.3", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.0", features=["ssl"] } -actix-files = { version = "0.1.1" } +actix-files = "0.1.1" +actix = { version = "0.8.3" } rand = "0.6" env_logger = "0.6" serde_derive = "1.0" diff --git a/MIGRATION.md b/MIGRATION.md index 8b5d7dd49..a2591a1d5 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -15,7 +15,7 @@ ``` -## 1.0 +## 1.0.0 * Resource registration. 1.0 version uses generalized resource registration via `.service()` method. diff --git a/src/test.rs b/src/test.rs index 89c1a1268..5ab417bd6 100644 --- a/src/test.rs +++ b/src/test.rs @@ -7,7 +7,7 @@ use actix_http::http::{HttpTryFrom, Method, StatusCode, Uri, Version}; use actix_http::test::TestRequest as HttpTestRequest; use actix_http::{cookie::Cookie, Extensions, Request}; use actix_router::{Path, ResourceDef, Url}; -use actix_rt::Runtime; +use actix_rt::{System, SystemRunner}; use actix_server_config::ServerConfig; use actix_service::{IntoNewService, IntoService, NewService, Service}; use bytes::{Bytes, BytesMut}; @@ -29,14 +29,14 @@ use crate::{Error, HttpRequest, HttpResponse}; thread_local! { static RT: RefCell = { - RefCell::new(Inner(Some(Runtime::new().unwrap()))) + RefCell::new(Inner(Some(System::builder().build()))) }; } -struct Inner(Option); +struct Inner(Option); impl Inner { - fn get_mut(&mut self) -> &mut Runtime { + fn get_mut(&mut self) -> &mut SystemRunner { self.0.as_mut().unwrap() } } @@ -714,4 +714,42 @@ mod tests { let res = block_fn(|| app.call(req)).unwrap(); assert!(res.status().is_success()); } + + #[test] + fn test_actor() { + use actix::Actor; + + struct MyActor; + + struct Num(usize); + impl actix::Message for Num { + type Result = usize; + } + impl actix::Actor for MyActor { + type Context = actix::Context; + } + impl actix::Handler for MyActor { + type Result = usize; + fn handle(&mut self, msg: Num, _: &mut Self::Context) -> Self::Result { + msg.0 + } + } + + let addr = run_on(|| MyActor.start()); + let mut app = init_service(App::new().service( + web::resource("/index.html").to_async(move || { + addr.send(Num(1)).from_err().and_then(|res| { + if res == 1 { + HttpResponse::Ok() + } else { + HttpResponse::BadRequest() + } + }) + }), + )); + + let req = TestRequest::post().uri("/index.html").to_request(); + let res = block_fn(|| app.call(req)).unwrap(); + assert!(res.status().is_success()); + } } From 7450ae37a7dbf87b78094e73955ed1f2590d7de2 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 12 Jun 2019 16:45:05 +0600 Subject: [PATCH 04/80] Re-apply patch from #637 #894 --- CHANGES.md | 2 + actix-identity/Cargo.toml | 1 + src/types/json.rs | 100 ++++++++++++++++++++++++++++++++++---- 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 14400add5..1794a8126 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,8 @@ * Allow to test an app that uses async actors #897 +* Re-apply patch from #637 #894 + ## [1.0.0] - 2019-06-05 diff --git a/actix-identity/Cargo.toml b/actix-identity/Cargo.toml index 3b1b90865..e645275a2 100644 --- a/actix-identity/Cargo.toml +++ b/actix-identity/Cargo.toml @@ -27,3 +27,4 @@ time = "0.1.42" [dev-dependencies] actix-rt = "0.2.2" actix-http = "0.2.3" +bytes = "0.4" \ No newline at end of file diff --git a/src/types/json.rs b/src/types/json.rs index 4e827942f..0789fb612 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -175,15 +175,15 @@ where #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { let req2 = req.clone(); - let (limit, err) = req + let (limit, err, ctype) = req .app_data::() - .map(|c| (c.limit, c.ehandler.clone())) - .unwrap_or((32768, None)); + .map(|c| (c.limit, c.ehandler.clone(), c.content_type.clone())) + .unwrap_or((32768, None, None)); let path = req.path().to_string(); Box::new( - JsonBody::new(req, payload) + JsonBody::new(req, payload, ctype) .limit(limit) .map_err(move |e| { log::debug!( @@ -224,6 +224,9 @@ where /// // change json extractor configuration /// web::Json::::configure(|cfg| { /// cfg.limit(4096) +/// .content_type(|mime| { // <- accept text/plain content type +/// mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN +/// }) /// .error_handler(|err, req| { // <- create custom error response /// error::InternalError::from_response( /// err, HttpResponse::Conflict().finish()).into() @@ -237,6 +240,7 @@ where pub struct JsonConfig { limit: usize, ehandler: Option Error + Send + Sync>>, + content_type: Option bool + Send + Sync>>, } impl JsonConfig { @@ -254,6 +258,15 @@ impl JsonConfig { self.ehandler = Some(Arc::new(f)); self } + + /// Set predicate for allowed content types + pub fn content_type(mut self, predicate: F) -> Self + where + F: Fn(mime::Mime) -> bool + Send + Sync + 'static, + { + self.content_type = Some(Arc::new(predicate)); + self + } } impl Default for JsonConfig { @@ -261,6 +274,7 @@ impl Default for JsonConfig { JsonConfig { limit: 32768, ehandler: None, + content_type: None, } } } @@ -271,6 +285,7 @@ impl Default for JsonConfig { /// Returns error: /// /// * content type is not `application/json` +/// (unless specified in [`JsonConfig`](struct.JsonConfig.html)) /// * content length is greater than 256k pub struct JsonBody { limit: usize, @@ -285,13 +300,20 @@ where U: DeserializeOwned + 'static, { /// Create `JsonBody` for request. - pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self { + pub fn new( + req: &HttpRequest, + payload: &mut Payload, + ctype: Option bool + Send + Sync>>, + ) -> Self { // check content-type let json = if let Ok(Some(mime)) = req.mime_type() { - mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON) + mime.subtype() == mime::JSON + || mime.suffix() == Some(mime::JSON) + || ctype.as_ref().map_or(false, |predicate| predicate(mime)) } else { false }; + if !json { return JsonBody { limit: 262_144, @@ -512,7 +534,7 @@ mod tests { #[test] fn test_json_body() { let (req, mut pl) = TestRequest::default().to_http_parts(); - let json = block_on(JsonBody::::new(&req, &mut pl)); + let json = block_on(JsonBody::::new(&req, &mut pl, None)); assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType)); let (req, mut pl) = TestRequest::default() @@ -521,7 +543,7 @@ mod tests { header::HeaderValue::from_static("application/text"), ) .to_http_parts(); - let json = block_on(JsonBody::::new(&req, &mut pl)); + let json = block_on(JsonBody::::new(&req, &mut pl, None)); assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType)); let (req, mut pl) = TestRequest::default() @@ -535,7 +557,7 @@ mod tests { ) .to_http_parts(); - let json = block_on(JsonBody::::new(&req, &mut pl).limit(100)); + let json = block_on(JsonBody::::new(&req, &mut pl, None).limit(100)); assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow)); let (req, mut pl) = TestRequest::default() @@ -550,7 +572,7 @@ mod tests { .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .to_http_parts(); - let json = block_on(JsonBody::::new(&req, &mut pl)); + let json = block_on(JsonBody::::new(&req, &mut pl, None)); assert_eq!( json.ok().unwrap(), MyObject { @@ -558,4 +580,62 @@ mod tests { } ); } + + #[test] + fn test_with_json_and_bad_content_type() { + let (req, mut pl) = TestRequest::with_header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/plain"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .data(JsonConfig::default().limit(4096)) + .to_http_parts(); + + let s = block_on(Json::::from_request(&req, &mut pl)); + assert!(s.is_err()) + } + + #[test] + fn test_with_json_and_good_custom_content_type() { + let (req, mut pl) = TestRequest::with_header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/plain"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .data(JsonConfig::default().content_type(|mime: mime::Mime| { + mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN + })) + .to_http_parts(); + + let s = block_on(Json::::from_request(&req, &mut pl)); + assert!(s.is_ok()) + } + + #[test] + fn test_with_json_and_bad_custom_content_type() { + let (req, mut pl) = TestRequest::with_header( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/html"), + ) + .header( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + ) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .data(JsonConfig::default().content_type(|mime: mime::Mime| { + mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN + })) + .to_http_parts(); + + let s = block_on(Json::::from_request(&req, &mut pl)); + assert!(s.is_err()) + } } From 36e6f0cb4b96bcec8c8f4dd44ab623cb9866b631 Mon Sep 17 00:00:00 2001 From: Aliaksandr Rahalevich Date: Wed, 12 Jun 2019 03:47:00 -0700 Subject: [PATCH 05/80] add "put" and "sput" methods for test server (#909) --- test-server/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index b8f5934ae..1fbaa6c74 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -255,6 +255,16 @@ impl TestServerRuntime { self.client.head(self.surl(path.as_ref()).as_str()) } + /// Create `PUT` request + pub fn put>(&self, path: S) -> ClientRequest { + self.client.put(self.url(path.as_ref()).as_str()) + } + + /// Create https `PUT` request + pub fn sput>(&self, path: S) -> ClientRequest { + self.client.put(self.surl(path.as_ref()).as_str()) + } + /// Connect to test http server pub fn request>(&self, method: Method, path: S) -> ClientRequest { self.client.request(method, path.as_ref()) From 13e618b128e3f80d9fe031af8dc787116cbe6391 Mon Sep 17 00:00:00 2001 From: Lucas Berezy Date: Wed, 12 Jun 2019 20:49:56 +1000 Subject: [PATCH 06/80] Added initial support for PathConfig, allows setting custom error handler. (#903) --- src/error.rs | 19 +++++++++++ src/types/mod.rs | 2 +- src/types/path.rs | 80 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/error.rs b/src/error.rs index e1cc79845..d8e2b1d00 100644 --- a/src/error.rs +++ b/src/error.rs @@ -92,6 +92,25 @@ impl ResponseError for JsonPayloadError { } } +/// A set of errors that can occur during parsing request paths +#[derive(Debug, Display, From)] +pub enum PathPayloadError { + /// Deserialize error + #[display(fmt = "Path deserialize error: {}", _0)] + Deserialize(de::Error), +} + +/// Return `BadRequest` for `PathPayloadError` +impl ResponseError for PathPayloadError { + fn error_response(&self) -> HttpResponse { + match *self { + PathPayloadError::Deserialize(_) => { + HttpResponse::new(StatusCode::BAD_REQUEST) + } + } + } +} + /// A set of errors that can occur during parsing query strings #[derive(Debug, Display, From)] pub enum QueryPayloadError { diff --git a/src/types/mod.rs b/src/types/mod.rs index d01d597b7..43a189e2c 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -9,6 +9,6 @@ pub(crate) mod readlines; pub use self::form::{Form, FormConfig}; pub use self::json::{Json, JsonConfig}; -pub use self::path::Path; +pub use self::path::{Path, PathConfig}; pub use self::payload::{Payload, PayloadConfig}; pub use self::query::{Query, QueryConfig}; diff --git a/src/types/path.rs b/src/types/path.rs index 5f0a05af9..4f1d3d54a 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -1,5 +1,6 @@ //! Path extractor +use std::sync::Arc; use std::{fmt, ops}; use actix_http::error::{Error, ErrorNotFound}; @@ -7,6 +8,7 @@ use actix_router::PathDeserializer; use serde::de; use crate::dev::Payload; +use crate::error::PathPayloadError; use crate::request::HttpRequest; use crate::FromRequest; @@ -156,15 +158,89 @@ impl FromRequest for Path where T: de::DeserializeOwned, { - type Config = (); type Error = Error; type Future = Result; + type Config = PathConfig; #[inline] fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + let error_handler = req + .app_data::() + .map(|c| c.ehandler.clone()) + .unwrap_or(None); + de::Deserialize::deserialize(PathDeserializer::new(req.match_info())) .map(|inner| Path { inner }) - .map_err(ErrorNotFound) + .map_err(move |e| { + log::debug!( + "Failed during Path extractor deserialization. \ + Request path: {:?}", + req.path() + ); + if let Some(error_handler) = error_handler { + let e = PathPayloadError::Deserialize(e); + (error_handler)(e, req) + } else { + ErrorNotFound(e) + } + }) + } +} + +/// Path extractor configuration +/// +/// ```rust +// #[macro_use] +// extern crate serde_derive; +// use actix_web::web::PathConfig; +// use actix_web::{error, web, App, FromRequest, HttpResponse}; + +// #[derive(Deserialize, Debug)] +// enum Folder { +// #[serde(rename = "inbox")] +// Inbox, +// #[serde(rename = "outbox")] +// Outbox, +// } + +// /// deserialize `Info` from request's path +// fn index(folder: web::Path) -> String { +// format!("Selected folder: {}!", folder) +// } + +// fn main() { +// let app = App::new().service( +// web::resource("messages/{folder}") +// .data(PathConfig::default().error_handler(|err, req| { +// error::InternalError::from_response( +// err, +// HttpResponse::Conflict().finish(), +// ) +// .into() +// })) +// .route(web::post().to(index)), +// ); +// } +/// ``` +#[derive(Clone)] +pub struct PathConfig { + ehandler: Option Error + Send + Sync>>, +} + +impl PathConfig { + /// Set custom error handler + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(PathPayloadError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.ehandler = Some(Arc::new(f)); + self + } +} + +impl Default for PathConfig { + fn default() -> Self { + PathConfig { ehandler: None } } } From e7ba67e1a8ef8fac448357e8aceffc703b401e6b Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 12 Jun 2019 17:02:45 +0600 Subject: [PATCH 07/80] rename PathPayloadError and test for path config --- CHANGES.md | 2 ++ src/error.rs | 10 +++--- src/types/path.rs | 88 ++++++++++++++++++++++++++++------------------- 3 files changed, 59 insertions(+), 41 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1794a8126..5f3d519a7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ ### Add +* Add support for PathConfig #903 + * Add `middleware::identity::RequestIdentity` trait to `get_identity` from `HttpMessage`. ### Changes diff --git a/src/error.rs b/src/error.rs index d8e2b1d00..9f31582ed 100644 --- a/src/error.rs +++ b/src/error.rs @@ -94,19 +94,17 @@ impl ResponseError for JsonPayloadError { /// A set of errors that can occur during parsing request paths #[derive(Debug, Display, From)] -pub enum PathPayloadError { +pub enum PathError { /// Deserialize error #[display(fmt = "Path deserialize error: {}", _0)] Deserialize(de::Error), } -/// Return `BadRequest` for `PathPayloadError` -impl ResponseError for PathPayloadError { +/// Return `BadRequest` for `PathError` +impl ResponseError for PathError { fn error_response(&self) -> HttpResponse { match *self { - PathPayloadError::Deserialize(_) => { - HttpResponse::new(StatusCode::BAD_REQUEST) - } + PathError::Deserialize(_) => HttpResponse::new(StatusCode::BAD_REQUEST), } } } diff --git a/src/types/path.rs b/src/types/path.rs index 4f1d3d54a..2c37a49fb 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -8,7 +8,7 @@ use actix_router::PathDeserializer; use serde::de; use crate::dev::Payload; -use crate::error::PathPayloadError; +use crate::error::PathError; use crate::request::HttpRequest; use crate::FromRequest; @@ -178,7 +178,7 @@ where req.path() ); if let Some(error_handler) = error_handler { - let e = PathPayloadError::Deserialize(e); + let e = PathError::Deserialize(e); (error_handler)(e, req) } else { ErrorNotFound(e) @@ -190,48 +190,48 @@ where /// Path extractor configuration /// /// ```rust -// #[macro_use] -// extern crate serde_derive; -// use actix_web::web::PathConfig; -// use actix_web::{error, web, App, FromRequest, HttpResponse}; - -// #[derive(Deserialize, Debug)] -// enum Folder { -// #[serde(rename = "inbox")] -// Inbox, -// #[serde(rename = "outbox")] -// Outbox, -// } - -// /// deserialize `Info` from request's path -// fn index(folder: web::Path) -> String { -// format!("Selected folder: {}!", folder) -// } - -// fn main() { -// let app = App::new().service( -// web::resource("messages/{folder}") -// .data(PathConfig::default().error_handler(|err, req| { -// error::InternalError::from_response( -// err, -// HttpResponse::Conflict().finish(), -// ) -// .into() -// })) -// .route(web::post().to(index)), -// ); -// } +/// # #[macro_use] +/// # extern crate serde_derive; +/// use actix_web::web::PathConfig; +/// use actix_web::{error, web, App, FromRequest, HttpResponse}; +/// +/// #[derive(Deserialize, Debug)] +/// enum Folder { +/// #[serde(rename = "inbox")] +/// Inbox, +/// #[serde(rename = "outbox")] +/// Outbox, +/// } +/// +/// // deserialize `Info` from request's path +/// fn index(folder: web::Path) -> String { +/// format!("Selected folder: {}!", folder) +/// } +/// +/// fn main() { +/// let app = App::new().service( +/// web::resource("/messages/{folder}") +/// .data(PathConfig::default().error_handler(|err, req| { +/// error::InternalError::from_response( +/// err, +/// HttpResponse::Conflict().finish(), +/// ) +/// .into() +/// })) +/// .route(web::post().to(index)), +/// ); +/// } /// ``` #[derive(Clone)] pub struct PathConfig { - ehandler: Option Error + Send + Sync>>, + ehandler: Option Error + Send + Sync>>, } impl PathConfig { /// Set custom error handler pub fn error_handler(mut self, f: F) -> Self where - F: Fn(PathPayloadError, &HttpRequest) -> Error + Send + Sync + 'static, + F: Fn(PathError, &HttpRequest) -> Error + Send + Sync + 'static, { self.ehandler = Some(Arc::new(f)); self @@ -252,6 +252,7 @@ mod tests { use super::*; use crate::test::{block_on, TestRequest}; + use crate::{error, http, HttpResponse}; #[derive(Deserialize, Debug, Display)] #[display(fmt = "MyStruct({}, {})", key, value)] @@ -347,4 +348,21 @@ mod tests { assert_eq!(res[1], "32".to_owned()); } + #[test] + fn test_custom_err_handler() { + let (req, mut pl) = TestRequest::with_uri("/name/user1/") + .data(PathConfig::default().error_handler(|err, _| { + error::InternalError::from_response( + err, + HttpResponse::Conflict().finish(), + ) + .into() + })) + .to_http_parts(); + + let s = block_on(Path::<(usize,)>::from_request(&req, &mut pl)).unwrap_err(); + let res: HttpResponse = s.into(); + + assert_eq!(res.status(), http::StatusCode::CONFLICT); + } } From 959eef05ae2bb1059162df728c9747cd7998fe4b Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 12 Jun 2019 08:03:27 -0400 Subject: [PATCH 08/80] updated actix-session to support login and logout functionality (renew and purge) --- actix-session/src/lib.rs | 62 ++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index fb316f394..30d71552f 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -98,10 +98,23 @@ impl UserSession for ServiceRequest { } } +#[derive(PartialEq, Clone, Debug)] +pub enum SessionStatus { + Changed, + Purged, + Renewed, + Unchanged +} +impl Default for SessionStatus { + fn default() -> SessionStatus { + SessionStatus::Unchanged + } +} + #[derive(Default)] struct SessionInner { state: HashMap, - changed: bool, + pub status: SessionStatus, } impl Session { @@ -117,7 +130,7 @@ impl Session { /// Set a `value` from the session. pub fn set(&self, key: &str, value: T) -> Result<(), Error> { let mut inner = self.0.borrow_mut(); - inner.changed = true; + inner.status = SessionStatus::Changed; inner .state .insert(key.to_owned(), serde_json::to_string(&value)?); @@ -127,17 +140,30 @@ impl Session { /// Remove value from the session. pub fn remove(&self, key: &str) { let mut inner = self.0.borrow_mut(); - inner.changed = true; + inner.status = SessionStatus::Changed; inner.state.remove(key); } /// Clear the session. pub fn clear(&self) { let mut inner = self.0.borrow_mut(); - inner.changed = true; + inner.status = SessionStatus::Changed; inner.state.clear() } + /// Removes session, both client and server side. + pub fn purge(&self) { + let mut inner = self.0.borrow_mut(); + inner.status = SessionStatus::Purged; + inner.state.clear(); + } + + /// Renews the session key, assigning existing session state to new key. + pub fn renew(&self) { + let mut inner = self.0.borrow_mut(); + inner.status = SessionStatus::Renewed; + } + pub fn set_session( data: impl Iterator, req: &mut ServiceRequest, @@ -149,7 +175,7 @@ impl Session { pub fn get_changes( res: &mut ServiceResponse, - ) -> Option> { + ) -> (SessionStatus, Option>) { if let Some(s_impl) = res .request() .extensions() @@ -157,9 +183,9 @@ impl Session { { let state = std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new()); - Some(state.into_iter()) + (s_impl.borrow().status.clone(), Some(state.into_iter())) } else { - None + (SessionStatus::Unchanged, None) } } @@ -224,7 +250,8 @@ mod tests { session.remove("key"); let mut res = req.into_response(HttpResponse::Ok().finish()); - let changes: Vec<_> = Session::get_changes(&mut res).unwrap().collect(); + let (_status, state) = Session::get_changes(&mut res); + let changes: Vec<_> = state.unwrap().collect(); assert_eq!(changes, [("key2".to_string(), "\"value2\"".to_string())]); } @@ -241,4 +268,23 @@ mod tests { let res = session.get::("key").unwrap(); assert_eq!(res, Some("value".to_string())); } + + #[test] + fn purge_session() { + let mut req = test::TestRequest::default().to_srv_request(); + let session = Session::get_session(&mut *req.extensions_mut()); + assert_eq!(session.0.borrow().status, SessionStatus::Unchanged); + session.purge(); + assert_eq!(session.0.borrow().status, SessionStatus::Purged); + } + + + #[test] + fn renew_session() { + let mut req = test::TestRequest::default().to_srv_request(); + let session = Session::get_session(&mut *req.extensions_mut()); + assert_eq!(session.0.borrow().status, SessionStatus::Unchanged); + session.renew(); + assert_eq!(session.0.borrow().status, SessionStatus::Renewed); + } } From 65732197b8f1e3abdf8847edcbe24ca70f8a21b5 Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 12 Jun 2019 10:11:38 -0400 Subject: [PATCH 09/80] modified so as to consider unanticipated state changes --- actix-session/src/lib.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index 30d71552f..aaf0ab02f 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -130,25 +130,31 @@ impl Session { /// Set a `value` from the session. pub fn set(&self, key: &str, value: T) -> Result<(), Error> { let mut inner = self.0.borrow_mut(); - inner.status = SessionStatus::Changed; - inner - .state - .insert(key.to_owned(), serde_json::to_string(&value)?); + if inner.status != SessionStatus::Purged { + inner.status = SessionStatus::Changed; + inner + .state + .insert(key.to_owned(), serde_json::to_string(&value)?); + } Ok(()) } /// Remove value from the session. pub fn remove(&self, key: &str) { let mut inner = self.0.borrow_mut(); - inner.status = SessionStatus::Changed; - inner.state.remove(key); + if inner.status != SessionStatus::Purged { + inner.status = SessionStatus::Changed; + inner.state.remove(key); + } } /// Clear the session. pub fn clear(&self) { let mut inner = self.0.borrow_mut(); - inner.status = SessionStatus::Changed; - inner.state.clear() + if inner.status != SessionStatus::Purged { + inner.status = SessionStatus::Changed; + inner.state.clear() + } } /// Removes session, both client and server side. @@ -161,7 +167,9 @@ impl Session { /// Renews the session key, assigning existing session state to new key. pub fn renew(&self) { let mut inner = self.0.borrow_mut(); - inner.status = SessionStatus::Renewed; + if inner.status != SessionStatus::Purged { + inner.status = SessionStatus::Renewed; + } } pub fn set_session( From c8118e841135594ef46d2f3662872d40378d3b3d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 12 Jun 2019 20:12:15 +0600 Subject: [PATCH 10/80] fix path doc tests --- src/types/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/path.rs b/src/types/path.rs index 2c37a49fb..2a6ce2879 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -205,7 +205,7 @@ where /// /// // deserialize `Info` from request's path /// fn index(folder: web::Path) -> String { -/// format!("Selected folder: {}!", folder) +/// format!("Selected folder: {:?}!", folder) /// } /// /// fn main() { From bf48798bcec35580c408d190b50cc2e42526f1a2 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 13 Jun 2019 15:27:21 +0600 Subject: [PATCH 11/80] Content-Length is 0 for NamedFile HEAD request #914 --- actix-files/CHANGES.md | 6 ++++-- actix-files/src/lib.rs | 23 +++++++++++++++++++++++ actix-files/src/named.rs | 26 +++++++++++--------------- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 862a59442..e79d80967 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,8 +1,10 @@ # Changes -## [0.1.2] - 2019-06-06 +## [0.1.2] - 2019-06-13 -* Fix ring dependency from actix-web default features for #741. +* Content-Length is 0 for NamedFile HEAD request #914 + +* Fix ring dependency from actix-web default features for #741 ## [0.1.1] - 2019-06-01 diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 301d9d81d..9f526f3f0 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -926,6 +926,29 @@ mod tests { assert_eq!(bytes.freeze(), data); } + #[test] + fn test_head_content_length_headers() { + let mut srv = test::init_service( + App::new().service(Files::new("test", ".").index_file("tests/test.binary")), + ); + + // Valid range header + let request = TestRequest::default() + .method(Method::HEAD) + .uri("/t%65st/tests/test.binary") + .to_request(); + let response = test::call_service(&mut srv, request); + + let contentlength = response + .headers() + .get(header::CONTENT_LENGTH) + .unwrap() + .to_str() + .unwrap(); + + assert_eq!(contentlength, "100"); + } + #[test] fn test_static_files_with_spaces() { let mut srv = test::init_service( diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 29e9eee41..3ece7c212 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -422,20 +422,16 @@ impl Responder for NamedFile { return Ok(resp.status(StatusCode::NOT_MODIFIED).finish()); } - if *req.method() == Method::HEAD { - Ok(resp.finish()) - } else { - let reader = ChunkedReadFile { - offset, - size: length, - file: Some(self.file), - fut: None, - counter: 0, - }; - if offset != 0 || length != self.md.len() { - return Ok(resp.status(StatusCode::PARTIAL_CONTENT).streaming(reader)); - }; - Ok(resp.body(SizedStream::new(length, reader))) - } + let reader = ChunkedReadFile { + offset, + size: length, + file: Some(self.file), + fut: None, + counter: 0, + }; + if offset != 0 || length != self.md.len() { + return Ok(resp.status(StatusCode::PARTIAL_CONTENT).streaming(reader)); + }; + Ok(resp.body(SizedStream::new(length, reader))) } } From ca4ed0932e880bdd44dd971a5248a5867679305e Mon Sep 17 00:00:00 2001 From: dowwie Date: Thu, 13 Jun 2019 08:59:59 -0400 Subject: [PATCH 12/80] made Session::get_session public --- actix-session/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index aaf0ab02f..beee6b07e 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -197,7 +197,7 @@ impl Session { } } - fn get_session(extensions: &mut Extensions) -> Session { + pub fn get_session(extensions: &mut Extensions) -> Session { if let Some(s_impl) = extensions.get::>>() { return Session(Rc::clone(&s_impl)); } From 32a66a99bf71d621e55f4bc83100ba3d56f2912a Mon Sep 17 00:00:00 2001 From: dowwie Date: Thu, 13 Jun 2019 09:19:03 -0400 Subject: [PATCH 13/80] reverting change to get_session due to side effects --- actix-session/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index beee6b07e..aaf0ab02f 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -197,7 +197,7 @@ impl Session { } } - pub fn get_session(extensions: &mut Extensions) -> Session { + fn get_session(extensions: &mut Extensions) -> Session { if let Some(s_impl) = extensions.get::>>() { return Session(Rc::clone(&s_impl)); } From cd323f2ff1da9129e0d0ba63131f85f6e433cbb2 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 15 Jun 2019 09:34:16 +0600 Subject: [PATCH 14/80] Move cors middleware to actix-cors crate --- CHANGES.md | 4 ++- Cargo.toml | 3 ++ actix-cors/CHANGES.md | 5 ++++ actix-cors/Cargo.toml | 28 +++++++++++++++++++ actix-cors/LICENSE-APACHE | 1 + actix-cors/LICENSE-MIT | 1 + actix-cors/README.md | 9 ++++++ .../cors.rs => actix-cors/src/lib.rs | 20 ++++++------- src/middleware/mod.rs | 4 ++- 9 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 actix-cors/CHANGES.md create mode 100644 actix-cors/Cargo.toml create mode 120000 actix-cors/LICENSE-APACHE create mode 120000 actix-cors/LICENSE-MIT create mode 100644 actix-cors/README.md rename src/middleware/cors.rs => actix-cors/src/lib.rs (98%) diff --git a/CHANGES.md b/CHANGES.md index 5f3d519a7..1f34b7977 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,10 +10,12 @@ ### Changes -* Disable default feature `secure-cookies`. +* Move cors middleware to `actix-cors` crate. * Move identity middleware to `actix-identity` crate. +* Disable default feature `secure-cookies`. + * Allow to test an app that uses async actors #897 * Re-apply patch from #637 #894 diff --git a/Cargo.toml b/Cargo.toml index 871ed7451..56a42bf97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ members = [ ".", "awc", "actix-http", + "actix-cors", "actix-files", "actix-framed", "actix-session", @@ -80,6 +81,8 @@ actix-server-config = "0.1.1" actix-threadpool = "0.1.1" awc = { version = "0.2.1", optional = true } +# actix-cors = "0.1."{ path="./actix-cors" } + bytes = "0.4" derive_more = "0.14" encoding = "0.2" diff --git a/actix-cors/CHANGES.md b/actix-cors/CHANGES.md new file mode 100644 index 000000000..1e842f37e --- /dev/null +++ b/actix-cors/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## [0.1.0] - 2019-06-15 + +* Move cors middleware to separate crate diff --git a/actix-cors/Cargo.toml b/actix-cors/Cargo.toml new file mode 100644 index 000000000..a62cc664d --- /dev/null +++ b/actix-cors/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "actix-cors" +version = "0.1.0" +authors = ["Nikolay Kim "] +description = "Cross-origin resource sharing (CORS) for Actix applications." +readme = "README.md" +keywords = ["http", "web", "framework", "async", "futures"] +homepage = "https://actix.rs" +repository = "https://github.com/actix/actix-web.git" +documentation = "https://docs.rs/actix-cors/" +license = "MIT/Apache-2.0" +edition = "2018" +workspace = ".." + +[lib] +name = "actix_cors" +path = "src/lib.rs" + +[dependencies] +actix-web = "1.0.0" +actix-service = "0.4.0" +derive_more = "0.14.1" +futures = "0.1.25" + +[dev-dependencies] +actix-rt = "0.2.2" +#actix-http = "0.2.3" +#bytes = "0.4" \ No newline at end of file diff --git a/actix-cors/LICENSE-APACHE b/actix-cors/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/actix-cors/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/actix-cors/LICENSE-MIT b/actix-cors/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/actix-cors/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/actix-cors/README.md b/actix-cors/README.md new file mode 100644 index 000000000..60b615c76 --- /dev/null +++ b/actix-cors/README.md @@ -0,0 +1,9 @@ +# Identity service for actix web framework [![Build Status](https://travis-ci.org/actix/actix-web.svg?branch=master)](https://travis-ci.org/actix/actix-web) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) [![crates.io](https://meritbadge.herokuapp.com/actix-identity)](https://crates.io/crates/actix-identity) [![Join the chat at https://gitter.im/actix/actix](https://badges.gitter.im/actix/actix.svg)](https://gitter.im/actix/actix?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Documentation & community resources + +* [User Guide](https://actix.rs/docs/) +* [API Documentation](https://docs.rs/actix-identity/) +* [Chat on gitter](https://gitter.im/actix/actix) +* Cargo package: [actix-session](https://crates.io/crates/actix-identity) +* Minimum supported Rust version: 1.34 or later diff --git a/src/middleware/cors.rs b/actix-cors/src/lib.rs similarity index 98% rename from src/middleware/cors.rs rename to actix-cors/src/lib.rs index f731f49bd..5d0d013e3 100644 --- a/src/middleware/cors.rs +++ b/actix-cors/src/lib.rs @@ -7,7 +7,7 @@ //! # Example //! //! ```rust -//! use actix_web::middleware::cors::Cors; +//! use actix_cors::Cors; //! use actix_web::{http, web, App, HttpRequest, HttpResponse, HttpServer}; //! //! fn index(req: HttpRequest) -> &'static str { @@ -42,17 +42,15 @@ use std::iter::FromIterator; use std::rc::Rc; use actix_service::{IntoTransform, Service, Transform}; +use actix_web::dev::{RequestHead, ServiceRequest, ServiceResponse}; +use actix_web::error::{Error, ResponseError, Result}; +use actix_web::http::header::{self, HeaderName, HeaderValue}; +use actix_web::http::{self, HttpTryFrom, Method, StatusCode, Uri}; +use actix_web::HttpResponse; use derive_more::Display; use futures::future::{ok, Either, Future, FutureResult}; use futures::Poll; -use crate::dev::RequestHead; -use crate::error::{Error, ResponseError, Result}; -use crate::http::header::{self, HeaderName, HeaderValue}; -use crate::http::{self, HttpTryFrom, Method, StatusCode, Uri}; -use crate::service::{ServiceRequest, ServiceResponse}; -use crate::HttpResponse; - /// A set of errors that can occur during processing CORS #[derive(Debug, Display)] pub enum CorsError { @@ -152,11 +150,11 @@ impl AllOrSome { /// # Example /// /// ```rust +/// use actix_cors::Cors; /// use actix_web::http::header; -/// use actix_web::middleware::cors; /// /// # fn main() { -/// let cors = cors::Cors::new() +/// let cors = Cors::new() /// .allowed_origin("https://www.rust-lang.org/") /// .allowed_methods(vec!["GET", "POST"]) /// .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT]) @@ -806,9 +804,9 @@ where #[cfg(test)] mod tests { use actix_service::{IntoService, Transform}; + use actix_web::test::{self, block_on, TestRequest}; use super::*; - use crate::test::{self, block_on, TestRequest}; impl Cors { fn finish(self, srv: F) -> CorsMiddleware diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 99c6cb457..f0b90e773 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -2,7 +2,6 @@ mod compress; pub use self::compress::{BodyEncoding, Compress}; -pub mod cors; mod defaultheaders; pub mod errhandlers; mod logger; @@ -11,3 +10,6 @@ mod normalize; pub use self::defaultheaders::DefaultHeaders; pub use self::logger::Logger; pub use self::normalize::NormalizePath; + +// +// use actix_cors as cors; From d7ec241fd081c625551ef07a1039b322935b5821 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 15 Jun 2019 21:47:06 +0600 Subject: [PATCH 15/80] re-export identity and cors middleware --- Cargo.toml | 16 ++++++++++------ actix-cors/Cargo.toml | 9 ++------- src/app.rs | 3 +-- src/middleware/mod.rs | 15 +++++++++++++-- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 56a42bf97..8531a93ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ members = [ ] [features] -default = ["brotli", "flate2-zlib", "client", "fail"] +default = ["brotli", "flate2-zlib", "client", "fail", "depracated"] # http client client = ["awc"] @@ -68,6 +68,9 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] # rustls rust-tls = ["rustls", "actix-server/rust-tls"] +# deprecated middlewares +depracated = ["actix-cors", "actix-identity"] + [dependencies] actix-codec = "0.1.2" actix-service = "0.4.0" @@ -81,13 +84,15 @@ actix-server-config = "0.1.1" actix-threadpool = "0.1.1" awc = { version = "0.2.1", optional = true } -# actix-cors = "0.1."{ path="./actix-cors" } +# deprecated middlewares +actix-cors = { version = "0.1.0", optional = true } +actix-identity = { version = "0.1.0", optional = true } bytes = "0.4" derive_more = "0.14" encoding = "0.2" futures = "0.1.25" -hashbrown = "0.3.0" +hashbrown = "0.3.1" log = "0.4" mime = "0.3" net2 = "0.2.33" @@ -104,10 +109,9 @@ openssl = { version="0.10", optional = true } rustls = { version = "0.15", optional = true } [dev-dependencies] +actix = { version = "0.8.3" } actix-http = { version = "0.2.3", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.0", features=["ssl"] } -actix-files = "0.1.1" -actix = { version = "0.8.3" } rand = "0.6" env_logger = "0.6" serde_derive = "1.0" @@ -121,7 +125,7 @@ opt-level = 3 codegen-units = 1 [patch.crates-io] -actix-web = { path = "." } +# actix-web = { path = "." } actix-http = { path = "actix-http" } actix-http-test = { path = "test-server" } actix-web-codegen = { path = "actix-web-codegen" } diff --git a/actix-cors/Cargo.toml b/actix-cors/Cargo.toml index a62cc664d..98ed67a2a 100644 --- a/actix-cors/Cargo.toml +++ b/actix-cors/Cargo.toml @@ -4,13 +4,13 @@ version = "0.1.0" authors = ["Nikolay Kim "] description = "Cross-origin resource sharing (CORS) for Actix applications." readme = "README.md" -keywords = ["http", "web", "framework", "async", "futures"] +keywords = ["web", "framework"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" documentation = "https://docs.rs/actix-cors/" license = "MIT/Apache-2.0" edition = "2018" -workspace = ".." +#workspace = ".." [lib] name = "actix_cors" @@ -21,8 +21,3 @@ actix-web = "1.0.0" actix-service = "0.4.0" derive_more = "0.14.1" futures = "0.1.25" - -[dev-dependencies] -actix-rt = "0.2.2" -#actix-http = "0.2.3" -#bytes = "0.4" \ No newline at end of file diff --git a/src/app.rs b/src/app.rs index 4f8b283e1..897b36459 100644 --- a/src/app.rs +++ b/src/app.rs @@ -225,7 +225,6 @@ where /// It is also possible to use static files as default service. /// /// ```rust - /// use actix_files::Files; /// use actix_web::{web, App, HttpResponse}; /// /// fn main() { @@ -233,7 +232,7 @@ where /// .service( /// web::resource("/index.html").to(|| HttpResponse::Ok())) /// .default_service( - /// Files::new("", "./static") + /// web::to(|| HttpResponse::NotFound()) /// ); /// } /// ``` diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index f0b90e773..c2001e00f 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -11,5 +11,16 @@ pub use self::defaultheaders::DefaultHeaders; pub use self::logger::Logger; pub use self::normalize::NormalizePath; -// -// use actix_cors as cors; +#[cfg(feature = "deprecated")] +#[deprecated( + since = "1.0.1", + note = "please use `actix_cors` instead. support will be removed in actix-web 1.0.2" +)] +pub use actix_cors as cors; + +#[cfg(feature = "deprecated")] +#[deprecated( + since = "1.0.1", + note = "please use `actix_identity` instead. support will be removed in actix-web 1.0.2" +)] +pub use actix_identity as identity; From d293ae2a691fb6f9b9981346643e56932114d2da Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 15 Jun 2019 22:12:20 +0600 Subject: [PATCH 16/80] fix nested resource map registration #915 --- CHANGES.md | 4 ++++ src/rmap.rs | 3 ++- src/scope.rs | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1f34b7977..87729eb6a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,10 @@ * Re-apply patch from #637 #894 +### Fixed + +* HttpRequest::url_for is broken with nested scopes #915 + ## [1.0.0] - 2019-06-05 diff --git a/src/rmap.rs b/src/rmap.rs index 6a543b75c..cad62dca0 100644 --- a/src/rmap.rs +++ b/src/rmap.rs @@ -38,7 +38,8 @@ impl ResourceMap { pub(crate) fn finish(&self, current: Rc) { for (_, nested) in &self.patterns { if let Some(ref nested) = nested { - *nested.parent.borrow_mut() = Some(current.clone()) + *nested.parent.borrow_mut() = Some(current.clone()); + nested.finish(nested.clone()); } } } diff --git a/src/scope.rs b/src/scope.rs index ad97fcb62..400da668d 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -1135,4 +1135,24 @@ mod tests { let body = read_body(resp); assert_eq!(body, &b"https://youtube.com/watch/xxxxxx"[..]); } + + #[test] + fn test_url_for_nested() { + let mut srv = init_service(App::new().service(web::scope("/a").service( + web::scope("/b").service(web::resource("/c/{stuff}").name("c").route( + web::get().to(|req: HttpRequest| { + HttpResponse::Ok() + .body(format!("{}", req.url_for("c", &["12345"]).unwrap())) + }), + )), + ))); + let req = TestRequest::with_uri("/a/b/c/test").to_request(); + let resp = call_service(&mut srv, req); + assert_eq!(resp.status(), StatusCode::OK); + let body = read_body(resp); + assert_eq!( + body, + Bytes::from_static(b"http://localhost:8080/a/b/c/12345") + ); + } } From eaa371db8b6a2d1637c4cc31855fe029b576b6a6 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 15 Jun 2019 22:20:46 +0600 Subject: [PATCH 17/80] update migration --- MIGRATION.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index a2591a1d5..5273a0135 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,5 +1,19 @@ ## 1.0.1 +* Cors middleware has been moved to `actix-cors` crate + + instead of + + ```rust + use actix_web::middleware::cors::Cors; + ``` + + use + + ```rust + use actix_cors::Cors; + ``` + * Identity middleware has been moved to `actix-identity` crate instead of From 7c0f57084559ce9c97fb09a49047e8c9059551f8 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 16 Jun 2019 21:54:17 +0600 Subject: [PATCH 18/80] Do not compress NoContent (204) responses #918 --- Cargo.toml | 4 ++-- actix-http/CHANGES.md | 7 +++++++ actix-http/Cargo.toml | 4 ++-- actix-http/src/encoding/encoder.rs | 2 ++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8531a93ac..a18635684 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,10 +89,10 @@ actix-cors = { version = "0.1.0", optional = true } actix-identity = { version = "0.1.0", optional = true } bytes = "0.4" -derive_more = "0.14" +derive_more = "0.15.0" encoding = "0.2" futures = "0.1.25" -hashbrown = "0.3.1" +hashbrown = "0.5.0" log = "0.4" mime = "0.3" net2 = "0.2.33" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index d0c75da76..93c352898 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.2.4] - 2019-06-16 + +### Fixed + +* Do not compress NoContent (204) responses #918 + + ## [0.2.3] - 2019-06-02 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 1847a5ba2..4411bdf6d 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -56,11 +56,11 @@ bitflags = "1.0" bytes = "0.4" byteorder = "1.2" copyless = "0.1.2" -derive_more = "0.14" +derive_more = "0.15.0" either = "1.5.2" encoding = "0.2" futures = "0.1.25" -hashbrown = "0.3.0" +hashbrown = "0.5.0" h2 = "0.1.16" http = "0.1.17" httparse = "1.3" diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index aabce292a..d793eb4c7 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -33,6 +33,7 @@ impl Encoder { ) -> ResponseBody> { let can_encode = !(head.headers().contains_key(&CONTENT_ENCODING) || head.status == StatusCode::SWITCHING_PROTOCOLS + || head.status == StatusCode::NO_CONTENT || encoding == ContentEncoding::Identity || encoding == ContentEncoding::Auto); @@ -122,6 +123,7 @@ impl MessageBody for Encoder { Async::NotReady => return Ok(Async::NotReady), Async::Ready(Some(chunk)) => { if let Some(mut encoder) = self.encoder.take() { + self.encoded += chunk.len(); if chunk.len() < INPLACE { encoder.write(&chunk)?; let chunk = encoder.take(); From d2b6502c7a743bed3f10eea269aa4031930a1972 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 16 Jun 2019 21:59:22 +0600 Subject: [PATCH 19/80] prepare actix-http release --- actix-http/Cargo.toml | 2 +- actix-http/src/encoding/encoder.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 4411bdf6d..2da410130 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.2.3" +version = "0.2.4" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index d793eb4c7..fa95d798a 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -123,7 +123,6 @@ impl MessageBody for Encoder { Async::NotReady => return Ok(Async::NotReady), Async::Ready(Some(chunk)) => { if let Some(mut encoder) = self.encoder.take() { - self.encoded += chunk.len(); if chunk.len() < INPLACE { encoder.write(&chunk)?; let chunk = encoder.take(); From 686e5f1595b4a740d695d94c23cd5c8bb3b35872 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sun, 16 Jun 2019 22:10:22 +0600 Subject: [PATCH 20/80] update deps --- Cargo.toml | 6 +++--- actix-files/Cargo.toml | 6 +++--- actix-multipart/Cargo.toml | 6 +++--- actix-session/Cargo.toml | 8 ++++---- actix-web-actors/Cargo.toml | 4 ++-- actix-web-codegen/Cargo.toml | 4 ++-- awc/Cargo.toml | 10 +++++----- test-server/CHANGES.md | 4 ++++ test-server/Cargo.toml | 8 ++++---- 9 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a18635684..a4c37cfa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,12 +73,12 @@ depracated = ["actix-cors", "actix-identity"] [dependencies] actix-codec = "0.1.2" -actix-service = "0.4.0" +actix-service = "0.4.1" actix-utils = "0.4.1" actix-router = "0.1.5" actix-rt = "0.2.2" actix-web-codegen = "0.1.2" -actix-http = "0.2.3" +actix-http = "0.2.4" actix-server = "0.5.1" actix-server-config = "0.1.1" actix-threadpool = "0.1.1" @@ -110,7 +110,7 @@ rustls = { version = "0.15", optional = true } [dev-dependencies] actix = { version = "0.8.3" } -actix-http = { version = "0.2.3", features=["ssl", "brotli", "flate2-zlib"] } +actix-http = { version = "0.2.4", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.0", features=["ssl"] } rand = "0.6" env_logger = "0.6" diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index b1428a22b..9df93834a 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -19,12 +19,12 @@ path = "src/lib.rs" [dependencies] actix-web = { version = "1.0.0", default-features = false } -actix-http = "0.2.3" -actix-service = "0.4.0" +actix-http = "0.2.4" +actix-service = "0.4.1" bitflags = "1" bytes = "0.4" futures = "0.1.25" -derive_more = "0.14" +derive_more = "0.15.0" log = "0.4" mime = "0.3" mime_guess = "2.0.0-alpha" diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index d377be1f4..b26681e25 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -19,9 +19,9 @@ path = "src/lib.rs" [dependencies] actix-web = { version = "1.0.0", default-features = false } -actix-service = "0.4.0" +actix-service = "0.4.1" bytes = "0.4" -derive_more = "0.14" +derive_more = "0.15.0" httparse = "1.3" futures = "0.1.25" log = "0.4" @@ -31,4 +31,4 @@ twoway = "0.2" [dev-dependencies] actix-rt = "0.2.2" -actix-http = "0.2.2" \ No newline at end of file +actix-http = "0.2.4" \ No newline at end of file diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index 1101ceffc..4c1d66570 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -24,12 +24,12 @@ default = ["cookie-session"] cookie-session = ["actix-web/secure-cookies"] [dependencies] -actix-web = "1.0.0-rc" -actix-service = "0.4.0" +actix-web = "1.0.0" +actix-service = "0.4.1" bytes = "0.4" -derive_more = "0.14" +derive_more = "0.15.0" futures = "0.1.25" -hashbrown = "0.3.0" +hashbrown = "0.5.0" serde = "1.0" serde_json = "1.0" time = "0.1.42" diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 565b53a57..90d0a00f9 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -19,8 +19,8 @@ path = "src/lib.rs" [dependencies] actix = "0.8.3" -actix-web = "1.0.0-rc" -actix-http = "0.2.2" +actix-web = "1.0.0" +actix-http = "0.2.4" actix-codec = "0.1.2" bytes = "0.4" futures = "0.1.25" diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 23e9a432f..29abb4897 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -16,7 +16,7 @@ quote = "0.6.12" syn = { version = "0.15.34", features = ["full", "parsing", "extra-traits"] } [dev-dependencies] -actix-web = { version = "1.0.0-rc" } -actix-http = { version = "0.2.2", features=["ssl"] } +actix-web = { version = "1.0.0" } +actix-http = { version = "0.2.4", 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 cad52033e..d0629f4fa 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -40,11 +40,11 @@ flate2-rust = ["actix-http/flate2-rust"] [dependencies] actix-codec = "0.1.2" -actix-service = "0.4.0" -actix-http = "0.2.3" +actix-service = "0.4.1" +actix-http = "0.2.4" base64 = "0.10.1" bytes = "0.4" -derive_more = "0.14" +derive_more = "0.15.0" futures = "0.1.25" log =" 0.4" mime = "0.3" @@ -58,8 +58,8 @@ openssl = { version="0.10", optional = true } [dev-dependencies] actix-rt = "0.2.2" -actix-web = { version = "1.0.0-rc", features=["ssl"] } -actix-http = { version = "0.2.3", features=["ssl"] } +actix-web = { version = "1.0.0", features=["ssl"] } +actix-http = { version = "0.2.4", features=["ssl"] } actix-http-test = { version = "0.2.0", features=["ssl"] } actix-utils = "0.4.1" actix-server = { version = "0.5.1", features=["ssl"] } diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index a31937909..e7292c0ec 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.2.2] - 2019-06-16 + +* Add .put() and .sput() methods + ## [0.2.1] - 2019-06-05 * Add license files diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index a8f4425ba..4231b17bf 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "0.2.1" +version = "0.2.2" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -32,7 +32,7 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] [dependencies] actix-codec = "0.1.2" actix-rt = "0.2.2" -actix-service = "0.4.0" +actix-service = "0.4.1" actix-server = "0.5.1" actix-utils = "0.4.1" awc = "0.2.1" @@ -55,5 +55,5 @@ tokio-timer = "0.2" openssl = { version="0.10", optional = true } [dev-dependencies] -actix-web = "1.0.0-rc" -actix-http = "0.2.3" +actix-web = "1.0.0" +actix-http = "0.2.4" From acda1c075a000a8b94f04b25b8d3668954d7938e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 17 Jun 2019 12:23:30 +0600 Subject: [PATCH 21/80] prepare actix-web release --- CHANGES.md | 2 +- Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 87729eb6a..385264139 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.1] - 2019-06-xx +## [1.0.1] - 2019-06-17 ### Add diff --git a/Cargo.toml b/Cargo.toml index a4c37cfa4..d8a143d63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.0" +version = "1.0.1" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -111,7 +111,7 @@ rustls = { version = "0.15", optional = true } [dev-dependencies] actix = { version = "0.8.3" } actix-http = { version = "0.2.4", features=["ssl", "brotli", "flate2-zlib"] } -actix-http-test = { version = "0.2.0", features=["ssl"] } +actix-http-test = { version = "0.2.2", features=["ssl"] } rand = "0.6" env_logger = "0.6" serde_derive = "1.0" From 546a8a58db0e9f985310ae1ed56878a089f7ba09 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 17 Jun 2019 12:33:00 +0600 Subject: [PATCH 22/80] remove cors and identity middlewares --- CHANGES.md | 9 +++++++++ Cargo.toml | 11 ++--------- src/middleware/mod.rs | 14 -------------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 385264139..9f899ea9d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,14 @@ # Changes +## [1.0.2] - 2019-06-17 + +### Changes + +* Move cors middleware to `actix-cors` crate. + +* Move identity middleware to `actix-identity` crate. + + ## [1.0.1] - 2019-06-17 ### Add diff --git a/Cargo.toml b/Cargo.toml index d8a143d63..996d9470b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ members = [ ] [features] -default = ["brotli", "flate2-zlib", "client", "fail", "depracated"] +default = ["brotli", "flate2-zlib", "client", "fail"] # http client client = ["awc"] @@ -68,9 +68,6 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] # rustls rust-tls = ["rustls", "actix-server/rust-tls"] -# deprecated middlewares -depracated = ["actix-cors", "actix-identity"] - [dependencies] actix-codec = "0.1.2" actix-service = "0.4.1" @@ -84,10 +81,6 @@ actix-server-config = "0.1.1" actix-threadpool = "0.1.1" awc = { version = "0.2.1", optional = true } -# deprecated middlewares -actix-cors = { version = "0.1.0", optional = true } -actix-identity = { version = "0.1.0", optional = true } - bytes = "0.4" derive_more = "0.15.0" encoding = "0.2" @@ -125,7 +118,7 @@ opt-level = 3 codegen-units = 1 [patch.crates-io] -# actix-web = { path = "." } +actix-web = { path = "." } actix-http = { path = "actix-http" } actix-http-test = { path = "test-server" } actix-web-codegen = { path = "actix-web-codegen" } diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index c2001e00f..814993f0c 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -10,17 +10,3 @@ mod normalize; pub use self::defaultheaders::DefaultHeaders; pub use self::logger::Logger; pub use self::normalize::NormalizePath; - -#[cfg(feature = "deprecated")] -#[deprecated( - since = "1.0.1", - note = "please use `actix_cors` instead. support will be removed in actix-web 1.0.2" -)] -pub use actix_cors as cors; - -#[cfg(feature = "deprecated")] -#[deprecated( - since = "1.0.1", - note = "please use `actix_identity` instead. support will be removed in actix-web 1.0.2" -)] -pub use actix_identity as identity; From ad0e6f73b3edd666fced6c29e8dd74f3991dab66 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 17 Jun 2019 12:35:00 +0600 Subject: [PATCH 23/80] update version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 996d9470b..9f7f8776a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.1" +version = "1.0.2" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" From d7780d53c929fcd650710c35d9d276aeab822af3 Mon Sep 17 00:00:00 2001 From: Joe Roberts Date: Tue, 18 Jun 2019 02:27:23 +0100 Subject: [PATCH 24/80] Fix typo in `actix_web::web::Data::get_ref docstring` (#921) --- src/data.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data.rs b/src/data.rs index 9fd8b67fc..bd166b79c 100644 --- a/src/data.rs +++ b/src/data.rs @@ -73,7 +73,7 @@ impl Data { Data(Arc::new(state)) } - /// Get referecnce to inner app data. + /// Get reference to inner app data. pub fn get_ref(&self) -> &T { self.0.as_ref() } From 313ac4876586472ca070cabc647d164971688b76 Mon Sep 17 00:00:00 2001 From: messense Date: Tue, 18 Jun 2019 14:43:25 +0800 Subject: [PATCH 25/80] Use encoding_rs crate instead of unmaintained encoding crate (#922) * Use encoding_rs crate instead of unmaintained encoding crate * Update changelog --- CHANGES.md | 16 +++++++++++----- Cargo.toml | 2 +- actix-http/CHANGES.md | 8 +++++++- actix-http/Cargo.toml | 2 +- actix-http/src/httpmessage.rs | 15 +++++++-------- src/types/form.rs | 13 ++++++------- src/types/payload.rs | 11 +++++------ src/types/readlines.rs | 35 +++++++++++++++++++---------------- 8 files changed, 57 insertions(+), 45 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9f899ea9d..a20713107 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,14 @@ # Changes +## [1.0.3] - unreleased + +### Changed + +* Use `encoding_rs` crate instead of unmaintained `encoding` crate + ## [1.0.2] - 2019-06-17 -### Changes +### Changed * Move cors middleware to `actix-cors` crate. @@ -17,7 +23,7 @@ * Add `middleware::identity::RequestIdentity` trait to `get_identity` from `HttpMessage`. -### Changes +### Changed * Move cors middleware to `actix-cors` crate. @@ -47,7 +53,7 @@ * Add macros for head, options, trace, connect and patch http methods -### Changes +### Changed * Drop an unnecessary `Option<_>` indirection around `ServerBuilder` from `HttpServer`. #863 @@ -65,7 +71,7 @@ * Add `Query::from_query()` to extract parameters from a query string. #846 * `QueryConfig`, similar to `JsonConfig` for customizing error handling of query extractors. -### Changes +### Changed * `JsonConfig` is now `Send + Sync`, this implies that `error_handler` must be `Send + Sync` too. @@ -80,7 +86,7 @@ * Allow to set/override app data on scope level -### Changes +### Changed * `App::configure` take an `FnOnce` instead of `Fn` * Upgrade actix-net crates diff --git a/Cargo.toml b/Cargo.toml index 9f7f8776a..4f8cd745d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,7 @@ awc = { version = "0.2.1", optional = true } bytes = "0.4" derive_more = "0.15.0" -encoding = "0.2" +encoding_rs = "0.8" futures = "0.1.25" hashbrown = "0.5.0" log = "0.4" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 93c352898..891967f10 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [0.2.5] - unreleased + +### Changed + +* Use `encoding_rs` crate instead of unmaintained `encoding` crate + ## [0.2.4] - 2019-06-16 ### Fixed @@ -83,7 +89,7 @@ ## [0.1.1] - 2019-04-19 -### Changes +### Changed * Cookie::max_age() accepts value in seconds diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 2da410130..c3930a7a6 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -58,7 +58,7 @@ byteorder = "1.2" copyless = "0.1.2" derive_more = "0.15.0" either = "1.5.2" -encoding = "0.2" +encoding_rs = "0.8" futures = "0.1.25" hashbrown = "0.5.0" h2 = "0.1.16" diff --git a/actix-http/src/httpmessage.rs b/actix-http/src/httpmessage.rs index 1534973a8..05d668c10 100644 --- a/actix-http/src/httpmessage.rs +++ b/actix-http/src/httpmessage.rs @@ -1,9 +1,7 @@ use std::cell::{Ref, RefMut}; use std::str; -use encoding::all::UTF_8; -use encoding::label::encoding_from_whatwg_label; -use encoding::EncodingRef; +use encoding_rs::{Encoding, UTF_8}; use http::header; use mime::Mime; @@ -59,10 +57,12 @@ pub trait HttpMessage: Sized { /// Get content type encoding /// /// UTF-8 is used by default, If request charset is not set. - fn encoding(&self) -> Result { + fn encoding(&self) -> Result<&'static Encoding, ContentTypeError> { if let Some(mime_type) = self.mime_type()? { if let Some(charset) = mime_type.get_param("charset") { - if let Some(enc) = encoding_from_whatwg_label(charset.as_str()) { + if let Some(enc) = + Encoding::for_label_no_replacement(charset.as_str().as_bytes()) + { Ok(enc) } else { Err(ContentTypeError::UnknownEncoding) @@ -166,8 +166,7 @@ where #[cfg(test)] mod tests { use bytes::Bytes; - use encoding::all::ISO_8859_2; - use encoding::Encoding; + use encoding_rs::ISO_8859_2; use mime; use super::*; @@ -223,7 +222,7 @@ mod tests { "application/json; charset=ISO-8859-2", ) .finish(); - assert_eq!(ISO_8859_2.name(), req.encoding().unwrap().name()); + assert_eq!(ISO_8859_2, req.encoding().unwrap()); } #[test] diff --git a/src/types/form.rs b/src/types/form.rs index 0bc6a0303..32d0edb69 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -5,9 +5,7 @@ use std::{fmt, ops}; use actix_http::{Error, HttpMessage, Payload}; use bytes::BytesMut; -use encoding::all::UTF_8; -use encoding::types::{DecoderTrap, Encoding}; -use encoding::EncodingRef; +use encoding_rs::{Encoding, UTF_8}; use futures::{Future, Poll, Stream}; use serde::de::DeserializeOwned; @@ -187,7 +185,7 @@ pub struct UrlEncoded { stream: Option>, limit: usize, length: Option, - encoding: EncodingRef, + encoding: &'static Encoding, err: Option, fut: Option>>, } @@ -286,13 +284,14 @@ where } }) .and_then(move |body| { - if (encoding as *const Encoding) == UTF_8 { + if encoding == UTF_8 { serde_urlencoded::from_bytes::(&body) .map_err(|_| UrlencodedError::Parse) } else { let body = encoding - .decode(&body, DecoderTrap::Strict) - .map_err(|_| UrlencodedError::Parse)?; + .decode_without_bom_handling_and_without_replacement(&body) + .map(|s| s.into_owned()) + .ok_or(UrlencodedError::Parse)?; serde_urlencoded::from_str::(&body) .map_err(|_| UrlencodedError::Parse) } diff --git a/src/types/payload.rs b/src/types/payload.rs index 8e4dd7030..a8e85e4f3 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -4,8 +4,7 @@ use std::str; use actix_http::error::{Error, ErrorBadRequest, PayloadError}; use actix_http::HttpMessage; use bytes::{Bytes, BytesMut}; -use encoding::all::UTF_8; -use encoding::types::{DecoderTrap, Encoding}; +use encoding_rs::UTF_8; use futures::future::{err, Either, FutureResult}; use futures::{Future, Poll, Stream}; use mime::Mime; @@ -208,15 +207,15 @@ impl FromRequest for String { .limit(limit) .from_err() .and_then(move |body| { - let enc: *const Encoding = encoding as *const Encoding; - if enc == UTF_8 { + if encoding == UTF_8 { Ok(str::from_utf8(body.as_ref()) .map_err(|_| ErrorBadRequest("Can not decode body"))? .to_owned()) } else { Ok(encoding - .decode(&body, DecoderTrap::Strict) - .map_err(|_| ErrorBadRequest("Can not decode body"))?) + .decode_without_bom_handling_and_without_replacement(&body) + .map(|s| s.into_owned()) + .ok_or_else(|| ErrorBadRequest("Can not decode body"))?) } }), )) diff --git a/src/types/readlines.rs b/src/types/readlines.rs index c23b84434..cea63e43b 100644 --- a/src/types/readlines.rs +++ b/src/types/readlines.rs @@ -1,9 +1,8 @@ +use std::borrow::Cow; use std::str; use bytes::{Bytes, BytesMut}; -use encoding::all::UTF_8; -use encoding::types::{DecoderTrap, Encoding}; -use encoding::EncodingRef; +use encoding_rs::{Encoding, UTF_8}; use futures::{Async, Poll, Stream}; use crate::dev::Payload; @@ -16,7 +15,7 @@ pub struct Readlines { buff: BytesMut, limit: usize, checked_buff: bool, - encoding: EncodingRef, + encoding: &'static Encoding, err: Option, } @@ -87,15 +86,17 @@ where if ind + 1 > self.limit { return Err(ReadlinesError::LimitOverflow); } - let enc: *const Encoding = self.encoding as *const Encoding; - let line = if enc == UTF_8 { + let line = if self.encoding == UTF_8 { str::from_utf8(&self.buff.split_to(ind + 1)) .map_err(|_| ReadlinesError::EncodingError)? .to_owned() } else { self.encoding - .decode(&self.buff.split_to(ind + 1), DecoderTrap::Strict) - .map_err(|_| ReadlinesError::EncodingError)? + .decode_without_bom_handling_and_without_replacement( + &self.buff.split_to(ind + 1), + ) + .map(Cow::into_owned) + .ok_or(ReadlinesError::EncodingError)? }; return Ok(Async::Ready(Some(line))); } @@ -117,15 +118,17 @@ where if ind + 1 > self.limit { return Err(ReadlinesError::LimitOverflow); } - let enc: *const Encoding = self.encoding as *const Encoding; - let line = if enc == UTF_8 { + let line = if self.encoding == UTF_8 { str::from_utf8(&bytes.split_to(ind + 1)) .map_err(|_| ReadlinesError::EncodingError)? .to_owned() } else { self.encoding - .decode(&bytes.split_to(ind + 1), DecoderTrap::Strict) - .map_err(|_| ReadlinesError::EncodingError)? + .decode_without_bom_handling_and_without_replacement( + &bytes.split_to(ind + 1), + ) + .map(Cow::into_owned) + .ok_or(ReadlinesError::EncodingError)? }; // extend buffer with rest of the bytes; self.buff.extend_from_slice(&bytes); @@ -143,15 +146,15 @@ where if self.buff.len() > self.limit { return Err(ReadlinesError::LimitOverflow); } - let enc: *const Encoding = self.encoding as *const Encoding; - let line = if enc == UTF_8 { + let line = if self.encoding == UTF_8 { str::from_utf8(&self.buff) .map_err(|_| ReadlinesError::EncodingError)? .to_owned() } else { self.encoding - .decode(&self.buff, DecoderTrap::Strict) - .map_err(|_| ReadlinesError::EncodingError)? + .decode_without_bom_handling_and_without_replacement(&self.buff) + .map(Cow::into_owned) + .ok_or(ReadlinesError::EncodingError)? }; self.buff.clear(); Ok(Async::Ready(Some(line))) From 47fab0e393802030808c842565c918c06c22c278 Mon Sep 17 00:00:00 2001 From: messense Date: Wed, 19 Jun 2019 18:41:42 +0800 Subject: [PATCH 26/80] Bump derive_more crate version to 0.15.0 in actix-cors (#927) --- actix-cors/CHANGES.md | 4 ++++ actix-cors/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/actix-cors/CHANGES.md b/actix-cors/CHANGES.md index 1e842f37e..10e408ede 100644 --- a/actix-cors/CHANGES.md +++ b/actix-cors/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.1.1] - unreleased + +* Bump `derive_more` crate version to 0.15.0 + ## [0.1.0] - 2019-06-15 * Move cors middleware to separate crate diff --git a/actix-cors/Cargo.toml b/actix-cors/Cargo.toml index 98ed67a2a..091c94044 100644 --- a/actix-cors/Cargo.toml +++ b/actix-cors/Cargo.toml @@ -19,5 +19,5 @@ path = "src/lib.rs" [dependencies] actix-web = "1.0.0" actix-service = "0.4.0" -derive_more = "0.14.1" +derive_more = "0.15.0" futures = "0.1.25" From 1a24ff871728bacaf4853c4000a9d2be665abd56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Vis=C3=A9e?= Date: Fri, 21 Jun 2019 09:06:29 +0200 Subject: [PATCH 27/80] Add builder function for HTTP 429 Too Many Requests status (#931) --- actix-http/src/httpcodes.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-http/src/httpcodes.rs b/actix-http/src/httpcodes.rs index e7eda2da8..3cac35eb7 100644 --- a/actix-http/src/httpcodes.rs +++ b/actix-http/src/httpcodes.rs @@ -61,6 +61,7 @@ impl Response { STATIC_RESP!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE); STATIC_RESP!(ExpectationFailed, StatusCode::EXPECTATION_FAILED); STATIC_RESP!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY); + STATIC_RESP!(TooManyRequests, StatusCode::TOO_MANY_REQUESTS); STATIC_RESP!(InternalServerError, StatusCode::INTERNAL_SERVER_ERROR); STATIC_RESP!(NotImplemented, StatusCode::NOT_IMPLEMENTED); From b948f74b540c70036cef60d16cba554ffb71f0cd Mon Sep 17 00:00:00 2001 From: Dustin Bensing Date: Mon, 24 Jun 2019 03:16:04 +0200 Subject: [PATCH 28/80] Extractor configuration Migration (#937) added guide for Extractor configuration in MIGRATION.md --- MIGRATION.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/MIGRATION.md b/MIGRATION.md index 5273a0135..2f0f369ad 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -31,6 +31,64 @@ ## 1.0.0 +* Extractor configuration. In version 1.0 this is handled with the new `Data` mechanism for both setting and retrieving the configuration + + instead of + + ```rust + + #[derive(Default)] + struct ExtractorConfig { + config: String, + } + + impl FromRequest for YourExtractor { + type Config = ExtractorConfig; + type Result = Result; + + fn from_request(req: &HttpRequest, cfg: &Self::Config) -> Self::Result { + println!("use the config: {:?}", cfg.config); + ... + } + } + + App::new().resource("/route_with_config", |r| { + r.post().with_config(handler_fn, |cfg| { + cfg.0.config = "test".to_string(); + }) + }) + + ``` + + use the HttpRequest to get the configuration like any other `Data` with `req.app_data::()` and set it with the `data()` method on the `resource` + + ```rust + #[derive(Default)] + struct ExtractorConfig { + config: String, + } + + impl FromRequest for YourExtractor { + type Error = Error; + type Future = Result; + type Config = ExtractorConfig; + + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + let cfg = req.app_data::(); + println!("config data?: {:?}", cfg.unwrap().role); + ... + } + } + + App::new().service( + resource("/route_with_config") + .data(ExtractorConfig { + config: "test".to_string(), + }) + .route(post().to(handler_fn)), + ) + ``` + * Resource registration. 1.0 version uses generalized resource registration via `.service()` method. From fa7e0fe6df27c98da0117384b1e9ac5864b736d1 Mon Sep 17 00:00:00 2001 From: dowwie Date: Mon, 24 Jun 2019 18:40:14 -0400 Subject: [PATCH 29/80] updated cookie.rs req to get_changes --- actix-session/src/cookie.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index ac08d1146..55904f5bd 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -308,7 +308,7 @@ where Session::set_session(state.into_iter(), &mut req); Box::new(self.service.call(req).map(move |mut res| { - if let Some(state) = Session::get_changes(&mut res) { + if let (_status, Some(state)) = Session::get_changes(&mut res) { res.checked_expr(|res| inner.set_cookie(res, state)) } else { res From c0c71f82c00fdac964bcf588c2ea49c4c18d5de7 Mon Sep 17 00:00:00 2001 From: Cameron Dershem Date: Tue, 25 Jun 2019 13:23:36 -0400 Subject: [PATCH 30/80] Fixes typo. (#940) Small typo fix. --- src/resource.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resource.rs b/src/resource.rs index ad08a15ff..c2691eebe 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -27,7 +27,7 @@ type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error /// Resource in turn has at least one route. /// Route consists of an handlers objects and list of guards /// (objects that implement `Guard` trait). -/// Resources and rouets uses builder-like pattern for configuration. +/// Resources and routes uses builder-like pattern for configuration. /// During request handling, resource object iterate through all routes /// and check guards for specific route, if request matches all /// guards, route considered matched and route handler get called. From af9fb5d1908c425c522d54214291e6a80604e5d7 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 10:43:52 +0600 Subject: [PATCH 31/80] Support asynchronous data factories #850 --- CHANGES.md | 9 +++++-- src/app.rs | 66 +++++++++++++++++++++++++++++++++------------- src/app_service.rs | 44 +++++++++++++++++++++++-------- 3 files changed, 88 insertions(+), 31 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a20713107..dcefdec55 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,10 +2,15 @@ ## [1.0.3] - unreleased +### Added + +* Support asynchronous data factories #850 + ### Changed * Use `encoding_rs` crate instead of unmaintained `encoding` crate + ## [1.0.2] - 2019-06-17 ### Changed @@ -17,7 +22,7 @@ ## [1.0.1] - 2019-06-17 -### Add +### Added * Add support for PathConfig #903 @@ -42,7 +47,7 @@ ## [1.0.0] - 2019-06-05 -### Add +### Added * Add `Scope::configure()` method. diff --git a/src/app.rs b/src/app.rs index 897b36459..3b063a841 100644 --- a/src/app.rs +++ b/src/app.rs @@ -8,7 +8,7 @@ use actix_service::boxed::{self, BoxedNewService}; use actix_service::{ apply_transform, IntoNewService, IntoTransform, NewService, Transform, }; -use futures::IntoFuture; +use futures::{Future, IntoFuture}; use crate::app_service::{AppEntry, AppInit, AppRoutingFactory}; use crate::config::{AppConfig, AppConfigInner, ServiceConfig}; @@ -23,6 +23,7 @@ use crate::service::{ }; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; +type FnDataFactory = Box Box, Error = ()>>>; /// Application builder - structure that follows the builder pattern /// for building application instances. @@ -32,6 +33,7 @@ pub struct App { default: Option>, factory_ref: Rc>>, data: Vec>, + data_factories: Vec, config: AppConfigInner, external: Vec, _t: PhantomData<(B)>, @@ -44,6 +46,7 @@ impl App { App { endpoint: AppEntry::new(fref.clone()), data: Vec::new(), + data_factories: Vec::new(), services: Vec::new(), default: None, factory_ref: fref, @@ -100,6 +103,31 @@ where self } + /// Set application data factory. This function is + /// similar to `.data()` but it accepts data factory. Data object get + /// constructed asynchronously during application initialization. + pub fn data_factory(mut self, data: F) -> Self + where + F: Fn() -> Out + 'static, + Out: IntoFuture + 'static, + Out::Error: std::fmt::Debug, + { + self.data_factories.push(Box::new(move || { + Box::new( + data() + .into_future() + .map_err(|e| { + log::error!("Can not construct data instance: {:?}", e); + }) + .map(|data| { + let data: Box = Box::new(Data::new(data)); + data + }), + ) + })); + self + } + /// Set application data. Application data could be accessed /// by using `Data` extractor where `T` is data type. pub fn register_data(mut self, data: Data) -> Self { @@ -349,6 +377,7 @@ where App { endpoint, data: self.data, + data_factories: self.data_factories, services: self.services, default: self.default, factory_ref: self.factory_ref, @@ -423,6 +452,7 @@ where fn into_new_service(self) -> AppInit { AppInit { data: Rc::new(self.data), + data_factories: Rc::new(self.data_factories), endpoint: self.endpoint, services: Rc::new(RefCell::new(self.services)), external: RefCell::new(self.external), @@ -490,24 +520,24 @@ mod tests { assert_eq!(resp.status(), StatusCode::CREATED); } - // #[test] - // fn test_data_factory() { - // let mut srv = - // init_service(App::new().data_factory(|| Ok::<_, ()>(10usize)).service( - // web::resource("/").to(|_: web::Data| HttpResponse::Ok()), - // )); - // let req = TestRequest::default().to_request(); - // let resp = block_on(srv.call(req)).unwrap(); - // assert_eq!(resp.status(), StatusCode::OK); + #[test] + fn test_data_factory() { + let mut srv = + init_service(App::new().data_factory(|| Ok::<_, ()>(10usize)).service( + web::resource("/").to(|_: web::Data| HttpResponse::Ok()), + )); + let req = TestRequest::default().to_request(); + let resp = block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::OK); - // let mut srv = - // init_service(App::new().data_factory(|| Ok::<_, ()>(10u32)).service( - // web::resource("/").to(|_: web::Data| HttpResponse::Ok()), - // )); - // let req = TestRequest::default().to_request(); - // let resp = block_on(srv.call(req)).unwrap(); - // assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); - // } + let mut srv = + init_service(App::new().data_factory(|| Ok::<_, ()>(10u32)).service( + web::resource("/").to(|_: web::Data| HttpResponse::Ok()), + )); + let req = TestRequest::default().to_request(); + let resp = block_on(srv.call(req)).unwrap(); + assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR); + } fn md( req: ServiceRequest, diff --git a/src/app_service.rs b/src/app_service.rs index 5a9731bf2..8ab9b352a 100644 --- a/src/app_service.rs +++ b/src/app_service.rs @@ -25,6 +25,7 @@ type BoxedResponse = Either< FutureResult, Box>, >; +type FnDataFactory = Box Box, Error = ()>>>; /// Service factory to convert `Request` to a `ServiceRequest`. /// It also executes data factories. @@ -40,6 +41,7 @@ where { pub(crate) endpoint: T, pub(crate) data: Rc>>, + pub(crate) data_factories: Rc>, pub(crate) config: RefCell, pub(crate) services: Rc>>>, pub(crate) default: Option>, @@ -119,16 +121,12 @@ where let rmap = Rc::new(rmap); rmap.finish(rmap.clone()); - // create app data container - let mut data = Extensions::new(); - for f in self.data.iter() { - f.create(&mut data); - } - AppInitResult { endpoint: None, endpoint_fut: self.endpoint.new_service(&()), - data: Rc::new(data), + data: self.data.clone(), + data_factories: Vec::new(), + data_factories_fut: self.data_factories.iter().map(|f| f()).collect(), config, rmap, _t: PhantomData, @@ -144,7 +142,9 @@ where endpoint_fut: T::Future, rmap: Rc, config: AppConfig, - data: Rc, + data: Rc>>, + data_factories: Vec>, + data_factories_fut: Vec, Error = ()>>>, _t: PhantomData, } @@ -159,21 +159,43 @@ where >, { type Item = AppInitService; - type Error = T::InitError; + type Error = (); fn poll(&mut self) -> Poll { + // async data factories + let mut idx = 0; + while idx < self.data_factories_fut.len() { + match self.data_factories_fut[idx].poll()? { + Async::Ready(f) => { + self.data_factories.push(f); + self.data_factories_fut.remove(idx); + } + Async::NotReady => idx += 1, + } + } + if self.endpoint.is_none() { if let Async::Ready(srv) = self.endpoint_fut.poll()? { self.endpoint = Some(srv); } } - if self.endpoint.is_some() { + if self.endpoint.is_some() && self.data_factories_fut.is_empty() { + // create app data container + let mut data = Extensions::new(); + for f in self.data.iter() { + f.create(&mut data); + } + + for f in &self.data_factories { + f.create(&mut data); + } + Ok(Async::Ready(AppInitService { service: self.endpoint.take().unwrap(), rmap: self.rmap.clone(), config: self.config.clone(), - data: self.data.clone(), + data: Rc::new(data), pool: HttpRequestPool::create(), })) } else { From 44bb79cd07af726c23825fd19a0f028ba3fd3a80 Mon Sep 17 00:00:00 2001 From: messense Date: Fri, 28 Jun 2019 12:44:53 +0800 Subject: [PATCH 32/80] Call req.path() on Json extractor error only (#945) * Call req.path() on Json extractor error only * Cleanup len parse code --- src/types/json.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/types/json.rs b/src/types/json.rs index 0789fb612..de0ffb54c 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -180,16 +180,14 @@ where .map(|c| (c.limit, c.ehandler.clone(), c.content_type.clone())) .unwrap_or((32768, None, None)); - let path = req.path().to_string(); - Box::new( JsonBody::new(req, payload, ctype) .limit(limit) .map_err(move |e| { log::debug!( "Failed to deserialize Json from payload. \ - Request path: {:?}", - path + Request path: {}", + req2.path() ); if let Some(err) = err { (*err)(e, &req2) @@ -324,14 +322,11 @@ where }; } - let mut len = None; - if let Some(l) = req.headers().get(&CONTENT_LENGTH) { - if let Ok(s) = l.to_str() { - if let Ok(l) = s.parse::() { - len = Some(l) - } - } - } + let len = req + .headers() + .get(&CONTENT_LENGTH) + .and_then(|l| l.to_str().ok()) + .and_then(|s| s.parse::().ok()); let payload = Decompress::from_headers(payload.take(), req.headers()); JsonBody { From 768859513a5b3eeb1741ab7d5180c0c93eabfafe Mon Sep 17 00:00:00 2001 From: anthonyjchriste Date: Thu, 27 Jun 2019 18:49:03 -1000 Subject: [PATCH 33/80] Expose the max limit for payload sizes in Websocket Actors. #925 (#933) * Expose the max limit for payload sizes in Websocket Actors. * Revert to previous not-formatted code. * Implement WebsocketContext::with_codec and make Codec Copy and Clone. * Fix formatting. * Fix formatting. --- actix-http/src/ws/codec.rs | 2 +- actix-web-actors/src/ws.rs | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/actix-http/src/ws/codec.rs b/actix-http/src/ws/codec.rs index ad599ffa7..9891bfa6e 100644 --- a/actix-http/src/ws/codec.rs +++ b/actix-http/src/ws/codec.rs @@ -37,7 +37,7 @@ pub enum Frame { Close(Option), } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] /// WebSockets protocol codec pub struct Codec { max_size: usize, diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 0ef3c9169..16f475a7f 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -177,9 +177,26 @@ where inner: ContextParts::new(mb.sender_producer()), messages: VecDeque::new(), }; - ctx.add_stream(WsStream::new(stream)); + ctx.add_stream(WsStream::new(stream, Codec::new())); - WebsocketContextFut::new(ctx, actor, mb) + WebsocketContextFut::new(ctx, actor, mb, Codec::new()) + } + + #[inline] + /// Create a new Websocket context from a request, an actor, and a codec + pub fn with_codec(actor: A, stream: S, codec: Codec) -> impl Stream + where + A: StreamHandler, + S: Stream + 'static, + { + let mb = Mailbox::default(); + let mut ctx = WebsocketContext { + inner: ContextParts::new(mb.sender_producer()), + messages: VecDeque::new(), + }; + ctx.add_stream(WsStream::new(stream, codec)); + + WebsocketContextFut::new(ctx, actor, mb, codec) } /// Create a new Websocket context @@ -197,11 +214,11 @@ where inner: ContextParts::new(mb.sender_producer()), messages: VecDeque::new(), }; - ctx.add_stream(WsStream::new(stream)); + ctx.add_stream(WsStream::new(stream, Codec::new())); let act = f(&mut ctx); - WebsocketContextFut::new(ctx, act, mb) + WebsocketContextFut::new(ctx, act, mb, Codec::new()) } } @@ -288,11 +305,11 @@ impl WebsocketContextFut where A: Actor>, { - fn new(ctx: WebsocketContext, act: A, mailbox: Mailbox) -> Self { + fn new(ctx: WebsocketContext, act: A, mailbox: Mailbox, codec: Codec) -> Self { let fut = ContextFut::new(ctx, act, mailbox); WebsocketContextFut { fut, - encoder: Codec::new(), + encoder: codec, buf: BytesMut::new(), closed: false, } @@ -353,10 +370,10 @@ impl WsStream where S: Stream, { - fn new(stream: S) -> Self { + fn new(stream: S, codec: Codec) -> Self { Self { stream, - decoder: Codec::new(), + decoder: codec, buf: BytesMut::new(), closed: false, } From 596483ff55b6aceba1d78adec8a27b347130a789 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 10:54:23 +0600 Subject: [PATCH 34/80] prepare actix-web-actors release --- actix-web-actors/CHANGES.md | 4 ++++ actix-web-actors/Cargo.toml | 4 ++-- actix-web-actors/src/ws.rs | 12 ++++++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 89b4be818..115af87b9 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [1.0.1] - 2019-06-28 + +* Allow to use custom ws codec with `WebsocketContext` #925 + ## [1.0.0] - 2019-05-29 * Update actix-http and actix-web diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 90d0a00f9..864d8d953 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" +version = "1.0.1" 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.3" -actix-web = "1.0.0" +actix-web = "1.0.2" actix-http = "0.2.4" actix-codec = "0.1.2" bytes = "0.4" diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 16f475a7f..fece826dd 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -184,10 +184,14 @@ where #[inline] /// Create a new Websocket context from a request, an actor, and a codec - pub fn with_codec(actor: A, stream: S, codec: Codec) -> impl Stream - where - A: StreamHandler, - S: Stream + 'static, + pub fn with_codec( + actor: A, + stream: S, + codec: Codec, + ) -> impl Stream + where + A: StreamHandler, + S: Stream + 'static, { let mb = Mailbox::default(); let mut ctx = WebsocketContext { From a3a78ac6fb50c17b73f9d4ac6cac816ceae68bb3 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 11:42:20 +0600 Subject: [PATCH 35/80] Do not set Content-Length header, let actix-http set it #930 --- actix-files/CHANGES.md | 5 +++++ actix-files/Cargo.toml | 6 ++--- actix-files/src/lib.rs | 48 ++++++++++++++++++++-------------------- actix-files/src/named.rs | 2 -- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index e79d80967..2f98e15c2 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## [0.1.3] - 2019-06-28 + +* Do not set `Content-Length` header, let actix-http set it #930 + + ## [0.1.2] - 2019-06-13 * Content-Length is 0 for NamedFile HEAD request #914 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 9df93834a..c9d9cfecb 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.1.2" +version = "0.1.3" 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 = { version = "1.0.0", default-features = false } +actix-web = { version = "1.0.2", default-features = false } actix-http = "0.2.4" actix-service = "0.4.1" bitflags = "1" @@ -32,4 +32,4 @@ percent-encoding = "1.0" v_htmlescape = "0.4" [dev-dependencies] -actix-web = { version = "1.0.0", features=["ssl"] } +actix-web = { version = "1.0.2", features=["ssl"] } diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 9f526f3f0..8e87f7d89 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -855,6 +855,8 @@ mod tests { #[test] fn test_named_file_content_length_headers() { + use actix_web::body::{MessageBody, ResponseBody}; + let mut srv = test::init_service( App::new().service(Files::new("test", ".").index_file("tests/test.binary")), ); @@ -866,14 +868,13 @@ mod tests { .to_request(); let response = test::call_service(&mut srv, request); - let contentlength = response - .headers() - .get(header::CONTENT_LENGTH) - .unwrap() - .to_str() - .unwrap(); - - assert_eq!(contentlength, "11"); + // let contentlength = response + // .headers() + // .get(header::CONTENT_LENGTH) + // .unwrap() + // .to_str() + // .unwrap(); + // assert_eq!(contentlength, "11"); // Invalid range header let request = TestRequest::get() @@ -890,14 +891,13 @@ mod tests { .to_request(); let response = test::call_service(&mut srv, request); - let contentlength = response - .headers() - .get(header::CONTENT_LENGTH) - .unwrap() - .to_str() - .unwrap(); - - assert_eq!(contentlength, "100"); + // let contentlength = response + // .headers() + // .get(header::CONTENT_LENGTH) + // .unwrap() + // .to_str() + // .unwrap(); + // assert_eq!(contentlength, "100"); // chunked let request = TestRequest::get() @@ -939,14 +939,14 @@ mod tests { .to_request(); let response = test::call_service(&mut srv, request); - let contentlength = response - .headers() - .get(header::CONTENT_LENGTH) - .unwrap() - .to_str() - .unwrap(); - - assert_eq!(contentlength, "100"); + // TODO: fix check + // let contentlength = response + // .headers() + // .get(header::CONTENT_LENGTH) + // .unwrap() + // .to_str() + // .unwrap(); + // assert_eq!(contentlength, "100"); } #[test] diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 3ece7c212..6b948da8e 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -414,8 +414,6 @@ impl Responder for NamedFile { }; }; - resp.header(header::CONTENT_LENGTH, format!("{}", length)); - if precondition_failed { return Ok(resp.status(StatusCode::PRECONDITION_FAILED).finish()); } else if not_modified { From cac162aed765431d1e405f7aeb276425bd62031a Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 12:34:43 +0600 Subject: [PATCH 36/80] update actix-http changes --- .travis.yml | 2 +- actix-http/CHANGES.md | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2dea00c58..5f7d01a3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ before_install: before_cache: | if [[ "$TRAVIS_RUST_VERSION" == "nightly-2019-04-02" ]]; then - RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install cargo-tarpaulin + RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install --version 0.6.11 cargo-tarpaulin fi # Add clippy diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 891967f10..6dea516dc 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,7 +4,10 @@ ### Changed -* Use `encoding_rs` crate instead of unmaintained `encoding` crate +* Use `encoding_rs` crate instead of unmaintained `encoding` crate + +* Add `Copy` and `Clone` impls for `ws::Codec` + ## [0.2.4] - 2019-06-16 From d286ccb4f5a86eca12c65b1632506a8bd8b37d19 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 14:34:26 +0600 Subject: [PATCH 37/80] Add on-connect callback #946 --- actix-http/CHANGES.md | 6 ++++- actix-http/Cargo.toml | 6 ++--- actix-http/src/builder.rs | 21 +++++++++++++++ actix-http/src/h1/dispatcher.rs | 17 ++++++++++-- actix-http/src/h1/service.rs | 33 ++++++++++++++++++++++- actix-http/src/h2/dispatcher.rs | 6 ++++- actix-http/src/h2/service.rs | 36 ++++++++++++++++++++++++-- actix-http/src/helpers.rs | 14 ++++++++++ actix-http/src/service.rs | 46 ++++++++++++++++++++++++++++++--- 9 files changed, 171 insertions(+), 14 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 6dea516dc..636cbedf7 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,10 @@ # Changes -## [0.2.5] - unreleased +## [0.2.5] - 2019-06-28 + +### Added + +* Add `on-connect` callback, `HttpServiceBuilder::on_connect()` #946 ### Changed diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index c3930a7a6..afbf0a487 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.2.4" +version = "0.2.5" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" @@ -44,10 +44,10 @@ fail = ["failure"] secure-cookies = ["ring"] [dependencies] -actix-service = "0.4.0" +actix-service = "0.4.1" actix-codec = "0.1.2" actix-connect = "0.2.0" -actix-utils = "0.4.1" +actix-utils = "0.4.2" actix-server-config = "0.1.1" actix-threadpool = "0.1.0" diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index b1b193a9e..b6967d94d 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -1,5 +1,6 @@ use std::fmt; use std::marker::PhantomData; +use std::rc::Rc; use actix_codec::Framed; use actix_server_config::ServerConfig as SrvConfig; @@ -10,6 +11,7 @@ use crate::config::{KeepAlive, ServiceConfig}; use crate::error::Error; use crate::h1::{Codec, ExpectHandler, H1Service, UpgradeHandler}; use crate::h2::H2Service; +use crate::helpers::{Data, DataFactory}; use crate::request::Request; use crate::response::Response; use crate::service::HttpService; @@ -24,6 +26,7 @@ pub struct HttpServiceBuilder> { client_disconnect: u64, expect: X, upgrade: Option, + on_connect: Option Box>>, _t: PhantomData<(T, S)>, } @@ -41,6 +44,7 @@ where client_disconnect: 0, expect: ExpectHandler, upgrade: None, + on_connect: None, _t: PhantomData, } } @@ -115,6 +119,7 @@ where client_disconnect: self.client_disconnect, expect: expect.into_new_service(), upgrade: self.upgrade, + on_connect: self.on_connect, _t: PhantomData, } } @@ -140,10 +145,24 @@ where client_disconnect: self.client_disconnect, expect: self.expect, upgrade: Some(upgrade.into_new_service()), + on_connect: self.on_connect, _t: PhantomData, } } + /// Set on-connect callback. + /// + /// It get called once per connection and result of the call + /// get stored to the request's extensions. + pub fn on_connect(mut self, f: F) -> Self + where + F: Fn(&T) -> I + 'static, + I: Clone + 'static, + { + self.on_connect = Some(Rc::new(move |io| Box::new(Data(f(io))))); + self + } + /// Finish service configuration and create *http service* for HTTP/1 protocol. pub fn h1(self, service: F) -> H1Service where @@ -161,6 +180,7 @@ where H1Service::with_config(cfg, service.into_new_service()) .expect(self.expect) .upgrade(self.upgrade) + .on_connect(self.on_connect) } /// Finish service configuration and create *http service* for HTTP/2 protocol. @@ -199,5 +219,6 @@ where HttpService::with_config(cfg, service.into_new_service()) .expect(self.expect) .upgrade(self.upgrade) + .on_connect(self.on_connect) } } diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 220984f8d..91990d05c 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -16,6 +16,8 @@ use crate::body::{Body, BodySize, MessageBody, ResponseBody}; use crate::config::ServiceConfig; use crate::error::{DispatchError, Error}; use crate::error::{ParseError, PayloadError}; +use crate::helpers::DataFactory; +use crate::httpmessage::HttpMessage; use crate::request::Request; use crate::response::Response; @@ -81,6 +83,7 @@ where service: CloneableService, expect: CloneableService, upgrade: Option>, + on_connect: Option>, flags: Flags, peer_addr: Option, error: Option, @@ -174,12 +177,13 @@ where U::Error: fmt::Display, { /// Create http/1 dispatcher. - pub fn new( + pub(crate) fn new( stream: T, config: ServiceConfig, service: CloneableService, expect: CloneableService, upgrade: Option>, + on_connect: Option>, ) -> Self { Dispatcher::with_timeout( stream, @@ -190,11 +194,12 @@ where service, expect, upgrade, + on_connect, ) } /// Create http/1 dispatcher with slow request timeout. - pub fn with_timeout( + pub(crate) fn with_timeout( io: T, codec: Codec, config: ServiceConfig, @@ -203,6 +208,7 @@ where service: CloneableService, expect: CloneableService, upgrade: Option>, + on_connect: Option>, ) -> Self { let keepalive = config.keep_alive_enabled(); let flags = if keepalive { @@ -234,6 +240,7 @@ where service, expect, upgrade, + on_connect, flags, ka_expire, ka_timer, @@ -495,6 +502,11 @@ where let pl = self.codec.message_type(); req.head_mut().peer_addr = self.peer_addr; + // on_connect data + if let Some(ref on_connect) = self.on_connect { + on_connect.set(&mut req.extensions_mut()); + } + if pl == MessageType::Stream && self.upgrade.is_some() { self.messages.push_back(DispatcherMessage::Upgrade(req)); break; @@ -851,6 +863,7 @@ mod tests { ), CloneableService::new(ExpectHandler), None, + None, ); assert!(h1.poll().is_err()); diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 2c0a48eba..192d1b598 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -1,5 +1,6 @@ use std::fmt; use std::marker::PhantomData; +use std::rc::Rc; use actix_codec::Framed; use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; @@ -11,6 +12,7 @@ use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream}; use crate::body::MessageBody; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error, ParseError}; +use crate::helpers::DataFactory; use crate::request::Request; use crate::response::Response; @@ -24,6 +26,7 @@ pub struct H1Service> { cfg: ServiceConfig, expect: X, upgrade: Option, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -44,6 +47,7 @@ where srv: service.into_new_service(), expect: ExpectHandler, upgrade: None, + on_connect: None, _t: PhantomData, } } @@ -55,6 +59,7 @@ where srv: service.into_new_service(), expect: ExpectHandler, upgrade: None, + on_connect: None, _t: PhantomData, } } @@ -79,6 +84,7 @@ where cfg: self.cfg, srv: self.srv, upgrade: self.upgrade, + on_connect: self.on_connect, _t: PhantomData, } } @@ -94,9 +100,19 @@ where cfg: self.cfg, srv: self.srv, expect: self.expect, + on_connect: self.on_connect, _t: PhantomData, } } + + /// Set on connect callback. + pub(crate) fn on_connect( + mut self, + f: Option Box>>, + ) -> Self { + self.on_connect = f; + self + } } impl NewService for H1Service @@ -133,6 +149,7 @@ where fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)), expect: None, upgrade: None, + on_connect: self.on_connect.clone(), cfg: Some(self.cfg.clone()), _t: PhantomData, } @@ -157,6 +174,7 @@ where fut_upg: Option, expect: Option, upgrade: Option, + on_connect: Option Box>>, cfg: Option, _t: PhantomData<(T, P, B)>, } @@ -205,6 +223,7 @@ where service, self.expect.take().unwrap(), self.upgrade.take(), + self.on_connect.clone(), ))) } } @@ -214,6 +233,7 @@ pub struct H1ServiceHandler { srv: CloneableService, expect: CloneableService, upgrade: Option>, + on_connect: Option Box>>, cfg: ServiceConfig, _t: PhantomData<(T, P, B)>, } @@ -234,12 +254,14 @@ where srv: S, expect: X, upgrade: Option, + on_connect: Option Box>>, ) -> H1ServiceHandler { H1ServiceHandler { srv: CloneableService::new(srv), expect: CloneableService::new(expect), upgrade: upgrade.map(|s| CloneableService::new(s)), cfg, + on_connect, _t: PhantomData, } } @@ -292,12 +314,21 @@ where } fn call(&mut self, req: Self::Request) -> Self::Future { + let io = req.into_parts().0; + + let on_connect = if let Some(ref on_connect) = self.on_connect { + Some(on_connect(&io)) + } else { + None + }; + Dispatcher::new( - req.into_parts().0, + io, self.cfg.clone(), self.srv.clone(), self.expect.clone(), self.upgrade.clone(), + on_connect, ) } } diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index e66ff63c3..48d32993d 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -22,6 +22,7 @@ use tokio_timer::Delay; use crate::body::{Body, BodySize, MessageBody, ResponseBody}; use crate::config::ServiceConfig; use crate::error::{DispatchError, Error, ParseError, PayloadError, ResponseError}; +use crate::helpers::DataFactory; use crate::message::ResponseHead; use crate::payload::Payload; use crate::request::Request; @@ -33,6 +34,7 @@ const CHUNK_SIZE: usize = 16_384; pub struct Dispatcher, B: MessageBody> { service: CloneableService, connection: Connection, + on_connect: Option>, config: ServiceConfig, peer_addr: Option, ka_expire: Instant, @@ -49,9 +51,10 @@ where S::Response: Into>, B: MessageBody + 'static, { - pub fn new( + pub(crate) fn new( service: CloneableService, connection: Connection, + on_connect: Option>, config: ServiceConfig, timeout: Option, peer_addr: Option, @@ -77,6 +80,7 @@ where config, peer_addr, connection, + on_connect, ka_expire, ka_timer, _t: PhantomData, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index b4191f03a..efc400da1 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; use std::marker::PhantomData; -use std::{io, net}; +use std::{io, net, rc}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; @@ -16,6 +16,7 @@ use log::error; use crate::body::MessageBody; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error, ParseError, ResponseError}; +use crate::helpers::DataFactory; use crate::payload::Payload; use crate::request::Request; use crate::response::Response; @@ -26,6 +27,7 @@ use super::dispatcher::Dispatcher; pub struct H2Service { srv: S, cfg: ServiceConfig, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -43,6 +45,7 @@ where H2Service { cfg, + on_connect: None, srv: service.into_new_service(), _t: PhantomData, } @@ -52,10 +55,20 @@ where pub fn with_config>(cfg: ServiceConfig, service: F) -> Self { H2Service { cfg, + on_connect: None, srv: service.into_new_service(), _t: PhantomData, } } + + /// Set on connect callback. + pub(crate) fn on_connect( + mut self, + f: Option Box>>, + ) -> Self { + self.on_connect = f; + self + } } impl NewService for H2Service @@ -79,6 +92,7 @@ where H2ServiceResponse { fut: self.srv.new_service(cfg).into_future(), cfg: Some(self.cfg.clone()), + on_connect: self.on_connect.clone(), _t: PhantomData, } } @@ -88,6 +102,7 @@ where pub struct H2ServiceResponse { fut: ::Future, cfg: Option, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -107,6 +122,7 @@ where let service = try_ready!(self.fut.poll()); Ok(Async::Ready(H2ServiceHandler::new( self.cfg.take().unwrap(), + self.on_connect.clone(), service, ))) } @@ -116,6 +132,7 @@ where pub struct H2ServiceHandler { srv: CloneableService, cfg: ServiceConfig, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -127,9 +144,14 @@ where S::Response: Into>, B: MessageBody + 'static, { - fn new(cfg: ServiceConfig, srv: S) -> H2ServiceHandler { + fn new( + cfg: ServiceConfig, + on_connect: Option Box>>, + srv: S, + ) -> H2ServiceHandler { H2ServiceHandler { cfg, + on_connect, srv: CloneableService::new(srv), _t: PhantomData, } @@ -161,11 +183,18 @@ where fn call(&mut self, req: Self::Request) -> Self::Future { let io = req.into_parts().0; let peer_addr = io.peer_addr(); + let on_connect = if let Some(ref on_connect) = self.on_connect { + Some(on_connect(&io)) + } else { + None + }; + H2ServiceHandlerResponse { state: State::Handshake( Some(self.srv.clone()), Some(self.cfg.clone()), peer_addr, + on_connect, server::handshake(io), ), } @@ -181,6 +210,7 @@ where Option>, Option, Option, + Option>, Handshake, ), } @@ -216,12 +246,14 @@ where ref mut srv, ref mut config, ref peer_addr, + ref mut on_connect, ref mut handshake, ) => match handshake.poll() { Ok(Async::Ready(conn)) => { self.state = State::Incoming(Dispatcher::new( srv.take().unwrap(), conn, + on_connect.take(), config.take().unwrap(), None, peer_addr.clone(), diff --git a/actix-http/src/helpers.rs b/actix-http/src/helpers.rs index e8dbcd82a..e4583ee37 100644 --- a/actix-http/src/helpers.rs +++ b/actix-http/src/helpers.rs @@ -3,6 +3,8 @@ use std::{io, mem, ptr, slice}; use bytes::{BufMut, BytesMut}; use http::Version; +use crate::extensions::Extensions; + const DEC_DIGITS_LUT: &[u8] = b"0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ @@ -180,6 +182,18 @@ impl<'a> io::Write for Writer<'a> { } } +pub(crate) trait DataFactory { + fn set(&self, ext: &mut Extensions); +} + +pub(crate) struct Data(pub(crate) T); + +impl DataFactory for Data { + fn set(&self, ext: &mut Extensions) { + ext.insert(self.0.clone()) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index b762f3cb9..1ac018803 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -1,5 +1,5 @@ use std::marker::PhantomData; -use std::{fmt, io, net}; +use std::{fmt, io, net, rc}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_server_config::{ @@ -15,6 +15,7 @@ use crate::body::MessageBody; use crate::builder::HttpServiceBuilder; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error}; +use crate::helpers::DataFactory; use crate::request::Request; use crate::response::Response; use crate::{h1, h2::Dispatcher}; @@ -25,6 +26,7 @@ pub struct HttpService, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -61,6 +63,7 @@ where srv: service.into_new_service(), expect: h1::ExpectHandler, upgrade: None, + on_connect: None, _t: PhantomData, } } @@ -75,6 +78,7 @@ where srv: service.into_new_service(), expect: h1::ExpectHandler, upgrade: None, + on_connect: None, _t: PhantomData, } } @@ -104,6 +108,7 @@ where cfg: self.cfg, srv: self.srv, upgrade: self.upgrade, + on_connect: self.on_connect, _t: PhantomData, } } @@ -127,9 +132,19 @@ where cfg: self.cfg, srv: self.srv, expect: self.expect, + on_connect: self.on_connect, _t: PhantomData, } } + + /// Set on connect callback. + pub(crate) fn on_connect( + mut self, + f: Option Box>>, + ) -> Self { + self.on_connect = f; + self + } } impl NewService for HttpService @@ -167,6 +182,7 @@ where fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)), expect: None, upgrade: None, + on_connect: self.on_connect.clone(), cfg: Some(self.cfg.clone()), _t: PhantomData, } @@ -180,6 +196,7 @@ pub struct HttpServiceResponse, expect: Option, upgrade: Option, + on_connect: Option Box>>, cfg: Option, _t: PhantomData<(T, P, B)>, } @@ -229,6 +246,7 @@ where service, self.expect.take().unwrap(), self.upgrade.take(), + self.on_connect.clone(), ))) } } @@ -239,6 +257,7 @@ pub struct HttpServiceHandler { expect: CloneableService, upgrade: Option>, cfg: ServiceConfig, + on_connect: Option Box>>, _t: PhantomData<(T, P, B, X)>, } @@ -259,9 +278,11 @@ where srv: S, expect: X, upgrade: Option, + on_connect: Option Box>>, ) -> HttpServiceHandler { HttpServiceHandler { cfg, + on_connect, srv: CloneableService::new(srv), expect: CloneableService::new(expect), upgrade: upgrade.map(|s| CloneableService::new(s)), @@ -319,6 +340,13 @@ where fn call(&mut self, req: Self::Request) -> Self::Future { let (io, _, proto) = req.into_parts(); + + let on_connect = if let Some(ref on_connect) = self.on_connect { + Some(on_connect(&io)) + } else { + None + }; + match proto { Protocol::Http2 => { let peer_addr = io.peer_addr(); @@ -332,6 +360,7 @@ where self.cfg.clone(), self.srv.clone(), peer_addr, + on_connect, ))), } } @@ -342,6 +371,7 @@ where self.srv.clone(), self.expect.clone(), self.upgrade.clone(), + on_connect, )), }, _ => HttpServiceHandlerResponse { @@ -352,6 +382,7 @@ where self.srv.clone(), self.expect.clone(), self.upgrade.clone(), + on_connect, ))), }, } @@ -380,6 +411,7 @@ where CloneableService, CloneableService, Option>, + Option>, )>, ), Handshake( @@ -388,6 +420,7 @@ where ServiceConfig, CloneableService, Option, + Option>, )>, ), } @@ -448,7 +481,8 @@ where } else { panic!() } - let (io, buf, cfg, srv, expect, upgrade) = data.take().unwrap(); + let (io, buf, cfg, srv, expect, upgrade, on_connect) = + data.take().unwrap(); if buf[..14] == HTTP2_PREFACE[..] { let peer_addr = io.peer_addr(); let io = Io { @@ -460,6 +494,7 @@ where cfg, srv, peer_addr, + on_connect, ))); } else { self.state = State::H1(h1::Dispatcher::with_timeout( @@ -471,6 +506,7 @@ where srv, expect, upgrade, + on_connect, )) } self.poll() @@ -488,8 +524,10 @@ where } else { panic!() }; - let (_, cfg, srv, peer_addr) = data.take().unwrap(); - self.state = State::H2(Dispatcher::new(srv, conn, cfg, None, peer_addr)); + let (_, cfg, srv, peer_addr, on_connect) = data.take().unwrap(); + self.state = State::H2(Dispatcher::new( + srv, conn, on_connect, cfg, None, peer_addr, + )); self.poll() } } From b77ed193f79e1d5ad70cc34e479e12c315c5e98e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 14:36:20 +0600 Subject: [PATCH 38/80] prepare actix-web release --- CHANGES.md | 2 +- Cargo.toml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dcefdec55..6c7a8b31f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.3] - unreleased +## [1.0.3] - 2019-06-28 ### Added diff --git a/Cargo.toml b/Cargo.toml index 4f8cd745d..4e492e19e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.2" +version = "1.0.3" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -71,11 +71,11 @@ rust-tls = ["rustls", "actix-server/rust-tls"] [dependencies] actix-codec = "0.1.2" actix-service = "0.4.1" -actix-utils = "0.4.1" +actix-utils = "0.4.2" actix-router = "0.1.5" -actix-rt = "0.2.2" +actix-rt = "0.2.3" actix-web-codegen = "0.1.2" -actix-http = "0.2.4" +actix-http = "0.2.5" actix-server = "0.5.1" actix-server-config = "0.1.1" actix-threadpool = "0.1.1" @@ -103,7 +103,7 @@ rustls = { version = "0.15", optional = true } [dev-dependencies] actix = { version = "0.8.3" } -actix-http = { version = "0.2.4", features=["ssl", "brotli", "flate2-zlib"] } +actix-http = { version = "0.2.5", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.2", features=["ssl"] } rand = "0.6" env_logger = "0.6" From 12b51748503d9802a51814bd49c032ec1e7344ce Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 28 Jun 2019 14:46:26 +0600 Subject: [PATCH 39/80] update deps --- actix-web-actors/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 864d8d953..eb5fb1115 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -19,8 +19,8 @@ path = "src/lib.rs" [dependencies] actix = "0.8.3" -actix-web = "1.0.2" -actix-http = "0.2.4" +actix-web = "1.0.3" +actix-http = "0.2.5" actix-codec = "0.1.2" bytes = "0.4" futures = "0.1.25" From 37f4ce8604f3a3cc8cb789d17ee5b4aac8b5111c Mon Sep 17 00:00:00 2001 From: Cameron Dershem Date: Sat, 29 Jun 2019 00:38:16 -0400 Subject: [PATCH 40/80] Fixes typo in docs. (#948) Small typo in docs. --- src/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test.rs b/src/test.rs index 5ab417bd6..208360a29 100644 --- a/src/test.rs +++ b/src/test.rs @@ -64,7 +64,7 @@ where RT.with(move |rt| rt.borrow_mut().get_mut().block_on(f.into_future())) } -/// Runs the provided function, blocking the current thread until the resul +/// Runs the provided function, blocking the current thread until the result /// future completes. /// /// This function can be used to synchronously block the current thread From 0e05b37082fa57444858b46e1a8b57b731777f1c Mon Sep 17 00:00:00 2001 From: dowwie Date: Sat, 29 Jun 2019 14:24:02 -0400 Subject: [PATCH 41/80] updated cookie session to update on change --- actix-session/src/cookie.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index 55904f5bd..de1faea96 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -28,7 +28,7 @@ use futures::future::{ok, Future, FutureResult}; use futures::Poll; use serde_json::error::Error as JsonError; -use crate::Session; +use crate::{Session, SessionStatus}; /// Errors that can occur during handling cookie session #[derive(Debug, From, Display)] @@ -308,10 +308,10 @@ where Session::set_session(state.into_iter(), &mut req); Box::new(self.service.call(req).map(move |mut res| { - if let (_status, Some(state)) = Session::get_changes(&mut res) { - res.checked_expr(|res| inner.set_cookie(res, state)) - } else { - res + match Session::get_changes(&mut res) { + (SessionStatus::Changed, Some(state)) => + res.checked_expr(|res| inner.set_cookie(res, state)), + _ => res } })) } From 5901dfee1a1ed553cab216ad480ff784baa7435f Mon Sep 17 00:00:00 2001 From: Sindre Johansen Date: Sun, 30 Jun 2019 17:30:04 +0200 Subject: [PATCH 42/80] Fix link to actix-cors (#950) --- actix-cors/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-cors/README.md b/actix-cors/README.md index 60b615c76..980d98ca1 100644 --- a/actix-cors/README.md +++ b/actix-cors/README.md @@ -3,7 +3,7 @@ ## Documentation & community resources * [User Guide](https://actix.rs/docs/) -* [API Documentation](https://docs.rs/actix-identity/) +* [API Documentation](https://docs.rs/actix-cors/) * [Chat on gitter](https://gitter.im/actix/actix) -* Cargo package: [actix-session](https://crates.io/crates/actix-identity) +* Cargo package: [actix-cors](https://crates.io/crates/actix-cors) * Minimum supported Rust version: 1.34 or later From d2eb1edac33f0617ca5d9869258f678365428803 Mon Sep 17 00:00:00 2001 From: Alec Moskvin Date: Sun, 30 Jun 2019 23:34:42 -0400 Subject: [PATCH 43/80] Actix-web client: Always append a colon after username in basic auth (#949) * Always append a colon after username in basic auth * Update CHANGES.md --- awc/CHANGES.md | 7 +++++++ awc/src/builder.rs | 4 ++-- awc/src/request.rs | 4 ++-- awc/src/ws.rs | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index b5f64dd37..fd5d01903 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.2.2] - TBD + +### Changed + +* Always append a colon after username in basic auth + + ## [0.2.1] - 2019-06-05 ### Added diff --git a/awc/src/builder.rs b/awc/src/builder.rs index 2bc52a431..a58265c5f 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -115,7 +115,7 @@ impl ClientBuilder { { let auth = match password { Some(password) => format!("{}:{}", username, password), - None => format!("{}", username), + None => format!("{}:", username), }; self.header( header::AUTHORIZATION, @@ -164,7 +164,7 @@ mod tests { .unwrap() .to_str() .unwrap(), - "Basic dXNlcm5hbWU=" + "Basic dXNlcm5hbWU6" ); } diff --git a/awc/src/request.rs b/awc/src/request.rs index 5c09df816..36cd6fcf3 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -280,7 +280,7 @@ impl ClientRequest { { let auth = match password { Some(password) => format!("{}:{}", username, password), - None => format!("{}", username), + None => format!("{}:", username), }; self.header( header::AUTHORIZATION, @@ -664,7 +664,7 @@ mod tests { .unwrap() .to_str() .unwrap(), - "Basic dXNlcm5hbWU=" + "Basic dXNlcm5hbWU6" ); } diff --git a/awc/src/ws.rs b/awc/src/ws.rs index d3e06d3d5..95bf6ef70 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -195,7 +195,7 @@ impl WebsocketsRequest { { let auth = match password { Some(password) => format!("{}:{}", username, password), - None => format!("{}", username), + None => format!("{}:", username), }; self.header(AUTHORIZATION, format!("Basic {}", base64::encode(&auth))) } @@ -443,7 +443,7 @@ mod tests { .unwrap() .to_str() .unwrap(), - "Basic dXNlcm5hbWU=" + "Basic dXNlcm5hbWU6" ); } From dbab55dd6b971c97684d7deca23f327a3a2694f6 Mon Sep 17 00:00:00 2001 From: messense Date: Mon, 1 Jul 2019 11:37:03 +0800 Subject: [PATCH 44/80] Bump rand crate version to 0.7 (#951) --- CHANGES.md | 6 ++++++ Cargo.toml | 2 +- actix-http/CHANGES.md | 6 ++++++ actix-http/Cargo.toml | 2 +- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 6 +++--- 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 6c7a8b31f..641e09bdd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [1.0.4] - TBD + +### Changed + +* Upgrade `rand` dependency version to 0.7 + ## [1.0.3] - 2019-06-28 ### Added diff --git a/Cargo.toml b/Cargo.toml index 4e492e19e..57676accc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,7 @@ rustls = { version = "0.15", optional = true } actix = { version = "0.8.3" } actix-http = { version = "0.2.5", features=["ssl", "brotli", "flate2-zlib"] } actix-http-test = { version = "0.2.2", features=["ssl"] } -rand = "0.6" +rand = "0.7" env_logger = "0.6" serde_derive = "1.0" tokio-timer = "0.2.8" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 636cbedf7..516793264 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,5 +1,11 @@ # Changes +## [0.2.6] - TBD + +### Changed + +* Upgrade `rand` dependency version to 0.7 + ## [0.2.5] - 2019-06-28 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index afbf0a487..b4d5e2068 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -70,7 +70,7 @@ language-tags = "0.2" log = "0.4" mime = "0.3" percent-encoding = "1.0" -rand = "0.6" +rand = "0.7" regex = "1.0" serde = "1.0" serde_json = "1.0" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index fd5d01903..3020eb2f9 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -6,6 +6,8 @@ * Always append a colon after username in basic auth +* Upgrade `rand` dependency version to 0.7 + ## [0.2.1] - 2019-06-05 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index d0629f4fa..ecc9b949f 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -49,7 +49,7 @@ futures = "0.1.25" log =" 0.4" mime = "0.3" percent-encoding = "1.0" -rand = "0.6" +rand = "0.7" serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.5.3" @@ -66,5 +66,5 @@ actix-server = { version = "0.5.1", features=["ssl"] } brotli2 = { version="0.3.2" } flate2 = { version="1.0.2" } env_logger = "0.6" -rand = "0.6" -tokio-tcp = "0.1" \ No newline at end of file +rand = "0.7" +tokio-tcp = "0.1" From a0a469fe8541466d38a4d8c963c505a486f4fb93 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 1 Jul 2019 11:33:11 +0600 Subject: [PATCH 45/80] disable travis cargo cache --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5f7d01a3f..97a05cc96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ sudo: required dist: trusty cache: - cargo: true + # cargo: true apt: true matrix: From a28b7139e6bd2dedeeb24d839aeaebf5276cc8ca Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 1 Jul 2019 11:34:57 +0600 Subject: [PATCH 46/80] prepare awc release --- awc/CHANGES.md | 2 +- awc/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 3020eb2f9..602f9a3b6 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [0.2.2] - TBD +## [0.2.2] - 2019-07-01 ### Changed diff --git a/awc/Cargo.toml b/awc/Cargo.toml index ecc9b949f..234662e97 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "0.2.1" +version = "0.2.2" authors = ["Nikolay Kim "] description = "Actix http client." readme = "README.md" From 099a8ff7d82184512ae5862ca0e6d088a8838367 Mon Sep 17 00:00:00 2001 From: dowwie Date: Mon, 1 Jul 2019 15:26:19 -0400 Subject: [PATCH 47/80] updated session cookie to support login, logout, changes --- actix-session/src/cookie.rs | 42 ++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index de1faea96..45f24817e 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -119,7 +119,21 @@ impl CookieSessionInner { Ok(()) } - fn load(&self, req: &ServiceRequest) -> HashMap { + /// invalidates session cookie + fn remove_cookie(&self, res: &mut ServiceResponse) + -> Result<(), Error> { + let mut cookie = Cookie::named(self.name.clone()); + cookie.set_value(""); + cookie.set_max_age(time::Duration::seconds(0)); + cookie.set_expires(time::now() - time::Duration::days(365)); + + let val = HeaderValue::from_str(&cookie.to_string())?; + res.headers_mut().append(SET_COOKIE, val); + + Ok(()) + } + + fn load(&self, req: &ServiceRequest) -> (bool, HashMap) { if let Ok(cookies) = req.cookies() { for cookie in cookies.iter() { if cookie.name() == self.name { @@ -134,13 +148,13 @@ impl CookieSessionInner { }; if let Some(cookie) = cookie_opt { if let Ok(val) = serde_json::from_str(cookie.value()) { - return val; + return (false, val); } } } } } - HashMap::new() + (true, HashMap::new()) } } @@ -302,15 +316,33 @@ where self.service.poll_ready() } + /// On first request, a new session cookie is returned in response, regardless + /// of whether any session state is set. With subsequent requests, if the + /// session state changes, then set-cookie is returned in response. As + /// a user logs out, call session.purge() to set SessionStatus accordingly + /// and this will trigger removal of the session cookie in the response. fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let inner = self.inner.clone(); - let state = self.inner.load(&req); + let (is_new, state) = self.inner.load(&req); Session::set_session(state.into_iter(), &mut req); Box::new(self.service.call(req).map(move |mut res| { match Session::get_changes(&mut res) { - (SessionStatus::Changed, Some(state)) => + (SessionStatus::Changed, Some(state)) + | (SessionStatus::Renewed, Some(state)) => res.checked_expr(|res| inner.set_cookie(res, state)), + (SessionStatus::Unchanged, _) => + // set a new session cookie upon first request (new client) + if is_new { + let state: HashMap = HashMap::new(); + res.checked_expr(|res| inner.set_cookie(res, state.into_iter())) + } else { + res + }, + (SessionStatus::Purged, _) => { + inner.remove_cookie(&mut res); + res + }, _ => res } })) From 5bf5b0acd2b60c5d56ab60b0d33523b9952916c1 Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 3 Jul 2019 07:46:46 -0400 Subject: [PATCH 48/80] updated CHANGES with info about actix-session update --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a20713107..243dc8278 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,9 @@ ### Changed * Use `encoding_rs` crate instead of unmaintained `encoding` crate +* Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` + at successful login to cycle a session (new key, cookie). Use ``Session.purge()`` + at logout to invalid a session cookie (and remove from redis cache, if applicable). ## [1.0.2] - 2019-06-17 From dabc4fe00b1b2cf149793fae40440e36a6e5e95f Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 3 Jul 2019 07:50:11 -0400 Subject: [PATCH 49/80] updated actix-session/CHANGES with info --- actix-session/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actix-session/CHANGES.md b/actix-session/CHANGES.md index 10aea8700..ec1606ded 100644 --- a/actix-session/CHANGES.md +++ b/actix-session/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## [0.2.0] - 2019-07-03 +* Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` + at successful login to cycle a session (new key, cookie). Use ``Session.purge()`` + at logout to invalid a session cookie (and remove from redis cache, if applicable). + ## [0.1.1] - 2019-06-03 * Fix optional cookie session support From 2d424957fb4d4feea0e3c104b84f60d4ac0af2cf Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 3 Jul 2019 07:50:45 -0400 Subject: [PATCH 50/80] updated version in Cargo to 0.2 --- actix-session/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-session/Cargo.toml b/actix-session/Cargo.toml index 4c1d66570..d973661ef 100644 --- a/actix-session/Cargo.toml +++ b/actix-session/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-session" -version = "0.1.1" +version = "0.2.0" authors = ["Nikolay Kim "] description = "Session for actix web framework." readme = "README.md" From 1fdd77bffac9f16d780eff9aaefc23889eeae513 Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 3 Jul 2019 07:56:50 -0400 Subject: [PATCH 51/80] reworded session info in CHANGES --- CHANGES.md | 5 +++-- actix-session/CHANGES.md | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 243dc8278..5937cf066 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,8 +6,9 @@ * Use `encoding_rs` crate instead of unmaintained `encoding` crate * Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` - at successful login to cycle a session (new key, cookie). Use ``Session.purge()`` - at logout to invalid a session cookie (and remove from redis cache, if applicable). + at successful login to cycle a session (new key/cookie but keeps state). + Use ``Session.purge()`` at logout to invalid a session cookie (and remove + from redis cache, if applicable). ## [1.0.2] - 2019-06-17 diff --git a/actix-session/CHANGES.md b/actix-session/CHANGES.md index ec1606ded..927485051 100644 --- a/actix-session/CHANGES.md +++ b/actix-session/CHANGES.md @@ -2,8 +2,10 @@ ## [0.2.0] - 2019-07-03 * Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` - at successful login to cycle a session (new key, cookie). Use ``Session.purge()`` - at logout to invalid a session cookie (and remove from redis cache, if applicable). + at successful login to cycle a session (new key/cookie but keeps state). + Use ``Session.purge()`` at logout to invalid a session cookie (and remove + from redis cache, if applicable). + ## [0.1.1] - 2019-06-03 From 7596ab69e0b0a40a0c07627a55a2f2a47c8ecc6a Mon Sep 17 00:00:00 2001 From: dowwie Date: Wed, 3 Jul 2019 08:55:29 -0400 Subject: [PATCH 52/80] reverted actix-web/CHANGES.md --- CHANGES.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5937cf066..a20713107 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,10 +5,6 @@ ### Changed * Use `encoding_rs` crate instead of unmaintained `encoding` crate -* Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` - at successful login to cycle a session (new key/cookie but keeps state). - Use ``Session.purge()`` at logout to invalid a session cookie (and remove - from redis cache, if applicable). ## [1.0.2] - 2019-06-17 From 0d8a4304a922b8f2da0fd50579dc2cc3dacc3ded Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Fri, 5 Jul 2019 17:46:55 +0300 Subject: [PATCH 53/80] Drop a duplicated word (#958) --- src/types/query.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/types/query.rs b/src/types/query.rs index 2c07edfbd..17240c0b5 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -13,7 +13,7 @@ use crate::extract::FromRequest; use crate::request::HttpRequest; #[derive(PartialEq, Eq, PartialOrd, Ord)] -/// Extract typed information from from the request's query. +/// Extract typed information from the request's query. /// /// ## Example /// @@ -90,7 +90,7 @@ impl fmt::Display for Query { } } -/// Extract typed information from from the request's query. +/// Extract typed information from the request's query. /// /// ## Example /// From e1fcd203f8f29b8e2c2cc38a9862c5c52a466af4 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Mon, 8 Jul 2019 05:48:20 -0400 Subject: [PATCH 54/80] Update the copyless version to 0.1.4 (#956) < 0.1.4 failed to check for null when doing allocations which could lead to null dereferences. --- actix-http/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index b4d5e2068..5db7a6ca3 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -55,7 +55,7 @@ base64 = "0.10" bitflags = "1.0" bytes = "0.4" byteorder = "1.2" -copyless = "0.1.2" +copyless = "0.1.4" derive_more = "0.15.0" either = "1.5.2" encoding_rs = "0.8" From f410f3330fb771e8d51b7448ea2b0d3981d95891 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 8 Jul 2019 23:25:51 +0600 Subject: [PATCH 55/80] prepare actix-session release --- actix-session/CHANGES.md | 6 +++--- actix-session/README.md | 2 +- actix-session/src/cookie.rs | 24 +++++++++++++----------- actix-session/src/lib.rs | 8 +++++--- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/actix-session/CHANGES.md b/actix-session/CHANGES.md index 927485051..d85f6d5f1 100644 --- a/actix-session/CHANGES.md +++ b/actix-session/CHANGES.md @@ -1,12 +1,12 @@ # Changes -## [0.2.0] - 2019-07-03 +## [0.2.0] - 2019-07-08 + * Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()`` at successful login to cycle a session (new key/cookie but keeps state). - Use ``Session.purge()`` at logout to invalid a session cookie (and remove + Use ``Session.purge()`` at logout to invalid a session cookie (and remove from redis cache, if applicable). - ## [0.1.1] - 2019-06-03 * Fix optional cookie session support diff --git a/actix-session/README.md b/actix-session/README.md index 7d6830412..0aee756fd 100644 --- a/actix-session/README.md +++ b/actix-session/README.md @@ -6,4 +6,4 @@ * [API Documentation](https://docs.rs/actix-session/) * [Chat on gitter](https://gitter.im/actix/actix) * Cargo package: [actix-session](https://crates.io/crates/actix-session) -* Minimum supported Rust version: 1.33 or later +* Minimum supported Rust version: 1.34 or later diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index 45f24817e..8627ce4c8 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -120,8 +120,7 @@ impl CookieSessionInner { } /// invalidates session cookie - fn remove_cookie(&self, res: &mut ServiceResponse) - -> Result<(), Error> { + fn remove_cookie(&self, res: &mut ServiceResponse) -> Result<(), Error> { let mut cookie = Cookie::named(self.name.clone()); cookie.set_value(""); cookie.set_max_age(time::Duration::seconds(0)); @@ -317,7 +316,7 @@ where } /// On first request, a new session cookie is returned in response, regardless - /// of whether any session state is set. With subsequent requests, if the + /// of whether any session state is set. With subsequent requests, if the /// session state changes, then set-cookie is returned in response. As /// a user logs out, call session.purge() to set SessionStatus accordingly /// and this will trigger removal of the session cookie in the response. @@ -329,21 +328,24 @@ where Box::new(self.service.call(req).map(move |mut res| { match Session::get_changes(&mut res) { (SessionStatus::Changed, Some(state)) - | (SessionStatus::Renewed, Some(state)) => - res.checked_expr(|res| inner.set_cookie(res, state)), + | (SessionStatus::Renewed, Some(state)) => { + res.checked_expr(|res| inner.set_cookie(res, state)) + } (SessionStatus::Unchanged, _) => - // set a new session cookie upon first request (new client) + // set a new session cookie upon first request (new client) + { if is_new { let state: HashMap = HashMap::new(); res.checked_expr(|res| inner.set_cookie(res, state.into_iter())) } else { res - }, + } + } (SessionStatus::Purged, _) => { - inner.remove_cookie(&mut res); - res - }, - _ => res + inner.remove_cookie(&mut res); + res + } + _ => res, } })) } diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index aaf0ab02f..27ad2b876 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -103,7 +103,7 @@ pub enum SessionStatus { Changed, Purged, Renewed, - Unchanged + Unchanged, } impl Default for SessionStatus { fn default() -> SessionStatus { @@ -183,7 +183,10 @@ impl Session { pub fn get_changes( res: &mut ServiceResponse, - ) -> (SessionStatus, Option>) { + ) -> ( + SessionStatus, + Option>, + ) { if let Some(s_impl) = res .request() .extensions() @@ -286,7 +289,6 @@ mod tests { assert_eq!(session.0.borrow().status, SessionStatus::Purged); } - #[test] fn renew_session() { let mut req = test::TestRequest::default().to_srv_request(); From 69456991f6d19e056e13b5f7572f9ecbb959d802 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 11 Jul 2019 14:40:37 +0600 Subject: [PATCH 56/80] update api doc example for client and add panic info for connection_info --- awc/src/lib.rs | 2 +- src/request.rs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 9fbda8aa8..45231326d 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -1,7 +1,7 @@ //! An HTTP Client //! //! ```rust -//! # use futures::future::{Future, lazy}; +//! use futures::future::{lazy, Future}; //! use actix_rt::System; //! use awc::Client; //! diff --git a/src/request.rs b/src/request.rs index 07aac8cf7..d0d24f4f0 100644 --- a/src/request.rs +++ b/src/request.rs @@ -186,6 +186,9 @@ impl HttpRequest { } /// Get *ConnectionInfo* for the current request. + /// + /// This method panics if request's extensions container is already + /// borrowed. #[inline] pub fn connection_info(&self) -> Ref { ConnectionInfo::get(self.head(), &*self.app_config()) From b1143168e53a65824b23b6cfff6d2db7921846ef Mon Sep 17 00:00:00 2001 From: messense Date: Thu, 11 Jul 2019 16:42:58 +0800 Subject: [PATCH 57/80] Impl Responder for (T, StatusCode) where T: Responder (#954) --- CHANGES.md | 4 ++++ src/responder.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 641e09bdd..0b3f3e0c3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ## [1.0.4] - TBD +### Added + +* Add `Responder` impl for `(T, StatusCode) where T: Responder` + ### Changed * Upgrade `rand` dependency version to 0.7 diff --git a/src/responder.rs b/src/responder.rs index 47a8800ef..6bd25e6eb 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -137,6 +137,22 @@ impl Responder for () { } } +impl Responder for (T, StatusCode) +where + T: Responder, +{ + type Error = T::Error; + type Future = CustomResponderFut; + + fn respond_to(self, req: &HttpRequest) -> Self::Future { + CustomResponderFut { + fut: self.0.respond_to(req).into_future(), + status: Some(self.1), + headers: None, + } + } +} + impl Responder for &'static str { type Error = Error; type Future = FutureResult; @@ -624,4 +640,29 @@ pub(crate) mod tests { HeaderValue::from_static("json") ); } + + #[test] + fn test_tuple_responder_with_status_code() { + let req = TestRequest::default().to_http_request(); + let res = block_on( + ("test".to_string(), StatusCode::BAD_REQUEST).respond_to(&req) + ) + .unwrap(); + assert_eq!(res.status(), StatusCode::BAD_REQUEST); + assert_eq!(res.body().bin_ref(), b"test"); + + let req = TestRequest::default().to_http_request(); + let res = block_on( + ("test".to_string(), StatusCode::OK) + .with_header("content-type", "json") + .respond_to(&req) + ) + .unwrap(); + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.body().bin_ref(), b"test"); + assert_eq!( + res.headers().get(CONTENT_TYPE).unwrap(), + HeaderValue::from_static("json") + ); + } } From 8d17c8651f5f1eb721ffe2ba550512aa7241ef1d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 11 Jul 2019 14:45:58 +0600 Subject: [PATCH 58/80] update bench link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cae737b68..e533c848c 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ You may consider checking out ## Benchmarks -* [TechEmpower Framework Benchmark](https://www.techempower.com/benchmarks/#section=data-r16&hw=ph&test=plaintext) +* [TechEmpower Framework Benchmark](https://www.techempower.com/benchmarks/#section=data-r18) ## License From 6f71409355d6c51501dfdad2deb2efac13a8174f Mon Sep 17 00:00:00 2001 From: Andrea Corradi Date: Tue, 16 Jul 2019 06:19:28 +0200 Subject: [PATCH 59/80] Add DELETE, PATCH, OPTIONS methods to TestServerRunner (#973) --- CHANGES.md | 1 + test-server/src/lib.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 0b3f3e0c3..0943fbdcf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ ### Added * Add `Responder` impl for `(T, StatusCode) where T: Responder` +* Add `delete`, `options`, `patch` methods to `TestServerRunner` ### Changed diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 1fbaa6c74..c49026faa 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -265,6 +265,36 @@ impl TestServerRuntime { self.client.put(self.surl(path.as_ref()).as_str()) } + /// Create `PATCH` request + pub fn patch>(&self, path: S) -> ClientRequest { + self.client.patch(self.url(path.as_ref()).as_str()) + } + + /// Create https `PATCH` request + pub fn spatch>(&self, path: S) -> ClientRequest { + self.client.patch(self.surl(path.as_ref()).as_str()) + } + + /// Create `DELETE` request + pub fn delete>(&self, path: S) -> ClientRequest { + self.client.delete(self.url(path.as_ref()).as_str()) + } + + /// Create https `DELETE` request + pub fn sdelete>(&self, path: S) -> ClientRequest { + self.client.delete(self.surl(path.as_ref()).as_str()) + } + + /// Create `OPTIONS` request + pub fn options>(&self, path: S) -> ClientRequest { + self.client.options(self.url(path.as_ref()).as_str()) + } + + /// Create https `OPTIONS` request + pub fn soptions>(&self, path: S) -> ClientRequest { + self.client.options(self.surl(path.as_ref()).as_str()) + } + /// Connect to test http server pub fn request>(&self, method: Method, path: S) -> ClientRequest { self.client.request(method, path.as_ref()) From c45728ac01743aed6f12308aa2d1c3ef32aa2b19 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Tue, 16 Jul 2019 10:21:52 +0600 Subject: [PATCH 60/80] prep test server release --- CHANGES.md | 1 - src/responder.rs | 9 ++++----- test-server/CHANGES.md | 4 ++++ test-server/Cargo.toml | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0943fbdcf..0b3f3e0c3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,7 +5,6 @@ ### Added * Add `Responder` impl for `(T, StatusCode) where T: Responder` -* Add `delete`, `options`, `patch` methods to `TestServerRunner` ### Changed diff --git a/src/responder.rs b/src/responder.rs index 6bd25e6eb..39927c78f 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -644,10 +644,9 @@ pub(crate) mod tests { #[test] fn test_tuple_responder_with_status_code() { let req = TestRequest::default().to_http_request(); - let res = block_on( - ("test".to_string(), StatusCode::BAD_REQUEST).respond_to(&req) - ) - .unwrap(); + let res = + block_on(("test".to_string(), StatusCode::BAD_REQUEST).respond_to(&req)) + .unwrap(); assert_eq!(res.status(), StatusCode::BAD_REQUEST); assert_eq!(res.body().bin_ref(), b"test"); @@ -655,7 +654,7 @@ pub(crate) mod tests { let res = block_on( ("test".to_string(), StatusCode::OK) .with_header("content-type", "json") - .respond_to(&req) + .respond_to(&req), ) .unwrap(); assert_eq!(res.status(), StatusCode::OK); diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index e7292c0ec..f3e98010a 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.2.3] - 2019-07-16 + +* Add `delete`, `options`, `patch` methods to `TestServerRunner` + ## [0.2.2] - 2019-06-16 * Add .put() and .sput() methods diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 4231b17bf..445ed33e6 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "0.2.2" +version = "0.2.3" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -35,7 +35,7 @@ actix-rt = "0.2.2" actix-service = "0.4.1" actix-server = "0.5.1" actix-utils = "0.4.1" -awc = "0.2.1" +awc = "0.2.2" base64 = "0.10" bytes = "0.4" From c65dbaf88ed6172484d10e18473aa27d7fcf7338 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 11:33:05 +0600 Subject: [PATCH 61/80] expose app's ResourceMap via resource_map method --- CHANGES.md | 4 ++++ src/request.rs | 6 ++++++ src/service.rs | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 0b3f3e0c3..11158925c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,10 +6,14 @@ * Add `Responder` impl for `(T, StatusCode) where T: Responder` +* Allow to access app's resource map via + `ServiceRequest::resource_map()` and `HttpRequest::resource_map()` methods. + ### Changed * Upgrade `rand` dependency version to 0.7 + ## [1.0.3] - 2019-06-28 ### Added diff --git a/src/request.rs b/src/request.rs index d0d24f4f0..0fc0647ff 100644 --- a/src/request.rs +++ b/src/request.rs @@ -174,6 +174,12 @@ impl HttpRequest { self.url_for(name, &NO_PARAMS) } + #[inline] + /// Get a reference to a `ResourceMap` of current application. + pub fn resource_map(&self) -> &ResourceMap { + &self.0.rmap + } + /// Peer socket address /// /// Peer address is actual socket address, if proxy is used in front of diff --git a/src/service.rs b/src/service.rs index 722813a9f..5863a100e 100644 --- a/src/service.rs +++ b/src/service.rs @@ -18,6 +18,7 @@ use crate::dev::insert_slash; use crate::guard::Guard; use crate::info::ConnectionInfo; use crate::request::HttpRequest; +use crate::rmap::ResourceMap; pub trait HttpServiceFactory { fn register(self, config: &mut AppService); @@ -169,10 +170,17 @@ impl ServiceRequest { } #[inline] + /// Get a mutable reference to the Path parameters. pub fn match_info_mut(&mut self) -> &mut Path { self.0.match_info_mut() } + #[inline] + /// Get a reference to a `ResourceMap` of current application. + pub fn resource_map(&self) -> &ResourceMap { + self.0.resource_map() + } + /// Service configuration #[inline] pub fn app_config(&self) -> &AppConfig { From 7b1dcaffda60648b77535c2cec34946ab57cb0ed Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 11:44:39 +0600 Subject: [PATCH 62/80] cleanup deprecation warning for Box --- actix-cors/src/lib.rs | 2 +- actix-files/src/lib.rs | 8 ++++---- actix-framed/src/app.rs | 6 +++--- actix-framed/src/helpers.rs | 14 +++++++------- actix-framed/src/route.rs | 2 +- actix-http/src/client/connection.rs | 6 ++++-- actix-identity/src/lib.rs | 2 +- actix-session/src/cookie.rs | 2 +- awc/src/connect.rs | 4 ++-- src/app_service.rs | 6 +++--- src/extract.rs | 4 ++-- src/middleware/defaultheaders.rs | 2 +- src/middleware/errhandlers.rs | 4 ++-- src/resource.rs | 6 +++--- src/responder.rs | 6 +++--- src/route.rs | 15 ++++++++------- src/scope.rs | 6 +++--- src/types/form.rs | 4 ++-- src/types/json.rs | 4 ++-- src/types/payload.rs | 10 ++++++---- 20 files changed, 59 insertions(+), 54 deletions(-) diff --git a/actix-cors/src/lib.rs b/actix-cors/src/lib.rs index 5d0d013e3..ea1eb383b 100644 --- a/actix-cors/src/lib.rs +++ b/actix-cors/src/lib.rs @@ -681,7 +681,7 @@ where type Error = Error; type Future = Either< FutureResult, - Either>>, + Either>>, >; fn poll_ready(&mut self) -> Poll<(), Self::Error> { diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 8e87f7d89..82abb9990 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -50,7 +50,7 @@ pub struct ChunkedReadFile { size: u64, offset: u64, file: Option, - fut: Option>>>, + fut: Option>>>, counter: u64, } @@ -370,7 +370,7 @@ impl NewService for Files { type Error = Error; type Service = FilesService; type InitError = (); - type Future = Box>; + type Future = Box>; fn new_service(&self, _: &()) -> Self::Future { let mut srv = FilesService { @@ -416,7 +416,7 @@ impl FilesService { req: ServiceRequest, ) -> Either< FutureResult, - Box>, + Box>, > { log::debug!("Files: Failed to handle {}: {}", req.path(), e); if let Some(ref mut default) = self.default { @@ -433,7 +433,7 @@ impl Service for FilesService { type Error = Error; type Future = Either< FutureResult, - Box>, + Box>, >; fn poll_ready(&mut self) -> Poll<(), Self::Error> { diff --git a/actix-framed/src/app.rs b/actix-framed/src/app.rs index 297796bd1..a9d73a25c 100644 --- a/actix-framed/src/app.rs +++ b/actix-framed/src/app.rs @@ -13,7 +13,7 @@ use crate::helpers::{BoxedHttpNewService, BoxedHttpService, HttpNewService}; use crate::request::FramedRequest; use crate::state::State; -type BoxedResponse = Box>; +type BoxedResponse = Box>; pub trait HttpServiceFactory { type Factory: NewService; @@ -61,7 +61,7 @@ impl FramedApp { Request = FramedRequest, Response = (), Error = Error, - Future = Box>, + Future = Box>, >, { let path = factory.path().to_string(); @@ -129,7 +129,7 @@ pub struct CreateService { enum CreateServiceItem { Future( Option, - Box>, Error = ()>>, + Box>, Error = ()>>, ), Service(String, BoxedHttpService>), } diff --git a/actix-framed/src/helpers.rs b/actix-framed/src/helpers.rs index 944b729d4..5e84ad88c 100644 --- a/actix-framed/src/helpers.rs +++ b/actix-framed/src/helpers.rs @@ -7,7 +7,7 @@ pub(crate) type BoxedHttpService = Box< Request = Req, Response = (), Error = Error, - Future = Box>, + Future = Box>, >, >; @@ -19,7 +19,7 @@ pub(crate) type BoxedHttpNewService = Box< Error = Error, InitError = (), Service = BoxedHttpService, - Future = Box, Error = ()>>, + Future = Box, Error = ()>>, >, >; @@ -30,7 +30,7 @@ where T: NewService, T::Response: 'static, T::Future: 'static, - T::Service: Service>> + 'static, + T::Service: Service>> + 'static, ::Future: 'static, { pub fn new(service: T) -> Self { @@ -43,7 +43,7 @@ where T: NewService, T::Request: 'static, T::Future: 'static, - T::Service: Service>> + 'static, + T::Service: Service>> + 'static, ::Future: 'static, { type Config = (); @@ -52,7 +52,7 @@ where type Error = Error; type InitError = (); type Service = BoxedHttpService; - type Future = Box>; + type Future = Box>; fn new_service(&self, _: &()) -> Self::Future { Box::new(self.0.new_service(&()).map_err(|_| ()).and_then(|service| { @@ -70,7 +70,7 @@ impl Service for HttpServiceWrapper where T: Service< Response = (), - Future = Box>, + Future = Box>, Error = Error, >, T::Request: 'static, @@ -78,7 +78,7 @@ where type Request = T::Request; type Response = (); type Error = Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() diff --git a/actix-framed/src/route.rs b/actix-framed/src/route.rs index c50401d6d..5beb24165 100644 --- a/actix-framed/src/route.rs +++ b/actix-framed/src/route.rs @@ -140,7 +140,7 @@ where type Request = FramedRequest; type Response = (); type Error = Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { Ok(Async::Ready(())) diff --git a/actix-http/src/client/connection.rs b/actix-http/src/client/connection.rs index 9354fca4a..2f3103d4e 100644 --- a/actix-http/src/client/connection.rs +++ b/actix-http/src/client/connection.rs @@ -94,7 +94,8 @@ where T: AsyncRead + AsyncWrite + 'static, { type Io = T; - type Future = Box>; + type Future = + Box>; fn protocol(&self) -> Protocol { match self.io { @@ -169,7 +170,8 @@ where B: AsyncRead + AsyncWrite + 'static, { type Io = EitherIo; - type Future = Box>; + type Future = + Box>; fn protocol(&self) -> Protocol { match self { diff --git a/actix-identity/src/lib.rs b/actix-identity/src/lib.rs index 6664df676..fe7216a01 100644 --- a/actix-identity/src/lib.rs +++ b/actix-identity/src/lib.rs @@ -261,7 +261,7 @@ where type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.borrow_mut().poll_ready() diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index 8627ce4c8..87fc0b164 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -309,7 +309,7 @@ where type Request = ServiceRequest; type Response = ServiceResponse; type Error = S::Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() diff --git a/awc/src/connect.rs b/awc/src/connect.rs index 4b564d777..8344abbdc 100644 --- a/awc/src/connect.rs +++ b/awc/src/connect.rs @@ -20,7 +20,7 @@ pub(crate) trait Connect { head: RequestHead, body: Body, addr: Option, - ) -> Box>; + ) -> Box>; /// Send request, returns Response and Framed fn open_tunnel( @@ -49,7 +49,7 @@ where head: RequestHead, body: Body, addr: Option, - ) -> Box> { + ) -> Box> { Box::new( self.0 // connect to the host diff --git a/src/app_service.rs b/src/app_service.rs index 8ab9b352a..6012dcda9 100644 --- a/src/app_service.rs +++ b/src/app_service.rs @@ -23,7 +23,7 @@ type HttpService = BoxedService; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type BoxedResponse = Either< FutureResult, - Box>, + Box>, >; type FnDataFactory = Box Box, Error = ()>>>; @@ -297,14 +297,14 @@ impl NewService for AppRoutingFactory { } } -type HttpServiceFut = Box>; +type HttpServiceFut = Box>; /// Create app service #[doc(hidden)] pub struct AppRoutingFactoryResponse { fut: Vec, default: Option, - default_fut: Option>>, + default_fut: Option>>, } enum CreateAppRoutingItem { diff --git a/src/extract.rs b/src/extract.rs index 17b5cb40c..1687973ac 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -94,7 +94,7 @@ where { type Config = T::Config; type Error = Error; - type Future = Box, Error = Error>>; + type Future = Box, Error = Error>>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { @@ -165,7 +165,7 @@ where { type Config = T::Config; type Error = Error; - type Future = Box, Error = Error>>; + type Future = Box, Error = Error>>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index bddcdd552..ab2d36c2c 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -119,7 +119,7 @@ where type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() diff --git a/src/middleware/errhandlers.rs b/src/middleware/errhandlers.rs index ac166e0eb..afe7c72f1 100644 --- a/src/middleware/errhandlers.rs +++ b/src/middleware/errhandlers.rs @@ -15,7 +15,7 @@ pub enum ErrorHandlerResponse { /// New http response got generated Response(ServiceResponse), /// Result is a future that resolves to a new http response - Future(Box, Error = Error>>), + Future(Box, Error = Error>>), } type ErrorHandler = Fn(ServiceResponse) -> Result>; @@ -117,7 +117,7 @@ where type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Box>; + type Future = Box>; fn poll_ready(&mut self) -> Poll<(), Self::Error> { self.service.poll_ready() diff --git a/src/resource.rs b/src/resource.rs index c2691eebe..d09beb27b 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -245,7 +245,7 @@ where /// ```rust /// # use actix_web::*; /// # use futures::future::Future; - /// # fn index(req: HttpRequest) -> Box> { + /// # fn index(req: HttpRequest) -> Box> { /// # unimplemented!() /// # } /// App::new().service(web::resource("/").route(web::route().to_async(index))); @@ -478,7 +478,7 @@ pub struct CreateResourceService { fut: Vec, data: Option>, default: Option, - default_fut: Option>>, + default_fut: Option>>, } impl Future for CreateResourceService { @@ -542,7 +542,7 @@ impl Service for ResourceService { type Error = Error; type Future = Either< FutureResult, - Box>, + Box>, >; fn poll_ready(&mut self) -> Poll<(), Self::Error> { diff --git a/src/responder.rs b/src/responder.rs index 39927c78f..4988ad5bc 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -337,7 +337,7 @@ impl Future for CustomResponderFut { /// use actix_web::{Either, Error, HttpResponse}; /// /// type RegisterResult = -/// Either>>; +/// Either>>; /// /// fn index() -> RegisterResult { /// if is_a_variant() { @@ -411,13 +411,13 @@ where } } -impl Responder for Box> +impl Responder for Box> where I: Responder + 'static, E: Into + 'static, { type Error = Error; - type Future = Box>; + type Future = Box>; #[inline] fn respond_to(self, req: &HttpRequest) -> Self::Future { diff --git a/src/route.rs b/src/route.rs index 660b82002..591175d15 100644 --- a/src/route.rs +++ b/src/route.rs @@ -19,7 +19,7 @@ type BoxedRouteService = Box< Error = Error, Future = Either< FutureResult, - Box>, + Box>, >, >, >; @@ -32,7 +32,7 @@ type BoxedRouteNewService = Box< Error = Error, InitError = (), Service = BoxedRouteService, - Future = Box, Error = ()>>, + Future = Box, Error = ()>>, >, >; @@ -78,8 +78,9 @@ impl NewService for Route { } } -type RouteFuture = - Box, Error = ()>>; +type RouteFuture = Box< + dyn Future, Error = ()>, +>; pub struct CreateRouteService { fut: RouteFuture, @@ -123,7 +124,7 @@ impl Service for RouteService { type Error = Error; type Future = Either< FutureResult, - Box>, + Box>, >; fn poll_ready(&mut self) -> Poll<(), Self::Error> { @@ -317,7 +318,7 @@ where type Error = Error; type InitError = (); type Service = BoxedRouteService; - type Future = Box>; + type Future = Box>; fn new_service(&self, _: &()) -> Self::Future { Box::new( @@ -351,7 +352,7 @@ where type Error = Error; type Future = Either< FutureResult, - Box>, + Box>, >; fn poll_ready(&mut self) -> Poll<(), Self::Error> { diff --git a/src/scope.rs b/src/scope.rs index 400da668d..99afd7d16 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -28,7 +28,7 @@ type HttpService = BoxedService; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type BoxedResponse = Either< FutureResult, - Box>, + Box>, >; /// Resources scope. @@ -503,10 +503,10 @@ pub struct ScopeFactoryResponse { fut: Vec, data: Option>, default: Option, - default_fut: Option>>, + default_fut: Option>>, } -type HttpServiceFut = Box>; +type HttpServiceFut = Box>; enum CreateScopeServiceItem { Future(Option, Option, HttpServiceFut), diff --git a/src/types/form.rs b/src/types/form.rs index 32d0edb69..e61145b0d 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -73,7 +73,7 @@ where { type Config = FormConfig; type Error = Error; - type Future = Box>; + type Future = Box>; #[inline] fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { @@ -187,7 +187,7 @@ pub struct UrlEncoded { length: Option, encoding: &'static Encoding, err: Option, - fut: Option>>, + fut: Option>>, } impl UrlEncoded { diff --git a/src/types/json.rs b/src/types/json.rs index de0ffb54c..f309a3c5a 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -169,7 +169,7 @@ where T: DeserializeOwned + 'static, { type Error = Error; - type Future = Box>; + type Future = Box>; type Config = JsonConfig; #[inline] @@ -290,7 +290,7 @@ pub struct JsonBody { length: Option, stream: Option>, err: Option, - fut: Option>>, + fut: Option>>, } impl JsonBody diff --git a/src/types/payload.rs b/src/types/payload.rs index a8e85e4f3..8a634b4c9 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -124,7 +124,7 @@ impl FromRequest for Bytes { type Config = PayloadConfig; type Error = Error; type Future = - Either>, FutureResult>; + Either>, FutureResult>; #[inline] fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { @@ -177,8 +177,10 @@ impl FromRequest for Bytes { impl FromRequest for String { type Config = PayloadConfig; type Error = Error; - type Future = - Either>, FutureResult>; + type Future = Either< + Box>, + FutureResult, + >; #[inline] fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { @@ -291,7 +293,7 @@ pub struct HttpMessageBody { length: Option, stream: Option>, err: Option, - fut: Option>>, + fut: Option>>, } impl HttpMessageBody { From c01611d8b51ddc57841dce48270eaa66f0ab9030 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 12:07:12 +0600 Subject: [PATCH 63/80] prepare actix-web release --- CHANGES.md | 2 +- Cargo.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 11158925c..cb5f51126 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.4] - TBD +## [1.0.4] - 2019-07-17 ### Added diff --git a/Cargo.toml b/Cargo.toml index 57676accc..d781422ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.3" +version = "1.0.4" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -71,9 +71,9 @@ rust-tls = ["rustls", "actix-server/rust-tls"] [dependencies] actix-codec = "0.1.2" actix-service = "0.4.1" -actix-utils = "0.4.2" +actix-utils = "0.4.3" actix-router = "0.1.5" -actix-rt = "0.2.3" +actix-rt = "0.2.4" actix-web-codegen = "0.1.2" actix-http = "0.2.5" actix-server = "0.5.1" From 32718b7e3101e6d1507f883318dcc050890eda37 Mon Sep 17 00:00:00 2001 From: Ravi Shankar Date: Wed, 17 Jul 2019 12:28:42 +0530 Subject: [PATCH 64/80] Expose factory traits and some clippy fixes (#983) --- src/data.rs | 2 +- src/handler.rs | 2 +- src/info.rs | 2 +- src/lib.rs | 2 ++ src/middleware/compress.rs | 1 + src/middleware/defaultheaders.rs | 1 + src/middleware/logger.rs | 4 ++-- src/resource.rs | 2 +- src/rmap.rs | 2 +- src/scope.rs | 4 ++-- src/types/form.rs | 1 + src/types/json.rs | 1 + src/types/payload.rs | 1 + 13 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/data.rs b/src/data.rs index bd166b79c..3461d24f3 100644 --- a/src/data.rs +++ b/src/data.rs @@ -118,7 +118,7 @@ impl FromRequest for Data { impl DataFactory for Data { fn create(&self, extensions: &mut Extensions) -> bool { if !extensions.contains::>() { - let _ = extensions.insert(Data(self.0.clone())); + extensions.insert(Data(self.0.clone())); true } else { false diff --git a/src/handler.rs b/src/handler.rs index bd0b35517..078abbf1d 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -250,7 +250,7 @@ where Ok(Async::Ready(res)) => { self.fut2 = Some(res.respond_to(self.req.as_ref().unwrap()).into_future()); - return self.poll(); + self.poll() } Ok(Async::NotReady) => Ok(Async::NotReady), Err(e) => { diff --git a/src/info.rs b/src/info.rs index e9b375875..a6a7d7282 100644 --- a/src/info.rs +++ b/src/info.rs @@ -25,7 +25,7 @@ impl ConnectionInfo { Ref::map(req.extensions(), |e| e.get().unwrap()) } - #[allow(clippy::cyclomatic_complexity)] + #[allow(clippy::cyclomatic_complexity, clippy::cognitive_complexity, clippy::borrow_interior_mutable_const)] fn new(req: &RequestHead, cfg: &AppConfig) -> ConnectionInfo { let mut host = None; let mut scheme = None; diff --git a/src/lib.rs b/src/lib.rs index fffbc2f5e..345987ffa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -134,6 +134,8 @@ pub mod dev { //! ``` pub use crate::config::{AppConfig, AppService}; + #[doc(hidden)] + pub use crate::handler::{AsyncFactory, Factory}; pub use crate::info::ConnectionInfo; pub use crate::rmap::ResourceMap; pub use crate::service::{ diff --git a/src/middleware/compress.rs b/src/middleware/compress.rs index 86665d824..c9d2107f4 100644 --- a/src/middleware/compress.rs +++ b/src/middleware/compress.rs @@ -107,6 +107,7 @@ where self.service.poll_ready() } + #[allow(clippy::borrow_interior_mutable_const)] fn call(&mut self, req: ServiceRequest) -> Self::Future { // negotiate content-encoding let encoding = if let Some(val) = req.headers().get(&ACCEPT_ENCODING) { diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index ab2d36c2c..a353f5fc5 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -125,6 +125,7 @@ where self.service.poll_ready() } + #[allow(clippy::borrow_interior_mutable_const)] fn call(&mut self, req: ServiceRequest) -> Self::Future { let inner = self.inner.clone(); diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index d47e45023..24aabb95d 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -415,9 +415,9 @@ impl FormatText { )) }; } - FormatText::UrlPath => *self = FormatText::Str(format!("{}", req.path())), + FormatText::UrlPath => *self = FormatText::Str(req.path().to_string()), FormatText::RequestTime => { - *self = FormatText::Str(format!("{}", now.rfc3339())) + *self = FormatText::Str(now.rfc3339().to_string()) } FormatText::RequestHeader(ref name) => { let s = if let Some(val) = req.headers().get(name) { diff --git a/src/resource.rs b/src/resource.rs index d09beb27b..0d66aa843 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -426,7 +426,7 @@ where fn into_new_service(self) -> T { *self.factory_ref.borrow_mut() = Some(ResourceFactory { routes: self.routes, - data: self.data.map(|data| Rc::new(data)), + data: self.data.map(Rc::new), default: self.default, }); diff --git a/src/rmap.rs b/src/rmap.rs index cad62dca0..42ddb1349 100644 --- a/src/rmap.rs +++ b/src/rmap.rs @@ -123,7 +123,7 @@ impl ResourceMap { I: AsRef, { if let Some(pattern) = self.named.get(name) { - if pattern.pattern().starts_with("/") { + if pattern.pattern().starts_with('/') { self.fill_root(path, elements)?; } if pattern.resource_path(path, elements) { diff --git a/src/scope.rs b/src/scope.rs index 99afd7d16..714f0354a 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -195,7 +195,7 @@ where self.external.extend(cfg.external); if !cfg.data.is_empty() { - let mut data = self.data.unwrap_or_else(|| Extensions::new()); + let mut data = self.data.unwrap_or_else(Extensions::new); for value in cfg.data.iter() { value.create(&mut data); @@ -425,7 +425,7 @@ where // complete scope pipeline creation *self.factory_ref.borrow_mut() = Some(ScopeFactory { - data: self.data.take().map(|data| Rc::new(data)), + data: self.data.take().map(Rc::new), default: self.default.clone(), services: Rc::new( cfg.into_services() diff --git a/src/types/form.rs b/src/types/form.rs index e61145b0d..ac202b17d 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -192,6 +192,7 @@ pub struct UrlEncoded { impl UrlEncoded { /// Create a new future to URL encode a request + #[allow(clippy::borrow_interior_mutable_const)] pub fn new(req: &HttpRequest, payload: &mut Payload) -> UrlEncoded { // check content type if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" { diff --git a/src/types/json.rs b/src/types/json.rs index f309a3c5a..70feef8d3 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -298,6 +298,7 @@ where U: DeserializeOwned + 'static, { /// Create `JsonBody` for request. + #[allow(clippy::borrow_interior_mutable_const)] pub fn new( req: &HttpRequest, payload: &mut Payload, diff --git a/src/types/payload.rs b/src/types/payload.rs index 8a634b4c9..34c3e2984 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -298,6 +298,7 @@ pub struct HttpMessageBody { impl HttpMessageBody { /// Create `MessageBody` for request. + #[allow(clippy::borrow_interior_mutable_const)] pub fn new(req: &HttpRequest, payload: &mut dev::Payload) -> HttpMessageBody { let mut len = None; if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) { From baaa7b3fbb61cec96d9e0255d4b798334fb4518c Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 13:55:44 +0600 Subject: [PATCH 65/80] Replace ClonableService with local copy --- Cargo.toml | 2 +- actix-http/CHANGES.md | 5 ++- actix-http/Cargo.toml | 6 +-- actix-http/src/client/connector.rs | 1 + actix-http/src/client/pool.rs | 4 +- actix-http/src/cloneable.rs | 42 +++++++++++++++++++ actix-http/src/cookie/mod.rs | 1 + actix-http/src/cookie/secure/key.rs | 2 +- actix-http/src/h1/dispatcher.rs | 2 +- actix-http/src/h1/service.rs | 4 +- actix-http/src/h2/dispatcher.rs | 2 +- actix-http/src/h2/service.rs | 4 +- .../src/header/common/content_disposition.rs | 7 +++- actix-http/src/lib.rs | 5 ++- actix-http/src/message.rs | 1 + actix-http/src/service.rs | 4 +- actix-http/src/ws/proto.rs | 5 +-- src/info.rs | 6 ++- 18 files changed, 80 insertions(+), 23 deletions(-) create mode 100644 actix-http/src/cloneable.rs diff --git a/Cargo.toml b/Cargo.toml index d781422ee..470644e0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ rust-tls = ["rustls", "actix-server/rust-tls"] [dependencies] actix-codec = "0.1.2" actix-service = "0.4.1" -actix-utils = "0.4.3" +actix-utils = "0.4.4" actix-router = "0.1.5" actix-rt = "0.2.4" actix-web-codegen = "0.1.2" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 516793264..84033531d 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,11 +1,14 @@ # Changes -## [0.2.6] - TBD +## [0.2.6] - 2019-07-17 ### Changed +* Replace `ClonableService` with local copy + * Upgrade `rand` dependency version to 0.7 + ## [0.2.5] - 2019-06-28 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 5db7a6ca3..e922c86d9 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -46,10 +46,10 @@ secure-cookies = ["ring"] [dependencies] actix-service = "0.4.1" actix-codec = "0.1.2" -actix-connect = "0.2.0" -actix-utils = "0.4.2" +actix-connect = "0.2.1" +actix-utils = "0.4.4" actix-server-config = "0.1.1" -actix-threadpool = "0.1.0" +actix-threadpool = "0.1.1" base64 = "0.10" bitflags = "1.0" diff --git a/actix-http/src/client/connector.rs b/actix-http/src/client/connector.rs index 0241e8472..cd3ae3d9e 100644 --- a/actix-http/src/client/connector.rs +++ b/actix-http/src/client/connector.rs @@ -47,6 +47,7 @@ pub struct Connector { } impl Connector<(), ()> { + #[allow(clippy::new_ret_no_self)] pub fn new() -> Connector< impl Service< Request = TcpConnect, diff --git a/actix-http/src/client/pool.rs b/actix-http/src/client/pool.rs index 8dedf72f5..4739141d0 100644 --- a/actix-http/src/client/pool.rs +++ b/actix-http/src/client/pool.rs @@ -427,7 +427,9 @@ where fn check_availibility(&self) { if !self.waiters_queue.is_empty() && self.acquired < self.limit { - self.task.as_ref().map(|t| t.notify()); + if let Some(t) = self.task.as_ref() { + t.notify() + } } } } diff --git a/actix-http/src/cloneable.rs b/actix-http/src/cloneable.rs new file mode 100644 index 000000000..ffc1d0611 --- /dev/null +++ b/actix-http/src/cloneable.rs @@ -0,0 +1,42 @@ +use std::cell::UnsafeCell; +use std::rc::Rc; + +use actix_service::Service; +use futures::Poll; + +#[doc(hidden)] +/// Service that allows to turn non-clone service to a service with `Clone` impl +pub(crate) struct CloneableService(Rc>); + +impl CloneableService { + pub(crate) fn new(service: T) -> Self + where + T: Service, + { + Self(Rc::new(UnsafeCell::new(service))) + } +} + +impl Clone for CloneableService { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl Service for CloneableService +where + T: Service, +{ + type Request = T::Request; + type Response = T::Response; + type Error = T::Error; + type Future = T::Future; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + unsafe { &mut *self.0.as_ref().get() }.poll_ready() + } + + fn call(&mut self, req: T::Request) -> Self::Future { + unsafe { &mut *self.0.as_ref().get() }.call(req) + } +} diff --git a/actix-http/src/cookie/mod.rs b/actix-http/src/cookie/mod.rs index ddcb12bbf..f576a4521 100644 --- a/actix-http/src/cookie/mod.rs +++ b/actix-http/src/cookie/mod.rs @@ -104,6 +104,7 @@ impl CookieStr { } } + #[allow(clippy::ptr_arg)] fn to_raw_str<'s, 'c: 's>(&'s self, string: &'s Cow<'c, str>) -> Option<&'c str> { match *self { CookieStr::Indexed(i, j) => match *string { diff --git a/actix-http/src/cookie/secure/key.rs b/actix-http/src/cookie/secure/key.rs index 4e74f6e78..8435ce3ab 100644 --- a/actix-http/src/cookie/secure/key.rs +++ b/actix-http/src/cookie/secure/key.rs @@ -7,7 +7,7 @@ use super::private::KEY_LEN as PRIVATE_KEY_LEN; use super::signed::KEY_LEN as SIGNED_KEY_LEN; static HKDF_DIGEST: &'static Algorithm = &SHA256; -const KEYS_INFO: &'static str = "COOKIE;SIGNED:HMAC-SHA256;PRIVATE:AEAD-AES-256-GCM"; +const KEYS_INFO: &str = "COOKIE;SIGNED:HMAC-SHA256;PRIVATE:AEAD-AES-256-GCM"; /// A cryptographic master key for use with `Signed` and/or `Private` jars. /// diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 91990d05c..5e9c0b53d 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -5,7 +5,6 @@ use std::{fmt, io, net}; use actix_codec::{Decoder, Encoder, Framed, FramedParts}; use actix_server_config::IoStream; use actix_service::Service; -use actix_utils::cloneable::CloneableService; use bitflags::bitflags; use bytes::{BufMut, BytesMut}; use futures::{Async, Future, Poll}; @@ -13,6 +12,7 @@ use log::{error, trace}; use tokio_timer::Delay; use crate::body::{Body, BodySize, MessageBody, ResponseBody}; +use crate::cloneable::CloneableService; use crate::config::ServiceConfig; use crate::error::{DispatchError, Error}; use crate::error::{ParseError, PayloadError}; diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 192d1b598..108b7079e 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -5,11 +5,11 @@ use std::rc::Rc; use actix_codec::Framed; use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; use actix_service::{IntoNewService, NewService, Service}; -use actix_utils::cloneable::CloneableService; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream}; use crate::body::MessageBody; +use crate::cloneable::CloneableService; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error, ParseError}; use crate::helpers::DataFactory; @@ -259,7 +259,7 @@ where H1ServiceHandler { srv: CloneableService::new(srv), expect: CloneableService::new(expect), - upgrade: upgrade.map(|s| CloneableService::new(s)), + upgrade: upgrade.map(CloneableService::new), cfg, on_connect, _t: PhantomData, diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 48d32993d..2bd7940dd 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -6,7 +6,6 @@ use std::{fmt, mem, net}; use actix_codec::{AsyncRead, AsyncWrite}; use actix_server_config::IoStream; use actix_service::Service; -use actix_utils::cloneable::CloneableService; use bitflags::bitflags; use bytes::{Bytes, BytesMut}; use futures::{try_ready, Async, Future, Poll, Sink, Stream}; @@ -20,6 +19,7 @@ use log::{debug, error, trace}; use tokio_timer::Delay; use crate::body::{Body, BodySize, MessageBody, ResponseBody}; +use crate::cloneable::CloneableService; use crate::config::ServiceConfig; use crate::error::{DispatchError, Error, ParseError, PayloadError, ResponseError}; use crate::helpers::DataFactory; diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index efc400da1..487d5b6ab 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -5,7 +5,6 @@ use std::{io, net, rc}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig}; use actix_service::{IntoNewService, NewService, Service}; -use actix_utils::cloneable::CloneableService; use bytes::Bytes; use futures::future::{ok, FutureResult}; use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream}; @@ -14,6 +13,7 @@ use h2::RecvStream; use log::error; use crate::body::MessageBody; +use crate::cloneable::CloneableService; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error, ParseError, ResponseError}; use crate::helpers::DataFactory; @@ -256,7 +256,7 @@ where on_connect.take(), config.take().unwrap(), None, - peer_addr.clone(), + *peer_addr, )); self.poll() } diff --git a/actix-http/src/header/common/content_disposition.rs b/actix-http/src/header/common/content_disposition.rs index badf307a0..14fcc3517 100644 --- a/actix-http/src/header/common/content_disposition.rs +++ b/actix-http/src/header/common/content_disposition.rs @@ -70,6 +70,7 @@ impl<'a> From<&'a str> for DispositionType { /// assert_eq!(param.as_filename().unwrap(), "sample.txt"); /// ``` #[derive(Clone, Debug, PartialEq)] +#[allow(clippy::large_enum_variant)] pub enum DispositionParam { /// For [`DispositionType::FormData`] (i.e. *multipart/form-data*), the name of an field from /// the form. @@ -719,8 +720,10 @@ mod tests { }; assert_eq!(a, b); - let a = - HeaderValue::from_str("form-data; name=upload; filename=\"余固知謇謇之為患兮,忍而不能舍也.pptx\"").unwrap(); + let a = HeaderValue::from_str( + "form-data; name=upload; filename=\"余固知謇謇之為患兮,忍而不能舍也.pptx\"", + ) + .unwrap(); let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap(); let b = ContentDisposition { disposition: DispositionType::FormData, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index ac085eaea..6b8874b23 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -1,8 +1,10 @@ //! Basic http primitives for actix-net framework. #![allow( clippy::type_complexity, + clippy::too_many_arguments, clippy::new_without_default, - clippy::borrow_interior_mutable_const + clippy::borrow_interior_mutable_const, + clippy::write_with_newline )] #[macro_use] @@ -11,6 +13,7 @@ extern crate log; pub mod body; mod builder; pub mod client; +mod cloneable; mod config; pub mod encoding; mod extensions; diff --git a/actix-http/src/message.rs b/actix-http/src/message.rs index f3c01a12b..cf23a401c 100644 --- a/actix-http/src/message.rs +++ b/actix-http/src/message.rs @@ -385,6 +385,7 @@ impl Drop for BoxedResponseHead { pub struct MessagePool(RefCell>>); #[doc(hidden)] +#[allow(clippy::vec_box)] /// Request's objects pool pub struct BoxedResponsePool(RefCell>>); diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index 1ac018803..d37d377e5 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -6,13 +6,13 @@ use actix_server_config::{ Io as ServerIo, IoStream, Protocol, ServerConfig as SrvConfig, }; use actix_service::{IntoNewService, NewService, Service}; -use actix_utils::cloneable::CloneableService; use bytes::{Buf, BufMut, Bytes, BytesMut}; use futures::{try_ready, Async, Future, IntoFuture, Poll}; use h2::server::{self, Handshake}; use crate::body::MessageBody; use crate::builder::HttpServiceBuilder; +use crate::cloneable::CloneableService; use crate::config::{KeepAlive, ServiceConfig}; use crate::error::{DispatchError, Error}; use crate::helpers::DataFactory; @@ -285,7 +285,7 @@ where on_connect, srv: CloneableService::new(srv), expect: CloneableService::new(expect), - upgrade: upgrade.map(|s| CloneableService::new(s)), + upgrade: upgrade.map(CloneableService::new), _t: PhantomData, } } diff --git a/actix-http/src/ws/proto.rs b/actix-http/src/ws/proto.rs index eef874741..9b51b9229 100644 --- a/actix-http/src/ws/proto.rs +++ b/actix-http/src/ws/proto.rs @@ -47,10 +47,7 @@ impl Into for OpCode { Ping => 9, Pong => 10, Bad => { - debug_assert!( - false, - "Attempted to convert invalid opcode to u8. This is a bug." - ); + log::error!("Attempted to convert invalid opcode to u8. This is a bug."); 8 // if this somehow happens, a close frame will help us tear down quickly } } diff --git a/src/info.rs b/src/info.rs index a6a7d7282..0caa96832 100644 --- a/src/info.rs +++ b/src/info.rs @@ -25,7 +25,11 @@ impl ConnectionInfo { Ref::map(req.extensions(), |e| e.get().unwrap()) } - #[allow(clippy::cyclomatic_complexity, clippy::cognitive_complexity, clippy::borrow_interior_mutable_const)] + #[allow( + clippy::cyclomatic_complexity, + clippy::cognitive_complexity, + clippy::borrow_interior_mutable_const + )] fn new(req: &RequestHead, cfg: &AppConfig) -> ConnectionInfo { let mut host = None; let mut scheme = None; From ef3e1037a86f2d6d2176e9f60847fe3a1d7c84cd Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 14:18:26 +0600 Subject: [PATCH 66/80] bump version --- actix-http/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index e922c86d9..ae12cbc41 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.2.5" +version = "0.2.6" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" From 4092c7f326fa18c65b40ae703c68dfa4128be92d Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 15:08:30 +0600 Subject: [PATCH 67/80] clippy warnings --- actix-cors/src/lib.rs | 2 + actix-files/src/lib.rs | 4 +- actix-files/src/named.rs | 8 ++-- actix-framed/src/lib.rs | 6 +++ actix-identity/src/lib.rs | 12 +++--- actix-multipart/src/lib.rs | 2 + actix-multipart/src/server.rs | 12 +++--- actix-session/src/cookie.rs | 2 +- actix-web-actors/src/lib.rs | 1 + actix-web-actors/src/ws.rs | 2 +- actix-web-codegen/src/route.rs | 65 ++++++++++++++------------------ awc/src/builder.rs | 6 +++ awc/src/lib.rs | 1 + awc/src/request.rs | 20 +++------- awc/src/test.rs | 2 +- awc/src/ws.rs | 2 +- src/info.rs | 6 +-- src/lib.rs | 1 + src/middleware/compress.rs | 1 - src/middleware/defaultheaders.rs | 1 - src/server.rs | 8 ++-- src/test.rs | 2 +- src/types/form.rs | 1 - src/types/json.rs | 1 - src/types/payload.rs | 1 - test-server/src/lib.rs | 5 ++- 26 files changed, 84 insertions(+), 90 deletions(-) diff --git a/actix-cors/src/lib.rs b/actix-cors/src/lib.rs index ea1eb383b..d9a44d0b8 100644 --- a/actix-cors/src/lib.rs +++ b/actix-cors/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::borrow_interior_mutable_const, clippy::type_complexity)] //! Cross-origin resource sharing (CORS) for Actix applications //! //! CORS middleware could be used with application and with resource. @@ -162,6 +163,7 @@ impl AllOrSome { /// .max_age(3600); /// # } /// ``` +#[derive(Default)] pub struct Cors { cors: Option, methods: bool, diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 82abb9990..c870c9dd0 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::borrow_interior_mutable_const, clippy::type_complexity)] + //! Static files support use std::cell::RefCell; use std::fmt::Write; @@ -57,7 +59,7 @@ pub struct ChunkedReadFile { fn handle_error(err: BlockingError) -> Error { match err { BlockingError::Error(err) => err.into(), - BlockingError::Canceled => ErrorInternalServerError("Unexpected error").into(), + BlockingError::Canceled => ErrorInternalServerError("Unexpected error"), } } diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 6b948da8e..3273a4d67 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -24,8 +24,8 @@ use crate::ChunkedReadFile; bitflags! { pub(crate) struct Flags: u32 { - const ETAG = 0b00000001; - const LAST_MD = 0b00000010; + const ETAG = 0b0000_0001; + const LAST_MD = 0b0000_0010; } } @@ -311,8 +311,8 @@ impl Responder for NamedFile { return Ok(resp.streaming(reader)); } - match req.method() { - &Method::HEAD | &Method::GET => (), + match *req.method() { + Method::HEAD | Method::GET => (), _ => { return Ok(HttpResponse::MethodNotAllowed() .header(header::CONTENT_TYPE, "text/plain") diff --git a/actix-framed/src/lib.rs b/actix-framed/src/lib.rs index c6405e20b..5e72ba5ba 100644 --- a/actix-framed/src/lib.rs +++ b/actix-framed/src/lib.rs @@ -1,3 +1,9 @@ +#![allow( + clippy::type_complexity, + clippy::new_without_default, + dead_code, + deprecated +)] mod app; mod helpers; mod request; diff --git a/actix-identity/src/lib.rs b/actix-identity/src/lib.rs index fe7216a01..0ae58fe89 100644 --- a/actix-identity/src/lib.rs +++ b/actix-identity/src/lib.rs @@ -333,8 +333,7 @@ struct CookieIdentityExtention { impl CookieIdentityInner { fn new(key: &[u8]) -> CookieIdentityInner { - let key_v2: Vec = - key.iter().chain([1, 0, 0, 0].iter()).map(|e| *e).collect(); + let key_v2: Vec = key.iter().chain([1, 0, 0, 0].iter()).cloned().collect(); CookieIdentityInner { key: Key::from_master(key), key_v2: Key::from_master(&key_v2), @@ -585,13 +584,14 @@ impl IdentityPolicy for CookieIdentityPolicy { ) } else if self.0.always_update_cookie() && id.is_some() { let visit_timestamp = SystemTime::now(); - let mut login_timestamp = None; - if self.0.requires_oob_data() { + let login_timestamp = if self.0.requires_oob_data() { let CookieIdentityExtention { login_timestamp: lt, } = res.request().extensions_mut().remove().unwrap(); - login_timestamp = lt; - } + lt + } else { + None + }; self.0.set_cookie( res, Some(CookieValue { diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index d8f365b2c..43eb048ca 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(clippy::borrow_interior_mutable_const)] + mod error; mod extractor; mod server; diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index e1a5543d4..c28a8d6af 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -418,7 +418,7 @@ impl Stream for Field { inner.poll(&self.safety) } else if !self.safety.is_clean() { - return Err(MultipartError::NotConsumed); + Err(MultipartError::NotConsumed) } else { Ok(Async::NotReady) } @@ -533,11 +533,9 @@ impl InnerField { let b_size = boundary.len() + b_len; if len < b_size { return Ok(Async::NotReady); - } else { - if &payload.buf[b_len..b_size] == boundary.as_bytes() { - // found boundary - return Ok(Async::Ready(None)); - } + } else if &payload.buf[b_len..b_size] == boundary.as_bytes() { + // found boundary + return Ok(Async::Ready(None)); } } } @@ -557,7 +555,7 @@ impl InnerField { // check boundary if (&payload.buf[cur..cur + 2] == b"\r\n" && &payload.buf[cur + 2..cur + 4] == b"--") - || (&payload.buf[cur..cur + 1] == b"\r" + || (&payload.buf[cur..=cur] == b"\r" && &payload.buf[cur + 1..cur + 3] == b"--") { if cur != 0 { diff --git a/actix-session/src/cookie.rs b/actix-session/src/cookie.rs index 87fc0b164..192737780 100644 --- a/actix-session/src/cookie.rs +++ b/actix-session/src/cookie.rs @@ -342,7 +342,7 @@ where } } (SessionStatus::Purged, _) => { - inner.remove_cookie(&mut res); + let _ = inner.remove_cookie(&mut res); res } _ => res, diff --git a/actix-web-actors/src/lib.rs b/actix-web-actors/src/lib.rs index 5b64d7e0a..6360917cd 100644 --- a/actix-web-actors/src/lib.rs +++ b/actix-web-actors/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::borrow_interior_mutable_const)] //! Actix actors integration for Actix web framework mod context; pub mod ws; diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index fece826dd..08d8b1089 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -435,7 +435,7 @@ where } } Frame::Binary(data) => Message::Binary( - data.map(|b| b.freeze()).unwrap_or_else(|| Bytes::new()), + data.map(|b| b.freeze()).unwrap_or_else(Bytes::new), ), Frame::Ping(s) => Message::Ping(s), Frame::Pong(s) => Message::Pong(s), diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 268adecb0..5215f60c8 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -12,9 +12,9 @@ enum ResourceType { impl fmt::Display for ResourceType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &ResourceType::Async => write!(f, "to_async"), - &ResourceType::Sync => write!(f, "to"), + match *self { + ResourceType::Async => write!(f, "to_async"), + ResourceType::Sync => write!(f, "to"), } } } @@ -34,16 +34,16 @@ pub enum GuardType { impl fmt::Display for GuardType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &GuardType::Get => write!(f, "Get"), - &GuardType::Post => write!(f, "Post"), - &GuardType::Put => write!(f, "Put"), - &GuardType::Delete => write!(f, "Delete"), - &GuardType::Head => write!(f, "Head"), - &GuardType::Connect => write!(f, "Connect"), - &GuardType::Options => write!(f, "Options"), - &GuardType::Trace => write!(f, "Trace"), - &GuardType::Patch => write!(f, "Patch"), + match *self { + GuardType::Get => write!(f, "Get"), + GuardType::Post => write!(f, "Post"), + GuardType::Put => write!(f, "Put"), + GuardType::Delete => write!(f, "Delete"), + GuardType::Head => write!(f, "Head"), + GuardType::Connect => write!(f, "Connect"), + GuardType::Options => write!(f, "Options"), + GuardType::Trace => write!(f, "Trace"), + GuardType::Patch => write!(f, "Patch"), } } } @@ -92,37 +92,27 @@ impl actix_web::dev::HttpServiceFactory for {name} {{ fn guess_resource_type(typ: &syn::Type) -> ResourceType { let mut guess = ResourceType::Sync; - match typ { - syn::Type::ImplTrait(typ) => { - for bound in typ.bounds.iter() { - match bound { - syn::TypeParamBound::Trait(bound) => { - for bound in bound.path.segments.iter() { - if bound.ident == "Future" { - guess = ResourceType::Async; - break; - } else if bound.ident == "Responder" { - guess = ResourceType::Sync; - break; - } - } + if let syn::Type::ImplTrait(typ) = typ { + for bound in typ.bounds.iter() { + if let syn::TypeParamBound::Trait(bound) = bound { + for bound in bound.path.segments.iter() { + if bound.ident == "Future" { + guess = ResourceType::Async; + break; + } else if bound.ident == "Responder" { + guess = ResourceType::Sync; + break; } - _ => (), } } } - _ => (), } guess } impl Args { - pub fn new( - args: &Vec, - input: TokenStream, - guard: GuardType, - ) -> Self { + pub fn new(args: &[syn::NestedMeta], input: TokenStream, guard: GuardType) -> Self { if args.is_empty() { panic!( "invalid server definition, expected: #[{}(\"some path\")]", @@ -164,9 +154,10 @@ impl Args { ResourceType::Async } else { match ast.decl.output { - syn::ReturnType::Default => { - panic!("Function {} has no return type. Cannot be used as handler") - } + syn::ReturnType::Default => panic!( + "Function {} has no return type. Cannot be used as handler", + name + ), syn::ReturnType::Type(_, ref typ) => guess_resource_type(typ.as_ref()), } }; diff --git a/awc/src/builder.rs b/awc/src/builder.rs index a58265c5f..463f40303 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -21,6 +21,12 @@ pub struct ClientBuilder { max_redirects: usize, } +impl Default for ClientBuilder { + fn default() -> Self { + Self::new() + } +} + impl ClientBuilder { pub fn new() -> Self { ClientBuilder { diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 45231326d..da63bbd93 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::borrow_interior_mutable_const)] //! An HTTP Client //! //! ```rust diff --git a/awc/src/request.rs b/awc/src/request.rs index 36cd6fcf3..0e5445897 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -185,9 +185,7 @@ impl ClientRequest { { match HeaderName::try_from(key) { Ok(key) => match value.try_into() { - Ok(value) => { - let _ = self.head.headers.append(key, value); - } + Ok(value) => self.head.headers.append(key, value), Err(e) => self.err = Some(e.into()), }, Err(e) => self.err = Some(e.into()), @@ -203,9 +201,7 @@ impl ClientRequest { { match HeaderName::try_from(key) { Ok(key) => match value.try_into() { - Ok(value) => { - let _ = self.head.headers.insert(key, value); - } + Ok(value) => self.head.headers.insert(key, value), Err(e) => self.err = Some(e.into()), }, Err(e) => self.err = Some(e.into()), @@ -223,9 +219,7 @@ impl ClientRequest { Ok(key) => { if !self.head.headers.contains_key(&key) { match value.try_into() { - Ok(value) => { - let _ = self.head.headers.insert(key, value); - } + Ok(value) => self.head.headers.insert(key, value), Err(e) => self.err = Some(e.into()), } } @@ -257,9 +251,7 @@ impl ClientRequest { HeaderValue: HttpTryFrom, { match HeaderValue::try_from(value) { - Ok(value) => { - let _ = self.head.headers.insert(header::CONTENT_TYPE, value); - } + Ok(value) => self.head.headers.insert(header::CONTENT_TYPE, value), Err(e) => self.err = Some(e.into()), } self @@ -321,7 +313,7 @@ impl ClientRequest { /// })); /// } /// ``` - pub fn cookie<'c>(mut self, cookie: Cookie<'c>) -> Self { + pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { if self.cookies.is_none() { let mut jar = CookieJar::new(); jar.add(cookie.into_owned()); @@ -465,7 +457,7 @@ impl ClientRequest { }); // set request timeout - if let Some(timeout) = slf.timeout.or_else(|| config.timeout.clone()) { + if let Some(timeout) = slf.timeout.or_else(|| config.timeout) { Either::B(Either::A(Timeout::new(fut, timeout).map_err(|e| { if let Some(e) = e.into_inner() { e diff --git a/awc/src/test.rs b/awc/src/test.rs index f2c513bab..b852adb2d 100644 --- a/awc/src/test.rs +++ b/awc/src/test.rs @@ -68,7 +68,7 @@ impl TestResponse { } /// Set cookie for this response - pub fn cookie<'a>(mut self, cookie: Cookie<'a>) -> Self { + pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { self.cookies.add(cookie.into_owned()); self } diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 95bf6ef70..27f454ed3 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -90,7 +90,7 @@ impl WebsocketsRequest { } /// Set a cookie - pub fn cookie<'c>(mut self, cookie: Cookie<'c>) -> Self { + pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { if self.cookies.is_none() { let mut jar = CookieJar::new(); jar.add(cookie.into_owned()); diff --git a/src/info.rs b/src/info.rs index 0caa96832..ba59605de 100644 --- a/src/info.rs +++ b/src/info.rs @@ -25,11 +25,7 @@ impl ConnectionInfo { Ref::map(req.extensions(), |e| e.get().unwrap()) } - #[allow( - clippy::cyclomatic_complexity, - clippy::cognitive_complexity, - clippy::borrow_interior_mutable_const - )] + #[allow(clippy::cognitive_complexity)] fn new(req: &RequestHead, cfg: &AppConfig) -> ConnectionInfo { let mut host = None; let mut scheme = None; diff --git a/src/lib.rs b/src/lib.rs index 345987ffa..857bc294e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::borrow_interior_mutable_const)] //! Actix web is a small, pragmatic, and extremely fast web framework //! for Rust. //! diff --git a/src/middleware/compress.rs b/src/middleware/compress.rs index c9d2107f4..86665d824 100644 --- a/src/middleware/compress.rs +++ b/src/middleware/compress.rs @@ -107,7 +107,6 @@ where self.service.poll_ready() } - #[allow(clippy::borrow_interior_mutable_const)] fn call(&mut self, req: ServiceRequest) -> Self::Future { // negotiate content-encoding let encoding = if let Some(val) = req.headers().get(&ACCEPT_ENCODING) { diff --git a/src/middleware/defaultheaders.rs b/src/middleware/defaultheaders.rs index a353f5fc5..ab2d36c2c 100644 --- a/src/middleware/defaultheaders.rs +++ b/src/middleware/defaultheaders.rs @@ -125,7 +125,6 @@ where self.service.poll_ready() } - #[allow(clippy::borrow_interior_mutable_const)] fn call(&mut self, req: ServiceRequest) -> Self::Future { let inner = self.inner.clone(); diff --git a/src/server.rs b/src/server.rs index 353f29ba9..43236fa34 100644 --- a/src/server.rs +++ b/src/server.rs @@ -288,13 +288,13 @@ where lst, move || { let c = cfg.lock(); - acceptor.clone().map_err(|e| SslError::Ssl(e)).and_then( + acceptor.clone().map_err(SslError::Ssl).and_then( HttpService::build() .keep_alive(c.keep_alive) .client_timeout(c.client_timeout) .client_disconnect(c.client_shutdown) .finish(factory()) - .map_err(|e| SslError::Service(e)) + .map_err(SslError::Service) .map_init_err(|_| ()), ) }, @@ -339,13 +339,13 @@ where lst, move || { let c = cfg.lock(); - acceptor.clone().map_err(|e| SslError::Ssl(e)).and_then( + acceptor.clone().map_err(SslError::Ssl).and_then( HttpService::build() .keep_alive(c.keep_alive) .client_timeout(c.client_timeout) .client_disconnect(c.client_shutdown) .finish(factory()) - .map_err(|e| SslError::Service(e)) + .map_err(SslError::Service) .map_init_err(|_| ()), ) }, diff --git a/src/test.rs b/src/test.rs index 208360a29..562fdf436 100644 --- a/src/test.rs +++ b/src/test.rs @@ -79,7 +79,7 @@ where F: FnOnce() -> R, R: IntoFuture, { - RT.with(move |rt| rt.borrow_mut().get_mut().block_on(lazy(|| f()))) + RT.with(move |rt| rt.borrow_mut().get_mut().block_on(lazy(f))) } #[doc(hidden)] diff --git a/src/types/form.rs b/src/types/form.rs index ac202b17d..e61145b0d 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -192,7 +192,6 @@ pub struct UrlEncoded { impl UrlEncoded { /// Create a new future to URL encode a request - #[allow(clippy::borrow_interior_mutable_const)] pub fn new(req: &HttpRequest, payload: &mut Payload) -> UrlEncoded { // check content type if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" { diff --git a/src/types/json.rs b/src/types/json.rs index 70feef8d3..f309a3c5a 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -298,7 +298,6 @@ where U: DeserializeOwned + 'static, { /// Create `JsonBody` for request. - #[allow(clippy::borrow_interior_mutable_const)] pub fn new( req: &HttpRequest, payload: &mut Payload, diff --git a/src/types/payload.rs b/src/types/payload.rs index 34c3e2984..8a634b4c9 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -298,7 +298,6 @@ pub struct HttpMessageBody { impl HttpMessageBody { /// Create `MessageBody` for request. - #[allow(clippy::borrow_interior_mutable_const)] pub fn new(req: &HttpRequest, payload: &mut dev::Payload) -> HttpMessageBody { let mut len = None; if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) { diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index c49026faa..38405cd55 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -65,7 +65,7 @@ where F: FnOnce() -> R, R: IntoFuture, { - RT.with(move |rt| rt.borrow_mut().get_mut().block_on(lazy(|| f()))) + RT.with(move |rt| rt.borrow_mut().get_mut().block_on(lazy(f))) } /// The `TestServer` type. @@ -107,6 +107,7 @@ pub struct TestServerRuntime { } impl TestServer { + #[allow(clippy::new_ret_no_self)] /// Start new test server with application factory pub fn new(factory: F) -> TestServerRuntime { let (tx, rx) = mpsc::channel(); @@ -191,7 +192,7 @@ impl TestServerRuntime { F: FnOnce() -> R, R: Future, { - self.rt.block_on(lazy(|| f())) + self.rt.block_on(lazy(f)) } /// Execute function on current core From 2a2d7f57687b635262b426f873702562b5395005 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 17 Jul 2019 15:48:37 +0600 Subject: [PATCH 68/80] nightly clippy warnings --- Cargo.toml | 4 ++-- actix-cors/src/lib.rs | 6 +++--- actix-files/src/lib.rs | 16 ++++++++-------- actix-files/src/range.rs | 2 +- actix-framed/src/helpers.rs | 4 ++-- actix-http/src/builder.rs | 2 +- actix-http/src/client/connection.rs | 4 ++-- actix-http/src/cookie/secure/key.rs | 2 +- actix-http/src/cookie/secure/private.rs | 2 +- actix-http/src/cookie/secure/signed.rs | 2 +- actix-http/src/error.rs | 4 ++-- actix-http/src/extensions.rs | 8 ++++---- actix-http/src/h1/decoder.rs | 6 +++--- actix-http/src/h1/service.rs | 10 +++++----- actix-http/src/h2/service.rs | 10 +++++----- actix-http/src/service.rs | 10 +++++----- actix-http/src/ws/proto.rs | 2 +- actix-identity/src/lib.rs | 4 ++-- actix-session/src/lib.rs | 4 ++-- awc/src/connect.rs | 16 ++++++++-------- src/app.rs | 7 ++++--- src/app_service.rs | 15 ++++++++------- src/config.rs | 12 ++++++------ src/guard.rs | 6 +++--- src/middleware/errhandlers.rs | 2 +- src/middleware/logger.rs | 4 +++- src/resource.rs | 4 ++-- src/route.rs | 12 ++++++------ src/scope.rs | 8 ++++---- src/service.rs | 4 ++-- src/types/form.rs | 2 +- src/types/path.rs | 2 +- src/types/payload.rs | 4 ++-- src/types/query.rs | 3 ++- 34 files changed, 104 insertions(+), 99 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 470644e0e..866a7628f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ actix-utils = "0.4.4" actix-router = "0.1.5" actix-rt = "0.2.4" actix-web-codegen = "0.1.2" -actix-http = "0.2.5" +actix-http = "0.2.6" actix-server = "0.5.1" actix-server-config = "0.1.1" actix-threadpool = "0.1.1" @@ -89,7 +89,7 @@ hashbrown = "0.5.0" log = "0.4" mime = "0.3" net2 = "0.2.33" -parking_lot = "0.8" +parking_lot = "0.9" regex = "1.0" serde = { version = "1.0", features=["derive"] } serde_json = "1.0" diff --git a/actix-cors/src/lib.rs b/actix-cors/src/lib.rs index d9a44d0b8..c76bae925 100644 --- a/actix-cors/src/lib.rs +++ b/actix-cors/src/lib.rs @@ -587,10 +587,10 @@ impl Inner { } Err(CorsError::BadOrigin) } else { - return match self.origins { + match self.origins { AllOrSome::All => Ok(()), _ => Err(CorsError::MissingOrigin), - }; + } } } @@ -665,7 +665,7 @@ impl Inner { } Err(CorsError::BadRequestHeaders) } else { - return Ok(()); + Ok(()) } } } diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index c870c9dd0..cf07153fa 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -107,7 +107,7 @@ impl Stream for ChunkedReadFile { } type DirectoryRenderer = - Fn(&Directory, &HttpRequest) -> Result; + dyn Fn(&Directory, &HttpRequest) -> Result; /// A directory; responds with the generated directory listing. #[derive(Debug)] @@ -211,7 +211,7 @@ fn directory_listing( )) } -type MimeOverride = Fn(&mime::Name) -> DispositionType; +type MimeOverride = dyn Fn(&mime::Name) -> DispositionType; /// Static files handling /// @@ -475,7 +475,7 @@ impl Service for FilesService { Err(e) => ServiceResponse::from_err(e, req), })) } - Err(e) => return self.handle_err(e, req), + Err(e) => self.handle_err(e, req), } } else if self.show_index { let dir = Directory::new(self.directory.clone(), path); @@ -483,7 +483,7 @@ impl Service for FilesService { let x = (self.renderer)(&dir, &req); match x { Ok(resp) => Either::A(ok(resp)), - Err(e) => return Either::A(ok(ServiceResponse::from_err(e, req))), + Err(e) => Either::A(ok(ServiceResponse::from_err(e, req))), } } else { Either::A(ok(ServiceResponse::from_err( @@ -857,7 +857,7 @@ mod tests { #[test] fn test_named_file_content_length_headers() { - use actix_web::body::{MessageBody, ResponseBody}; + // use actix_web::body::{MessageBody, ResponseBody}; let mut srv = test::init_service( App::new().service(Files::new("test", ".").index_file("tests/test.binary")), @@ -868,7 +868,7 @@ mod tests { .uri("/t%65st/tests/test.binary") .header(header::RANGE, "bytes=10-20") .to_request(); - let response = test::call_service(&mut srv, request); + let _response = test::call_service(&mut srv, request); // let contentlength = response // .headers() @@ -891,7 +891,7 @@ mod tests { .uri("/t%65st/tests/test.binary") // .no_default_headers() .to_request(); - let response = test::call_service(&mut srv, request); + let _response = test::call_service(&mut srv, request); // let contentlength = response // .headers() @@ -939,7 +939,7 @@ mod tests { .method(Method::HEAD) .uri("/t%65st/tests/test.binary") .to_request(); - let response = test::call_service(&mut srv, request); + let _response = test::call_service(&mut srv, request); // TODO: fix check // let contentlength = response diff --git a/actix-files/src/range.rs b/actix-files/src/range.rs index d97a35e7e..47673b0b0 100644 --- a/actix-files/src/range.rs +++ b/actix-files/src/range.rs @@ -5,7 +5,7 @@ pub struct HttpRange { pub length: u64, } -static PREFIX: &'static str = "bytes="; +static PREFIX: &str = "bytes="; const PREFIX_LEN: usize = 6; impl HttpRange { diff --git a/actix-framed/src/helpers.rs b/actix-framed/src/helpers.rs index 5e84ad88c..b343301f3 100644 --- a/actix-framed/src/helpers.rs +++ b/actix-framed/src/helpers.rs @@ -3,7 +3,7 @@ use actix_service::{NewService, Service}; use futures::{Future, Poll}; pub(crate) type BoxedHttpService = Box< - Service< + dyn Service< Request = Req, Response = (), Error = Error, @@ -12,7 +12,7 @@ pub(crate) type BoxedHttpService = Box< >; pub(crate) type BoxedHttpNewService = Box< - NewService< + dyn NewService< Config = (), Request = Req, Response = (), diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index b6967d94d..bab0f5e1e 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -26,7 +26,7 @@ pub struct HttpServiceBuilder> { client_disconnect: u64, expect: X, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, S)>, } diff --git a/actix-http/src/client/connection.rs b/actix-http/src/client/connection.rs index 2f3103d4e..36913c5f0 100644 --- a/actix-http/src/client/connection.rs +++ b/actix-http/src/client/connection.rs @@ -130,7 +130,7 @@ where type TunnelFuture = Either< Box< - Future< + dyn Future< Item = (ResponseHead, Framed), Error = SendRequestError, >, @@ -192,7 +192,7 @@ where } type TunnelFuture = Box< - Future< + dyn Future< Item = (ResponseHead, Framed), Error = SendRequestError, >, diff --git a/actix-http/src/cookie/secure/key.rs b/actix-http/src/cookie/secure/key.rs index 8435ce3ab..39575c93f 100644 --- a/actix-http/src/cookie/secure/key.rs +++ b/actix-http/src/cookie/secure/key.rs @@ -6,7 +6,7 @@ use ring::rand::{SecureRandom, SystemRandom}; use super::private::KEY_LEN as PRIVATE_KEY_LEN; use super::signed::KEY_LEN as SIGNED_KEY_LEN; -static HKDF_DIGEST: &'static Algorithm = &SHA256; +static HKDF_DIGEST: &Algorithm = &SHA256; const KEYS_INFO: &str = "COOKIE;SIGNED:HMAC-SHA256;PRIVATE:AEAD-AES-256-GCM"; /// A cryptographic master key for use with `Signed` and/or `Private` jars. diff --git a/actix-http/src/cookie/secure/private.rs b/actix-http/src/cookie/secure/private.rs index e59743767..eb8e9beb1 100644 --- a/actix-http/src/cookie/secure/private.rs +++ b/actix-http/src/cookie/secure/private.rs @@ -10,7 +10,7 @@ use crate::cookie::{Cookie, CookieJar}; // Keep these in sync, and keep the key len synced with the `private` docs as // well as the `KEYS_INFO` const in secure::Key. -static ALGO: &'static Algorithm = &AES_256_GCM; +static ALGO: &Algorithm = &AES_256_GCM; const NONCE_LEN: usize = 12; pub const KEY_LEN: usize = 32; diff --git a/actix-http/src/cookie/secure/signed.rs b/actix-http/src/cookie/secure/signed.rs index 1b1799cf4..36a277cd5 100644 --- a/actix-http/src/cookie/secure/signed.rs +++ b/actix-http/src/cookie/secure/signed.rs @@ -6,7 +6,7 @@ use crate::cookie::{Cookie, CookieJar}; // Keep these in sync, and keep the key len synced with the `signed` docs as // well as the `KEYS_INFO` const in secure::Key. -static HMAC_DIGEST: &'static Algorithm = &SHA256; +static HMAC_DIGEST: &Algorithm = &SHA256; const BASE64_DIGEST_LEN: usize = 44; pub const KEY_LEN: usize = 32; diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 4913c3d9d..368ee6dde 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -43,12 +43,12 @@ pub type Result = result::Result; /// if you have access to an actix `Error` you can always get a /// `ResponseError` reference from it. pub struct Error { - cause: Box, + cause: Box, } impl Error { /// Returns the reference to the underlying `ResponseError`. - pub fn as_response_error(&self) -> &ResponseError { + pub fn as_response_error(&self) -> &dyn ResponseError { self.cause.as_ref() } } diff --git a/actix-http/src/extensions.rs b/actix-http/src/extensions.rs index 148e4c18e..c6266f56e 100644 --- a/actix-http/src/extensions.rs +++ b/actix-http/src/extensions.rs @@ -6,7 +6,7 @@ use hashbrown::HashMap; #[derive(Default)] /// A type map of request extensions. pub struct Extensions { - map: HashMap>, + map: HashMap>, } impl Extensions { @@ -35,14 +35,14 @@ impl Extensions { pub fn get(&self) -> Option<&T> { self.map .get(&TypeId::of::()) - .and_then(|boxed| (&**boxed as &(Any + 'static)).downcast_ref()) + .and_then(|boxed| (&**boxed as &(dyn Any + 'static)).downcast_ref()) } /// Get a mutable reference to a type previously inserted on this `Extensions`. pub fn get_mut(&mut self) -> Option<&mut T> { self.map .get_mut(&TypeId::of::()) - .and_then(|boxed| (&mut **boxed as &mut (Any + 'static)).downcast_mut()) + .and_then(|boxed| (&mut **boxed as &mut (dyn Any + 'static)).downcast_mut()) } /// Remove a type from this `Extensions`. @@ -50,7 +50,7 @@ impl Extensions { /// If a extension of this type existed, it will be returned. pub fn remove(&mut self) -> Option { self.map.remove(&TypeId::of::()).and_then(|boxed| { - (boxed as Box) + (boxed as Box) .downcast() .ok() .map(|boxed| *boxed) diff --git a/actix-http/src/h1/decoder.rs b/actix-http/src/h1/decoder.rs index 12419d665..c7ef065a5 100644 --- a/actix-http/src/h1/decoder.rs +++ b/actix-http/src/h1/decoder.rs @@ -502,15 +502,15 @@ impl ChunkedState { fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll { let radix = 16; match byte!(rdr) { - b @ b'0'...b'9' => { + b @ b'0'..=b'9' => { *size *= radix; *size += u64::from(b - b'0'); } - b @ b'a'...b'f' => { + b @ b'a'..=b'f' => { *size *= radix; *size += u64::from(b + 10 - b'a'); } - b @ b'A'...b'F' => { + b @ b'A'..=b'F' => { *size *= radix; *size += u64::from(b + 10 - b'A'); } diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 108b7079e..89bf08e9b 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -26,7 +26,7 @@ pub struct H1Service> { cfg: ServiceConfig, expect: X, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -108,7 +108,7 @@ where /// Set on connect callback. pub(crate) fn on_connect( mut self, - f: Option Box>>, + f: Option Box>>, ) -> Self { self.on_connect = f; self @@ -174,7 +174,7 @@ where fut_upg: Option, expect: Option, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, cfg: Option, _t: PhantomData<(T, P, B)>, } @@ -233,7 +233,7 @@ pub struct H1ServiceHandler { srv: CloneableService, expect: CloneableService, upgrade: Option>, - on_connect: Option Box>>, + on_connect: Option Box>>, cfg: ServiceConfig, _t: PhantomData<(T, P, B)>, } @@ -254,7 +254,7 @@ where srv: S, expect: X, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, ) -> H1ServiceHandler { H1ServiceHandler { srv: CloneableService::new(srv), diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 487d5b6ab..e894cf660 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -27,7 +27,7 @@ use super::dispatcher::Dispatcher; pub struct H2Service { srv: S, cfg: ServiceConfig, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -64,7 +64,7 @@ where /// Set on connect callback. pub(crate) fn on_connect( mut self, - f: Option Box>>, + f: Option Box>>, ) -> Self { self.on_connect = f; self @@ -102,7 +102,7 @@ where pub struct H2ServiceResponse { fut: ::Future, cfg: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -132,7 +132,7 @@ where pub struct H2ServiceHandler { srv: CloneableService, cfg: ServiceConfig, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -146,7 +146,7 @@ where { fn new( cfg: ServiceConfig, - on_connect: Option Box>>, + on_connect: Option Box>>, srv: S, ) -> H2ServiceHandler { H2ServiceHandler { diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index d37d377e5..be021b252 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -26,7 +26,7 @@ pub struct HttpService, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B)>, } @@ -140,7 +140,7 @@ where /// Set on connect callback. pub(crate) fn on_connect( mut self, - f: Option Box>>, + f: Option Box>>, ) -> Self { self.on_connect = f; self @@ -196,7 +196,7 @@ pub struct HttpServiceResponse, expect: Option, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, cfg: Option, _t: PhantomData<(T, P, B)>, } @@ -257,7 +257,7 @@ pub struct HttpServiceHandler { expect: CloneableService, upgrade: Option>, cfg: ServiceConfig, - on_connect: Option Box>>, + on_connect: Option Box>>, _t: PhantomData<(T, P, B, X)>, } @@ -278,7 +278,7 @@ where srv: S, expect: X, upgrade: Option, - on_connect: Option Box>>, + on_connect: Option Box>>, ) -> HttpServiceHandler { HttpServiceHandler { cfg, diff --git a/actix-http/src/ws/proto.rs b/actix-http/src/ws/proto.rs index 9b51b9229..e14651a56 100644 --- a/actix-http/src/ws/proto.rs +++ b/actix-http/src/ws/proto.rs @@ -203,7 +203,7 @@ impl> From<(CloseCode, T)> for CloseReason { } } -static WS_GUID: &'static str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +static WS_GUID: &str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; // TODO: hash is always same size, we dont need String pub fn hash_key(key: &[u8]) -> String { diff --git a/actix-identity/src/lib.rs b/actix-identity/src/lib.rs index 0ae58fe89..7216104eb 100644 --- a/actix-identity/src/lib.rs +++ b/actix-identity/src/lib.rs @@ -283,7 +283,7 @@ where res.request().extensions_mut().remove::(); if let Some(id) = id { - return Either::A( + Either::A( backend .to_response(id.id, id.changed, &mut res) .into_future() @@ -291,7 +291,7 @@ where Ok(_) => Ok(res), Err(e) => Ok(res.error_response(e)), }), - ); + ) } else { Either::B(ok(res)) } diff --git a/actix-session/src/lib.rs b/actix-session/src/lib.rs index 27ad2b876..2e9e51714 100644 --- a/actix-session/src/lib.rs +++ b/actix-session/src/lib.rs @@ -282,7 +282,7 @@ mod tests { #[test] fn purge_session() { - let mut req = test::TestRequest::default().to_srv_request(); + let req = test::TestRequest::default().to_srv_request(); let session = Session::get_session(&mut *req.extensions_mut()); assert_eq!(session.0.borrow().status, SessionStatus::Unchanged); session.purge(); @@ -291,7 +291,7 @@ mod tests { #[test] fn renew_session() { - let mut req = test::TestRequest::default().to_srv_request(); + let req = test::TestRequest::default().to_srv_request(); let session = Session::get_session(&mut *req.extensions_mut()); assert_eq!(session.0.borrow().status, SessionStatus::Unchanged); session.renew(); diff --git a/awc/src/connect.rs b/awc/src/connect.rs index 8344abbdc..04f08ecdc 100644 --- a/awc/src/connect.rs +++ b/awc/src/connect.rs @@ -28,7 +28,7 @@ pub(crate) trait Connect { head: RequestHead, addr: Option, ) -> Box< - Future< + dyn Future< Item = (ResponseHead, Framed), Error = SendRequestError, >, @@ -69,7 +69,7 @@ where head: RequestHead, addr: Option, ) -> Box< - Future< + dyn Future< Item = (ResponseHead, Framed), Error = SendRequestError, >, @@ -93,21 +93,21 @@ where } trait AsyncSocket { - fn as_read(&self) -> &AsyncRead; - fn as_read_mut(&mut self) -> &mut AsyncRead; - fn as_write(&mut self) -> &mut AsyncWrite; + fn as_read(&self) -> &dyn AsyncRead; + fn as_read_mut(&mut self) -> &mut dyn AsyncRead; + fn as_write(&mut self) -> &mut dyn AsyncWrite; } struct Socket(T); impl AsyncSocket for Socket { - fn as_read(&self) -> &AsyncRead { + fn as_read(&self) -> &dyn AsyncRead { &self.0 } - fn as_read_mut(&mut self) -> &mut AsyncRead { + fn as_read_mut(&mut self) -> &mut dyn AsyncRead { &mut self.0 } - fn as_write(&mut self) -> &mut AsyncWrite { + fn as_write(&mut self) -> &mut dyn AsyncWrite { &mut self.0 } } diff --git a/src/app.rs b/src/app.rs index 3b063a841..f93859c7e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -23,16 +23,17 @@ use crate::service::{ }; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; -type FnDataFactory = Box Box, Error = ()>>>; +type FnDataFactory = + Box Box, Error = ()>>>; /// Application builder - structure that follows the builder pattern /// for building application instances. pub struct App { endpoint: T, - services: Vec>, + services: Vec>, default: Option>, factory_ref: Rc>>, - data: Vec>, + data: Vec>, data_factories: Vec, config: AppConfigInner, external: Vec, diff --git a/src/app_service.rs b/src/app_service.rs index 6012dcda9..736c35010 100644 --- a/src/app_service.rs +++ b/src/app_service.rs @@ -18,14 +18,15 @@ use crate::request::{HttpRequest, HttpRequestPool}; use crate::rmap::ResourceMap; use crate::service::{ServiceFactory, ServiceRequest, ServiceResponse}; -type Guards = Vec>; +type Guards = Vec>; type HttpService = BoxedService; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type BoxedResponse = Either< FutureResult, Box>, >; -type FnDataFactory = Box Box, Error = ()>>>; +type FnDataFactory = + Box Box, Error = ()>>>; /// Service factory to convert `Request` to a `ServiceRequest`. /// It also executes data factories. @@ -40,10 +41,10 @@ where >, { pub(crate) endpoint: T, - pub(crate) data: Rc>>, + pub(crate) data: Rc>>, pub(crate) data_factories: Rc>, pub(crate) config: RefCell, - pub(crate) services: Rc>>>, + pub(crate) services: Rc>>>, pub(crate) default: Option>, pub(crate) factory_ref: Rc>>, pub(crate) external: RefCell>, @@ -142,9 +143,9 @@ where endpoint_fut: T::Future, rmap: Rc, config: AppConfig, - data: Rc>>, - data_factories: Vec>, - data_factories_fut: Vec, Error = ()>>>, + data: Rc>>, + data_factories: Vec>, + data_factories_fut: Vec, Error = ()>>>, _t: PhantomData, } diff --git a/src/config.rs b/src/config.rs index 8de43f36c..bbbb3bb01 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,7 +16,7 @@ use crate::service::{ ServiceResponse, }; -type Guards = Vec>; +type Guards = Vec>; type HttpNewService = boxed::BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; @@ -31,7 +31,7 @@ pub struct AppService { Option, Option>, )>, - service_data: Rc>>, + service_data: Rc>>, } impl AppService { @@ -39,7 +39,7 @@ impl AppService { pub(crate) fn new( config: AppConfig, default: Rc, - service_data: Rc>>, + service_data: Rc>>, ) -> Self { AppService { config, @@ -101,7 +101,7 @@ impl AppService { pub fn register_service( &mut self, rdef: ResourceDef, - guards: Option>>, + guards: Option>>, service: F, nested: Option>, ) where @@ -174,8 +174,8 @@ impl Default for AppConfigInner { /// to set of external methods. This could help with /// modularization of big application configuration. pub struct ServiceConfig { - pub(crate) services: Vec>, - pub(crate) data: Vec>, + pub(crate) services: Vec>, + pub(crate) data: Vec>, pub(crate) external: Vec, } diff --git a/src/guard.rs b/src/guard.rs index 0990e876a..6522a9845 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -100,7 +100,7 @@ pub fn Any(guard: F) -> AnyGuard { } /// Matches if any of supplied guards matche. -pub struct AnyGuard(Vec>); +pub struct AnyGuard(Vec>); impl AnyGuard { /// Add guard to a list of guards to check @@ -140,7 +140,7 @@ pub fn All(guard: F) -> AllGuard { } /// Matches if all of supplied guards. -pub struct AllGuard(Vec>); +pub struct AllGuard(Vec>); impl AllGuard { /// Add new guard to the list of guards to check @@ -167,7 +167,7 @@ pub fn Not(guard: F) -> NotGuard { } #[doc(hidden)] -pub struct NotGuard(Box); +pub struct NotGuard(Box); impl Guard for NotGuard { fn check(&self, request: &RequestHead) -> bool { diff --git a/src/middleware/errhandlers.rs b/src/middleware/errhandlers.rs index afe7c72f1..5f73d4d7e 100644 --- a/src/middleware/errhandlers.rs +++ b/src/middleware/errhandlers.rs @@ -18,7 +18,7 @@ pub enum ErrorHandlerResponse { Future(Box, Error = Error>>), } -type ErrorHandler = Fn(ServiceResponse) -> Result>; +type ErrorHandler = dyn Fn(ServiceResponse) -> Result>; /// `Middleware` for allowing custom handlers for responses. /// diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 24aabb95d..9e332fb83 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -444,7 +444,9 @@ impl FormatText { } } -pub(crate) struct FormatDisplay<'a>(&'a Fn(&mut Formatter) -> Result<(), fmt::Error>); +pub(crate) struct FormatDisplay<'a>( + &'a dyn Fn(&mut Formatter) -> Result<(), fmt::Error>, +); impl<'a> fmt::Display for FormatDisplay<'a> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { diff --git a/src/resource.rs b/src/resource.rs index 0d66aa843..0af43a424 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -50,7 +50,7 @@ pub struct Resource { name: Option, routes: Vec, data: Option, - guards: Vec>, + guards: Vec>, default: Rc>>>, factory_ref: Rc>>, } @@ -118,7 +118,7 @@ where self } - pub(crate) fn add_guards(mut self, guards: Vec>) -> Self { + pub(crate) fn add_guards(mut self, guards: Vec>) -> Self { self.guards.extend(guards); self } diff --git a/src/route.rs b/src/route.rs index 591175d15..f4d303632 100644 --- a/src/route.rs +++ b/src/route.rs @@ -13,7 +13,7 @@ use crate::service::{ServiceRequest, ServiceResponse}; use crate::HttpResponse; type BoxedRouteService = Box< - Service< + dyn Service< Request = Req, Response = Res, Error = Error, @@ -25,7 +25,7 @@ type BoxedRouteService = Box< >; type BoxedRouteNewService = Box< - NewService< + dyn NewService< Config = (), Request = Req, Response = Res, @@ -42,7 +42,7 @@ type BoxedRouteNewService = Box< /// If handler is not explicitly set, default *404 Not Found* handler is used. pub struct Route { service: BoxedRouteNewService, - guards: Rc>>, + guards: Rc>>, } impl Route { @@ -56,7 +56,7 @@ impl Route { } } - pub(crate) fn take_guards(&mut self) -> Vec> { + pub(crate) fn take_guards(&mut self) -> Vec> { std::mem::replace(Rc::get_mut(&mut self.guards).unwrap(), Vec::new()) } } @@ -84,7 +84,7 @@ type RouteFuture = Box< pub struct CreateRouteService { fut: RouteFuture, - guards: Rc>>, + guards: Rc>>, } impl Future for CreateRouteService { @@ -104,7 +104,7 @@ impl Future for CreateRouteService { pub struct RouteService { service: BoxedRouteService, - guards: Rc>>, + guards: Rc>>, } impl RouteService { diff --git a/src/scope.rs b/src/scope.rs index 714f0354a..760fee478 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -23,7 +23,7 @@ use crate::service::{ ServiceFactory, ServiceFactoryWrapper, ServiceRequest, ServiceResponse, }; -type Guards = Vec>; +type Guards = Vec>; type HttpService = BoxedService; type HttpNewService = BoxedNewService<(), ServiceRequest, ServiceResponse, Error, ()>; type BoxedResponse = Either< @@ -64,8 +64,8 @@ pub struct Scope { endpoint: T, rdef: String, data: Option, - services: Vec>, - guards: Vec>, + services: Vec>, + guards: Vec>, default: Rc>>>, external: Vec, factory_ref: Rc>>, @@ -578,7 +578,7 @@ impl Future for ScopeFactoryResponse { pub struct ScopeService { data: Option>, - router: Router>>, + router: Router>>, default: Option, _ready: Option<(ServiceRequest, ResourceInfo)>, } diff --git a/src/service.rs b/src/service.rs index 5863a100e..1d475cf15 100644 --- a/src/service.rs +++ b/src/service.rs @@ -407,7 +407,7 @@ impl fmt::Debug for ServiceResponse { pub struct WebService { rdef: String, name: Option, - guards: Vec>, + guards: Vec>, } impl WebService { @@ -476,7 +476,7 @@ struct WebServiceImpl { srv: T, rdef: String, name: Option, - guards: Vec>, + guards: Vec>, } impl HttpServiceFactory for WebServiceImpl diff --git a/src/types/form.rs b/src/types/form.rs index e61145b0d..42e6363f1 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -141,7 +141,7 @@ impl fmt::Display for Form { #[derive(Clone)] pub struct FormConfig { limit: usize, - ehandler: Option Error>>, + ehandler: Option Error>>, } impl FormConfig { diff --git a/src/types/path.rs b/src/types/path.rs index 2a6ce2879..a46575764 100644 --- a/src/types/path.rs +++ b/src/types/path.rs @@ -224,7 +224,7 @@ where /// ``` #[derive(Clone)] pub struct PathConfig { - ehandler: Option Error + Send + Sync>>, + ehandler: Option Error + Send + Sync>>, } impl PathConfig { diff --git a/src/types/payload.rs b/src/types/payload.rs index 8a634b4c9..f33e2e5f1 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -128,7 +128,7 @@ impl FromRequest for Bytes { #[inline] fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { - let mut tmp; + let tmp; let cfg = if let Some(cfg) = req.app_data::() { cfg } else { @@ -184,7 +184,7 @@ impl FromRequest for String { #[inline] fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { - let mut tmp; + let tmp; let cfg = if let Some(cfg) = req.app_data::() { cfg } else { diff --git a/src/types/query.rs b/src/types/query.rs index 17240c0b5..2ad7106d0 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -192,7 +192,8 @@ where /// ``` #[derive(Clone)] pub struct QueryConfig { - ehandler: Option Error + Send + Sync>>, + ehandler: + Option Error + Send + Sync>>, } impl QueryConfig { From b36fdc46db7b606615c417d538059d30427b82fd Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 17 Jul 2019 18:45:17 -0400 Subject: [PATCH 69/80] Remove several usages of 'unsafe' (#968) * Replace UnsafeCell in DateServiceInner with Cell The previous API was extremely dangerous - calling `get_ref()` followed by `reset()` would trigger instant UB, without requiring any `unsafe` blocks in the caller. By making DateInner `Copy`, we can use a normal `Cell` instead of an `UnsafeCell`. This makes it impossible to cause UB (or even panic) with the API. * Split unsafe block HttpServiceHandlerResponse Also add explanation of the safety of the usage of `unsafe` * Replace UnsafeCell with RefCell in PayloadRef This ensures that a mistake in the usage of 'get_mut' will cause a panic, not undefined behavior. --- actix-http/src/config.rs | 24 ++++++++++++------------ actix-http/src/service.rs | 22 ++++++++++++---------- actix-multipart/src/server.rs | 29 +++++++++++++---------------- 3 files changed, 37 insertions(+), 38 deletions(-) diff --git a/actix-http/src/config.rs b/actix-http/src/config.rs index aba50a814..7d0e27635 100644 --- a/actix-http/src/config.rs +++ b/actix-http/src/config.rs @@ -1,4 +1,4 @@ -use std::cell::UnsafeCell; +use std::cell::Cell; use std::fmt; use std::fmt::Write; use std::rc::Rc; @@ -172,6 +172,7 @@ impl ServiceConfig { } } +#[derive(Copy, Clone)] struct Date { bytes: [u8; DATE_VALUE_LENGTH], pos: usize, @@ -205,28 +206,28 @@ impl fmt::Write for Date { struct DateService(Rc); struct DateServiceInner { - current: UnsafeCell>, + current: Cell>, } impl DateServiceInner { fn new() -> Self { DateServiceInner { - current: UnsafeCell::new(None), + current: Cell::new(None), } } - fn get_ref(&self) -> &Option<(Date, Instant)> { - unsafe { &*self.current.get() } + fn get(&self) -> Option<(Date, Instant)> { + self.current.get() } fn reset(&self) { - unsafe { (&mut *self.current.get()).take() }; + self.current.set(None); } fn update(&self) { let now = Instant::now(); let date = Date::new(); - *(unsafe { &mut *self.current.get() }) = Some((date, now)); + self.current.set(Some((date, now))); } } @@ -236,7 +237,7 @@ impl DateService { } fn check_date(&self) { - if self.0.get_ref().is_none() { + if self.0.get().is_none() { self.0.update(); // periodic date update @@ -252,14 +253,13 @@ impl DateService { fn now(&self) -> Instant { self.check_date(); - self.0.get_ref().as_ref().unwrap().1 + self.0.get().unwrap().1 } - fn date(&self) -> &Date { + fn date(&self) -> Date { self.check_date(); - let item = self.0.get_ref().as_ref().unwrap(); - &item.0 + self.0.get().unwrap().0 } } diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index be021b252..09b8077b3 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -466,16 +466,18 @@ where State::Unknown(ref mut data) => { if let Some(ref mut item) = data { loop { - unsafe { - let b = item.1.bytes_mut(); - let n = try_ready!(item.0.poll_read(b)); - if n == 0 { - return Ok(Async::Ready(())); - } - item.1.advance_mut(n); - if item.1.len() >= HTTP2_PREFACE.len() { - break; - } + // Safety - we only write to the returned slice. + let b = unsafe { item.1.bytes_mut() }; + let n = try_ready!(item.0.poll_read(b)); + if n == 0 { + return Ok(Async::Ready(())); + } + // Safety - we know that 'n' bytes have + // been initialized via the contract of + // 'poll_read' + unsafe { item.1.advance_mut(n) }; + if item.1.len() >= HTTP2_PREFACE.len() { + break; } } } else { diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index c28a8d6af..70eb61cb9 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -1,5 +1,5 @@ //! Multipart payload support -use std::cell::{Cell, RefCell, UnsafeCell}; +use std::cell::{Cell, RefCell, RefMut}; use std::marker::PhantomData; use std::rc::Rc; use std::{cmp, fmt}; @@ -112,7 +112,7 @@ impl Stream for Multipart { Err(err) } else if self.safety.current() { let mut inner = self.inner.as_mut().unwrap().borrow_mut(); - if let Some(payload) = inner.payload.get_mut(&self.safety) { + if let Some(mut payload) = inner.payload.get_mut(&self.safety) { payload.poll_stream()?; } inner.poll(&self.safety) @@ -265,12 +265,12 @@ impl InnerMultipart { } } - let headers = if let Some(payload) = self.payload.get_mut(safety) { + let headers = if let Some(mut payload) = self.payload.get_mut(safety) { match self.state { // read until first boundary InnerState::FirstBoundary => { match InnerMultipart::skip_until_boundary( - payload, + &mut *payload, &self.boundary, )? { Some(eof) => { @@ -286,7 +286,7 @@ impl InnerMultipart { } // read boundary InnerState::Boundary => { - match InnerMultipart::read_boundary(payload, &self.boundary)? { + match InnerMultipart::read_boundary(&mut *payload, &self.boundary)? { None => return Ok(Async::NotReady), Some(eof) => { if eof { @@ -303,7 +303,7 @@ impl InnerMultipart { // read field headers for next field if self.state == InnerState::Headers { - if let Some(headers) = InnerMultipart::read_headers(payload)? { + if let Some(headers) = InnerMultipart::read_headers(&mut *payload)? { self.state = InnerState::Boundary; headers } else { @@ -411,7 +411,7 @@ impl Stream for Field { fn poll(&mut self) -> Poll, Self::Error> { if self.safety.current() { let mut inner = self.inner.borrow_mut(); - if let Some(payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) + if let Some(mut payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) { payload.poll_stream()?; } @@ -582,12 +582,12 @@ impl InnerField { return Ok(Async::Ready(None)); } - let result = if let Some(payload) = self.payload.as_ref().unwrap().get_mut(s) { + let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) { if !self.eof { let res = if let Some(ref mut len) = self.length { - InnerField::read_len(payload, len)? + InnerField::read_len(&mut *payload, len)? } else { - InnerField::read_stream(payload, &self.boundary)? + InnerField::read_stream(&mut *payload, &self.boundary)? }; match res { @@ -618,7 +618,7 @@ impl InnerField { } struct PayloadRef { - payload: Rc>, + payload: Rc>, } impl PayloadRef { @@ -628,15 +628,12 @@ impl PayloadRef { } } - fn get_mut<'a, 'b>(&'a self, s: &'b Safety) -> Option<&'a mut PayloadBuffer> + fn get_mut<'a, 'b>(&'a self, s: &'b Safety) -> Option> where 'a: 'b, { - // Unsafe: Invariant is inforced by Safety Safety is used as ref counter, - // only top most ref can have mutable access to payload. if s.current() { - let payload: &mut PayloadBuffer = unsafe { &mut *self.payload.get() }; - Some(payload) + Some(self.payload.borrow_mut()) } else { None } From d03296237eb6cbfa019355eca5747032b0836539 Mon Sep 17 00:00:00 2001 From: Rotem Yaari Date: Thu, 18 Jul 2019 11:31:18 +0300 Subject: [PATCH 70/80] Log error results in Logger middleware (closes #938) (#984) * Log error results in Logger middleware (closes #938) * Log internal server errors with an ERROR log level * Logger middleware: don't log 500 internal server errors, as Actix now logs them always * Changelog --- CHANGES.md | 11 +++++++++++ actix-http/src/response.rs | 3 +++ src/middleware/logger.rs | 9 ++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index cb5f51126..d64a22397 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,16 @@ # Changes +## [1.0.5] - ? + +### Added + +* Actix now logs errors resulting in "internal server error" responses always, with the `error` + logging level + +### Fixed + +* Restored logging of errors through the `Logger` middleware + ## [1.0.4] - 2019-07-17 ### Added diff --git a/actix-http/src/response.rs b/actix-http/src/response.rs index ce986a472..124bf5f92 100644 --- a/actix-http/src/response.rs +++ b/actix-http/src/response.rs @@ -52,6 +52,9 @@ impl Response { #[inline] pub fn from_error(error: Error) -> Response { let mut resp = error.as_response_error().render_response(); + if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR { + error!("Internal Server Error: {:?}", error); + } resp.error = Some(error); resp } diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 9e332fb83..f450f0481 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -9,12 +9,13 @@ use actix_service::{Service, Transform}; use bytes::Bytes; use futures::future::{ok, FutureResult}; use futures::{Async, Future, Poll}; +use log::debug; use regex::Regex; use time; use crate::dev::{BodySize, MessageBody, ResponseBody}; use crate::error::{Error, Result}; -use crate::http::{HeaderName, HttpTryFrom}; +use crate::http::{HeaderName, HttpTryFrom, StatusCode}; use crate::service::{ServiceRequest, ServiceResponse}; use crate::HttpResponse; @@ -202,6 +203,12 @@ where fn poll(&mut self) -> Poll { let res = futures::try_ready!(self.fut.poll()); + if let Some(error) = res.response().error() { + if res.response().head().status != StatusCode::INTERNAL_SERVER_ERROR { + debug!("Error in response: {:?}", error); + } + } + if let Some(ref mut format) = self.format { for unit in &mut format.0 { unit.render_response(res.response()); From fbdda8acb191dcaaa02f582ed8fce0b9bb96a51e Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 18 Jul 2019 17:24:12 +0600 Subject: [PATCH 71/80] Unix domain sockets (HttpServer::bind_uds) #92 --- CHANGES.md | 5 +++- Cargo.toml | 9 ++++--- actix-multipart/src/server.rs | 11 +++++--- examples/uds.rs | 49 +++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/server.rs | 32 +++++++++++++++++++++++ test-server/CHANGES.md | 4 +++ test-server/Cargo.toml | 4 +-- test-server/src/lib.rs | 3 ++- 9 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 examples/uds.rs diff --git a/CHANGES.md b/CHANGES.md index d64a22397..80abfc599 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,11 @@ # Changes -## [1.0.5] - ? +## [1.0.5] - 2019-07-xx ### Added +* Unix domain sockets (HttpServer::bind_uds) #92 + * Actix now logs errors resulting in "internal server error" responses always, with the `error` logging level @@ -11,6 +13,7 @@ * Restored logging of errors through the `Logger` middleware + ## [1.0.4] - 2019-07-17 ### Added diff --git a/Cargo.toml b/Cargo.toml index 866a7628f..40817a1f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"] edition = "2018" [package.metadata.docs.rs] -features = ["ssl", "brotli", "flate2-zlib", "secure-cookies", "client", "rust-tls"] +features = ["ssl", "brotli", "flate2-zlib", "secure-cookies", "client", "rust-tls", "uds"] [badges] travis-ci = { repository = "actix/actix-web", branch = "master" } @@ -68,6 +68,9 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] # rustls rust-tls = ["rustls", "actix-server/rust-tls"] +# unix domain sockets support +uds = ["actix-server/uds"] + [dependencies] actix-codec = "0.1.2" actix-service = "0.4.1" @@ -76,8 +79,8 @@ actix-router = "0.1.5" actix-rt = "0.2.4" actix-web-codegen = "0.1.2" actix-http = "0.2.6" -actix-server = "0.5.1" -actix-server-config = "0.1.1" +actix-server = "0.6.0" +actix-server-config = "0.1.2" actix-threadpool = "0.1.1" awc = { version = "0.2.1", optional = true } diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index 70eb61cb9..e2111bb7b 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -286,7 +286,10 @@ impl InnerMultipart { } // read boundary InnerState::Boundary => { - match InnerMultipart::read_boundary(&mut *payload, &self.boundary)? { + match InnerMultipart::read_boundary( + &mut *payload, + &self.boundary, + )? { None => return Ok(Async::NotReady), Some(eof) => { if eof { @@ -411,7 +414,8 @@ impl Stream for Field { fn poll(&mut self) -> Poll, Self::Error> { if self.safety.current() { let mut inner = self.inner.borrow_mut(); - if let Some(mut payload) = inner.payload.as_ref().unwrap().get_mut(&self.safety) + if let Some(mut payload) = + inner.payload.as_ref().unwrap().get_mut(&self.safety) { payload.poll_stream()?; } @@ -582,7 +586,8 @@ impl InnerField { return Ok(Async::Ready(None)); } - let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) { + let result = if let Some(mut payload) = self.payload.as_ref().unwrap().get_mut(s) + { if !self.eof { let res = if let Some(ref mut len) = self.length { InnerField::read_len(&mut *payload, len)? diff --git a/examples/uds.rs b/examples/uds.rs new file mode 100644 index 000000000..4d6eca40c --- /dev/null +++ b/examples/uds.rs @@ -0,0 +1,49 @@ +use futures::IntoFuture; + +use actix_web::{ + get, middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer, +}; + +#[get("/resource1/{name}/index.html")] +fn index(req: HttpRequest, name: web::Path) -> String { + println!("REQ: {:?}", req); + format!("Hello: {}!\r\n", name) +} + +fn index_async(req: HttpRequest) -> impl IntoFuture { + println!("REQ: {:?}", req); + Ok("Hello world!\r\n") +} + +#[get("/")] +fn no_params() -> &'static str { + "Hello world!\r\n" +} + +fn main() -> std::io::Result<()> { + std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); + env_logger::init(); + + HttpServer::new(|| { + App::new() + .wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2")) + .wrap(middleware::Compress::default()) + .wrap(middleware::Logger::default()) + .service(index) + .service(no_params) + .service( + web::resource("/resource2/index.html") + .wrap( + middleware::DefaultHeaders::new().header("X-Version-R2", "0.3"), + ) + .default_service( + web::route().to(|| HttpResponse::MethodNotAllowed()), + ) + .route(web::get().to_async(index_async)), + ) + .service(web::resource("/test1.html").to(|| "Test\r\n")) + }) + .bind_uds("/Users/fafhrd91/uds-test")? + .workers(1) + .run() +} diff --git a/src/lib.rs b/src/lib.rs index 857bc294e..c7cdf1475 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ //! `c` compiler (default enabled) //! * `flate2-rust` - experimental rust based implementation for //! `gzip`, `deflate` compression. +//! * `uds` - Unix domain support, enables `HttpServer::bind_uds()` method. //! #![allow(clippy::type_complexity, clippy::new_without_default)] diff --git a/src/server.rs b/src/server.rs index 43236fa34..aa654e576 100644 --- a/src/server.rs +++ b/src/server.rs @@ -434,6 +434,38 @@ where } Ok(self) } + + #[cfg(feature = "uds")] + /// Start listening for incoming unix domain connections. + /// + /// This method is available with `uds` feature. + pub fn bind_uds(mut self, addr: A) -> io::Result + where + A: AsRef, + { + let cfg = self.config.clone(); + let factory = self.factory.clone(); + self.sockets.push(Socket { + scheme: "http", + addr: net::SocketAddr::new( + net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), + 8080, + ), + }); + + self.builder = self.builder.bind_uds( + format!("actix-web-service-{:?}", addr.as_ref()), + addr, + move || { + let c = cfg.lock(); + HttpService::build() + .keep_alive(c.keep_alive) + .client_timeout(c.client_timeout) + .finish(factory()) + }, + )?; + Ok(self) + } } impl HttpServer diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index f3e98010a..33314421b 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.2.4] - 2019-07-18 + +* Update actix-server to 0.6 + ## [0.2.3] - 2019-07-16 * Add `delete`, `options`, `patch` methods to `TestServerRunner` diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 445ed33e6..512f65e1c 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "0.2.3" +version = "0.2.4" authors = ["Nikolay Kim "] description = "Actix http test server" readme = "README.md" @@ -33,7 +33,7 @@ ssl = ["openssl", "actix-server/ssl", "awc/ssl"] actix-codec = "0.1.2" actix-rt = "0.2.2" actix-service = "0.4.1" -actix-server = "0.5.1" +actix-server = "0.6.0" actix-utils = "0.4.1" awc = "0.2.2" diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 38405cd55..ce73e181b 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -12,6 +12,7 @@ use futures::future::lazy; use futures::{Future, IntoFuture, Stream}; use http::Method; use net2::TcpBuilder; +use tokio_tcp::TcpStream; thread_local! { static RT: RefCell = { @@ -109,7 +110,7 @@ pub struct TestServerRuntime { impl TestServer { #[allow(clippy::new_ret_no_self)] /// Start new test server with application factory - pub fn new(factory: F) -> TestServerRuntime { + pub fn new>(factory: F) -> TestServerRuntime { let (tx, rx) = mpsc::channel(); // run server in separate thread From 29098f8397ff8ec8b8d615d72c5a08bec08fec4d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Thu, 18 Jul 2019 13:25:50 +0200 Subject: [PATCH 72/80] Add support for downcasting response errors (#986) * Add support for downcasting response errors * Added test for error casting --- actix-http/src/error.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 368ee6dde..c4d663ade 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -4,6 +4,7 @@ use std::io::Write; use std::str::Utf8Error; use std::string::FromUtf8Error; use std::{fmt, io, result}; +use std::any::TypeId; pub use actix_threadpool::BlockingError; use actix_utils::timeout::TimeoutError; @@ -51,6 +52,11 @@ impl Error { pub fn as_response_error(&self) -> &dyn ResponseError { self.cause.as_ref() } + + /// Similar to `as_response_error` but downcasts. + pub fn as_error(&self) -> Option<&T> { + ResponseError::downcast_ref(self.cause.as_ref()) + } } /// Error that can be converted to `Response` @@ -73,6 +79,22 @@ pub trait ResponseError: fmt::Debug + fmt::Display { ); resp.set_body(Body::from(buf)) } + + #[doc(hidden)] + fn __private_get_type_id__(&self) -> TypeId where Self: 'static { + TypeId::of::() + } +} + +impl ResponseError + 'static { + /// Downcasts a response error to a specific type. + pub fn downcast_ref(&self) -> Option<&T> { + if self.__private_get_type_id__() == TypeId::of::() { + unsafe { Some(&*(self as *const ResponseError as *const T)) } + } else { + None + } + } } impl fmt::Display for Error { @@ -1044,6 +1066,16 @@ mod tests { assert_eq!(resp.status(), StatusCode::OK); } + #[test] + fn test_error_casting() { + let err = PayloadError::Overflow; + let resp_err: &ResponseError = &err; + let err = resp_err.downcast_ref::().unwrap(); + assert_eq!(err.to_string(), "A payload reached size limit."); + let not_err = resp_err.downcast_ref::(); + assert!(not_err.is_none()); + } + #[test] fn test_error_helpers() { let r: Response = ErrorBadRequest("err").into(); From 9c3789cbd0c607d58f024afd2e51dc2f6a1198d5 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 18 Jul 2019 17:37:41 +0600 Subject: [PATCH 73/80] revert DateServiceInner changes --- actix-http/CHANGES.md | 7 +++++++ actix-http/src/config.rs | 31 +++++++++++++++---------------- actix-http/src/error.rs | 7 +++++-- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 84033531d..cc695fa63 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [0.2.7] - 2019-07-18 + +### Added + +* Add support for downcasting response errors #986 + + ## [0.2.6] - 2019-07-17 ### Changed diff --git a/actix-http/src/config.rs b/actix-http/src/config.rs index 7d0e27635..bdfecef30 100644 --- a/actix-http/src/config.rs +++ b/actix-http/src/config.rs @@ -1,4 +1,4 @@ -use std::cell::Cell; +use std::cell::UnsafeCell; use std::fmt; use std::fmt::Write; use std::rc::Rc; @@ -162,13 +162,17 @@ impl ServiceConfig { 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); + self.0 + .timer + .set_date(|date| buf[6..35].copy_from_slice(&date.bytes)); buf[35..].copy_from_slice(b"\r\n\r\n"); dst.extend_from_slice(&buf); } pub(crate) fn set_date_header(&self, dst: &mut BytesMut) { - dst.extend_from_slice(&self.0.timer.date().bytes); + self.0 + .timer + .set_date(|date| dst.extend_from_slice(&date.bytes)); } } @@ -206,28 +210,24 @@ impl fmt::Write for Date { struct DateService(Rc); struct DateServiceInner { - current: Cell>, + current: UnsafeCell>, } impl DateServiceInner { fn new() -> Self { DateServiceInner { - current: Cell::new(None), + current: UnsafeCell::new(None), } } - fn get(&self) -> Option<(Date, Instant)> { - self.current.get() - } - fn reset(&self) { - self.current.set(None); + unsafe { (&mut *self.current.get()).take() }; } fn update(&self) { let now = Instant::now(); let date = Date::new(); - self.current.set(Some((date, now))); + *(unsafe { &mut *self.current.get() }) = Some((date, now)); } } @@ -237,7 +237,7 @@ impl DateService { } fn check_date(&self) { - if self.0.get().is_none() { + if unsafe { (&*self.0.current.get()).is_none() } { self.0.update(); // periodic date update @@ -253,13 +253,12 @@ impl DateService { fn now(&self) -> Instant { self.check_date(); - self.0.get().unwrap().1 + unsafe { (&*self.0.current.get()).as_ref().unwrap().1 } } - fn date(&self) -> Date { + fn set_date(&self, mut f: F) { self.check_date(); - - self.0.get().unwrap().0 + f(&unsafe { (&*self.0.current.get()).as_ref().unwrap().0 }) } } diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index c4d663ade..cbb009a72 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -1,10 +1,10 @@ //! Error and Result module +use std::any::TypeId; use std::cell::RefCell; use std::io::Write; use std::str::Utf8Error; use std::string::FromUtf8Error; use std::{fmt, io, result}; -use std::any::TypeId; pub use actix_threadpool::BlockingError; use actix_utils::timeout::TimeoutError; @@ -81,7 +81,10 @@ pub trait ResponseError: fmt::Debug + fmt::Display { } #[doc(hidden)] - fn __private_get_type_id__(&self) -> TypeId where Self: 'static { + fn __private_get_type_id__(&self) -> TypeId + where + Self: 'static, + { TypeId::of::() } } From b6ff786ed361cb2d1c4111629dd9c96e697a0cfe Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 18 Jul 2019 17:50:10 +0600 Subject: [PATCH 74/80] update dependencies --- Cargo.toml | 6 +++--- actix-framed/Cargo.toml | 6 +++--- actix-http/Cargo.toml | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 40817a1f7..f2ed91603 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "1.0.4" +version = "1.0.5" authors = ["Nikolay Kim "] description = "Actix web is a simple, pragmatic and extremely fast web framework for Rust." readme = "README.md" @@ -82,7 +82,7 @@ actix-http = "0.2.6" actix-server = "0.6.0" actix-server-config = "0.1.2" actix-threadpool = "0.1.1" -awc = { version = "0.2.1", optional = true } +awc = { version = "0.2.2", optional = true } bytes = "0.4" derive_more = "0.15.0" @@ -107,7 +107,7 @@ rustls = { version = "0.15", optional = true } [dev-dependencies] actix = { version = "0.8.3" } actix-http = { version = "0.2.5", features=["ssl", "brotli", "flate2-zlib"] } -actix-http-test = { version = "0.2.2", features=["ssl"] } +actix-http-test = { version = "0.2.4", features=["ssl"] } rand = "0.7" env_logger = "0.6" serde_derive = "1.0" diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index c2ab26fa2..5fbd262d0 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -26,13 +26,13 @@ actix-utils = "0.4.0" actix-router = "0.1.2" actix-rt = "0.2.2" actix-http = "0.2.0" -actix-server-config = "0.1.1" +actix-server-config = "0.1.2" bytes = "0.4" futures = "0.1.25" log = "0.4" [dev-dependencies] -actix-server = { version = "0.5.0", features=["ssl"] } +actix-server = { version = "0.6.0", features=["ssl"] } actix-connect = { version = "0.2.0", features=["ssl"] } -actix-http-test = { version = "0.2.0", features=["ssl"] } +actix-http-test = { version = "0.2.4", features=["ssl"] } diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index ae12cbc41..0cbf5867f 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "0.2.6" +version = "0.2.7" authors = ["Nikolay Kim "] description = "Actix http primitives" readme = "README.md" @@ -48,7 +48,7 @@ actix-service = "0.4.1" actix-codec = "0.1.2" actix-connect = "0.2.1" actix-utils = "0.4.4" -actix-server-config = "0.1.1" +actix-server-config = "0.1.2" actix-threadpool = "0.1.1" base64 = "0.10" @@ -97,9 +97,9 @@ chrono = "0.4.6" [dev-dependencies] actix-rt = "0.2.2" -actix-server = { version = "0.5.0", features=["ssl"] } +actix-server = { version = "0.6.0", features=["ssl"] } actix-connect = { version = "0.2.0", features=["ssl"] } -actix-http-test = { version = "0.2.0", features=["ssl"] } +actix-http-test = { version = "0.2.4", features=["ssl"] } env_logger = "0.6" serde_derive = "1.0" openssl = { version="0.10" } From 6b7df6b242c1cf844ff95b26d963eb275b3d0ada Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Thu, 18 Jul 2019 17:51:51 +0600 Subject: [PATCH 75/80] prep actix-web release --- CHANGES.md | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 80abfc599..754c67f26 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## [1.0.5] - 2019-07-xx +## [1.0.5] - 2019-07-18 ### Added diff --git a/Cargo.toml b/Cargo.toml index f2ed91603..538ea0d38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ actix-utils = "0.4.4" actix-router = "0.1.5" actix-rt = "0.2.4" actix-web-codegen = "0.1.2" -actix-http = "0.2.6" +actix-http = "0.2.7" actix-server = "0.6.0" actix-server-config = "0.1.2" actix-threadpool = "0.1.1" From 3650f6d7b888c823c2af60c507904e4700c77b3a Mon Sep 17 00:00:00 2001 From: Anton Lazarev Date: Thu, 18 Jul 2019 21:28:43 -0700 Subject: [PATCH 76/80] Re-implement Host predicate (#989) * update HostGuard implementation * update/add tests for new HostGuard implementation --- src/guard.rs | 166 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 50 deletions(-) diff --git a/src/guard.rs b/src/guard.rs index 6522a9845..6fd6d1d2c 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -26,7 +26,7 @@ //! ``` #![allow(non_snake_case)] -use actix_http::http::{self, header, HttpTryFrom}; +use actix_http::http::{self, header, HttpTryFrom, uri::Uri}; use actix_http::RequestHead; /// Trait defines resource guards. Guards are used for routes selection. @@ -256,45 +256,68 @@ impl Guard for HeaderGuard { } } -// /// Return predicate that matches if request contains specified Host name. -// /// -// /// ```rust,ignore -// /// # extern crate actix_web; -// /// use actix_web::{pred, App, HttpResponse}; -// /// -// /// fn main() { -// /// App::new().resource("/index.html", |r| { -// /// r.route() -// /// .guard(pred::Host("www.rust-lang.org")) -// /// .f(|_| HttpResponse::MethodNotAllowed()) -// /// }); -// /// } -// /// ``` -// pub fn Host>(host: H) -> HostGuard { -// HostGuard(host.as_ref().to_string(), None) -// } +/// Return predicate that matches if request contains specified Host name. +/// +/// ```rust,ignore +/// # extern crate actix_web; +/// use actix_web::{guard::Host, App, HttpResponse}; +/// +/// fn main() { +/// App::new().resource("/index.html", |r| { +/// r.route() +/// .guard(Host("www.rust-lang.org")) +/// .f(|_| HttpResponse::MethodNotAllowed()) +/// }); +/// } +/// ``` +pub fn Host>(host: H) -> HostGuard { + HostGuard(host.as_ref().to_string(), None) +} -// #[doc(hidden)] -// pub struct HostGuard(String, Option); +fn get_host_uri(req: &RequestHead) -> Option { + use core::str::FromStr; + let host_value = req.headers.get(header::HOST)?; + let host = host_value.to_str().ok()?; + let uri = Uri::from_str(host).ok()?; + Some(uri) +} -// impl HostGuard { -// /// Set reuest scheme to match -// pub fn scheme>(&mut self, scheme: H) { -// self.1 = Some(scheme.as_ref().to_string()) -// } -// } +#[doc(hidden)] +pub struct HostGuard(String, Option); -// impl Guard for HostGuard { -// fn check(&self, _req: &RequestHead) -> bool { -// // let info = req.connection_info(); -// // if let Some(ref scheme) = self.1 { -// // self.0 == info.host() && scheme == info.scheme() -// // } else { -// // self.0 == info.host() -// // } -// false -// } -// } +impl HostGuard { + /// Set request scheme to match + pub fn scheme>(mut self, scheme: H) -> HostGuard { + self.1 = Some(scheme.as_ref().to_string()); + self + } +} + +impl Guard for HostGuard { + fn check(&self, req: &RequestHead) -> bool { + let req_host_uri = if let Some(uri) = get_host_uri(req) { + uri + } else { + return false; + }; + + if let Some(uri_host) = req_host_uri.host() { + if self.0 != uri_host { + return false; + } + } else { + return false; + } + + if let Some(ref scheme) = self.1 { + if let Some(ref req_host_uri_scheme) = req_host_uri.scheme_str() { + return scheme == req_host_uri_scheme; + } + } + + true + } +} #[cfg(test)] mod tests { @@ -318,21 +341,64 @@ mod tests { assert!(!pred.check(req.head())); } - // #[test] - // fn test_host() { - // let req = TestServiceRequest::default() - // .header( - // header::HOST, - // header::HeaderValue::from_static("www.rust-lang.org"), - // ) - // .request(); + #[test] + fn test_host() { + let req = TestRequest::default() + .header( + header::HOST, + header::HeaderValue::from_static("www.rust-lang.org"), + ) + .to_http_request(); - // let pred = Host("www.rust-lang.org"); - // assert!(pred.check(&req)); + let pred = Host("www.rust-lang.org"); + assert!(pred.check(req.head())); - // let pred = Host("localhost"); - // assert!(!pred.check(&req)); - // } + let pred = Host("www.rust-lang.org").scheme("https"); + assert!(pred.check(req.head())); + + let pred = Host("blog.rust-lang.org"); + assert!(!pred.check(req.head())); + + let pred = Host("blog.rust-lang.org").scheme("https"); + assert!(!pred.check(req.head())); + + let pred = Host("crates.io"); + assert!(!pred.check(req.head())); + + let pred = Host("localhost"); + assert!(!pred.check(req.head())); + } + + #[test] + fn test_host_scheme() { + let req = TestRequest::default() + .header( + header::HOST, + header::HeaderValue::from_static("https://www.rust-lang.org"), + ) + .to_http_request(); + + let pred = Host("www.rust-lang.org").scheme("https"); + assert!(pred.check(req.head())); + + let pred = Host("www.rust-lang.org"); + assert!(pred.check(req.head())); + + let pred = Host("www.rust-lang.org").scheme("http"); + assert!(!pred.check(req.head())); + + let pred = Host("blog.rust-lang.org"); + assert!(!pred.check(req.head())); + + let pred = Host("blog.rust-lang.org").scheme("https"); + assert!(!pred.check(req.head())); + + let pred = Host("crates.io").scheme("https"); + assert!(!pred.check(req.head())); + + let pred = Host("localhost"); + assert!(!pred.check(req.head())); + } #[test] fn test_methods() { From cccd82965653e951854ee293235ded2fb09a3baa Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 19 Jul 2019 11:07:52 +0600 Subject: [PATCH 77/80] update changes --- CHANGES.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 754c67f26..bc022e388 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,12 @@ # Changes +## [1.0.6] - 2019-xx-xx + +### Added + +* Re-implement Host predicate (#989) + + ## [1.0.5] - 2019-07-18 ### Added From c808364c072f0b1e5fefc59229facce6ef3595c1 Mon Sep 17 00:00:00 2001 From: jesskfullwood <38404589+jesskfullwood@users.noreply.github.com> Date: Fri, 19 Jul 2019 10:47:44 +0100 Subject: [PATCH 78/80] make Query payload public (#991) --- CHANGES.md | 4 ++++ src/types/query.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bc022e388..d56e5ce0f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,10 @@ * Re-implement Host predicate (#989) +### Changed + +* `Query` payload made `pub`. Allows user to pattern-match the payload. + ## [1.0.5] - 2019-07-18 diff --git a/src/types/query.rs b/src/types/query.rs index 2ad7106d0..d00f4600d 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -36,7 +36,7 @@ use crate::request::HttpRequest; /// // Use `Query` extractor for query information. /// // This handler get called only if request's query contains `username` field /// // The correct request for this handler would be `/index.html?id=64&response_type=Code"` -/// fn index(info: web::Query) -> String { +/// fn index(web::Query(info): web::Query) -> String { /// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type) /// } /// @@ -45,7 +45,7 @@ use crate::request::HttpRequest; /// web::resource("/index.html").route(web::get().to(index))); // <- use `Query` extractor /// } /// ``` -pub struct Query(T); +pub struct Query(pub T); impl Query { /// Deconstruct to a inner value From f8320fedd83e159ed78789815ad0765919d50284 Mon Sep 17 00:00:00 2001 From: jesskfullwood <38404589+jesskfullwood@users.noreply.github.com> Date: Fri, 19 Jul 2019 12:37:49 +0100 Subject: [PATCH 79/80] add note about Query decoding (#992) --- src/types/query.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/types/query.rs b/src/types/query.rs index d00f4600d..60b07085d 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -12,9 +12,12 @@ use crate::error::QueryPayloadError; use crate::extract::FromRequest; use crate::request::HttpRequest; -#[derive(PartialEq, Eq, PartialOrd, Ord)] /// Extract typed information from the request's query. /// +/// **Note**: A query string consists of unordered `key=value` pairs, therefore it cannot +/// be decoded into any type which depends upon data ordering e.g. tuples or tuple-structs. +/// Attempts to do so will *fail at runtime*. +/// /// ## Example /// /// ```rust @@ -33,9 +36,9 @@ use crate::request::HttpRequest; /// response_type: ResponseType, /// } /// -/// // Use `Query` extractor for query information. -/// // This handler get called only if request's query contains `username` field -/// // The correct request for this handler would be `/index.html?id=64&response_type=Code"` +/// // Use `Query` extractor for query information (and destructure it within the signature). +/// // This handler gets called only if the request's query string contains a `username` field. +/// // The correct request for this handler would be `/index.html?id=64&response_type=Code"`. /// fn index(web::Query(info): web::Query) -> String { /// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type) /// } @@ -45,6 +48,7 @@ use crate::request::HttpRequest; /// web::resource("/index.html").route(web::get().to(index))); // <- use `Query` extractor /// } /// ``` +#[derive(PartialEq, Eq, PartialOrd, Ord)] pub struct Query(pub T); impl Query { @@ -162,6 +166,8 @@ where /// Query extractor configuration /// +/// ## Example +/// /// ```rust /// #[macro_use] extern crate serde_derive; /// use actix_web::{error, web, App, FromRequest, HttpResponse}; From 941241c5f097260f552dd988fa5292d872c823d9 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Sat, 20 Jul 2019 10:50:36 +0600 Subject: [PATCH 80/80] Remove unneeded actix-utils dependency --- actix-framed/Cargo.toml | 8 ++++---- actix-framed/changes.md | 5 +++++ actix-framed/src/app.rs | 9 ++++----- actix-framed/src/lib.rs | 7 +------ src/guard.rs | 2 +- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/actix-framed/Cargo.toml b/actix-framed/Cargo.toml index 5fbd262d0..321041c7e 100644 --- a/actix-framed/Cargo.toml +++ b/actix-framed/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-framed" -version = "0.2.0" +version = "0.2.1" authors = ["Nikolay Kim "] description = "Actix framed app server" readme = "README.md" @@ -21,11 +21,10 @@ path = "src/lib.rs" [dependencies] actix-codec = "0.1.2" -actix-service = "0.4.0" -actix-utils = "0.4.0" +actix-service = "0.4.1" actix-router = "0.1.2" actix-rt = "0.2.2" -actix-http = "0.2.0" +actix-http = "0.2.7" actix-server-config = "0.1.2" bytes = "0.4" @@ -36,3 +35,4 @@ log = "0.4" actix-server = { version = "0.6.0", features=["ssl"] } actix-connect = { version = "0.2.0", features=["ssl"] } actix-http-test = { version = "0.2.4", features=["ssl"] } +actix-utils = "0.4.4" diff --git a/actix-framed/changes.md b/actix-framed/changes.md index 9f16c790a..6e67e00d8 100644 --- a/actix-framed/changes.md +++ b/actix-framed/changes.md @@ -1,5 +1,10 @@ # Changes +## [0.2.1] - 2019-07-20 + +* Remove unneeded actix-utils dependency + + ## [0.2.0] - 2019-05-12 * Update dependencies diff --git a/actix-framed/src/app.rs b/actix-framed/src/app.rs index a9d73a25c..ad5b1ec26 100644 --- a/actix-framed/src/app.rs +++ b/actix-framed/src/app.rs @@ -6,7 +6,6 @@ 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}; use crate::helpers::{BoxedHttpNewService, BoxedHttpService, HttpNewService}; @@ -100,7 +99,7 @@ where type Response = (); type Error = Error; type InitError = (); - type Service = CloneableService>; + type Service = FramedAppService; type Future = CreateService; fn new_service(&self, _: &ServerConfig) -> Self::Future { @@ -138,7 +137,7 @@ impl Future for CreateService where T: AsyncRead + AsyncWrite, { - type Item = CloneableService>; + type Item = FramedAppService; type Error = (); fn poll(&mut self) -> Poll { @@ -177,10 +176,10 @@ where } router }); - Ok(Async::Ready(CloneableService::new(FramedAppService { + Ok(Async::Ready(FramedAppService { router: router.finish(), state: self.state.clone(), - }))) + })) } else { Ok(Async::NotReady) } diff --git a/actix-framed/src/lib.rs b/actix-framed/src/lib.rs index 5e72ba5ba..250533f39 100644 --- a/actix-framed/src/lib.rs +++ b/actix-framed/src/lib.rs @@ -1,9 +1,4 @@ -#![allow( - clippy::type_complexity, - clippy::new_without_default, - dead_code, - deprecated -)] +#![allow(clippy::type_complexity, clippy::new_without_default, dead_code)] mod app; mod helpers; mod request; diff --git a/src/guard.rs b/src/guard.rs index 6fd6d1d2c..e0b4055ba 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -26,7 +26,7 @@ //! ``` #![allow(non_snake_case)] -use actix_http::http::{self, header, HttpTryFrom, uri::Uri}; +use actix_http::http::{self, header, uri::Uri, HttpTryFrom}; use actix_http::RequestHead; /// Trait defines resource guards. Guards are used for routes selection.