From ceac97bb8d11053002987a3ba735fd265a9d65ea Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 4 Nov 2020 15:08:12 +0000 Subject: [PATCH 01/24] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3e62958d8..d8c6d66ca 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,8 +1,15 @@ blank_issues_enabled: true contact_links: - - name: Gitter channel (actix-web) + - name: GitHub Discussions + url: https://github.com/actix/actix-web/discussions + about: Actix Web Q&A + - name: Gitter chat (actix-web) url: https://gitter.im/actix/actix-web - about: Please ask and answer questions about the actix-web here. - - name: Gitter channel (actix) + about: Actix Web Q&A + - name: Gitter chat (actix) url: https://gitter.im/actix/actix - about: Please ask and answer questions about the actix here. + about: Actix (actor framework) Q&A + - name: Actix Discord + url: https://discord.gg/NWpN5mmg3x + about: Actix developer discussion and community chat + From 9b6a089b3675d07805ce4b184b6a317418c7e5da Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Thu, 5 Nov 2020 06:20:01 +0800 Subject: [PATCH 02/24] fix awc doc example (#1772) * fix awc readme example Co-authored-by: Rob Ede --- awc/README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/awc/README.md b/awc/README.md index fb2468b4a..cbe299aaf 100644 --- a/awc/README.md +++ b/awc/README.md @@ -16,23 +16,21 @@ - Minimum Supported Rust Version (MSRV): 1.42.0 ## Example - ```rust use actix_rt::System; use awc::Client; -use futures::future::{Future, lazy}; fn main() { - System::new("test").block_on(lazy(|| { - let mut client = Client::default(); + System::new("test").block_on(async { + let client = Client::default(); - client.get("http://www.rust-lang.org") // <- Create request builder - .header("User-Agent", "Actix-web") - .send() // <- Send http request - .and_then(|response| { // <- server http response - println!("Response: {:?}", response); - Ok(()) - }) - })); + let res = client + .get("http://www.rust-lang.org") // <- Create request builder + .header("User-Agent", "Actix-web") + .send() // <- Send http request + .await; + + println!("Response: {:?}", res); // <- server http response + }); } ``` From 4bfd5c278177847623463594edb0187186c304a4 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 6 Nov 2020 01:36:15 +0900 Subject: [PATCH 03/24] Upgrade `serde_urlencoded` to `0.7` (#1773) --- CHANGES.md | 2 ++ Cargo.toml | 2 +- actix-http/CHANGES.md | 3 +++ actix-http/Cargo.toml | 2 +- awc/CHANGES.md | 3 ++- awc/Cargo.toml | 2 +- test-server/CHANGES.md | 1 + test-server/Cargo.toml | 2 +- 8 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index cc41f839b..9277d5bd2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,8 @@ # Changes ## Unreleased - 2020-xx-xx +### Changed +* Upgrade `serde_urlencoded` to `0.7`. ## 3.2.0 - 2020-10-30 diff --git a/Cargo.toml b/Cargo.toml index 33ec52fae..da511888a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ pin-project = "1.0.0" regex = "1.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde_urlencoded = "0.6.1" +serde_urlencoded = "0.7" time = { version = "0.2.7", default-features = false, features = ["std"] } url = "2.1" open-ssl = { package = "openssl", version = "0.10", optional = true } diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 2f4e44142..eeed4e14b 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -7,6 +7,9 @@ ### Fixed * Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767] +### Changed +* Upgrade `serde_urlencoded` to `0.7`. + [#1767]: https://github.com/actix/actix-web/pull/1767 [#1768]: https://github.com/actix/actix-web/pull/1768 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index a2d55460d..31495e395 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -78,7 +78,7 @@ serde = "1.0" serde_json = "1.0" sha-1 = "0.9" slab = "0.4" -serde_urlencoded = "0.6.1" +serde_urlencoded = "0.7" time = { version = "0.2.7", default-features = false, features = ["std"] } # compression diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 5e87362f0..e184dfbd1 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,7 +1,8 @@ # Changes ## Unreleased - 2020-xx-xx - +### Changed +* Upgrade `serde_urlencoded` to `0.7`. ## 2.0.1 - 2020-10-30 ### Changed diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 049c8e664..d92996fb9 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -53,7 +53,7 @@ percent-encoding = "2.1" rand = "0.7" serde = "1.0" serde_json = "1.0" -serde_urlencoded = "0.6.1" +serde_urlencoded = "0.7" open-ssl = { version = "0.10", package = "openssl", optional = true } rust-tls = { version = "0.18.0", package = "rustls", optional = true, features = ["dangerous_configuration"] } diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index e3a59e5bf..845b6e2dc 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -4,6 +4,7 @@ * add ability to set address for `TestServer` [#1645] * Upgrade `base64` to `0.13`. +* Upgrade `serde_urlencoded` to `0.7`. [#1645]: https://github.com/actix/actix-web/pull/1645 diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 3ee6b8a30..87db93469 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -47,7 +47,7 @@ socket2 = "0.3" serde = "1.0" serde_json = "1.0" slab = "0.4" -serde_urlencoded = "0.6.1" +serde_urlencoded = "0.7" time = { version = "0.2.7", default-features = false, features = ["std"] } open-ssl = { version = "0.10", package = "openssl", optional = true } From e5b86d189c1326f6260ee1d8c4b5af14d93afdff Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Thu, 5 Nov 2020 18:46:17 +0100 Subject: [PATCH 04/24] Fix typo in request_data.rs (#1774) --- src/request_data.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request_data.rs b/src/request_data.rs index c01930418..285154884 100644 --- a/src/request_data.rs +++ b/src/request_data.rs @@ -50,7 +50,7 @@ use crate::{dev::Payload, FromRequest, HttpRequest}; pub struct ReqData(T); impl ReqData { - /// Consumes the `ReqData`, returning it's wrapped data. + /// Consumes the `ReqData`, returning its wrapped data. pub fn into_inner(self) -> T { self.0 } From 9b42333fac0c37dd2a68a3f7cec66b23e344a63b Mon Sep 17 00:00:00 2001 From: Pouya Mobasher Behrouz Date: Fri, 6 Nov 2020 17:04:42 +0330 Subject: [PATCH 05/24] Fix typo in Query extractor docs (#1777) --- 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 f9440e1b4..7eded49c5 100644 --- a/src/types/query.rs +++ b/src/types/query.rs @@ -39,7 +39,7 @@ use crate::request::HttpRequest; /// } /// /// // 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. +/// // This handler gets called only if the request's query string contains `id` and `response_type` fields. /// // The correct request for this handler would be `/index.html?id=64&response_type=Code"`. /// async fn index(web::Query(info): web::Query) -> String { /// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type) @@ -117,7 +117,7 @@ impl fmt::Display for Query { /// } /// /// // Use `Query` extractor for query information. -/// // This handler get called only if request's query contains `username` field +/// // This handler get called only if request's query contains `id` and `response_type` fields. /// // The correct request for this handler would be `/index.html?id=64&response_type=Code"` /// async fn index(info: web::Query) -> String { /// format!("Authorization request for client with id={} and type={:?}!", info.id, info.response_type) From 49e945c88f9582eb1bf7b52b22975b3aef2a3200 Mon Sep 17 00:00:00 2001 From: Aravinth Date: Mon, 9 Nov 2020 19:31:36 +0530 Subject: [PATCH 06/24] switching to nightly for intra-doc links (#1783) --- .github/workflows/upload-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 99fa663cc..cdf05a979 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -16,7 +16,7 @@ jobs: - name: Install Rust uses: actions-rs/toolchain@v1 with: - toolchain: stable-x86_64-unknown-linux-gnu + toolchain: nightly-x86_64-unknown-linux-gnu profile: minimal override: true From a929209967f87577387c16831427bb7801677cc1 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Wed, 11 Nov 2020 05:24:38 +0530 Subject: [PATCH 07/24] `actix-files` intra-doc migration (#1785) --- actix-files/src/named.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index dacb51136..a9b95bad1 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -193,7 +193,7 @@ impl NamedFile { /// image, and video content types, and `attachment` otherwise, and /// the filename is taken from the path provided in the `open` method /// after converting it to UTF-8 using. - /// [to_string_lossy](https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_string_lossy). + /// [`std::ffi::OsStr::to_string_lossy`] #[inline] pub fn set_content_disposition(mut self, cd: header::ContentDisposition) -> Self { self.content_disposition = cd; From 4100c50c703798027203310502d3e9a860b9a032 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 20 Nov 2020 18:02:41 +0000 Subject: [PATCH 08/24] add either extractor (#1788) --- CHANGES.md | 5 + src/error.rs | 1 + src/lib.rs | 3 +- src/responder.rs | 76 ------------ src/types/either.rs | 274 ++++++++++++++++++++++++++++++++++++++++++++ src/types/mod.rs | 2 + 6 files changed, 284 insertions(+), 77 deletions(-) create mode 100644 src/types/either.rs diff --git a/CHANGES.md b/CHANGES.md index 9277d5bd2..b928712d0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,14 @@ # Changes ## Unreleased - 2020-xx-xx +### Added +* Add `Either` extractor helper. [#1788] + ### Changed * Upgrade `serde_urlencoded` to `0.7`. +[#1788]: https://github.com/actix/actix-web/pull/1788 + ## 3.2.0 - 2020-10-30 ### Added diff --git a/src/error.rs b/src/error.rs index 659ba05fd..60af8fa11 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,5 @@ //! Error and Result module + pub use actix_http::error::*; use derive_more::{Display, From}; use serde_json::error::Error as JsonError; diff --git a/src/lib.rs b/src/lib.rs index 088444e05..13e02c098 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,10 +102,11 @@ pub use crate::app::App; pub use crate::extract::FromRequest; pub use crate::request::HttpRequest; pub use crate::resource::Resource; -pub use crate::responder::{Either, Responder}; +pub use crate::responder::Responder; pub use crate::route::Route; pub use crate::scope::Scope; pub use crate::server::HttpServer; +pub use crate::types::{Either, EitherExtractError}; pub mod dev { //! The `actix-web` prelude for library developers diff --git a/src/responder.rs b/src/responder.rs index fc80831b8..d1c22323f 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -332,82 +332,6 @@ impl Future for CustomResponderFut { } } -/// Combines two different responder types into a single type -/// -/// ```rust -/// use actix_web::{Either, Error, HttpResponse}; -/// -/// type RegisterResult = Either>; -/// -/// fn index() -> RegisterResult { -/// if is_a_variant() { -/// // <- choose left variant -/// Either::A(HttpResponse::BadRequest().body("Bad data")) -/// } else { -/// Either::B( -/// // <- Right variant -/// Ok(HttpResponse::Ok() -/// .content_type("text/html") -/// .body("Hello!")) -/// ) -/// } -/// } -/// # fn is_a_variant() -> bool { true } -/// # fn main() {} -/// ``` -#[derive(Debug, PartialEq)] -pub enum Either { - /// First branch of the type - A(A), - /// Second branch of the type - B(B), -} - -impl Responder for Either -where - A: Responder, - B: Responder, -{ - type Error = Error; - type Future = EitherResponder; - - fn respond_to(self, req: &HttpRequest) -> Self::Future { - match self { - Either::A(a) => EitherResponder::A(a.respond_to(req)), - Either::B(b) => EitherResponder::B(b.respond_to(req)), - } - } -} - -#[pin_project(project = EitherResponderProj)] -pub enum EitherResponder -where - A: Responder, - B: Responder, -{ - A(#[pin] A::Future), - B(#[pin] B::Future), -} - -impl Future for EitherResponder -where - A: Responder, - B: Responder, -{ - type Output = Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - match self.project() { - EitherResponderProj::A(fut) => { - Poll::Ready(ready!(fut.poll(cx)).map_err(|e| e.into())) - } - EitherResponderProj::B(fut) => { - Poll::Ready(ready!(fut.poll(cx).map_err(|e| e.into()))) - } - } - } -} - impl Responder for InternalError where T: std::fmt::Debug + std::fmt::Display + 'static, diff --git a/src/types/either.rs b/src/types/either.rs new file mode 100644 index 000000000..9f1d81a0b --- /dev/null +++ b/src/types/either.rs @@ -0,0 +1,274 @@ +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; + +use actix_http::{Error, Response}; +use bytes::Bytes; +use futures_util::{future::LocalBoxFuture, ready, FutureExt, TryFutureExt}; +use pin_project::pin_project; + +use crate::{dev, request::HttpRequest, FromRequest, Responder}; + +/// Combines two different responder types into a single type +/// +/// ```rust +/// use actix_web::{Either, Error, HttpResponse}; +/// +/// type RegisterResult = Either>; +/// +/// fn index() -> RegisterResult { +/// if is_a_variant() { +/// // <- choose left variant +/// Either::A(HttpResponse::BadRequest().body("Bad data")) +/// } else { +/// Either::B( +/// // <- Right variant +/// Ok(HttpResponse::Ok() +/// .content_type("text/html") +/// .body("Hello!")) +/// ) +/// } +/// } +/// # fn is_a_variant() -> bool { true } +/// # fn main() {} +/// ``` +#[derive(Debug, PartialEq)] +pub enum Either { + /// First branch of the type + A(A), + /// Second branch of the type + B(B), +} + +#[cfg(test)] +impl Either { + pub(self) fn unwrap_left(self) -> A { + match self { + Either::A(data) => data, + Either::B(_) => { + panic!("Cannot unwrap left branch. Either contains a right branch.") + } + } + } + + pub(self) fn unwrap_right(self) -> B { + match self { + Either::A(_) => { + panic!("Cannot unwrap right branch. Either contains a left branch.") + } + Either::B(data) => data, + } + } +} + +impl Responder for Either +where + A: Responder, + B: Responder, +{ + type Error = Error; + type Future = EitherResponder; + + fn respond_to(self, req: &HttpRequest) -> Self::Future { + match self { + Either::A(a) => EitherResponder::A(a.respond_to(req)), + Either::B(b) => EitherResponder::B(b.respond_to(req)), + } + } +} + +#[pin_project(project = EitherResponderProj)] +pub enum EitherResponder +where + A: Responder, + B: Responder, +{ + A(#[pin] A::Future), + B(#[pin] B::Future), +} + +impl Future for EitherResponder +where + A: Responder, + B: Responder, +{ + type Output = Result; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + match self.project() { + EitherResponderProj::A(fut) => { + Poll::Ready(ready!(fut.poll(cx)).map_err(|e| e.into())) + } + EitherResponderProj::B(fut) => { + Poll::Ready(ready!(fut.poll(cx).map_err(|e| e.into()))) + } + } + } +} + +/// A composite error resulting from failure to extract an `Either`. +/// +/// The implementation of `Into` will return the payload buffering error or the +/// error from the primary extractor. To access the fallback error, use a match clause. +#[derive(Debug)] +pub enum EitherExtractError { + /// Error from payload buffering, such as exceeding payload max size limit. + Bytes(Error), + + /// Error from primary extractor. + Extract(A, B), +} + +impl Into for EitherExtractError +where + A: Into, + B: Into, +{ + fn into(self) -> Error { + match self { + EitherExtractError::Bytes(err) => err, + EitherExtractError::Extract(a_err, _b_err) => a_err.into(), + } + } +} + +/// Provides a mechanism for trying two extractors, a primary and a fallback. Useful for +/// "polymorphic payloads" where, for example, a form might be JSON or URL encoded. +/// +/// It is important to note that this extractor, by necessity, buffers the entire request payload +/// as part of its implementation. Though, it does respect a `PayloadConfig`'s maximum size limit. +impl FromRequest for Either +where + A: FromRequest + 'static, + B: FromRequest + 'static, +{ + type Error = EitherExtractError; + type Future = LocalBoxFuture<'static, Result>; + type Config = (); + + fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { + let req2 = req.clone(); + + Bytes::from_request(req, payload) + .map_err(EitherExtractError::Bytes) + .and_then(|bytes| bytes_to_a_or_b(req2, bytes)) + .boxed_local() + } +} + +async fn bytes_to_a_or_b( + req: HttpRequest, + bytes: Bytes, +) -> Result, EitherExtractError> +where + A: FromRequest + 'static, + B: FromRequest + 'static, +{ + let fallback = bytes.clone(); + let a_err; + + let mut pl = payload_from_bytes(bytes); + match A::from_request(&req, &mut pl).await { + Ok(a_data) => return Ok(Either::A(a_data)), + // store A's error for returning if B also fails + Err(err) => a_err = err, + }; + + let mut pl = payload_from_bytes(fallback); + match B::from_request(&req, &mut pl).await { + Ok(b_data) => return Ok(Either::B(b_data)), + Err(b_err) => Err(EitherExtractError::Extract(a_err, b_err)), + } +} + +fn payload_from_bytes(bytes: Bytes) -> dev::Payload { + let (_, mut h1_payload) = actix_http::h1::Payload::create(true); + h1_payload.unread_data(bytes); + dev::Payload::from(h1_payload) +} + +#[cfg(test)] +mod tests { + use serde::{Deserialize, Serialize}; + + use super::*; + use crate::{ + test::TestRequest, + web::{Form, Json}, + }; + + #[derive(Debug, Clone, Serialize, Deserialize)] + struct TestForm { + hello: String, + } + + #[actix_rt::test] + async fn test_either_extract_first_try() { + let (req, mut pl) = TestRequest::default() + .set_form(&TestForm { + hello: "world".to_owned(), + }) + .to_http_parts(); + + let form = Either::, Json>::from_request(&req, &mut pl) + .await + .unwrap() + .unwrap_left() + .into_inner(); + assert_eq!(&form.hello, "world"); + } + + #[actix_rt::test] + async fn test_either_extract_fallback() { + let (req, mut pl) = TestRequest::default() + .set_json(&TestForm { + hello: "world".to_owned(), + }) + .to_http_parts(); + + let form = Either::, Json>::from_request(&req, &mut pl) + .await + .unwrap() + .unwrap_right() + .into_inner(); + assert_eq!(&form.hello, "world"); + } + + #[actix_rt::test] + async fn test_either_extract_recursive_fallback() { + let (req, mut pl) = TestRequest::default() + .set_payload(Bytes::from_static(b"!@$%^&*()")) + .to_http_parts(); + + let payload = + Either::, Json>, Bytes>::from_request( + &req, &mut pl, + ) + .await + .unwrap() + .unwrap_right(); + assert_eq!(&payload.as_ref(), &b"!@$%^&*()"); + } + + #[actix_rt::test] + async fn test_either_extract_recursive_fallback_inner() { + let (req, mut pl) = TestRequest::default() + .set_json(&TestForm { + hello: "world".to_owned(), + }) + .to_http_parts(); + + let form = + Either::, Json>, Bytes>::from_request( + &req, &mut pl, + ) + .await + .unwrap() + .unwrap_left() + .unwrap_right() + .into_inner(); + assert_eq!(&form.hello, "world"); + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index b32711e2a..cedf86dd2 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,6 @@ //! Helper types +mod either; pub(crate) mod form; pub(crate) mod json; mod path; @@ -7,6 +8,7 @@ pub(crate) mod payload; mod query; pub(crate) mod readlines; +pub use self::either::{Either, EitherExtractError}; pub use self::form::{Form, FormConfig}; pub use self::json::{Json, JsonConfig}; pub use self::path::{Path, PathConfig}; From 2f11ef089bed1b03f5312b80068e2c50deda325b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 24 Nov 2020 00:29:13 +0000 Subject: [PATCH 09/24] fix rustdoc uploads --- .github/workflows/upload-doc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index cdf05a979..ba87a5637 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -30,7 +30,7 @@ jobs: run: echo "" > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@3.5.8 + uses: JamesIves/github-pages-deploy-action@3.7.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages From 70f4747a2391ce870c0a33383a2ddc38c7bb1e99 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 24 Nov 2020 10:08:57 +0000 Subject: [PATCH 10/24] add method for getting accept type preference (#1793) --- actix-http/CHANGES.md | 2 + actix-http/src/header/common/accept.rs | 141 ++++++++++++++++++- actix-http/src/header/shared/quality_item.rs | 4 +- 3 files changed, 138 insertions(+), 9 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index eeed4e14b..cafaa5e09 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - 2020-xx-xx ### Added * HttpResponse builders for 1xx status codes. [#1768] +* `Accept::mime_precedence` and `Accept::mime_preference`. [#1793] ### Fixed * Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767] @@ -12,6 +13,7 @@ [#1767]: https://github.com/actix/actix-web/pull/1767 [#1768]: https://github.com/actix/actix-web/pull/1768 +[#1793]: https://github.com/actix/actix-web/pull/1793 ## 2.1.0 - 2020-10-30 diff --git a/actix-http/src/header/common/accept.rs b/actix-http/src/header/common/accept.rs index d52eba241..da26b0261 100644 --- a/actix-http/src/header/common/accept.rs +++ b/actix-http/src/header/common/accept.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use mime::Mime; use crate::header::{qitem, QualityItem}; @@ -7,7 +9,7 @@ header! { /// `Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2) /// /// The `Accept` header field can be used by user agents to specify - /// response media types that are acceptable. Accept header fields can + /// response media types that are acceptable. Accept header fields can /// be used to indicate that the request is specifically limited to a /// small set of desired types, as in the case of a request for an /// in-line image @@ -97,14 +99,14 @@ header! { test_header!( test1, vec![b"audio/*; q=0.2, audio/basic"], - Some(HeaderField(vec![ + Some(Accept(vec![ QualityItem::new("audio/*".parse().unwrap(), q(200)), qitem("audio/basic".parse().unwrap()), ]))); test_header!( test2, vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"], - Some(HeaderField(vec![ + Some(Accept(vec![ QualityItem::new(mime::TEXT_PLAIN, q(500)), qitem(mime::TEXT_HTML), QualityItem::new( @@ -138,23 +140,148 @@ header! { } impl Accept { - /// A constructor to easily create `Accept: */*`. + /// Construct `Accept: */*`. pub fn star() -> Accept { Accept(vec![qitem(mime::STAR_STAR)]) } - /// A constructor to easily create `Accept: application/json`. + /// Construct `Accept: application/json`. pub fn json() -> Accept { Accept(vec![qitem(mime::APPLICATION_JSON)]) } - /// A constructor to easily create `Accept: text/*`. + /// Construct `Accept: text/*`. pub fn text() -> Accept { Accept(vec![qitem(mime::TEXT_STAR)]) } - /// A constructor to easily create `Accept: image/*`. + /// Construct `Accept: image/*`. pub fn image() -> Accept { Accept(vec![qitem(mime::IMAGE_STAR)]) } + + /// Construct `Accept: text/html`. + pub fn html() -> Accept { + Accept(vec![qitem(mime::TEXT_HTML)]) + } + + /// Returns a sorted list of mime types from highest to lowest preference, accounting for + /// [q-factor weighting] and specificity. + /// + /// [q-factor weighting]: https://tools.ietf.org/html/rfc7231#section-5.3.2 + pub fn mime_precedence(&self) -> Vec { + let mut types = self.0.clone(); + + // use stable sort so items with equal q-factor and specificity retain listed order + types.sort_by(|a, b| { + // sort by q-factor descending + b.quality.cmp(&a.quality).then_with(|| { + // use specificity rules on mime types with + // same q-factor (eg. text/html > text/* > */*) + + // subtypes are not comparable if main type is star, so return + match (a.item.type_(), b.item.type_()) { + (mime::STAR, mime::STAR) => return Ordering::Equal, + + // a is sorted after b + (mime::STAR, _) => return Ordering::Greater, + + // a is sorted before b + (_, mime::STAR) => return Ordering::Less, + + _ => {} + } + + // in both these match expressions, the returned ordering appears + // inverted because sort is high-to-low ("descending") precedence + match (a.item.subtype(), b.item.subtype()) { + (mime::STAR, mime::STAR) => Ordering::Equal, + + // a is sorted after b + (mime::STAR, _) => Ordering::Greater, + + // a is sorted before b + (_, mime::STAR) => Ordering::Less, + + _ => Ordering::Equal, + } + }) + }); + + types.into_iter().map(|qitem| qitem.item).collect() + } + + /// Extracts the most preferable mime type, accounting for [q-factor weighting]. + /// + /// If no q-factors are provided, the first mime type is chosen. Note that items without + /// q-factors are given the maximum preference value. + /// + /// Returns `None` if contained list is empty. + /// + /// [q-factor weighting]: https://tools.ietf.org/html/rfc7231#section-5.3.2 + pub fn mime_preference(&self) -> Option { + let types = self.mime_precedence(); + types.first().cloned() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::header::q; + + #[test] + fn test_mime_precedence() { + let test = Accept(vec![]); + assert!(test.mime_precedence().is_empty()); + + let test = Accept(vec![qitem(mime::APPLICATION_JSON)]); + assert_eq!(test.mime_precedence(), vec!(mime::APPLICATION_JSON)); + + let test = Accept(vec![ + qitem(mime::TEXT_HTML), + "application/xhtml+xml".parse().unwrap(), + QualityItem::new("application/xml".parse().unwrap(), q(0.9)), + QualityItem::new(mime::STAR_STAR, q(0.8)), + ]); + assert_eq!( + test.mime_precedence(), + vec![ + mime::TEXT_HTML, + "application/xhtml+xml".parse().unwrap(), + "application/xml".parse().unwrap(), + mime::STAR_STAR, + ] + ); + + let test = Accept(vec![ + qitem(mime::STAR_STAR), + qitem(mime::IMAGE_STAR), + qitem(mime::IMAGE_PNG), + ]); + assert_eq!( + test.mime_precedence(), + vec![mime::IMAGE_PNG, mime::IMAGE_STAR, mime::STAR_STAR] + ); + } + + #[test] + fn test_mime_preference() { + let test = Accept(vec![ + qitem(mime::TEXT_HTML), + "application/xhtml+xml".parse().unwrap(), + QualityItem::new("application/xml".parse().unwrap(), q(0.9)), + QualityItem::new(mime::STAR_STAR, q(0.8)), + ]); + assert_eq!(test.mime_preference(), Some(mime::TEXT_HTML)); + + let test = Accept(vec![ + QualityItem::new("video/*".parse().unwrap(), q(0.8)), + qitem(mime::IMAGE_PNG), + QualityItem::new(mime::STAR_STAR, q(0.5)), + qitem(mime::IMAGE_SVG), + QualityItem::new(mime::IMAGE_STAR, q(0.8)), + ]); + assert_eq!(test.mime_preference(), Some(mime::IMAGE_PNG)); + } } diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs index 98230dec1..f4331a18e 100644 --- a/actix-http/src/header/shared/quality_item.rs +++ b/actix-http/src/header/shared/quality_item.rs @@ -18,7 +18,7 @@ use self::internal::IntoQuality; /// /// [RFC7231 Section 5.3.1](https://tools.ietf.org/html/rfc7231#section-5.3.1) /// gives more information on quality values in HTTP header fields. -#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Quality(u16); impl Default for Quality { @@ -121,7 +121,7 @@ fn from_f32(f: f32) -> Quality { /// Convenience function to wrap a value in a `QualityItem` /// Sets `q` to the default 1.0 pub fn qitem(item: T) -> QualityItem { - QualityItem::new(item, Default::default()) + QualityItem::new(item, Quality::default()) } /// Convenience function to create a `Quality` from a float or integer. From 5af46775b8d89f3bc005e725a9918f316e6459f9 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 24 Nov 2020 11:37:05 +0000 Subject: [PATCH 11/24] refactor quality and use TryFrom instead of custom trait (#1797) --- actix-http/CHANGES.md | 2 + actix-http/src/header/mod.rs | 4 +- actix-http/src/header/shared/charset.rs | 4 +- actix-http/src/header/shared/quality_item.rs | 182 +++++++++++-------- 4 files changed, 106 insertions(+), 86 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index cafaa5e09..a25f44e36 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,7 @@ ### Added * HttpResponse builders for 1xx status codes. [#1768] * `Accept::mime_precedence` and `Accept::mime_preference`. [#1793] +* `TryFrom` and `TryFrom` for `http::header::Quality`. [#1797] ### Fixed * Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767] @@ -14,6 +15,7 @@ [#1767]: https://github.com/actix/actix-web/pull/1767 [#1768]: https://github.com/actix/actix-web/pull/1768 [#1793]: https://github.com/actix/actix-web/pull/1793 +[#1797]: https://github.com/actix/actix-web/pull/1797 ## 2.1.0 - 2020-10-30 diff --git a/actix-http/src/header/mod.rs b/actix-http/src/header/mod.rs index 46fb31a62..0f87516eb 100644 --- a/actix-http/src/header/mod.rs +++ b/actix-http/src/header/mod.rs @@ -370,9 +370,7 @@ impl fmt::Display for ExtendedValue { } /// Percent encode a sequence of bytes with a character set defined in -/// [https://tools.ietf.org/html/rfc5987#section-3.2][url] -/// -/// [url]: https://tools.ietf.org/html/rfc5987#section-3.2 +/// pub fn http_percent_encode(f: &mut fmt::Formatter<'_>, bytes: &[u8]) -> fmt::Result { let encoded = percent_encoding::percent_encode(bytes, HTTP_VALUE); fmt::Display::fmt(&encoded, f) diff --git a/actix-http/src/header/shared/charset.rs b/actix-http/src/header/shared/charset.rs index 00e7309d4..36bdbf7e2 100644 --- a/actix-http/src/header/shared/charset.rs +++ b/actix-http/src/header/shared/charset.rs @@ -7,9 +7,7 @@ use self::Charset::*; /// /// The string representation is normalized to upper case. /// -/// See [http://www.iana.org/assignments/character-sets/character-sets.xhtml][url]. -/// -/// [url]: http://www.iana.org/assignments/character-sets/character-sets.xhtml +/// See . #[derive(Clone, Debug, PartialEq)] #[allow(non_camel_case_types)] pub enum Charset { diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs index f4331a18e..01a3b988a 100644 --- a/actix-http/src/header/shared/quality_item.rs +++ b/actix-http/src/header/shared/quality_item.rs @@ -1,10 +1,17 @@ -use std::{cmp, fmt, str}; +use std::{ + cmp, + convert::{TryFrom, TryInto}, + fmt, str, +}; -use self::internal::IntoQuality; +use derive_more::{Display, Error}; + +const MAX_QUALITY: u16 = 1000; +const MAX_FLOAT_QUALITY: f32 = 1.0; /// Represents a quality used in quality values. /// -/// Can be created with the `q` function. +/// Can be created with the [`q`] function. /// /// # Implementation notes /// @@ -21,9 +28,51 @@ use self::internal::IntoQuality; #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Quality(u16); +impl Quality { + /// # Panics + /// Panics in debug mode when value is not in the range 0.0 <= n <= 1.0. + fn from_f32(value: f32) -> Self { + // Check that `value` is within range should be done before calling this method. + // Just in case, this debug_assert should catch if we were forgetful. + debug_assert!( + (0.0f32..=1.0f32).contains(&value), + "q value must be between 0.0 and 1.0" + ); + + Quality((value * MAX_QUALITY as f32) as u16) + } +} + impl Default for Quality { fn default() -> Quality { - Quality(1000) + Quality(MAX_QUALITY) + } +} + +#[derive(Debug, Clone, Display, Error)] +pub struct QualityOutOfBounds; + +impl TryFrom for Quality { + type Error = QualityOutOfBounds; + + fn try_from(value: u16) -> Result { + if (0..=MAX_QUALITY).contains(&value) { + Ok(Quality(value)) + } else { + Err(QualityOutOfBounds) + } + } +} + +impl TryFrom for Quality { + type Error = QualityOutOfBounds; + + fn try_from(value: f32) -> Result { + if (0.0..=MAX_FLOAT_QUALITY).contains(&value) { + Ok(Quality::from_f32(value)) + } else { + Err(QualityOutOfBounds) + } } } @@ -55,8 +104,9 @@ impl cmp::PartialOrd for QualityItem { impl fmt::Display for QualityItem { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.item, f)?; + match self.quality.0 { - 1000 => Ok(()), + MAX_QUALITY => Ok(()), 0 => f.write_str("; q=0"), x => write!(f, "; q=0.{}", format!("{:03}", x).trim_end_matches('0')), } @@ -66,56 +116,61 @@ impl fmt::Display for QualityItem { impl str::FromStr for QualityItem { type Err = crate::error::ParseError; - fn from_str(s: &str) -> Result, crate::error::ParseError> { - if !s.is_ascii() { + fn from_str(qitem_str: &str) -> Result, crate::error::ParseError> { + if !qitem_str.is_ascii() { return Err(crate::error::ParseError::Header); } + // Set defaults used if parsing fails. - let mut raw_item = s; + let mut raw_item = qitem_str; let mut quality = 1f32; - let parts: Vec<&str> = s.rsplitn(2, ';').map(|x| x.trim()).collect(); + let parts: Vec<_> = qitem_str.rsplitn(2, ';').map(str::trim).collect(); + if parts.len() == 2 { + // example for item with q-factor: + // + // gzip; q=0.65 + // ^^^^^^ parts[0] + // ^^ start + // ^^^^ q_val + // ^^^^ parts[1] + if parts[0].len() < 2 { + // Can't possibly be an attribute since an attribute needs at least a name followed + // by an equals sign. And bare identifiers are forbidden. return Err(crate::error::ParseError::Header); } + let start = &parts[0][0..2]; + if start == "q=" || start == "Q=" { - let q_part = &parts[0][2..parts[0].len()]; - if q_part.len() > 5 { + let q_val = &parts[0][2..]; + if q_val.len() > 5 { + // longer than 5 indicates an over-precise q-factor return Err(crate::error::ParseError::Header); } - match q_part.parse::() { - Ok(q_value) => { - if 0f32 <= q_value && q_value <= 1f32 { - quality = q_value; - raw_item = parts[1]; - } else { - return Err(crate::error::ParseError::Header); - } - } - Err(_) => return Err(crate::error::ParseError::Header), + + let q_value = q_val + .parse::() + .map_err(|_| crate::error::ParseError::Header)?; + + if (0f32..=1f32).contains(&q_value) { + quality = q_value; + raw_item = parts[1]; + } else { + return Err(crate::error::ParseError::Header); } } } - match raw_item.parse::() { - // we already checked above that the quality is within range - Ok(item) => Ok(QualityItem::new(item, from_f32(quality))), - Err(_) => Err(crate::error::ParseError::Header), - } - } -} -#[inline] -fn from_f32(f: f32) -> Quality { - // this function is only used internally. A check that `f` is within range - // should be done before calling this method. Just in case, this - // debug_assert should catch if we were forgetful - debug_assert!( - f >= 0f32 && f <= 1f32, - "q value must be between 0.0 and 1.0" - ); - Quality((f * 1000f32) as u16) + let item = raw_item + .parse::() + .map_err(|_| crate::error::ParseError::Header)?; + + // we already checked above that the quality is within range + Ok(QualityItem::new(item, Quality::from_f32(quality))) + } } /// Convenience function to wrap a value in a `QualityItem` @@ -127,44 +182,13 @@ pub fn qitem(item: T) -> QualityItem { /// Convenience function to create a `Quality` from a float or integer. /// /// Implemented for `u16` and `f32`. Panics if value is out of range. -pub fn q(val: T) -> Quality { - val.into_quality() -} - -mod internal { - use super::Quality; - - // TryFrom is probably better, but it's not stable. For now, we want to - // keep the functionality of the `q` function, while allowing it to be - // generic over `f32` and `u16`. - // - // `q` would panic before, so keep that behavior. `TryFrom` can be - // introduced later for a non-panicking conversion. - - pub trait IntoQuality: Sealed + Sized { - fn into_quality(self) -> Quality; - } - - impl IntoQuality for f32 { - fn into_quality(self) -> Quality { - assert!( - self >= 0f32 && self <= 1f32, - "float must be between 0.0 and 1.0" - ); - super::from_f32(self) - } - } - - impl IntoQuality for u16 { - fn into_quality(self) -> Quality { - assert!(self <= 1000, "u16 must be between 0 and 1000"); - Quality(self) - } - } - - pub trait Sealed {} - impl Sealed for u16 {} - impl Sealed for f32 {} +pub fn q(val: T) -> Quality +where + T: TryInto, + T::Error: fmt::Debug, +{ + // TODO: on next breaking change, handle unwrap differently + val.try_into().unwrap() } #[cfg(test)] @@ -270,15 +294,13 @@ mod tests { } #[test] - #[should_panic] // FIXME - 32-bit msvc unwinding broken - #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)] + #[should_panic] fn test_quality_invalid() { q(-1.0); } #[test] - #[should_panic] // FIXME - 32-bit msvc unwinding broken - #[cfg_attr(all(target_arch = "x86", target_env = "msvc"), ignore)] + #[should_panic] fn test_quality_invalid2() { q(2.0); } From f1a9b45437c1f2c8e89b3a54b854398c09c7e21e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 24 Nov 2020 20:23:09 +0000 Subject: [PATCH 12/24] improve docs for Files::new --- actix-files/CHANGES.md | 4 ++++ actix-files/src/files.rs | 26 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 978d1c69d..c4d56010f 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -3,6 +3,10 @@ ## Unreleased - 2020-xx-xx +## 0.4.1 - 2020-11-24 +* Clarify order of parameters in `Files::new` and improve docs. + + ## 0.4.0 - 2020-10-06 * Add `Files::prefer_utf8` option that adds UTF-8 charset on certain response types. [#1714] diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs index 5a783e2dd..a99b4699e 100644 --- a/actix-files/src/files.rs +++ b/actix-files/src/files.rs @@ -65,13 +65,25 @@ impl Clone for Files { } impl Files { - /// Create new `Files` instance for specified base directory. + /// Create new `Files` instance for a specified base directory. /// - /// `File` uses `ThreadPool` for blocking filesystem operations. - /// By default pool with 5x threads of available cpus is used. - /// Pool size can be changed by setting ACTIX_THREADPOOL environment variable. - pub fn new>(path: &str, dir: T) -> Files { - let orig_dir = dir.into(); + /// # Argument Order + /// The first argument (`mount_path`) is the root URL at which the static files are served. + /// For example, `/assets` will serve files at `example.com/assets/...`. + /// + /// The second argument (`serve_from`) is the location on disk at which files are loaded. + /// This can be a relative path. For example, `./` would serve files from the current + /// working directory. + /// + /// # Implementation Notes + /// If the mount path is set as the root path `/`, services registered after this one will + /// be inaccessible. Register more specific handlers and services first. + /// + /// `Files` uses a threadpool for blocking filesystem operations. By default, the pool uses a + /// number of threads equal to 5x the number of available logical CPUs. Pool size can be changed + /// by setting ACTIX_THREADPOOL environment variable. + pub fn new>(mount_path: &str, serve_from: T) -> Files { + let orig_dir = serve_from.into(); let dir = match orig_dir.canonicalize() { Ok(canon_dir) => canon_dir, Err(_) => { @@ -81,7 +93,7 @@ impl Files { }; Files { - path: path.to_string(), + path: mount_path.to_owned(), directory: dir, index: None, show_index: false, From 31057beccabbaf82ce8198769dbb940efe7c4a36 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 24 Nov 2020 20:33:23 +0000 Subject: [PATCH 13/24] prepare actix-files release 0.4.1 --- actix-files/Cargo.toml | 8 ++++---- actix-files/README.md | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index c829887ba..f7d32f8ec 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.4.0" +version = "0.4.1" authors = ["Nikolay Kim "] description = "Static file serving for Actix Web" readme = "README.md" @@ -21,14 +21,14 @@ actix-web = { version = "3.0.0", default-features = false } actix-service = "1.0.6" bitflags = "1" bytes = "0.5.3" -futures-core = { version = "0.3.5", default-features = false } -futures-util = { version = "0.3.5", default-features = false } +futures-core = { version = "0.3.7", default-features = false } +futures-util = { version = "0.3.7", default-features = false } derive_more = "0.99.2" log = "0.4" mime = "0.3" mime_guess = "2.0.1" percent-encoding = "2.1" -v_htmlescape = "0.10" +v_htmlescape = "0.11" [dev-dependencies] actix-rt = "1.0.0" diff --git a/actix-files/README.md b/actix-files/README.md index d31439361..685e5dbe5 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -2,12 +2,12 @@ > Static file serving for Actix Web -[![crates.io](https://meritbadge.herokuapp.com/actix-web)](https://crates.io/crates/actix-files) -[![Documentation](https://docs.rs/actix-files/badge.svg)](https://docs.rs/actix-files) +[![crates.io](https://img.shields.io/crates/v/actix-files?label=latest)](https://crates.io/crates/actix-files) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.4.1)](https://docs.rs/actix-files/0.4.1) [![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html) ![License](https://img.shields.io/crates/l/actix-files.svg)
-[![dependency status](https://deps.rs/crate/actix-files/0.4.0/status.svg)](https://deps.rs/crate/actix-files/0.4.0) +[![dependency status](https://deps.rs/crate/actix-files/0.4.1/status.svg)](https://deps.rs/crate/actix-files/0.4.1) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![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) From efc317d3b0cfaa19a5c5adfe0c78cbb54f43a0a0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 25 Nov 2020 00:07:56 +0000 Subject: [PATCH 14/24] prepare actix-http and awc releases --- actix-http/CHANGES.md | 6 +++++- actix-http/Cargo.toml | 2 +- actix-http/README.md | 6 +++--- awc/CHANGES.md | 8 +++++++- awc/README.md | 6 +++--- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index a25f44e36..c602ab2e1 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2020-xx-xx + + +## 2.2.0 - 2020-11-25 ### Added * HttpResponse builders for 1xx status codes. [#1768] * `Accept::mime_precedence` and `Accept::mime_preference`. [#1793] @@ -10,8 +13,9 @@ * Started dropping `transfer-encoding: chunked` and `Content-Length` for 1XX and 204 responses. [#1767] ### Changed -* Upgrade `serde_urlencoded` to `0.7`. +* Upgrade `serde_urlencoded` to `0.7`. [#1773] +[#1773]: https://github.com/actix/actix-web/pull/1773 [#1767]: https://github.com/actix/actix-web/pull/1767 [#1768]: https://github.com/actix/actix-web/pull/1768 [#1793]: https://github.com/actix/actix-web/pull/1793 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 31495e395..7375c6eb3 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "2.1.0" +version = "2.2.0" authors = ["Nikolay Kim "] description = "HTTP primitives for the Actix ecosystem" readme = "README.md" diff --git a/actix-http/README.md b/actix-http/README.md index e536276ca..9103cd184 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -3,14 +3,14 @@ > HTTP primitives for the Actix ecosystem. [![crates.io](https://img.shields.io/crates/v/actix-http?label=latest)](https://crates.io/crates/actix-http) -[![Documentation](https://docs.rs/actix-http/badge.svg?version=2.1.0)](https://docs.rs/actix-http/2.1.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=2.2.0)](https://docs.rs/actix-http/2.2.0) ![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-http) -[![Dependency Status](https://deps.rs/crate/actix-http/2.1.0/status.svg)](https://deps.rs/crate/actix-http/2.1.0) +[![Dependency Status](https://deps.rs/crate/actix-http/2.2.0/status.svg)](https://deps.rs/crate/actix-http/2.2.0) [![Join the chat at https://gitter.im/actix/actix-web](https://badges.gitter.im/actix/actix-web.svg)](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## Documentation & Resources -- [API Documentation](https://docs.rs/actix-http/2.1.0) +- [API Documentation](https://docs.rs/actix-http) - [Chat on Gitter](https://gitter.im/actix/actix-web) - Minimum Supported Rust Version (MSRV): 1.42.0 diff --git a/awc/CHANGES.md b/awc/CHANGES.md index e184dfbd1..3745079cd 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,8 +1,14 @@ # Changes ## Unreleased - 2020-xx-xx + + +## 2.0.2 - 2020-11-25 ### Changed -* Upgrade `serde_urlencoded` to `0.7`. +* Upgrade `serde_urlencoded` to `0.7`. [#1773] + +[#1773]: https://github.com/actix/actix-web/pull/1773 + ## 2.0.1 - 2020-10-30 ### Changed diff --git a/awc/README.md b/awc/README.md index cbe299aaf..d14dd82dd 100644 --- a/awc/README.md +++ b/awc/README.md @@ -3,14 +3,14 @@ > Async HTTP and WebSocket client library. [![crates.io](https://img.shields.io/crates/v/awc?label=latest)](https://crates.io/crates/awc) -[![Documentation](https://docs.rs/awc/badge.svg?version=2.0.1)](https://docs.rs/awc/2.0.1) +[![Documentation](https://docs.rs/awc/badge.svg?version=2.0.2)](https://docs.rs/awc/2.0.2) ![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/2.0.1/status.svg)](https://deps.rs/crate/awc/2.0.1) +[![Dependency Status](https://deps.rs/crate/awc/2.0.2/status.svg)](https://deps.rs/crate/awc/2.0.2) [![Join the chat at https://gitter.im/actix/actix-web](https://badges.gitter.im/actix/actix-web.svg)](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## Documentation & Resources -- [API Documentation](https://docs.rs/awc/2.0.1) +- [API Documentation](https://docs.rs/awc) - [Example Project](https://github.com/actix/examples/tree/HEAD/awc_https) - [Chat on Gitter](https://gitter.im/actix/actix-web) - Minimum Supported Rust Version (MSRV): 1.42.0 From e72b787ba701bc6db9a2ade9b498f801e6b1b90d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 25 Nov 2020 00:53:48 +0000 Subject: [PATCH 15/24] prepare actix-web and actix-http-test releases --- CHANGES.md | 6 ++++- Cargo.toml | 2 +- README.md | 4 +-- awc/Cargo.toml | 2 +- test-server/CHANGES.md | 55 ++++++++++++++++-------------------------- test-server/Cargo.toml | 4 +-- test-server/README.md | 20 +++++++++------ test-server/src/lib.rs | 5 ++++ 8 files changed, 50 insertions(+), 48 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b928712d0..1364d6a9b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,12 +1,16 @@ # Changes ## Unreleased - 2020-xx-xx + + +## 3.3.0 - 2020-11-25 ### Added * Add `Either` extractor helper. [#1788] ### Changed -* Upgrade `serde_urlencoded` to `0.7`. +* Upgrade `serde_urlencoded` to `0.7`. [#1773] +[#1773]: https://github.com/actix/actix-web/pull/1773 [#1788]: https://github.com/actix/actix-web/pull/1788 diff --git a/Cargo.toml b/Cargo.toml index da511888a..3a3a92da9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "3.2.0" +version = "3.3.0" authors = ["Nikolay Kim "] description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust" readme = "README.md" diff --git a/README.md b/README.md index b11a8ee7c..c1d857f81 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@

[![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web) -[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.2.0)](https://docs.rs/actix-web/3.2.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.0)](https://docs.rs/actix-web/3.3.0) [![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html) ![License](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/3.2.0/status.svg)](https://deps.rs/crate/actix-web/3.2.0) +[![Dependency Status](https://deps.rs/crate/actix-web/3.3.0/status.svg)](https://deps.rs/crate/actix-web/3.3.0)
[![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) diff --git a/awc/Cargo.toml b/awc/Cargo.toml index d92996fb9..d5b632a51 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "2.0.1" +version = "2.0.2" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library built on the Actix ecosystem" readme = "README.md" diff --git a/test-server/CHANGES.md b/test-server/CHANGES.md index 845b6e2dc..835b75ddc 100644 --- a/test-server/CHANGES.md +++ b/test-server/CHANGES.md @@ -2,15 +2,20 @@ ## Unreleased - 2020-xx-xx -* add ability to set address for `TestServer` [#1645] -* Upgrade `base64` to `0.13`. -* Upgrade `serde_urlencoded` to `0.7`. +## 2.1.0 - 2020-11-25 +* Add ability to set address for `TestServer`. [#1645] +* Upgrade `base64` to `0.13`. +* Upgrade `serde_urlencoded` to `0.7`. [#1773] + +[#1773]: https://github.com/actix/actix-web/pull/1773 [#1645]: https://github.com/actix/actix-web/pull/1645 + ## 2.0.0 - 2020-09-11 * Update actix-codec and actix-utils dependencies. + ## 2.0.0-alpha.1 - 2020-05-23 * Update the `time` dependency to 0.2.7 * Update `actix-connect` dependency to 2.0.0-alpha.2 @@ -20,74 +25,56 @@ * Update `base64` dependency to 0.12 * Update `env_logger` dependency to 0.7 -## [1.0.0] - 2019-12-13 - -### Changed - +## 1.0.0 - 2019-12-13 * Replaced `TestServer::start()` with `test_server()` -## [1.0.0-alpha.3] - 2019-12-07 - -### Changed - +## 1.0.0-alpha.3 - 2019-12-07 * Migrate to `std::future` -## [0.2.5] - 2019-09-17 - -### Changed - +## 0.2.5 - 2019-09-17 * Update serde_urlencoded to "0.6.1" * Increase TestServerRuntime timeouts from 500ms to 3000ms - -### Fixed - * Do not override current `System` -## [0.2.4] - 2019-07-18 - +## 0.2.4 - 2019-07-18 * Update actix-server to 0.6 -## [0.2.3] - 2019-07-16 +## 0.2.3 - 2019-07-16 * Add `delete`, `options`, `patch` methods to `TestServerRunner` -## [0.2.2] - 2019-06-16 +## 0.2.2 - 2019-06-16 * Add .put() and .sput() methods -## [0.2.1] - 2019-06-05 +## 0.2.1 - 2019-06-05 * Add license files -## [0.2.0] - 2019-05-12 +## 0.2.0 - 2019-05-12 * Update awc and actix-http deps -## [0.1.1] - 2019-04-24 +## 0.1.1 - 2019-04-24 * Always make new connection for http client -## [0.1.0] - 2019-04-16 - +## 0.1.0 - 2019-04-16 * No changes -## [0.1.0-alpha.3] - 2019-04-02 - +## 0.1.0-alpha.3 - 2019-04-02 * Request functions accept path #743 -## [0.1.0-alpha.2] - 2019-03-29 - +## 0.1.0-alpha.2 - 2019-03-29 * Added TestServerRuntime::load_body() method - * Update actix-http and awc libraries -## [0.1.0-alpha.1] - 2019-03-28 - +## 0.1.0-alpha.1 - 2019-03-28 * Initial impl diff --git a/test-server/Cargo.toml b/test-server/Cargo.toml index 87db93469..8b23bef1c 100644 --- a/test-server/Cargo.toml +++ b/test-server/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-http-test" -version = "2.0.0" +version = "2.1.0" authors = ["Nikolay Kim "] -description = "Actix HTTP test server" +description = "Various helpers for Actix applications to use during testing" readme = "README.md" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" diff --git a/test-server/README.md b/test-server/README.md index db0791db7..c847c8515 100644 --- a/test-server/README.md +++ b/test-server/README.md @@ -1,9 +1,15 @@ -# Actix http test server [![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-http-test)](https://crates.io/crates/actix-http-test) [![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) +# actix-http-test -## Documentation & community resources +> Various helpers for Actix applications to use during testing. -* [User Guide](https://actix.rs/docs/) -* [API Documentation](https://docs.rs/actix-http-test/) -* [Chat on gitter](https://gitter.im/actix/actix) -* Cargo package: [actix-http-test](https://crates.io/crates/actix-http-test) -* Minimum supported Rust version: 1.40 or later +[![crates.io](https://img.shields.io/crates/v/actix-http-test?label=latest)](https://crates.io/crates/actix-http-test) +[![Documentation](https://docs.rs/actix-http-test/badge.svg?version=2.1.0)](https://docs.rs/actix-http-test/2.1.0) +![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/actix-http-test) +[![Dependency Status](https://deps.rs/crate/actix-http-test/2.1.0/status.svg)](https://deps.rs/crate/actix-http-test/2.1.0) +[![Join the chat at https://gitter.im/actix/actix-web](https://badges.gitter.im/actix/actix-web.svg)](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +## Documentation & Resources + +- [API Documentation](https://docs.rs/actix-http-test) +- [Chat on Gitter](https://gitter.im/actix/actix-web) +- Minimum Supported Rust Version (MSRV): 1.42.0 diff --git a/test-server/src/lib.rs b/test-server/src/lib.rs index 4159c8d86..f881dfb4c 100644 --- a/test-server/src/lib.rs +++ b/test-server/src/lib.rs @@ -1,4 +1,9 @@ //! Various helpers for Actix applications to use during testing. + +#![deny(rust_2018_idioms)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] + use std::sync::mpsc; use std::{net, thread, time}; From fe6ad816cc730e545cf27e26d68ba26ddc20afe6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 25 Nov 2020 00:54:00 +0000 Subject: [PATCH 16/24] update dotgraphs --- docs/graphs/web-focus.dot | 42 ++++++++++++++++++++------------------- docs/graphs/web-only.dot | 2 ++ 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/docs/graphs/web-focus.dot b/docs/graphs/web-focus.dot index 7abd51268..bcae36616 100644 --- a/docs/graphs/web-focus.dot +++ b/docs/graphs/web-focus.dot @@ -2,29 +2,31 @@ digraph { subgraph cluster_web { label="actix/actix-web" "awc" - "actix-web" - "actix-files" - "actix-http" - "actix-multipart" - "actix-web-actors" - "actix-web-codegen" + "web" + "files" + "http" + "multipart" + "web-actors" + "codegen" + "http-test" } - "actix-web" -> { "actix-codec" "actix-service" "actix-utils" "actix-router" "actix-rt" "actix-server" "actix-testing" "actix-macros" "actix-threadpool" "actix-tls" "actix-web-codegen" "actix-http" "awc" } - "awc" -> { "actix-codec" "actix-service" "actix-http" "actix-rt" } - "actix-web-actors" -> { "actix" "actix-web" "actix-http" "actix-codec" } - "actix-multipart" -> { "actix-web" "actix-service" "actix-utils" } - "actix-http" -> { "actix-service" "actix-codec" "actix-connect" "actix-utils" "actix-rt" "actix-threadpool" } - "actix-http" -> { "actix" "actix-tls" }[color=blue] // optional - "actix-files" -> { "actix-web" "actix-http" } + "web" -> { "codec" "service" "utils" "router" "rt" "server" "testing" "macros" "threadpool" "tls" "codegen" "http" "awc" } + "awc" -> { "codec" "service" "http" "rt" } + "web-actors" -> { "actix" "web" "http" "codec" } + "multipart" -> { "web" "service" "utils" } + "http" -> { "service" "codec" "connect" "utils" "rt" "threadpool" } + "http" -> { "actix" "tls" }[color=blue] // optional + "files" -> { "web" "http" } + "http-test" -> { "service" "codec" "connect" "utils" "rt" "server" "testing" "awc" } // net - "actix-utils" -> { "actix-service" "actix-rt" "actix-codec" } - "actix-tracing" -> { "actix-service" } - "actix-tls" -> { "actix-service" "actix-codec" "actix-utils" } - "actix-testing" -> { "actix-rt" "actix-macros" "actix-server" "actix-service" } - "actix-server" -> { "actix-service" "actix-rt" "actix-codec" "actix-utils" } - "actix-rt" -> { "actix-macros" "actix-threadpool" } - "actix-connect" -> { "actix-service" "actix-codec" "actix-utils" "actix-rt" } + "utils" -> { "service" "rt" "codec" } + "tracing" -> { "service" } + "tls" -> { "service" "codec" "utils" } + "testing" -> { "rt" "macros" "server" "service" } + "server" -> { "service" "rt" "codec" "utils" } + "rt" -> { "macros" "threadpool" } + "connect" -> { "service" "codec" "utils" "rt" } } diff --git a/docs/graphs/web-only.dot b/docs/graphs/web-only.dot index 6e41fdc27..ee653e33b 100644 --- a/docs/graphs/web-only.dot +++ b/docs/graphs/web-only.dot @@ -8,6 +8,7 @@ digraph { "actix-multipart" "actix-web-actors" "actix-web-codegen" + "actix-http-test" } "actix-web" -> { "actix-web-codegen" "actix-http" "awc" } @@ -16,4 +17,5 @@ digraph { "actix-multipart" -> { "actix-web" } "actix-http" -> { "actix" }[color=blue] // optional "actix-files" -> { "actix-web" "actix-http" } + "actix-http-test" -> { "awc" } } From 0b5b463cfa951d96ec6b0167964ef613b0d2b091 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 29 Nov 2020 16:33:45 +0000 Subject: [PATCH 17/24] prepare web and awc releases closes #1799 --- Cargo.toml | 10 +++++----- README.md | 6 +++--- awc/Cargo.toml | 4 ++-- awc/README.md | 4 ++-- docs/graphs/web-focus.dot | 2 +- docs/graphs/web-only.dot | 4 ++-- src/lib.rs | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3a3a92da9..bdd87184c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "actix-web" -version = "3.3.0" +version = "3.3.1" authors = ["Nikolay Kim "] -description = "Actix web is a powerful, pragmatic, and extremely fast web framework for Rust" +description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" readme = "README.md" keywords = ["actix", "http", "web", "framework", "async"] homepage = "https://actix.rs" @@ -85,11 +85,11 @@ actix-threadpool = "0.3.1" actix-tls = "2.0.0" actix-web-codegen = "0.4.0" -actix-http = "2.1.0" -awc = { version = "2.0.0", default-features = false } +actix-http = "2.2.0" +awc = { version = "2.0.3", default-features = false } bytes = "0.5.3" -derive_more = "0.99.2" +derive_more = "0.99.5" encoding_rs = "0.8" futures-channel = { version = "0.3.5", default-features = false } futures-core = { version = "0.3.5", default-features = false } diff --git a/README.md b/README.md index c1d857f81..f67da03c1 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@

Actix web

- Actix web is a powerful, pragmatic, and extremely fast web framework for Rust + Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust

[![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web) -[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.0)](https://docs.rs/actix-web/3.3.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.1)](https://docs.rs/actix-web/3.3.1) [![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html) ![License](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/3.3.0/status.svg)](https://deps.rs/crate/actix-web/3.3.0) +[![Dependency Status](https://deps.rs/crate/actix-web/3.3.1/status.svg)](https://deps.rs/crate/actix-web/3.3.1)
[![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) diff --git a/awc/Cargo.toml b/awc/Cargo.toml index d5b632a51..3c1963d6b 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "2.0.2" +version = "2.0.3" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library built on the Actix ecosystem" readme = "README.md" @@ -39,7 +39,7 @@ compress = ["actix-http/compress"] [dependencies] actix-codec = "0.3.0" actix-service = "1.0.6" -actix-http = "2.0.0" +actix-http = "2.2.0" actix-rt = "1.0.0" base64 = "0.13" diff --git a/awc/README.md b/awc/README.md index d14dd82dd..b97d4fa00 100644 --- a/awc/README.md +++ b/awc/README.md @@ -3,9 +3,9 @@ > Async HTTP and WebSocket client library. [![crates.io](https://img.shields.io/crates/v/awc?label=latest)](https://crates.io/crates/awc) -[![Documentation](https://docs.rs/awc/badge.svg?version=2.0.2)](https://docs.rs/awc/2.0.2) +[![Documentation](https://docs.rs/awc/badge.svg?version=2.0.3)](https://docs.rs/awc/2.0.3) ![Apache 2.0 or MIT licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/2.0.2/status.svg)](https://deps.rs/crate/awc/2.0.2) +[![Dependency Status](https://deps.rs/crate/awc/2.0.3/status.svg)](https://deps.rs/crate/awc/2.0.3) [![Join the chat at https://gitter.im/actix/actix-web](https://badges.gitter.im/actix/actix-web.svg)](https://gitter.im/actix/actix-web?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ## Documentation & Resources diff --git a/docs/graphs/web-focus.dot b/docs/graphs/web-focus.dot index bcae36616..17228fe62 100644 --- a/docs/graphs/web-focus.dot +++ b/docs/graphs/web-focus.dot @@ -17,7 +17,7 @@ digraph { "multipart" -> { "web" "service" "utils" } "http" -> { "service" "codec" "connect" "utils" "rt" "threadpool" } "http" -> { "actix" "tls" }[color=blue] // optional - "files" -> { "web" "http" } + "files" -> { "web" } "http-test" -> { "service" "codec" "connect" "utils" "rt" "server" "testing" "awc" } // net diff --git a/docs/graphs/web-only.dot b/docs/graphs/web-only.dot index ee653e33b..9e1bb2805 100644 --- a/docs/graphs/web-only.dot +++ b/docs/graphs/web-only.dot @@ -11,11 +11,11 @@ digraph { "actix-http-test" } - "actix-web" -> { "actix-web-codegen" "actix-http" "awc" } + "actix-web" -> { "actix-web-codegen" "actix-http" "awc" } "awc" -> { "actix-http" } "actix-web-actors" -> { "actix" "actix-web" "actix-http" } "actix-multipart" -> { "actix-web" } "actix-http" -> { "actix" }[color=blue] // optional - "actix-files" -> { "actix-web" "actix-http" } + "actix-files" -> { "actix-web" } "actix-http-test" -> { "awc" } } diff --git a/src/lib.rs b/src/lib.rs index 13e02c098..a8fc50d83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -//! Actix web is a powerful, pragmatic, and extremely fast web framework for Rust. +//! Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust. //! //! ## Example //! From ea8bf361041b35aa281835540f1e8aba9679aceb Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 29 Nov 2020 16:35:35 +0000 Subject: [PATCH 18/24] update web and awc changelogs --- CHANGES.md | 2 ++ awc/CHANGES.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1364d6a9b..f30049c9d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,8 @@ # Changes ## Unreleased - 2020-xx-xx +### Fixed +* Ensure `actix-http` dependency uses same `serde_urlencoded`. ## 3.3.0 - 2020-11-25 diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 3745079cd..dfd8e3704 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,8 @@ # Changes ## Unreleased - 2020-xx-xx +### Fixed +* Ensure `actix-http` dependency uses same `serde_urlencoded`. ## 2.0.2 - 2020-11-25 From 32d59ca904bceaf7638a25c0ba367a9560dfc3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 30 Nov 2020 20:18:02 +0100 Subject: [PATCH 19/24] Upgrade socket2 dependency (#1803) Upgrades to a version not making invalid assumptions about the memory layout of std::net::SocketAddr --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bdd87184c..f8da9d90c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,7 @@ futures-util = { version = "0.3.5", default-features = false } fxhash = "0.2.1" log = "0.4" mime = "0.3" -socket2 = "0.3" +socket2 = "0.3.16" pin-project = "1.0.0" regex = "1.4" serde = { version = "1.0", features = ["derive"] } From 7981e0068a8d201e2f669772a0e81e5a73523688 Mon Sep 17 00:00:00 2001 From: Maciej Hirsz <1096222+maciejhirsz@users.noreply.github.com> Date: Tue, 1 Dec 2020 02:22:15 +0100 Subject: [PATCH 20/24] Remove a panic in normalize middleware (#1762) Co-authored-by: Yuki Okushi --- CHANGES.md | 1 + src/middleware/normalize.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f30049c9d..1175aa54a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - 2020-xx-xx ### Fixed * Ensure `actix-http` dependency uses same `serde_urlencoded`. +* Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. ## 3.3.0 - 2020-11-25 diff --git a/src/middleware/normalize.rs b/src/middleware/normalize.rs index e0ecd90dc..ac8ad71d5 100644 --- a/src/middleware/normalize.rs +++ b/src/middleware/normalize.rs @@ -137,9 +137,9 @@ where // so the change can not be deduced from the length comparison if path != original_path { let mut parts = head.uri.clone().into_parts(); - let pq = parts.path_and_query.as_ref().unwrap(); + let query = parts.path_and_query.as_ref().and_then(|pq| pq.query()); - let path = if let Some(q) = pq.query() { + let path = if let Some(q) = query { Bytes::from(format!("{}?{}", path, q)) } else { Bytes::copy_from_slice(path.as_bytes()) From 1f70ef155d76c4b96e8b7fdc01d338bf6b9b2185 Mon Sep 17 00:00:00 2001 From: Joshua Parkin Date: Tue, 1 Dec 2020 13:39:41 +0000 Subject: [PATCH 21/24] Fix match_pattern() returning None for scope with resource of empty path (#1798) * fix match_pattern function not returning pattern where scope has resource of path "" * remove print in test * make comparison on existing else if block * add fix to changelog --- CHANGES.md | 3 +++ src/request.rs | 36 ++++++++++++++++++++++++++++++++++++ src/rmap.rs | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1175aa54a..edf4380fb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,9 @@ ### Fixed * Ensure `actix-http` dependency uses same `serde_urlencoded`. * Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. +* Fix match_pattern() returning None for scope with resource of empty path. [#1798] + +[#1798]: https://github.com/actix/actix-web/pull/1798 ## 3.3.0 - 2020-11-25 diff --git a/src/request.rs b/src/request.rs index a1b42f926..bd4bbbf58 100644 --- a/src/request.rs +++ b/src/request.rs @@ -675,4 +675,40 @@ mod tests { let res = call_service(&mut srv, req).await; assert_eq!(res.status(), StatusCode::OK); } + + #[actix_rt::test] + async fn extract_path_pattern_complex() { + let mut srv = init_service( + App::new() + .service(web::scope("/user").service(web::scope("/{id}").service( + web::resource("").to(move |req: HttpRequest| { + assert_eq!(req.match_pattern(), Some("/user/{id}".to_owned())); + + HttpResponse::Ok().finish() + }), + ))) + .service(web::resource("/").to(move |req: HttpRequest| { + assert_eq!(req.match_pattern(), Some("/".to_owned())); + + HttpResponse::Ok().finish() + })) + .default_service(web::to(move |req: HttpRequest| { + assert!(req.match_pattern().is_none()); + HttpResponse::Ok().finish() + })), + ) + .await; + + let req = TestRequest::get().uri("/user/test").to_request(); + let res = call_service(&mut srv, req).await; + assert_eq!(res.status(), StatusCode::OK); + + let req = TestRequest::get().uri("/").to_request(); + let res = call_service(&mut srv, req).await; + assert_eq!(res.status(), StatusCode::OK); + + let req = TestRequest::get().uri("/not-exist").to_request(); + let res = call_service(&mut srv, req).await; + assert_eq!(res.status(), StatusCode::OK); + } } diff --git a/src/rmap.rs b/src/rmap.rs index 05c1f3f15..6827a11b2 100644 --- a/src/rmap.rs +++ b/src/rmap.rs @@ -86,7 +86,7 @@ impl ResourceMap { if let Some(plen) = pattern.is_prefix_match(path) { return rmap.has_resource(&path[plen..]); } - } else if pattern.is_match(path) { + } else if pattern.is_match(path) || pattern.pattern() == "" && path == "/" { return true; } } From 24d525d9784c61b1956f14841e9c78395037b0d6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 1 Dec 2020 22:22:46 +0000 Subject: [PATCH 22/24] prepare web 3.3.2 release --- CHANGES.md | 17 +++++++++++++---- Cargo.toml | 2 +- README.md | 4 ++-- awc/CHANGES.md | 3 +++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index edf4380fb..d9984224f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,12 +1,21 @@ # Changes ## Unreleased - 2020-xx-xx -### Fixed -* Ensure `actix-http` dependency uses same `serde_urlencoded`. -* Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. -* Fix match_pattern() returning None for scope with resource of empty path. [#1798] + +## 3.3.2 - 2020-12-01 +### Fixed +* Removed an occasional `unwrap` on `None` panic in `NormalizePathNormalization`. [#1762] +* Fix `match_pattern()` returning `None` for scope with empty path resource. [#1798] +* Increase minimum `socket2` version. [#1803] + +[#1762]: https://github.com/actix/actix-web/pull/1762 [#1798]: https://github.com/actix/actix-web/pull/1798 +[#1803]: https://github.com/actix/actix-web/pull/1803 + + +## 3.3.1 - 2020-11-29 +* Ensure `actix-http` dependency uses same `serde_urlencoded`. ## 3.3.0 - 2020-11-25 diff --git a/Cargo.toml b/Cargo.toml index f8da9d90c..a7b571123 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "3.3.1" +version = "3.3.2" authors = ["Nikolay Kim "] description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" readme = "README.md" diff --git a/README.md b/README.md index f67da03c1..b9f2b7594 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,10 @@

[![crates.io](https://img.shields.io/crates/v/actix-web?label=latest)](https://crates.io/crates/actix-web) -[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.1)](https://docs.rs/actix-web/3.3.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=3.3.2)](https://docs.rs/actix-web/3.3.2) [![Version](https://img.shields.io/badge/rustc-1.42+-ab6000.svg)](https://blog.rust-lang.org/2020/03/12/Rust-1.42.html) ![License](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/3.3.1/status.svg)](https://deps.rs/crate/actix-web/3.3.1) +[![Dependency Status](https://deps.rs/crate/actix-web/3.3.2/status.svg)](https://deps.rs/crate/actix-web/3.3.2)
[![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) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index dfd8e3704..7ca415336 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2020-xx-xx + + +## 2.0.3 - 2020-11-29 ### Fixed * Ensure `actix-http` dependency uses same `serde_urlencoded`. From d0c6ca7671d8e77a78432cf38cb4fb570f582f39 Mon Sep 17 00:00:00 2001 From: Arniu Tseng Date: Thu, 3 Dec 2020 01:23:30 +0800 Subject: [PATCH 23/24] test-server => actix-http-test (#1807) --- Cargo.toml | 6 +++--- {test-server => actix-http-test}/CHANGES.md | 0 {test-server => actix-http-test}/Cargo.toml | 0 {test-server => actix-http-test}/LICENSE-APACHE | 0 {test-server => actix-http-test}/LICENSE-MIT | 0 {test-server => actix-http-test}/README.md | 0 {test-server => actix-http-test}/src/lib.rs | 0 7 files changed, 3 insertions(+), 3 deletions(-) rename {test-server => actix-http-test}/CHANGES.md (100%) rename {test-server => actix-http-test}/Cargo.toml (100%) rename {test-server => actix-http-test}/LICENSE-APACHE (100%) rename {test-server => actix-http-test}/LICENSE-MIT (100%) rename {test-server => actix-http-test}/README.md (100%) rename {test-server => actix-http-test}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index a7b571123..31c4cca7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ members = [ "actix-multipart", "actix-web-actors", "actix-web-codegen", - "test-server", + "actix-http-test", ] [features] @@ -127,10 +127,10 @@ codegen-units = 1 [patch.crates-io] actix-web = { path = "." } actix-http = { path = "actix-http" } -actix-http-test = { path = "test-server" } +actix-http-test = { path = "actix-http-test" } actix-web-codegen = { path = "actix-web-codegen" } -actix-files = { path = "actix-files" } actix-multipart = { path = "actix-multipart" } +actix-files = { path = "actix-files" } awc = { path = "awc" } [[bench]] diff --git a/test-server/CHANGES.md b/actix-http-test/CHANGES.md similarity index 100% rename from test-server/CHANGES.md rename to actix-http-test/CHANGES.md diff --git a/test-server/Cargo.toml b/actix-http-test/Cargo.toml similarity index 100% rename from test-server/Cargo.toml rename to actix-http-test/Cargo.toml diff --git a/test-server/LICENSE-APACHE b/actix-http-test/LICENSE-APACHE similarity index 100% rename from test-server/LICENSE-APACHE rename to actix-http-test/LICENSE-APACHE diff --git a/test-server/LICENSE-MIT b/actix-http-test/LICENSE-MIT similarity index 100% rename from test-server/LICENSE-MIT rename to actix-http-test/LICENSE-MIT diff --git a/test-server/README.md b/actix-http-test/README.md similarity index 100% rename from test-server/README.md rename to actix-http-test/README.md diff --git a/test-server/src/lib.rs b/actix-http-test/src/lib.rs similarity index 100% rename from test-server/src/lib.rs rename to actix-http-test/src/lib.rs From b75a9b7a20b8cdc24842d38c7aa406e2b49f90c7 Mon Sep 17 00:00:00 2001 From: Petar Dambovaliev Date: Fri, 4 Dec 2020 20:57:56 +0100 Subject: [PATCH 24/24] add error to message in test helper func (#1812) --- CHANGES.md | 5 +++++ src/test.rs | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d9984224f..87c021b1e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,11 @@ # Changes ## Unreleased - 2020-xx-xx +### Fixed +* added the actual parsing error to `test::read_body_json` [#1812] + +[#1812]: https://github.com/actix/actix-web/pull/1812 + ## 3.3.2 - 2020-12-01 diff --git a/src/test.rs b/src/test.rs index ee51b71ee..cff6c3e51 100644 --- a/src/test.rs +++ b/src/test.rs @@ -269,8 +269,9 @@ where { let body = read_body(res).await; - serde_json::from_slice(&body) - .unwrap_or_else(|_| panic!("read_response_json failed during deserialization")) + serde_json::from_slice(&body).unwrap_or_else(|e| { + panic!("read_response_json failed during deserialization: {}", e) + }) } pub async fn load_stream(mut stream: S) -> Result