From b9f0faafde1d451cc73776992a99a1eb03595a69 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 00:02:54 +0000 Subject: [PATCH 001/314] add cache-status and cdn-cache-control header names (#2968) * add cache-status and cdn-cache-control header names * fix changelog * update docs with rfc numbers --- actix-http/CHANGES.md | 5 ++++- actix-http/src/header/common.rs | 12 ++++++++++++ actix-http/src/header/mod.rs | 5 +++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 7feec2a1a..4f765e28b 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -7,7 +7,9 @@ - Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868] - Automatic h2c detection via new service finalizer `HttpService::tcp_auto_h2c()`. [#2957] - `HeaderMap::retain()` [#2955]. -- Header name constants in `header` module. [#2956] +- Header name constants in `header` module. [#2956] [#2968] + - `CACHE_STATUS` + - `CDN_CACHE_CONTROL` - `CROSS_ORIGIN_EMBEDDER_POLICY` - `CROSS_ORIGIN_OPENER_POLICY` - `PERMISSIONS_POLICY` @@ -24,6 +26,7 @@ [#2957]: https://github.com/actix/actix-web/pull/2957 [#2955]: https://github.com/actix/actix-web/pull/2955 [#2956]: https://github.com/actix/actix-web/pull/2956 +[#2968]: https://github.com/actix/actix-web/pull/2968 ## 3.2.2 - 2022-09-11 diff --git a/actix-http/src/header/common.rs b/actix-http/src/header/common.rs index 52909099a..67b0a9069 100644 --- a/actix-http/src/header/common.rs +++ b/actix-http/src/header/common.rs @@ -4,6 +4,18 @@ use http::header::HeaderName; +/// Response header field that indicates how caches have handled that response and its corresponding +/// request. +/// +/// See [RFC 9211](https://www.rfc-editor.org/rfc/rfc9211) for full semantics. +pub const CACHE_STATUS: HeaderName = HeaderName::from_static("cache-status"); + +/// Response header field that allows origin servers to control the behavior of CDN caches +/// interposed between them and clients separately from other caches that might handle the response. +/// +/// See [RFC 9213](https://www.rfc-editor.org/rfc/rfc9213) for full semantics. +pub const CDN_CACHE_CONTROL: HeaderName = HeaderName::from_static("cdn-cache-control"); + /// Response header that prevents a document from loading any cross-origin resources that don't /// explicitly grant the document permission (using [CORP] or [CORS]). /// diff --git a/actix-http/src/header/mod.rs b/actix-http/src/header/mod.rs index e2c2fe912..a63174a92 100644 --- a/actix-http/src/header/mod.rs +++ b/actix-http/src/header/mod.rs @@ -55,8 +55,9 @@ pub use self::{ // re-export list is explicit so that any updates to `http` do not conflict with this set pub use self::common::{ - CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY, CROSS_ORIGIN_RESOURCE_POLICY, - PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST, X_FORWARDED_PROTO, + CACHE_STATUS, CDN_CACHE_CONTROL, CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY, + CROSS_ORIGIN_RESOURCE_POLICY, PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST, + X_FORWARDED_PROTO, }; /// An interface for types that already represent a valid header. From 2f0b8a264aa385a990d74034719b9b2589f94886 Mon Sep 17 00:00:00 2001 From: cumtyc Date: Sat, 21 Jan 2023 08:51:49 +0800 Subject: [PATCH 002/314] fix non-empty body of http2 HEAD response (#2920) Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 4 ++++ actix-http/src/h2/dispatcher.rs | 14 ++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 4f765e28b..fa254ccf2 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -17,12 +17,16 @@ - `X_FORWARDED_HOST` - `X_FORWARDED_PROTO` +### Fixed +- Fix non-empty body of HTTP/2 HEAD responses. [#2920] + ### Performance - Improve overall performance of operations on `Extensions`. [#2890] [#2959]: https://github.com/actix/actix-web/pull/2959 [#2868]: https://github.com/actix/actix-web/pull/2868 [#2890]: https://github.com/actix/actix-web/pull/2890 +[#2920]: https://github.com/actix/actix-web/pull/2920 [#2957]: https://github.com/actix/actix-web/pull/2957 [#2955]: https://github.com/actix/actix-web/pull/2955 [#2956]: https://github.com/actix/actix-web/pull/2956 diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 680936f0f..3e618820e 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -29,7 +29,7 @@ use crate::{ HeaderName, HeaderValue, CONNECTION, CONTENT_LENGTH, DATE, TRANSFER_ENCODING, UPGRADE, }, service::HttpFlow, - Extensions, OnConnectData, Payload, Request, Response, ResponseHead, + Extensions, Method, OnConnectData, Payload, Request, Response, ResponseHead, }; const CHUNK_SIZE: usize = 16_384; @@ -118,6 +118,7 @@ where let payload = crate::h2::Payload::new(body); let pl = Payload::H2 { payload }; let mut req = Request::with_payload(pl); + let head_req = parts.method == Method::HEAD; let head = req.head_mut(); head.uri = parts.uri; @@ -135,10 +136,10 @@ where actix_rt::spawn(async move { // resolve service call and send response. let res = match fut.await { - Ok(res) => handle_response(res.into(), tx, config).await, + Ok(res) => handle_response(res.into(), tx, config, head_req).await, Err(err) => { let res: Response = err.into(); - handle_response(res, tx, config).await + handle_response(res, tx, config, head_req).await } }; @@ -206,6 +207,7 @@ async fn handle_response( res: Response, mut tx: SendResponse, config: ServiceConfig, + head_req: bool, ) -> Result<(), DispatchError> where B: MessageBody, @@ -215,14 +217,14 @@ where // prepare response. let mut size = body.size(); let res = prepare_response(config, res.head(), &mut size); - let eof = size.is_eof(); + let eof_or_head = size.is_eof() || head_req; // send response head and return on eof. let mut stream = tx - .send_response(res, eof) + .send_response(res, eof_or_head) .map_err(DispatchError::SendResponse)?; - if eof { + if eof_or_head { return Ok(()); } From b00fe72cf61cb857df9b0c8f6c7af5419f7647bd Mon Sep 17 00:00:00 2001 From: citreae535 <81646018+citreae535@users.noreply.github.com> Date: Sat, 21 Jan 2023 09:36:08 +0800 Subject: [PATCH 003/314] Update base64 to 0.21 (#2966) Co-authored-by: Rob Ede --- actix-http-test/Cargo.toml | 1 - actix-http/Cargo.toml | 2 +- actix-http/src/ws/proto.rs | 3 ++- awc/Cargo.toml | 2 +- awc/src/builder.rs | 4 +++- awc/src/request.rs | 3 ++- awc/src/ws.rs | 9 +++++++-- awc/tests/test_client.rs | 3 ++- 8 files changed, 18 insertions(+), 9 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 1162c0a38..d70de6164 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -37,7 +37,6 @@ actix-rt = "2.2" actix-server = "2" awc = { version = "3", default-features = false } -base64 = "0.13" bytes = "1" futures-core = { version = "0.3.17", default-features = false } http = "0.2.5" diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 9939089b9..f10a069c6 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -86,7 +86,7 @@ h2 = { version = "0.3.9", optional = true } # websockets local-channel = { version = "0.1", optional = true } -base64 = { version = "0.13", optional = true } +base64 = { version = "0.21", optional = true } rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } diff --git a/actix-http/src/ws/proto.rs b/actix-http/src/ws/proto.rs index 7222168b7..0653c00b0 100644 --- a/actix-http/src/ws/proto.rs +++ b/actix-http/src/ws/proto.rs @@ -3,6 +3,7 @@ use std::{ fmt, }; +use base64::prelude::*; use tracing::error; /// Operation codes defined in [RFC 6455 §11.8]. @@ -244,7 +245,7 @@ pub fn hash_key(key: &[u8]) -> [u8; 28] { }; let mut hash_b64 = [0; 28]; - let n = base64::encode_config_slice(hash, base64::STANDARD, &mut hash_b64); + let n = BASE64_STANDARD.encode_slice(hash, &mut hash_b64).unwrap(); assert_eq!(n, 28); hash_b64 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 41be3ef83..c1ad669a9 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -63,7 +63,7 @@ actix-tls = { version = "3", features = ["connect", "uri"] } actix-utils = "3" ahash = "0.7" -base64 = "0.13" +base64 = "0.21" bytes = "1" cfg-if = "1" derive_more = "0.99.5" diff --git a/awc/src/builder.rs b/awc/src/builder.rs index 34a5f8505..79838a3f6 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -1,5 +1,7 @@ use std::{convert::TryFrom, fmt, net::IpAddr, rc::Rc, time::Duration}; +use base64::prelude::*; + use actix_http::{ error::HttpError, header::{self, HeaderMap, HeaderName, TryIntoHeaderPair}, @@ -210,7 +212,7 @@ where }; self.add_default_header(( header::AUTHORIZATION, - format!("Basic {}", base64::encode(auth)), + format!("Basic {}", BASE64_STANDARD.encode(auth)), )) } diff --git a/awc/src/request.rs b/awc/src/request.rs index 331c80af7..d3a4eda8c 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -1,5 +1,6 @@ use std::{convert::TryFrom, fmt, net, rc::Rc, time::Duration}; +use base64::prelude::*; use bytes::Bytes; use futures_core::Stream; use serde::Serialize; @@ -238,7 +239,7 @@ impl ClientRequest { self.insert_header(( header::AUTHORIZATION, - format!("Basic {}", base64::encode(auth)), + format!("Basic {}", BASE64_STANDARD.encode(auth)), )) } diff --git a/awc/src/ws.rs b/awc/src/ws.rs index f905b8ef2..406368e62 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -28,6 +28,8 @@ use std::{convert::TryFrom, fmt, net::SocketAddr, str}; +use base64::prelude::*; + use actix_codec::Framed; use actix_http::{ws, Payload, RequestHead}; use actix_rt::time::timeout; @@ -236,7 +238,10 @@ impl WebsocketsRequest { Some(password) => format!("{}:{}", username, password), None => format!("{}:", username), }; - self.header(AUTHORIZATION, format!("Basic {}", base64::encode(auth))) + self.header( + AUTHORIZATION, + format!("Basic {}", BASE64_STANDARD.encode(auth)), + ) } /// Set HTTP bearer authentication header @@ -321,7 +326,7 @@ impl WebsocketsRequest { // Generate a random key for the `Sec-WebSocket-Key` header which is a base64-encoded // (see RFC 4648 §4) value that, when decoded, is 16 bytes in length (RFC 6455 §1.3). let sec_key: [u8; 16] = rand::random(); - let key = base64::encode(sec_key); + let key = BASE64_STANDARD.encode(sec_key); self.head.headers.insert( header::SEC_WEBSOCKET_KEY, diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index 0949595cb..9c3543ff0 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -13,6 +13,7 @@ use std::{ }; use actix_utils::future::ok; +use base64::prelude::*; use bytes::Bytes; use cookie::Cookie; use futures_util::stream; @@ -783,7 +784,7 @@ async fn client_basic_auth() { .unwrap() .to_str() .unwrap() - == format!("Basic {}", base64::encode("username:password")) + == format!("Basic {}", BASE64_STANDARD.encode("username:password")) { HttpResponse::Ok() } else { From 72c80f9107775fd911bfbce05654a4488335e46b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 18:46:44 +0000 Subject: [PATCH 004/314] update tokio-uring support to 0.4 --- actix-files/CHANGES.md | 1 + actix-files/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 6e57bf7a7..7aa65e43b 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - 2022-xx-xx - XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. +- Update `tokio-uring` dependency to `0.4`. [#2903]: https://github.com/actix/actix-web/pull/2903 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 01dc2928a..47a5b3772 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -40,8 +40,8 @@ v_htmlescape= "0.15" # experimental-io-uring [target.'cfg(target_os = "linux")'.dependencies] -tokio-uring = { version = "0.3", optional = true, features = ["bytes"] } -actix-server = { version = "2.1", optional = true } # ensure matching tokio-uring versions +tokio-uring = { version = "0.4", optional = true, features = ["bytes"] } +actix-server = { version = "2.2", optional = true } # ensure matching tokio-uring versions [dev-dependencies] actix-rt = "2.7" From dd9ac4d9b89b91f2dbd2560737f6d7eb5ef04ad0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 18:52:57 +0000 Subject: [PATCH 005/314] prepare actix-http release 3.3.0 --- actix-http/CHANGES.md | 3 +++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index fa254ccf2..8171061da 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx + + +## 3.3.0 - 2023-01-21 ### Added - Implement `MessageBody` for `Cow<'static, str>` and `Cow<'static, [u8]>`. [#2959] - Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868] diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index f10a069c6..d7fb19757 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.2.2" +version = "3.3.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 994cf97c6..2dd2d248f 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -3,11 +3,11 @@ > 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=3.2.2)](https://docs.rs/actix-http/3.2.2) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.3.0)](https://docs.rs/actix-http/3.3.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.2.2/status.svg)](https://deps.rs/crate/actix-http/3.2.2) +[![dependency status](https://deps.rs/crate/actix-http/3.3.0/status.svg)](https://deps.rs/crate/actix-http/3.3.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index d1ae89c58..90c030a59 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -68,7 +68,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3", default-features = false, optional = true } -actix-http = { version = "3.2.2", features = ["http2", "ws"] } +actix-http = { version = "3.3", features = ["http2", "ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.1", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index c1ad669a9..2738915aa 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -57,7 +57,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3", features = ["http2", "ws"] } +actix-http = { version = "3.3", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3", features = ["connect", "uri"] } actix-utils = "3" From 8d4cb8c69af47e6ea33b86e035e5bb8bf358d8cc Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 18:54:58 +0000 Subject: [PATCH 006/314] prepare awc release 3.1.0 --- awc/CHANGES.md | 3 +++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 7892d9339..e8770723b 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx + + +## 3.1.0 - 2023-01-21 ### Changed - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 2738915aa..a717774f7 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.0.1" +version = "3.1.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 9f47e663b..cbe9af26a 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=3.0.1)](https://docs.rs/awc/3.0.1) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.1.0)](https://docs.rs/awc/3.1.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.0.1/status.svg)](https://deps.rs/crate/awc/3.0.1) +[![Dependency Status](https://deps.rs/crate/awc/3.1.0/status.svg)](https://deps.rs/crate/awc/3.1.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) ## Documentation & Resources From df6fde883c17c39ee30b71858a65c36eb0ed71c0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 18:57:42 +0000 Subject: [PATCH 007/314] prepare actix-web release 4.3.0 --- actix-web/CHANGES.md | 10 +++++++--- actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 6fc3c93d7..bf386acba 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -1,13 +1,16 @@ # Changelog ## Unreleased - 2022-xx-xx + + +## 4.3.0 - 2023-01-21 ### Added -- Add `ContentDisposition::attachment` constructor. [#2867] +- Add `ContentDisposition::attachment()` constructor. [#2867] - Add `ErrorHandlers::default_handler()` (as well as `default_handler_{server, client}()`) to make registering handlers for groups of response statuses easier. [#2784] - Add `Logger::custom_response_replace()`. [#2631] - Add rudimentary redirection service at `web::redirect()` / `web::Redirect`. [#1961] -- Add `guard::Acceptable` for matching against `Accept` header mime types. [#2265] -- Add fallible versions of test helpers: `try_call_service`, `try_call_and_read_body_json`, `try_read_body`, and `try_read_body_json`. [#2961] +- Add `guard::Acceptable` for matching against `Accept` header MIME types. [#2265] +- Add fallible versions of `test` helpers: `try_call_service()`, `try_call_and_read_body_json()`, `try_read_body()`, and `try_read_body_json()`. [#2961] ### Fixed - Add `Allow` header to `Resource`'s default responses when no routes are matched. [#2949] @@ -20,6 +23,7 @@ [#2949]: https://github.com/actix/actix-web/pull/2949 [#2961]: https://github.com/actix/actix-web/pull/2961 + ## 4.2.1 - 2022-09-12 ### Fixed - Bump minimum version of `actix-http` dependency to fix compatibility issue. [#2871] diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 90c030a59..3c7cef19c 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.2.1" +version = "4.3.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-web/README.md b/actix-web/README.md index 65076e0b8..20ca66fad 100644 --- a/actix-web/README.md +++ b/actix-web/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=4.2.1)](https://docs.rs/actix-web/4.2.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.3.0)](https://docs.rs/actix-web/4.3.0) ![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.2.1/status.svg)](https://deps.rs/crate/actix-web/4.2.1) +[![Dependency Status](https://deps.rs/crate/actix-web/4.3.0/status.svg)](https://deps.rs/crate/actix-web/4.3.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 98752c053c38debf0a4ec03b5aee7bc3a1aea594 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 18:59:13 +0000 Subject: [PATCH 008/314] prepare actix-multipart release 0.5.0 --- actix-multipart/CHANGES.md | 9 ++++++--- actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 655487e54..ed117d7d3 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,10 +1,13 @@ # Changes ## Unreleased - 2022-xx-xx -- Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. -- `Field::content_type()` now returns `Option<&mime::Mime>` [#2880] -[#2880]: https://github.com/actix/actix-web/pull/2880 + +## 0.5.0 - 2023-01-21 +- Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. +- `Field::content_type()` now returns `Option<&mime::Mime>` [#2885] + +[#2885]: https://github.com/actix/actix-web/pull/2885 ## 0.4.0 - 2022-02-25 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 4651d455b..7ed67e951 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.4.0" +version = "0.5.0" authors = ["Nikolay Kim "] description = "Multipart form support for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 21999716c..82587ffc0 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -3,11 +3,11 @@ > Multipart form support for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) -[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.4.0)](https://docs.rs/actix-multipart/0.4.0) +[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart/0.5.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart/0.4.0/status.svg)](https://deps.rs/crate/actix-multipart/0.4.0) +[![dependency status](https://deps.rs/crate/actix-multipart/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart/0.5.0) [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 845156da85bc91720389cdb4d538d3744ad7f25d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 19:01:08 +0000 Subject: [PATCH 009/314] prepare actix-web-actors release 4.2.0 --- actix-web-actors/CHANGES.md | 3 +++ actix-web-actors/Cargo.toml | 2 +- actix-web-actors/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 33d4712f8..c66c04d37 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx + + +## 4.2.0 - 2023-01-21 - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 2158f59e1..4a610ab95 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-actors" -version = "4.1.0" +version = "4.2.0" authors = ["Nikolay Kim "] description = "Actix actors support for Actix Web" keywords = ["actix", "http", "web", "framework", "async"] diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index a0578994c..29d766eab 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -3,11 +3,11 @@ > Actix actors support for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) -[![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.1.0)](https://docs.rs/actix-web-actors/4.1.0) +[![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.2.0)](https://docs.rs/actix-web-actors/4.2.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
-[![dependency status](https://deps.rs/crate/actix-web-actors/4.1.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.1.0) +[![dependency status](https://deps.rs/crate/actix-web-actors/4.2.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.2.0) [![Download](https://img.shields.io/crates/d/actix-web-actors.svg)](https://crates.io/crates/actix-web-actors) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 74688843bac4dd71b8ccb079ba99d2fe2bc60190 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 19:01:14 +0000 Subject: [PATCH 010/314] prepare actix-http-test release 3.1.0 --- actix-http-test/CHANGES.md | 3 +++ actix-http-test/Cargo.toml | 2 +- actix-http-test/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index 028fe3ddc..0eeb80454 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx + + +## 3.1.0 - 2023-01-21 - Minimum supported Rust version (MSRV) is now 1.59. diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index d70de6164..0942556da 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "3.0.0" +version = "3.1.0" authors = ["Nikolay Kim "] description = "Various helpers for Actix applications to use during testing" keywords = ["http", "web", "framework", "async", "futures"] diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 25e7c684e..910b5649d 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -3,11 +3,11 @@ > Various helpers for Actix applications to use during testing. [![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=3.0.0)](https://docs.rs/actix-http-test/3.0.0) +[![Documentation](https://docs.rs/actix-http-test/badge.svg?version=3.1.0)](https://docs.rs/actix-http-test/3.1.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
-[![Dependency Status](https://deps.rs/crate/actix-http-test/3.0.0/status.svg)](https://deps.rs/crate/actix-http-test/3.0.0) +[![Dependency Status](https://deps.rs/crate/actix-http-test/3.1.0/status.svg)](https://deps.rs/crate/actix-http-test/3.1.0) [![Download](https://img.shields.io/crates/d/actix-http-test.svg)](https://crates.io/crates/actix-http-test) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From c15016dafb5b2b7f42796b58ae63fb42643991e3 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 21 Jan 2023 19:03:19 +0000 Subject: [PATCH 011/314] prepare actix-files release 0.6.3 --- actix-files/CHANGES.md | 3 +++ actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 7aa65e43b..60d3ceb96 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx + + +## 0.6.3 - 2023-01-21 - XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. - Update `tokio-uring` dependency to `0.4`. diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 47a5b3772..4c29c95b2 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.6.2" +version = "0.6.3" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-files/README.md b/actix-files/README.md index a5078c8d5..9a7e6e722 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -3,11 +3,11 @@ > Static file serving for Actix Web [![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.6.2)](https://docs.rs/actix-files/0.6.2) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.3)](https://docs.rs/actix-files/0.6.3) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
-[![dependency status](https://deps.rs/crate/actix-files/0.6.2/status.svg)](https://deps.rs/crate/actix-files/0.6.2) +[![dependency status](https://deps.rs/crate/actix-files/0.6.3/status.svg)](https://deps.rs/crate/actix-files/0.6.3) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From fa106da55519ce94445b71773478db04cd6d1c21 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 30 Jan 2023 11:36:12 -0500 Subject: [PATCH 012/314] refactor: move Host guard into own module --- actix-http/CHANGES.md | 2 +- actix-web/src/guard/host.rs | 209 ++++++++++++++++++++++++++++++++++++ actix-web/src/guard/mod.rs | 207 +---------------------------------- actix-web/src/info.rs | 1 - 4 files changed, 214 insertions(+), 205 deletions(-) create mode 100644 actix-web/src/guard/host.rs diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 8171061da..4cc467ddc 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -9,7 +9,7 @@ - Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868] - Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868] - Automatic h2c detection via new service finalizer `HttpService::tcp_auto_h2c()`. [#2957] -- `HeaderMap::retain()` [#2955]. +- `HeaderMap::retain()`. [#2955] - Header name constants in `header` module. [#2956] [#2968] - `CACHE_STATUS` - `CDN_CACHE_CONTROL` diff --git a/actix-web/src/guard/host.rs b/actix-web/src/guard/host.rs new file mode 100644 index 000000000..f05c81183 --- /dev/null +++ b/actix-web/src/guard/host.rs @@ -0,0 +1,209 @@ +use actix_http::{header, uri::Uri, RequestHead}; + +use super::{Guard, GuardContext}; + +/// Creates a guard that matches requests targetting a specific host. +/// +/// # Matching Host +/// This guard will: +/// - match against the `Host` header, if present; +/// - fall-back to matching against the request target's host, if present; +/// - return false if host cannot be determined; +/// +/// # Matching Scheme +/// Optionally, this guard can match against the host's scheme. Set the scheme for matching using +/// `Host(host).scheme(protocol)`. If the request's scheme cannot be determined, it will not prevent +/// the guard from matching successfully. +/// +/// # Examples +/// The `Host` guard can be used to set up a form of [virtual hosting] within a single app. +/// Overlapping scope prefixes are usually discouraged, but when combined with non-overlapping guard +/// definitions they become safe to use in this way. Without these host guards, only routes under +/// the first-to-be-defined scope would be accessible. You can test this locally using `127.0.0.1` +/// and `localhost` as the `Host` guards. +/// ``` +/// use actix_web::{web, http::Method, guard, App, HttpResponse}; +/// +/// App::new() +/// .service( +/// web::scope("") +/// .guard(guard::Host("www.rust-lang.org")) +/// .default_service(web::to(|| async { +/// HttpResponse::Ok().body("marketing site") +/// })), +/// ) +/// .service( +/// web::scope("") +/// .guard(guard::Host("play.rust-lang.org")) +/// .default_service(web::to(|| async { +/// HttpResponse::Ok().body("playground frontend") +/// })), +/// ); +/// ``` +/// +/// The example below additionally guards on the host URI's scheme. This could allow routing to +/// different handlers for `http:` vs `https:` visitors; to redirect, for example. +/// ``` +/// use actix_web::{web, guard::Host, HttpResponse}; +/// +/// web::scope("/admin") +/// .guard(Host("admin.rust-lang.org").scheme("https")) +/// .default_service(web::to(|| async { +/// HttpResponse::Ok().body("admin connection is secure") +/// })); +/// ``` +/// +/// [virtual hosting]: https://en.wikipedia.org/wiki/Virtual_hosting +#[allow(non_snake_case)] +pub fn Host(host: impl AsRef) -> HostGuard { + HostGuard { + host: host.as_ref().to_string(), + scheme: None, + } +} + +fn get_host_uri(req: &RequestHead) -> Option { + req.headers + .get(header::HOST) + .and_then(|host_value| host_value.to_str().ok()) + .or_else(|| req.uri.host()) + .and_then(|host| host.parse().ok()) +} + +#[doc(hidden)] +pub struct HostGuard { + host: String, + scheme: Option, +} + +impl HostGuard { + /// Set request scheme to match + pub fn scheme>(mut self, scheme: H) -> HostGuard { + self.scheme = Some(scheme.as_ref().to_string()); + self + } +} + +impl Guard for HostGuard { + fn check(&self, ctx: &GuardContext<'_>) -> bool { + // parse host URI from header or request target + let req_host_uri = match get_host_uri(ctx.head()) { + Some(uri) => uri, + + // no match if host cannot be determined + None => return false, + }; + + match req_host_uri.host() { + // fall through to scheme checks + Some(uri_host) if self.host == uri_host => {} + + // Either: + // - request's host does not match guard's host; + // - It was possible that the parsed URI from request target did not contain a host. + _ => return false, + } + + if let Some(ref scheme) = self.scheme { + if let Some(ref req_host_uri_scheme) = req_host_uri.scheme_str() { + return scheme == req_host_uri_scheme; + } + + // TODO: is this the correct behavior? + // falls through if scheme cannot be determined + } + + // all conditions passed + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::TestRequest; + + #[test] + fn host_from_header() { + let req = TestRequest::default() + .insert_header(( + header::HOST, + header::HeaderValue::from_static("www.rust-lang.org"), + )) + .to_srv_request(); + + let host = Host("www.rust-lang.org"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("www.rust-lang.org").scheme("https"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org").scheme("https"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("crates.io"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("localhost"); + assert!(!host.check(&req.guard_ctx())); + } + + #[test] + fn host_without_header() { + let req = TestRequest::default() + .uri("www.rust-lang.org") + .to_srv_request(); + + let host = Host("www.rust-lang.org"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("www.rust-lang.org").scheme("https"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org").scheme("https"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("crates.io"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("localhost"); + assert!(!host.check(&req.guard_ctx())); + } + + #[test] + fn host_scheme() { + let req = TestRequest::default() + .insert_header(( + header::HOST, + header::HeaderValue::from_static("https://www.rust-lang.org"), + )) + .to_srv_request(); + + let host = Host("www.rust-lang.org").scheme("https"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("www.rust-lang.org"); + assert!(host.check(&req.guard_ctx())); + + let host = Host("www.rust-lang.org").scheme("http"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("blog.rust-lang.org").scheme("https"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("crates.io").scheme("https"); + assert!(!host.check(&req.guard_ctx())); + + let host = Host("localhost"); + assert!(!host.check(&req.guard_ctx())); + } +} diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index e086f8648..164032bdc 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -52,12 +52,15 @@ use std::{ rc::Rc, }; -use actix_http::{header, uri::Uri, Extensions, Method as HttpMethod, RequestHead}; +use actix_http::{header, Extensions, Method as HttpMethod, RequestHead}; use crate::{http::header::Header, service::ServiceRequest, HttpMessage as _}; mod acceptable; +mod host; + pub use self::acceptable::Acceptable; +pub use self::host::{Host, HostGuard}; /// Provides access to request parts that are useful during routing. #[derive(Debug)] @@ -371,124 +374,6 @@ impl Guard for HeaderGuard { } } -/// Creates a guard that matches requests targetting a specific host. -/// -/// # Matching Host -/// This guard will: -/// - match against the `Host` header, if present; -/// - fall-back to matching against the request target's host, if present; -/// - return false if host cannot be determined; -/// -/// # Matching Scheme -/// Optionally, this guard can match against the host's scheme. Set the scheme for matching using -/// `Host(host).scheme(protocol)`. If the request's scheme cannot be determined, it will not prevent -/// the guard from matching successfully. -/// -/// # Examples -/// The [module-level documentation](self) has an example of virtual hosting using `Host` guards. -/// -/// The example below additionally guards on the host URI's scheme. This could allow routing to -/// different handlers for `http:` vs `https:` visitors; to redirect, for example. -/// ``` -/// use actix_web::{web, guard::Host, HttpResponse}; -/// -/// web::scope("/admin") -/// .guard(Host("admin.rust-lang.org").scheme("https")) -/// .default_service(web::to(|| async { -/// HttpResponse::Ok().body("admin connection is secure") -/// })); -/// ``` -/// -/// The `Host` guard can be used to set up some form of [virtual hosting] within a single app. -/// Overlapping scope prefixes are usually discouraged, but when combined with non-overlapping guard -/// definitions they become safe to use in this way. Without these host guards, only routes under -/// the first-to-be-defined scope would be accessible. You can test this locally using `127.0.0.1` -/// and `localhost` as the `Host` guards. -/// ``` -/// use actix_web::{web, http::Method, guard, App, HttpResponse}; -/// -/// App::new() -/// .service( -/// web::scope("") -/// .guard(guard::Host("www.rust-lang.org")) -/// .default_service(web::to(|| async { -/// HttpResponse::Ok().body("marketing site") -/// })), -/// ) -/// .service( -/// web::scope("") -/// .guard(guard::Host("play.rust-lang.org")) -/// .default_service(web::to(|| async { -/// HttpResponse::Ok().body("playground frontend") -/// })), -/// ); -/// ``` -/// -/// [virtual hosting]: https://en.wikipedia.org/wiki/Virtual_hosting -#[allow(non_snake_case)] -pub fn Host(host: impl AsRef) -> HostGuard { - HostGuard { - host: host.as_ref().to_string(), - scheme: None, - } -} - -fn get_host_uri(req: &RequestHead) -> Option { - req.headers - .get(header::HOST) - .and_then(|host_value| host_value.to_str().ok()) - .or_else(|| req.uri.host()) - .and_then(|host| host.parse().ok()) -} - -#[doc(hidden)] -pub struct HostGuard { - host: String, - scheme: Option, -} - -impl HostGuard { - /// Set request scheme to match - pub fn scheme>(mut self, scheme: H) -> HostGuard { - self.scheme = Some(scheme.as_ref().to_string()); - self - } -} - -impl Guard for HostGuard { - fn check(&self, ctx: &GuardContext<'_>) -> bool { - // parse host URI from header or request target - let req_host_uri = match get_host_uri(ctx.head()) { - Some(uri) => uri, - - // no match if host cannot be determined - None => return false, - }; - - match req_host_uri.host() { - // fall through to scheme checks - Some(uri_host) if self.host == uri_host => {} - - // Either: - // - request's host does not match guard's host; - // - It was possible that the parsed URI from request target did not contain a host. - _ => return false, - } - - if let Some(ref scheme) = self.scheme { - if let Some(ref req_host_uri_scheme) = req_host_uri.scheme_str() { - return scheme == req_host_uri_scheme; - } - - // TODO: is this the correct behavior? - // falls through if scheme cannot be determined - } - - // all conditions passed - true - } -} - #[cfg(test)] mod tests { use actix_http::{header, Method}; @@ -515,90 +400,6 @@ mod tests { assert!(!hdr.check(&req.guard_ctx())); } - #[test] - fn host_from_header() { - let req = TestRequest::default() - .insert_header(( - header::HOST, - header::HeaderValue::from_static("www.rust-lang.org"), - )) - .to_srv_request(); - - let host = Host("www.rust-lang.org"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("www.rust-lang.org").scheme("https"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org").scheme("https"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("crates.io"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("localhost"); - assert!(!host.check(&req.guard_ctx())); - } - - #[test] - fn host_without_header() { - let req = TestRequest::default() - .uri("www.rust-lang.org") - .to_srv_request(); - - let host = Host("www.rust-lang.org"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("www.rust-lang.org").scheme("https"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org").scheme("https"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("crates.io"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("localhost"); - assert!(!host.check(&req.guard_ctx())); - } - - #[test] - fn host_scheme() { - let req = TestRequest::default() - .insert_header(( - header::HOST, - header::HeaderValue::from_static("https://www.rust-lang.org"), - )) - .to_srv_request(); - - let host = Host("www.rust-lang.org").scheme("https"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("www.rust-lang.org"); - assert!(host.check(&req.guard_ctx())); - - let host = Host("www.rust-lang.org").scheme("http"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("blog.rust-lang.org").scheme("https"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("crates.io").scheme("https"); - assert!(!host.check(&req.guard_ctx())); - - let host = Host("localhost"); - assert!(!host.check(&req.guard_ctx())); - } - #[test] fn method_guards() { let get_req = TestRequest::get().to_srv_request(); diff --git a/actix-web/src/info.rs b/actix-web/src/info.rs index 7c685406e..c5d9638f4 100644 --- a/actix-web/src/info.rs +++ b/actix-web/src/info.rs @@ -76,7 +76,6 @@ impl ConnectionInfo { for (name, val) in req .headers .get_all(&header::FORWARDED) - .into_iter() .filter_map(|hdr| hdr.to_str().ok()) // "for=1.2.3.4, for=5.6.7.8; scheme=https" .flat_map(|val| val.split(';')) From 4bff1d0abe3f90fa804c79c4a8b69fb2a0595216 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 3 Feb 2023 20:35:19 -0500 Subject: [PATCH 013/314] require safe tokio version range see https://rustsec.org/advisories/RUSTSEC-2023-0005 --- actix-http-test/Cargo.toml | 2 +- actix-http/Cargo.toml | 4 ++-- actix-multipart/Cargo.toml | 2 +- actix-test/Cargo.toml | 2 +- actix-web-actors/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 0942556da..23fffdc17 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -47,7 +47,7 @@ serde_json = "1.0" slab = "0.4" serde_urlencoded = "0.7" tls-openssl = { version = "0.10.9", package = "openssl", optional = true } -tokio = { version = "1.18.4", features = ["sync"] } +tokio = { version = "1.18.5", features = ["sync"] } [dev-dependencies] actix-web = { version = "4", default-features = false, features = ["cookies"] } diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index d7fb19757..19302d002 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -77,7 +77,7 @@ mime = "0.3" percent-encoding = "2.1" pin-project-lite = "0.2" smallvec = "1.6.1" -tokio = { version = "1.18.4", features = [] } +tokio = { version = "1.18.5", features = [] } tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } @@ -119,7 +119,7 @@ serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.9" } tls-rustls = { package = "rustls", version = "0.20.0" } -tokio = { version = "1.18.4", features = ["net", "rt", "macros"] } +tokio = { version = "1.18.5", features = ["net", "rt", "macros"] } [[example]] name = "ws" diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 7ed67e951..8f768563c 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -30,5 +30,5 @@ memchr = "2.5" actix-rt = "2.2" actix-http = "3" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } -tokio = { version = "1.18.4", features = ["sync"] } +tokio = { version = "1.18.5", features = ["sync"] } tokio-stream = "0.1" diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index d489d4a05..213d6bc36 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -45,4 +45,4 @@ serde_json = "1" serde_urlencoded = "0.7" tls-openssl = { package = "openssl", version = "0.10.9", optional = true } tls-rustls = { package = "rustls", version = "0.20.0", optional = true } -tokio = { version = "1.18.4", features = ["sync"] } +tokio = { version = "1.18.5", features = ["sync"] } diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 4a610ab95..4eb9ddc62 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -23,7 +23,7 @@ bytes = "1" bytestring = "1" futures-core = { version = "0.3.17", default-features = false } pin-project-lite = "0.2" -tokio = { version = "1.18.4", features = ["sync"] } +tokio = { version = "1.18.5", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec"] } [dev-dependencies] diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 3c7cef19c..44755035c 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -115,7 +115,7 @@ serde = { version = "1.0", features = ["derive"] } static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.9" } tls-rustls = { package = "rustls", version = "0.20.0" } -tokio = { version = "1.18.4", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.18.5", features = ["rt-multi-thread", "macros"] } zstd = "0.12" [[test]] diff --git a/awc/Cargo.toml b/awc/Cargo.toml index a717774f7..a69a07d67 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -80,7 +80,7 @@ rand = "0.8" serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" -tokio = { version = "1.18.4", features = ["sync"] } +tokio = { version = "1.18.5", features = ["sync"] } cookie = { version = "0.16", features = ["percent-encode"], optional = true } @@ -106,7 +106,7 @@ futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" rcgen = "0.9" rustls-pemfile = "1" -tokio = { version = "1.18.4", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.18.5", features = ["rt-multi-thread", "macros"] } zstd = "0.12" [[example]] From b933ed445611c752401342a3a020bbf185d2031d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 3 Feb 2023 21:04:07 -0500 Subject: [PATCH 014/314] add tests for files_listing_renderer --- actix-files/src/files.rs | 43 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs index a30ce6fd3..be2a450d2 100644 --- a/actix-files/src/files.rs +++ b/actix-files/src/files.rs @@ -142,7 +142,7 @@ impl Files { self } - /// Set custom directory renderer + /// Set custom directory renderer. pub fn files_listing_renderer(mut self, f: F) -> Self where for<'r, 's> F: @@ -152,7 +152,7 @@ impl Files { self } - /// Specifies mime override callback + /// Specifies MIME override callback. pub fn mime_override(mut self, f: F) -> Self where F: Fn(&mime::Name<'_>) -> DispositionType + 'static, @@ -390,3 +390,42 @@ impl ServiceFactory for Files { } } } + +#[cfg(test)] +mod tests { + use actix_web::{ + http::StatusCode, + test::{self, TestRequest}, + App, HttpResponse, + }; + + use super::*; + + #[actix_web::test] + async fn custom_files_listing_renderer() { + let srv = test::init_service( + App::new().service( + Files::new("/", "./tests") + .show_files_listing() + .files_listing_renderer(|dir, req| { + Ok(ServiceResponse::new( + req.clone(), + HttpResponse::Ok().body(dir.path.to_str().unwrap().to_owned()), + )) + }), + ), + ) + .await; + + let req = TestRequest::with_uri("/").to_request(); + let res = test::call_service(&srv, req).await; + + assert_eq!(res.status(), StatusCode::OK); + let body = test::read_body(res).await; + assert!( + body.ends_with(b"actix-files/tests/"), + "body {:?} does not end with `actix-files/tests/`", + body + ); + } +} From 65c0545a7a24fb2234f7793b4a9d4d7b6811c62c Mon Sep 17 00:00:00 2001 From: edgerunnergit Date: Mon, 6 Feb 2023 18:10:41 +0530 Subject: [PATCH 015/314] added support for creating custom methods with route macro (#2969) Co-authored-by: Rob Ede Closes https://github.com/actix/actix-web/issues/2893 --- actix-web-codegen/CHANGES.md | 3 + actix-web-codegen/src/lib.rs | 2 +- actix-web-codegen/src/route.rs | 149 ++++++++++++++---- actix-web-codegen/tests/test_macro.rs | 8 +- actix-web-codegen/tests/trybuild.rs | 4 +- .../tests/trybuild/route-custom-lowercase.rs | 19 +++ .../trybuild/route-custom-lowercase.stderr | 19 +++ ...-method-fail.rs => route-custom-method.rs} | 4 +- .../route-unexpected-method-fail.stderr | 19 --- actix-web/CHANGES.md | 1 - 10 files changed, 169 insertions(+), 59 deletions(-) create mode 100644 actix-web-codegen/tests/trybuild/route-custom-lowercase.rs create mode 100644 actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr rename actix-web-codegen/tests/trybuild/{route-unexpected-method-fail.rs => route-custom-method.rs} (71%) delete mode 100644 actix-web-codegen/tests/trybuild/route-unexpected-method-fail.stderr diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index cb37bfdb0..ffa2cd252 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,6 +1,9 @@ # Changes ## Unreleased - 2022-xx-xx +- Add support for Custom Methods with `#[route]` macro. [#2969] + +[#2969]: https://github.com/actix/actix-web/pull/2969 ## 4.1.0 - 2022-09-11 diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 4b6dc43c5..5d392be1d 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -105,7 +105,7 @@ mod route; /// ``` /// # use actix_web::HttpResponse; /// # use actix_web_codegen::route; -/// #[route("/test", method = "GET", method = "HEAD")] +/// #[route("/test", method = "GET", method = "HEAD", method = "CUSTOM")] /// async fn example() -> HttpResponse { /// HttpResponse::Ok().finish() /// } diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index e5493702d..594a58626 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -27,7 +27,13 @@ macro_rules! method_type { fn parse(method: &str) -> Result { match method { $(stringify!($upper) => Ok(Self::$variant),)+ - _ => Err(format!("Unexpected HTTP method: `{}`", method)), + _ => { + if method.chars().all(|c| c.is_ascii_uppercase()) { + Ok(Self::Method) + } else { + Err(format!("HTTP method must be uppercase: `{}`", method)) + } + }, } } @@ -41,6 +47,12 @@ macro_rules! method_type { }; } +#[derive(Eq, Hash, PartialEq)] +struct MethodTypeExt { + method: MethodType, + custom_method: Option, +} + method_type! { Get, GET, get, Post, POST, post, @@ -51,6 +63,7 @@ method_type! { Options, OPTIONS, options, Trace, TRACE, trace, Patch, PATCH, patch, + Method, METHOD, method, } impl ToTokens for MethodType { @@ -60,6 +73,21 @@ impl ToTokens for MethodType { } } +impl ToTokens for MethodTypeExt { + fn to_tokens(&self, stream: &mut TokenStream2) { + match self.method { + MethodType::Method => { + let ident = Ident::new( + self.custom_method.as_ref().unwrap().value().as_str(), + Span::call_site(), + ); + stream.append(ident); + } + _ => self.method.to_tokens(stream), + } + } +} + impl TryFrom<&syn::LitStr> for MethodType { type Error = syn::Error; @@ -74,7 +102,7 @@ struct Args { resource_name: Option, guards: Vec, wrappers: Vec, - methods: HashSet, + methods: HashSet, } impl Args { @@ -99,7 +127,12 @@ impl Args { let is_route_macro = method.is_none(); if let Some(method) = method { - methods.insert(method); + methods.insert({ + MethodTypeExt { + method, + custom_method: None, + } + }); } for arg in args { @@ -152,10 +185,22 @@ impl Args { )); } else if let syn::Lit::Str(ref lit) = nv.lit { let method = MethodType::try_from(lit)?; - if !methods.insert(method) { + if !methods.insert({ + if method == MethodType::Method { + MethodTypeExt { + method, + custom_method: Some(lit.clone()), + } + } else { + MethodTypeExt { + method, + custom_method: None, + } + } + }) { return Err(syn::Error::new_spanned( &nv.lit, - format!( + &format!( "HTTP method defined more than once: `{}`", lit.value() ), @@ -298,38 +343,72 @@ impl ToTokens for Route { .as_ref() .map_or_else(|| name.to_string(), LitStr::value); - let method_guards = { - let mut others = methods.iter(); - - // unwrapping since length is checked to be at least one - let first = others.next().unwrap(); - - if methods.len() > 1 { - quote! { - .guard( - ::actix_web::guard::Any(::actix_web::guard::#first()) - #(.or(::actix_web::guard::#others()))* - ) - } - } else { - quote! { - .guard(::actix_web::guard::#first()) + let method_guards = { + let mut others = methods.iter(); + let first = others.next().unwrap(); + let first_method = &first.method; + if methods.len() > 1 { + let mut mult_method_guards: Vec = Vec::new(); + for method_ext in methods { + let method_type = &method_ext.method; + let custom_method = &method_ext.custom_method; + match custom_method { + Some(lit) => { + mult_method_guards.push(quote! { + .or(::actix_web::guard::#method_type(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) + }); + } + None => { + mult_method_guards.push(quote! { + .or(::actix_web::guard::#method_type()) + }); + } + } + } + match &first.custom_method { + Some(lit) => { + quote! { + .guard( + ::actix_web::guard::Any(::actix_web::guard::#first_method(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) + #(#mult_method_guards)* + ) + } + } + None => { + quote! { + .guard( + ::actix_web::guard::Any(::actix_web::guard::#first_method()) + #(#mult_method_guards)* + ) + } + } + } + } else { + match &first.custom_method { + Some(lit) => { + quote! { + .guard(::actix_web::guard::#first_method(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) + } + } + None => { + quote! { + .guard(::actix_web::guard::#first_method()) + } + } + } } + }; + quote! { + let __resource = ::actix_web::Resource::new(#path) + .name(#resource_name) + #method_guards + #(.guard(::actix_web::guard::fn_guard(#guards)))* + #(.wrap(#wrappers))* + .to(#name); + ::actix_web::dev::HttpServiceFactory::register(__resource, __config); } - }; - - quote! { - let __resource = ::actix_web::Resource::new(#path) - .name(#resource_name) - #method_guards - #(.guard(::actix_web::guard::fn_guard(#guards)))* - #(.wrap(#wrappers))* - .to(#name); - - ::actix_web::dev::HttpServiceFactory::register(__resource, __config); - } - }) - .collect(); + }) + .collect(); let stream = quote! { #(#doc_attributes)* diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs index 10e906967..a95d2aa37 100644 --- a/actix-web-codegen/tests/test_macro.rs +++ b/actix-web-codegen/tests/test_macro.rs @@ -86,7 +86,13 @@ async fn get_param_test(_: web::Path) -> impl Responder { HttpResponse::Ok() } -#[route("/multi", method = "GET", method = "POST", method = "HEAD")] +#[route( + "/multi", + method = "GET", + method = "POST", + method = "HEAD", + method = "HELLO" +)] async fn route_test() -> impl Responder { HttpResponse::Ok() } diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 26aec7d28..8839dca3d 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -9,9 +9,11 @@ fn compile_macros() { t.pass("tests/trybuild/route-ok.rs"); t.compile_fail("tests/trybuild/route-missing-method-fail.rs"); t.compile_fail("tests/trybuild/route-duplicate-method-fail.rs"); - t.compile_fail("tests/trybuild/route-unexpected-method-fail.rs"); t.compile_fail("tests/trybuild/route-malformed-path-fail.rs"); + t.pass("tests/trybuild/route-custom-method.rs"); + t.compile_fail("tests/trybuild/route-custom-lowercase.rs"); + t.pass("tests/trybuild/routes-ok.rs"); t.compile_fail("tests/trybuild/routes-missing-method-fail.rs"); t.compile_fail("tests/trybuild/routes-missing-args-fail.rs"); diff --git a/actix-web-codegen/tests/trybuild/route-custom-lowercase.rs b/actix-web-codegen/tests/trybuild/route-custom-lowercase.rs new file mode 100644 index 000000000..61abb5bc2 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/route-custom-lowercase.rs @@ -0,0 +1,19 @@ +use actix_web_codegen::*; +use actix_web::http::Method; +use std::str::FromStr; + +#[route("/", method = "hello")] +async fn index() -> String { + "Hello World!".to_owned() +} + +#[actix_web::main] +async fn main() { + use actix_web::App; + + let srv = actix_test::start(|| App::new().service(index)); + + let request = srv.request(Method::from_str("hello").unwrap(), srv.url("/")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} diff --git a/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr new file mode 100644 index 000000000..243c4dd68 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr @@ -0,0 +1,19 @@ +error: HTTP method must be uppercase: `hello` + --> tests/trybuild/route-custom-lowercase.rs:5:23 + | +5 | #[route("/", method = "hello")] + | ^^^^^^^ + +error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied + --> tests/trybuild/route-custom-lowercase.rs:14:55 + | +14 | let srv = actix_test::start(|| App::new().service(index)); + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `App::::service` + --> $WORKSPACE/actix-web/src/app.rs + | + | F: HttpServiceFactory + 'static, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/route-unexpected-method-fail.rs b/actix-web-codegen/tests/trybuild/route-custom-method.rs similarity index 71% rename from actix-web-codegen/tests/trybuild/route-unexpected-method-fail.rs rename to actix-web-codegen/tests/trybuild/route-custom-method.rs index 1a50e01bc..6cc6af5a8 100644 --- a/actix-web-codegen/tests/trybuild/route-unexpected-method-fail.rs +++ b/actix-web-codegen/tests/trybuild/route-custom-method.rs @@ -1,4 +1,6 @@ use actix_web_codegen::*; +use actix_web::http::Method; +use std::str::FromStr; #[route("/", method="UNEXPECTED")] async fn index() -> String { @@ -11,7 +13,7 @@ async fn main() { let srv = actix_test::start(|| App::new().service(index)); - let request = srv.get("/"); + let request = srv.request(Method::from_str("UNEXPECTED").unwrap(), srv.url("/")); let response = request.send().await.unwrap(); assert!(response.status().is_success()); } diff --git a/actix-web-codegen/tests/trybuild/route-unexpected-method-fail.stderr b/actix-web-codegen/tests/trybuild/route-unexpected-method-fail.stderr deleted file mode 100644 index 3df5d9f5a..000000000 --- a/actix-web-codegen/tests/trybuild/route-unexpected-method-fail.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: Unexpected HTTP method: `UNEXPECTED` - --> tests/trybuild/route-unexpected-method-fail.rs:3:21 - | -3 | #[route("/", method="UNEXPECTED")] - | ^^^^^^^^^^^^ - -error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied - --> tests/trybuild/route-unexpected-method-fail.rs:12:55 - | -12 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` - | | - | required by a bound introduced by this call - | -note: required by a bound in `App::::service` - --> $WORKSPACE/actix-web/src/app.rs - | - | F: HttpServiceFactory + 'static, - | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index bf386acba..1e6a953f5 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,7 +2,6 @@ ## Unreleased - 2022-xx-xx - ## 4.3.0 - 2023-01-21 ### Added - Add `ContentDisposition::attachment()` constructor. [#2867] From 359d5d5c80dc893f4c75bf0bda20d332d3b306b9 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 6 Feb 2023 17:06:47 +0000 Subject: [PATCH 016/314] refactor codegen route guards --- actix-web-codegen/src/route.rs | 255 ++++++++++-------- actix-web-codegen/tests/test_macro.rs | 5 + .../tests/trybuild/route-custom-method.rs | 30 ++- 3 files changed, 168 insertions(+), 122 deletions(-) diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 594a58626..717ac844c 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -6,11 +6,11 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{parse_macro_input, AttributeArgs, Ident, LitStr, Meta, NestedMeta, Path}; -macro_rules! method_type { +macro_rules! standard_method_type { ( $($variant:ident, $upper:ident, $lower:ident,)+ ) => { - #[derive(Debug, PartialEq, Eq, Hash)] + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum MethodType { $( $variant, @@ -27,13 +27,7 @@ macro_rules! method_type { fn parse(method: &str) -> Result { match method { $(stringify!($upper) => Ok(Self::$variant),)+ - _ => { - if method.chars().all(|c| c.is_ascii_uppercase()) { - Ok(Self::Method) - } else { - Err(format!("HTTP method must be uppercase: `{}`", method)) - } - }, + _ => Err(format!("HTTP method must be uppercase: `{}`", method)), } } @@ -47,13 +41,7 @@ macro_rules! method_type { }; } -#[derive(Eq, Hash, PartialEq)] -struct MethodTypeExt { - method: MethodType, - custom_method: Option, -} - -method_type! { +standard_method_type! { Get, GET, get, Post, POST, post, Put, PUT, put, @@ -63,7 +51,15 @@ method_type! { Options, OPTIONS, options, Trace, TRACE, trace, Patch, PATCH, patch, - Method, METHOD, method, +} + +impl TryFrom<&syn::LitStr> for MethodType { + type Error = syn::Error; + + fn try_from(value: &syn::LitStr) -> Result { + Self::parse(value.value().as_str()) + .map_err(|message| syn::Error::new_spanned(value, message)) + } } impl ToTokens for MethodType { @@ -73,27 +69,107 @@ impl ToTokens for MethodType { } } -impl ToTokens for MethodTypeExt { - fn to_tokens(&self, stream: &mut TokenStream2) { - match self.method { - MethodType::Method => { - let ident = Ident::new( - self.custom_method.as_ref().unwrap().value().as_str(), - Span::call_site(), - ); - stream.append(ident); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +enum MethodTypeExt { + Standard(MethodType), + Custom(LitStr), +} + +impl MethodTypeExt { + /// Returns a single method guard token stream. + fn to_tokens_single_guard(&self) -> TokenStream2 { + match self { + MethodTypeExt::Standard(method) => { + quote! { + .guard(::actix_web::guard::#method()) + } + } + MethodTypeExt::Custom(lit) => { + quote! { + .guard(::actix_web::guard::Method( + ::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap() + )) + } + } + } + } + + /// Returns a multi-method guard chain token stream. + fn to_tokens_multi_guard(&self, or_chain: Vec) -> TokenStream2 { + debug_assert!( + or_chain.len() > 0, + "empty or_chain passed to multi-guard constructor" + ); + + match self { + MethodTypeExt::Standard(method) => { + quote! { + .guard( + ::actix_web::guard::Any(::actix_web::guard::#method()) + #(#or_chain)* + ) + } + } + MethodTypeExt::Custom(lit) => { + quote! { + .guard( + ::actix_web::guard::Any( + ::actix_web::guard::Method( + ::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap() + ) + ) + #(#or_chain)* + ) + } + } + } + } + + /// Returns a token stream containing the `.or` chain to be passed in to + /// [`MethodTypeExt::to_tokens_multi_guard()`]. + fn to_tokens_multi_guard_or_chain(&self) -> TokenStream2 { + match self { + MethodTypeExt::Standard(method_type) => { + quote! { + .or(::actix_web::guard::#method_type()) + } + } + MethodTypeExt::Custom(lit) => { + quote! { + .or( + ::actix_web::guard::Method( + ::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap() + ) + ) + } } - _ => self.method.to_tokens(stream), } } } -impl TryFrom<&syn::LitStr> for MethodType { +impl ToTokens for MethodTypeExt { + fn to_tokens(&self, stream: &mut TokenStream2) { + match self { + MethodTypeExt::Custom(lit_str) => { + let ident = Ident::new(lit_str.value().as_str(), Span::call_site()); + stream.append(ident); + } + MethodTypeExt::Standard(method) => method.to_tokens(stream), + } + } +} + +impl TryFrom<&syn::LitStr> for MethodTypeExt { type Error = syn::Error; fn try_from(value: &syn::LitStr) -> Result { - Self::parse(value.value().as_str()) - .map_err(|message| syn::Error::new_spanned(value, message)) + match MethodType::try_from(value) { + Ok(method) => Ok(MethodTypeExt::Standard(method)), + Err(_) if value.value().chars().all(|c| c.is_ascii_uppercase()) => { + Ok(MethodTypeExt::Custom(value.clone())) + } + Err(err) => Err(err), + } } } @@ -127,12 +203,7 @@ impl Args { let is_route_macro = method.is_none(); if let Some(method) = method { - methods.insert({ - MethodTypeExt { - method, - custom_method: None, - } - }); + methods.insert(MethodTypeExt::Standard(method)); } for arg in args { @@ -149,6 +220,7 @@ impl Args { )); } }, + NestedMeta::Meta(syn::Meta::NameValue(nv)) => { if nv.path.is_ident("name") { if let syn::Lit::Str(lit) = nv.lit { @@ -184,23 +256,10 @@ impl Args { "HTTP method forbidden here. To handle multiple methods, use `route` instead", )); } else if let syn::Lit::Str(ref lit) = nv.lit { - let method = MethodType::try_from(lit)?; - if !methods.insert({ - if method == MethodType::Method { - MethodTypeExt { - method, - custom_method: Some(lit.clone()), - } - } else { - MethodTypeExt { - method, - custom_method: None, - } - } - }) { + if !methods.insert(MethodTypeExt::try_from(lit)?) { return Err(syn::Error::new_spanned( &nv.lit, - &format!( + format!( "HTTP method defined more than once: `{}`", lit.value() ), @@ -219,11 +278,13 @@ impl Args { )); } } + arg => { return Err(syn::Error::new_spanned(arg, "Unknown attribute.")); } } } + Ok(Args { path: path.unwrap(), resource_name, @@ -343,72 +404,34 @@ impl ToTokens for Route { .as_ref() .map_or_else(|| name.to_string(), LitStr::value); - let method_guards = { - let mut others = methods.iter(); - let first = others.next().unwrap(); - let first_method = &first.method; - if methods.len() > 1 { - let mut mult_method_guards: Vec = Vec::new(); - for method_ext in methods { - let method_type = &method_ext.method; - let custom_method = &method_ext.custom_method; - match custom_method { - Some(lit) => { - mult_method_guards.push(quote! { - .or(::actix_web::guard::#method_type(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) - }); - } - None => { - mult_method_guards.push(quote! { - .or(::actix_web::guard::#method_type()) - }); - } - } - } - match &first.custom_method { - Some(lit) => { - quote! { - .guard( - ::actix_web::guard::Any(::actix_web::guard::#first_method(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) - #(#mult_method_guards)* - ) - } - } - None => { - quote! { - .guard( - ::actix_web::guard::Any(::actix_web::guard::#first_method()) - #(#mult_method_guards)* - ) - } - } - } - } else { - match &first.custom_method { - Some(lit) => { - quote! { - .guard(::actix_web::guard::#first_method(::actix_web::http::Method::from_bytes(#lit.as_bytes()).unwrap())) - } - } - None => { - quote! { - .guard(::actix_web::guard::#first_method()) - } - } - } - } - }; - quote! { - let __resource = ::actix_web::Resource::new(#path) - .name(#resource_name) - #method_guards - #(.guard(::actix_web::guard::fn_guard(#guards)))* - #(.wrap(#wrappers))* - .to(#name); - ::actix_web::dev::HttpServiceFactory::register(__resource, __config); + let method_guards = { + debug_assert!(methods.len() > 0, "Args::methods should not be empty"); + + let mut others = methods.iter(); + let first = others.next().unwrap(); + + if methods.len() > 1 { + let other_method_guards = others + .map(|method_ext| method_ext.to_tokens_multi_guard_or_chain()) + .collect(); + + first.to_tokens_multi_guard(other_method_guards) + } else { + first.to_tokens_single_guard() } - }) - .collect(); + }; + + quote! { + let __resource = ::actix_web::Resource::new(#path) + .name(#resource_name) + #method_guards + #(.guard(::actix_web::guard::fn_guard(#guards)))* + #(.wrap(#wrappers))* + .to(#name); + ::actix_web::dev::HttpServiceFactory::register(__resource, __config); + } + }) + .collect(); let stream = quote! { #(#doc_attributes)* diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs index a95d2aa37..f28654cd9 100644 --- a/actix-web-codegen/tests/test_macro.rs +++ b/actix-web-codegen/tests/test_macro.rs @@ -86,6 +86,11 @@ async fn get_param_test(_: web::Path) -> impl Responder { HttpResponse::Ok() } +#[route("/hello", method = "HELLO")] +async fn custom_route_test() -> impl Responder { + HttpResponse::Ok() +} + #[route( "/multi", method = "GET", diff --git a/actix-web-codegen/tests/trybuild/route-custom-method.rs b/actix-web-codegen/tests/trybuild/route-custom-method.rs index 6cc6af5a8..525a60b83 100644 --- a/actix-web-codegen/tests/trybuild/route-custom-method.rs +++ b/actix-web-codegen/tests/trybuild/route-custom-method.rs @@ -1,19 +1,37 @@ -use actix_web_codegen::*; -use actix_web::http::Method; use std::str::FromStr; -#[route("/", method="UNEXPECTED")] +use actix_web::http::Method; +use actix_web_codegen::route; + +#[route("/single", method = "CUSTOM")] async fn index() -> String { - "Hello World!".to_owned() + "Hello Single!".to_owned() +} + +#[route("/multi", method = "GET", method = "CUSTOM")] +async fn custom() -> String { + "Hello Multi!".to_owned() } #[actix_web::main] async fn main() { use actix_web::App; - let srv = actix_test::start(|| App::new().service(index)); + let srv = actix_test::start(|| App::new().service(index).service(custom)); - let request = srv.request(Method::from_str("UNEXPECTED").unwrap(), srv.url("/")); + let request = srv.request(Method::GET, srv.url("/")); + let response = request.send().await.unwrap(); + assert!(response.status().is_client_error()); + + let request = srv.request(Method::from_str("CUSTOM").unwrap(), srv.url("/single")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(Method::GET, srv.url("/multi")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(Method::from_str("CUSTOM").unwrap(), srv.url("/multi")); let response = request.send().await.unwrap(); assert!(response.status().is_success()); } From bf1f169be2b81f4fd5b2dc547e6ab68b363c544a Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Thu, 9 Feb 2023 10:32:04 +0100 Subject: [PATCH 017/314] [awc] change `client::Connect` to be public (#2690) --- awc/CHANGES.md | 4 +++- awc/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index e8770723b..6d313ea2f 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,8 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx +### Changed +- `client::Connect` is now public to allow tunneling connection with `client::Connector`. ## 3.1.0 - 2023-01-21 diff --git a/awc/src/lib.rs b/awc/src/lib.rs index bb7f06c93..42f029669 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -139,7 +139,7 @@ pub mod http { } pub use self::builder::ClientBuilder; -pub use self::client::{Client, Connector}; +pub use self::client::{Client, Connect, Connector}; pub use self::connect::{BoxConnectorService, BoxedSocket, ConnectRequest, ConnectResponse}; pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder}; pub use self::request::ClientRequest; From bf19a0e761f0ab1274bff1be956c1eaa82f057a7 Mon Sep 17 00:00:00 2001 From: yinho999 Date: Thu, 9 Feb 2023 12:37:01 -0800 Subject: [PATCH 018/314] added body manipulation example for error handlers (#2973) Closes https://github.com/actix/actix-web/issues/2856 --- actix-web/src/middleware/err_handlers.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index 4ddbc6318..00fb5cf59 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -50,6 +50,8 @@ type DefaultHandler = Option>>; /// will pass by unchanged by this middleware. /// /// # Examples +/// ## Handler Response +/// Header /// ``` /// use actix_web::http::{header, StatusCode}; /// use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; @@ -67,6 +69,28 @@ type DefaultHandler = Option>>; /// .wrap(ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, add_error_header)) /// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError))); /// ``` +/// +/// Body Content +/// ``` +/// use actix_web::http::{header, StatusCode}; +/// use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; +/// use actix_web::{dev, web, App, HttpResponse, Result}; +/// fn add_error_body(res: dev::ServiceResponse) -> Result> { +/// // Get the error message and status code +/// let error_message = "An error occurred"; +/// // Destructures ServiceResponse into request and response components +/// let (req, res) = res.into_parts(); +/// // Create a new response with the modified body +/// let res = res.set_body(error_message).map_into_boxed_body(); +/// // Create a new ServiceResponse with the modified response +/// let res = dev::ServiceResponse::new(req, res).map_into_right_body(); +/// Ok(ErrorHandlerResponse::Response(res)) +///} +/// +/// let app = App::new() +/// .wrap(ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, add_error_body)) +/// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError))); +/// ``` /// ## Registering default handler /// ``` /// # use actix_web::http::{header, StatusCode}; From 85d88ffadab590a8f0e66336b45c3f7e7d020972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roy=20Wellington=20=E2=85=A3?= Date: Sat, 11 Feb 2023 21:47:42 -0500 Subject: [PATCH 019/314] Fix minor typo in Markdown (#2977) --- actix-web/src/response/responder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/src/response/responder.rs b/actix-web/src/response/responder.rs index da8091981..965163a1f 100644 --- a/actix-web/src/response/responder.rs +++ b/actix-web/src/response/responder.rs @@ -21,7 +21,7 @@ use crate::{Error, HttpRequest, HttpResponse}; /// - `HttpResponse` and `HttpResponseBuilder` /// - `Option` where `R: Responder` /// - `Result` where `R: Responder` and [`E: ResponseError`](crate::ResponseError) -/// - `(R, StatusCode) where `R: Responder` +/// - `(R, StatusCode)` where `R: Responder` /// - `&'static str`, `String`, `&'_ String`, `Cow<'_, str>`, [`ByteString`](bytestring::ByteString) /// - `&'static [u8]`, `Vec`, `Bytes`, `BytesMut` /// - [`Json`](crate::web::Json) and [`Form`](crate::web::Form) where `T: Serialize` From dc08ea044b75a3f21fac632c9ab364cebe1ad61c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Feb 2023 21:09:20 +0000 Subject: [PATCH 020/314] clippy --- actix-web-codegen/src/route.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 717ac844c..0772dbd94 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -97,7 +97,7 @@ impl MethodTypeExt { /// Returns a multi-method guard chain token stream. fn to_tokens_multi_guard(&self, or_chain: Vec) -> TokenStream2 { debug_assert!( - or_chain.len() > 0, + !or_chain.is_empty(), "empty or_chain passed to multi-guard constructor" ); @@ -405,7 +405,7 @@ impl ToTokens for Route { .map_or_else(|| name.to_string(), LitStr::value); let method_guards = { - debug_assert!(methods.len() > 0, "Args::methods should not be empty"); + debug_assert!(!methods.is_empty(), "Args::methods should not be empty"); let mut others = methods.iter(); let first = others.next().unwrap(); From 42193bee295ce131f18fbc0d49b7206214717330 Mon Sep 17 00:00:00 2001 From: Lioness100 Date: Mon, 20 Feb 2023 03:11:16 -0500 Subject: [PATCH 021/314] fix typos (#2982) --- actix-files/src/path_buf.rs | 2 +- actix-http/CHANGES.md | 2 +- actix-web/MIGRATION-2.0.md | 2 +- actix-web/src/test/test_utils.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/actix-files/src/path_buf.rs b/actix-files/src/path_buf.rs index 9ee1338c6..650f55247 100644 --- a/actix-files/src/path_buf.rs +++ b/actix-files/src/path_buf.rs @@ -30,7 +30,7 @@ impl PathBufWrap { let mut segment_count = path.matches('/').count() + 1; // we can decode the whole path here (instead of per-segment decoding) - // because we will reject `%2F` in paths using `segement_count`. + // because we will reject `%2F` in paths using `segment_count`. let path = percent_encoding::percent_decode_str(path) .decode_utf8() .map_err(|_| UriSegmentError::NotValidUtf8)?; diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 4cc467ddc..6a45e79dd 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -681,7 +681,7 @@ - Reduce the level from `error` to `debug` for the log line that is emitted when a `500 Internal Server Error` is built using `HttpResponse::from_error`. [#2201] - `ResponseBuilder::message_body` now returns a `Result`. [#2201] - Remove `Unpin` bound on `ResponseBuilder::streaming`. [#2253] -- `HttpServer::{listen_rustls(), bind_rustls()}` now honor the ALPN protocols in the configuation parameter. [#2226] +- `HttpServer::{listen_rustls(), bind_rustls()}` now honor the ALPN protocols in the configuration parameter. [#2226] ### Removed - Stop re-exporting `http` crate's `HeaderMap` types in addition to ours. [#2171] diff --git a/actix-web/MIGRATION-2.0.md b/actix-web/MIGRATION-2.0.md index 0455062d1..3af5f6e1a 100644 --- a/actix-web/MIGRATION-2.0.md +++ b/actix-web/MIGRATION-2.0.md @@ -14,7 +14,7 @@ - `actix_http_test::TestServer` moved to `actix_web::test` module. To start test server use `test::start()` or `test_start_with_config()` methods -- `ResponseError` trait has been reafctored. `ResponseError::error_response()` renders +- `ResponseError` trait has been refactored. `ResponseError::error_response()` renders http response. - Feature `rust-tls` renamed to `rustls` diff --git a/actix-web/src/test/test_utils.rs b/actix-web/src/test/test_utils.rs index 398b29605..b985c3b36 100644 --- a/actix-web/src/test/test_utils.rs +++ b/actix-web/src/test/test_utils.rs @@ -268,7 +268,7 @@ where }) } -/// Fallible version of [`read_body_json`] that allows testing response deserialzation errors. +/// Fallible version of [`read_body_json`] that allows testing response deserialization errors. pub async fn try_read_body_json(res: ServiceResponse) -> Result> where B: MessageBody, From 358c1cf85baa06b1c7b75795e6de06599b84f52b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 22 Feb 2023 23:06:18 +0000 Subject: [PATCH 022/314] improve docs for app_config methods --- actix-web/src/app_service.rs | 8 ++++++-- actix-web/src/config.rs | 2 +- actix-web/src/request.rs | 2 +- actix-web/src/service.rs | 9 +++------ 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/actix-web/src/app_service.rs b/actix-web/src/app_service.rs index 0b5ba2ab6..0fc856203 100644 --- a/actix-web/src/app_service.rs +++ b/actix-web/src/app_service.rs @@ -21,7 +21,7 @@ use crate::{ Error, HttpResponse, }; -/// Service factory to convert `Request` to a `ServiceRequest`. +/// Service factory to convert [`Request`] to a [`ServiceRequest`]. /// /// It also executes data factories. pub struct AppInit @@ -155,7 +155,7 @@ where app_state: Rc, } -/// A collection of [`AppInitService`] state that shared across `HttpRequest`s. +/// A collection of state for [`AppInitService`] that is shared across [`HttpRequest`]s. pub(crate) struct AppInitServiceState { rmap: Rc, config: AppConfig, @@ -163,6 +163,7 @@ pub(crate) struct AppInitServiceState { } impl AppInitServiceState { + /// Constructs state collection from resource map and app config. pub(crate) fn new(rmap: Rc, config: AppConfig) -> Rc { Rc::new(AppInitServiceState { rmap, @@ -171,16 +172,19 @@ impl AppInitServiceState { }) } + /// Returns a reference to the application's resource map. #[inline] pub(crate) fn rmap(&self) -> &ResourceMap { &self.rmap } + /// Returns a reference to the application's configuration. #[inline] pub(crate) fn config(&self) -> &AppConfig { &self.config } + /// Returns a reference to the application's request pool. #[inline] pub(crate) fn pool(&self) -> &HttpRequestPool { &self.pool diff --git a/actix-web/src/config.rs b/actix-web/src/config.rs index 68bea34ca..11eaf8720 100644 --- a/actix-web/src/config.rs +++ b/actix-web/src/config.rs @@ -141,7 +141,7 @@ impl AppConfig { self.secure } - /// Returns the socket address of the local half of this TCP connection + /// Returns the socket address of the local half of this TCP connection. pub fn local_addr(&self) -> SocketAddr { self.addr } diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index 6a32bf838..a99dcaa3e 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -260,7 +260,7 @@ impl HttpRequest { Ref::map(self.extensions(), |data| data.get().unwrap()) } - /// App config + /// Returns a reference to the application's connection configuration. #[inline] pub fn app_config(&self) -> &AppConfig { self.app_state().config() diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index ea23f09f5..f7692ce16 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -238,11 +238,7 @@ impl ServiceRequest { self.req.connection_info() } - /// Returns reference to the Path parameters. - /// - /// Params is a container for URL parameters. A variable segment is specified in the form - /// `{identifier}`, where the identifier can be used later in a request handler to access the - /// matched value for that segment. + /// Counterpart to [`HttpRequest::match_info`]. #[inline] pub fn match_info(&self) -> &Path { self.req.match_info() @@ -267,12 +263,13 @@ impl ServiceRequest { } /// Returns a reference to the application's resource map. + /// Counterpart to [`HttpRequest::resource_map`]. #[inline] pub fn resource_map(&self) -> &ResourceMap { self.req.resource_map() } - /// Returns a reference to the application's configuration. + /// Counterpart to [`HttpRequest::app_config`]. #[inline] pub fn app_config(&self) -> &AppConfig { self.req.app_config() From d4b833ccf0dd16ca2623e3822062ac5579c36dd5 Mon Sep 17 00:00:00 2001 From: Jacob Halsey Date: Sun, 26 Feb 2023 03:26:06 +0000 Subject: [PATCH 023/314] actix-multipart: Feature: Add typed multipart form extractor (#2883) Co-authored-by: Rob Ede --- Cargo.toml | 2 + actix-multipart-derive/Cargo.toml | 26 + actix-multipart-derive/LICENSE-APACHE | 1 + actix-multipart-derive/LICENSE-MIT | 1 + actix-multipart-derive/README.md | 3 + actix-multipart-derive/src/lib.rs | 315 ++++++++ actix-multipart-derive/tests/trybuild.rs | 16 + .../tests/trybuild/all-required.rs | 19 + .../tests/trybuild/deny-duplicates.rs | 16 + .../tests/trybuild/deny-parse-fail.rs | 7 + .../tests/trybuild/deny-parse-fail.stderr | 5 + .../tests/trybuild/deny-unknown.rs | 16 + .../tests/trybuild/optional-and-list.rs | 18 + .../tests/trybuild/rename.rs | 18 + .../tests/trybuild/size-limit-parse-fail.rs | 21 + .../trybuild/size-limit-parse-fail.stderr | 17 + .../tests/trybuild/size-limits.rs | 21 + actix-multipart/CHANGES.md | 5 +- actix-multipart/Cargo.toml | 29 +- actix-multipart/src/error.rs | 44 +- actix-multipart/src/extractor.rs | 3 +- actix-multipart/src/form/bytes.rs | 53 ++ actix-multipart/src/form/json.rs | 195 +++++ actix-multipart/src/form/mod.rs | 744 ++++++++++++++++++ actix-multipart/src/form/tempfile.rs | 206 +++++ actix-multipart/src/form/text.rs | 196 +++++ actix-multipart/src/lib.rs | 7 + actix-multipart/src/server.rs | 41 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- 30 files changed, 2017 insertions(+), 32 deletions(-) create mode 100644 actix-multipart-derive/Cargo.toml create mode 120000 actix-multipart-derive/LICENSE-APACHE create mode 120000 actix-multipart-derive/LICENSE-MIT create mode 100644 actix-multipart-derive/README.md create mode 100644 actix-multipart-derive/src/lib.rs create mode 100644 actix-multipart-derive/tests/trybuild.rs create mode 100644 actix-multipart-derive/tests/trybuild/all-required.rs create mode 100644 actix-multipart-derive/tests/trybuild/deny-duplicates.rs create mode 100644 actix-multipart-derive/tests/trybuild/deny-parse-fail.rs create mode 100644 actix-multipart-derive/tests/trybuild/deny-parse-fail.stderr create mode 100644 actix-multipart-derive/tests/trybuild/deny-unknown.rs create mode 100644 actix-multipart-derive/tests/trybuild/optional-and-list.rs create mode 100644 actix-multipart-derive/tests/trybuild/rename.rs create mode 100644 actix-multipart-derive/tests/trybuild/size-limit-parse-fail.rs create mode 100644 actix-multipart-derive/tests/trybuild/size-limit-parse-fail.stderr create mode 100644 actix-multipart-derive/tests/trybuild/size-limits.rs create mode 100644 actix-multipart/src/form/bytes.rs create mode 100644 actix-multipart/src/form/json.rs create mode 100644 actix-multipart/src/form/mod.rs create mode 100644 actix-multipart/src/form/tempfile.rs create mode 100644 actix-multipart/src/form/text.rs diff --git a/Cargo.toml b/Cargo.toml index 26b5b91b2..65e3c6ae8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "actix-http-test", "actix-http", "actix-multipart", + "actix-multipart-derive", "actix-router", "actix-test", "actix-web-actors", @@ -27,6 +28,7 @@ actix-files = { path = "actix-files" } actix-http = { path = "actix-http" } actix-http-test = { path = "actix-http-test" } actix-multipart = { path = "actix-multipart" } +actix-multipart-derive = { path = "actix-multipart-derive" } actix-router = { path = "actix-router" } actix-test = { path = "actix-test" } actix-web = { path = "actix-web" } diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml new file mode 100644 index 000000000..4a30898b4 --- /dev/null +++ b/actix-multipart-derive/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "actix-multipart-derive" +version = "0.5.0" +authors = ["Jacob Halsey "] +description = "Multipart form derive macro for Actix Web" +keywords = ["http", "web", "framework", "async", "futures"] +homepage = "https://actix.rs" +repository = "https://github.com/actix/actix-web.git" +license = "MIT OR Apache-2.0" +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +darling = "0.14" +parse-size = "1" +proc-macro2 = "1" +quote = "1" +syn = "1" + +[dev-dependencies] +actix-multipart = "0.5" +actix-web = "4" +rustversion = "1" +trybuild = "1" diff --git a/actix-multipart-derive/LICENSE-APACHE b/actix-multipart-derive/LICENSE-APACHE new file mode 120000 index 000000000..965b606f3 --- /dev/null +++ b/actix-multipart-derive/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/actix-multipart-derive/LICENSE-MIT b/actix-multipart-derive/LICENSE-MIT new file mode 120000 index 000000000..76219eb72 --- /dev/null +++ b/actix-multipart-derive/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md new file mode 100644 index 000000000..95f80bc79 --- /dev/null +++ b/actix-multipart-derive/README.md @@ -0,0 +1,3 @@ +# actix-multipart-derive + +> The derive macro implementation for actix-multipart. diff --git a/actix-multipart-derive/src/lib.rs b/actix-multipart-derive/src/lib.rs new file mode 100644 index 000000000..9b6ecbae6 --- /dev/null +++ b/actix-multipart-derive/src/lib.rs @@ -0,0 +1,315 @@ +//! Multipart form derive macro for Actix Web. +//! +//! See [`macro@MultipartForm`] for usage examples. + +#![deny(rust_2018_idioms, nonstandard_style)] +#![warn(future_incompatible)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_cfg))] + +use std::{collections::HashSet, convert::TryFrom as _}; + +use darling::{FromDeriveInput, FromField, FromMeta}; +use parse_size::parse_size; +use proc_macro::TokenStream; +use proc_macro2::Ident; +use quote::quote; +use syn::{parse_macro_input, Type}; + +#[derive(FromMeta)] +enum DuplicateField { + Ignore, + Deny, + Replace, +} + +impl Default for DuplicateField { + fn default() -> Self { + Self::Ignore + } +} + +#[derive(FromDeriveInput, Default)] +#[darling(attributes(multipart), default)] +struct MultipartFormAttrs { + deny_unknown_fields: bool, + duplicate_field: DuplicateField, +} + +#[derive(FromField, Default)] +#[darling(attributes(multipart), default)] +struct FieldAttrs { + rename: Option, + limit: Option, +} + +struct ParsedField<'t> { + serialization_name: String, + rust_name: &'t Ident, + limit: Option, + ty: &'t Type, +} + +/// Implements `MultipartCollect` for a struct so that it can be used with the `MultipartForm` +/// extractor. +/// +/// # Basic Use +/// +/// Each field type should implement the `FieldReader` trait: +/// +/// ``` +/// use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; +/// +/// #[derive(MultipartForm)] +/// struct ImageUpload { +/// description: Text, +/// timestamp: Text, +/// image: TempFile, +/// } +/// ``` +/// +/// # Optional and List Fields +/// +/// You can also use `Vec` and `Option` provided that `T: FieldReader`. +/// +/// A [`Vec`] field corresponds to an upload with multiple parts under the [same field +/// name](https://www.rfc-editor.org/rfc/rfc7578#section-4.3). +/// +/// ``` +/// use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; +/// +/// #[derive(MultipartForm)] +/// struct Form { +/// category: Option>, +/// files: Vec, +/// } +/// ``` +/// +/// # Field Renaming +/// +/// You can use the `#[multipart(rename = "foo")]` attribute to receive a field by a different name. +/// +/// ``` +/// use actix_multipart::form::{tempfile::TempFile, MultipartForm}; +/// +/// #[derive(MultipartForm)] +/// struct Form { +/// #[multipart(rename = "files[]")] +/// files: Vec, +/// } +/// ``` +/// +/// # Field Limits +/// +/// You can use the `#[multipart(limit = "")]` attribute to set field level limits. The limit +/// string is parsed using [parse_size]. +/// +/// Note: the form is also subject to the global limits configured using `MultipartFormConfig`. +/// +/// ``` +/// use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; +/// +/// #[derive(MultipartForm)] +/// struct Form { +/// #[multipart(limit = "2 KiB")] +/// description: Text, +/// +/// #[multipart(limit = "512 MiB")] +/// files: Vec, +/// } +/// ``` +/// +/// # Unknown Fields +/// +/// By default fields with an unknown name are ignored. They can be rejected using the +/// `#[multipart(deny_unknown_fields)]` attribute: +/// +/// ``` +/// # use actix_multipart::form::MultipartForm; +/// #[derive(MultipartForm)] +/// #[multipart(deny_unknown_fields)] +/// struct Form { } +/// ``` +/// +/// # Duplicate Fields +/// +/// The behaviour for when multiple fields with the same name are received can be changed using the +/// `#[multipart(duplicate_field = "")]` attribute: +/// +/// - "ignore": (default) Extra fields are ignored. I.e., the first one is persisted. +/// - "deny": A `MultipartError::UnsupportedField` error response is returned. +/// - "replace": Each field is processed, but only the last one is persisted. +/// +/// Note that `Vec` fields will ignore this option. +/// +/// ``` +/// # use actix_multipart::form::MultipartForm; +/// #[derive(MultipartForm)] +/// #[multipart(duplicate_field = "deny")] +/// struct Form { } +/// ``` +/// +/// [parse_size]: https://docs.rs/parse-size/1/parse_size +#[proc_macro_derive(MultipartForm, attributes(multipart))] +pub fn impl_multipart_form(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let input: syn::DeriveInput = parse_macro_input!(input); + + let name = &input.ident; + + let data_struct = match &input.data { + syn::Data::Struct(data_struct) => data_struct, + _ => { + return compile_err(syn::Error::new( + input.ident.span(), + "`MultipartForm` can only be derived for structs", + )) + } + }; + + let fields = match &data_struct.fields { + syn::Fields::Named(fields_named) => fields_named, + _ => { + return compile_err(syn::Error::new( + input.ident.span(), + "`MultipartForm` can only be derived for a struct with named fields", + )) + } + }; + + let attrs = match MultipartFormAttrs::from_derive_input(&input) { + Ok(attrs) => attrs, + Err(err) => return err.write_errors().into(), + }; + + // Parse the field attributes + let parsed = match fields + .named + .iter() + .map(|field| { + let rust_name = field.ident.as_ref().unwrap(); + let attrs = FieldAttrs::from_field(field).map_err(|err| err.write_errors())?; + let serialization_name = attrs.rename.unwrap_or_else(|| rust_name.to_string()); + + let limit = match attrs.limit.map(|limit| match parse_size(&limit) { + Ok(size) => Ok(usize::try_from(size).unwrap()), + Err(err) => Err(syn::Error::new( + field.ident.as_ref().unwrap().span(), + format!("Could not parse size limit `{}`: {}", limit, err), + )), + }) { + Some(Err(err)) => return Err(compile_err(err)), + limit => limit.map(Result::unwrap), + }; + + Ok(ParsedField { + serialization_name, + rust_name, + limit, + ty: &field.ty, + }) + }) + .collect::, TokenStream>>() + { + Ok(attrs) => attrs, + Err(err) => return err, + }; + + // Check that field names are unique + let mut set = HashSet::new(); + for field in &parsed { + if !set.insert(field.serialization_name.clone()) { + return compile_err(syn::Error::new( + field.rust_name.span(), + format!("Multiple fields named: `{}`", field.serialization_name), + )); + } + } + + // Return value when a field name is not supported by the form + let unknown_field_result = if attrs.deny_unknown_fields { + quote!(::std::result::Result::Err( + ::actix_multipart::MultipartError::UnsupportedField(field.name().to_string()) + )) + } else { + quote!(::std::result::Result::Ok(())) + }; + + // Value for duplicate action + let duplicate_field = match attrs.duplicate_field { + DuplicateField::Ignore => quote!(::actix_multipart::form::DuplicateField::Ignore), + DuplicateField::Deny => quote!(::actix_multipart::form::DuplicateField::Deny), + DuplicateField::Replace => quote!(::actix_multipart::form::DuplicateField::Replace), + }; + + // limit() implementation + let mut limit_impl = quote!(); + for field in &parsed { + let name = &field.serialization_name; + if let Some(value) = field.limit { + limit_impl.extend(quote!( + #name => ::std::option::Option::Some(#value), + )); + } + } + + // handle_field() implementation + let mut handle_field_impl = quote!(); + for field in &parsed { + let name = &field.serialization_name; + let ty = &field.ty; + + handle_field_impl.extend(quote!( + #name => ::std::boxed::Box::pin( + <#ty as ::actix_multipart::form::FieldGroupReader>::handle_field(req, field, limits, state, #duplicate_field) + ), + )); + } + + // from_state() implementation + let mut from_state_impl = quote!(); + for field in &parsed { + let name = &field.serialization_name; + let rust_name = &field.rust_name; + let ty = &field.ty; + from_state_impl.extend(quote!( + #rust_name: <#ty as ::actix_multipart::form::FieldGroupReader>::from_state(#name, &mut state)?, + )); + } + + let gen = quote! { + impl ::actix_multipart::form::MultipartCollect for #name { + fn limit(field_name: &str) -> ::std::option::Option { + match field_name { + #limit_impl + _ => None, + } + } + + fn handle_field<'t>( + req: &'t ::actix_web::HttpRequest, + field: ::actix_multipart::Field, + limits: &'t mut ::actix_multipart::form::Limits, + state: &'t mut ::actix_multipart::form::State, + ) -> ::std::pin::Pin<::std::boxed::Box> + 't>> { + match field.name() { + #handle_field_impl + _ => return ::std::boxed::Box::pin(::std::future::ready(#unknown_field_result)), + } + } + + fn from_state(mut state: ::actix_multipart::form::State) -> ::std::result::Result { + Ok(Self { + #from_state_impl + }) + } + + } + }; + gen.into() +} + +/// Transform a syn error into a token stream for returning. +fn compile_err(err: syn::Error) -> TokenStream { + TokenStream::from(err.to_compile_error()) +} diff --git a/actix-multipart-derive/tests/trybuild.rs b/actix-multipart-derive/tests/trybuild.rs new file mode 100644 index 000000000..7b9f14ed7 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild.rs @@ -0,0 +1,16 @@ +#[rustversion::stable(1.59)] // MSRV +#[test] +fn compile_macros() { + let t = trybuild::TestCases::new(); + + t.pass("tests/trybuild/all-required.rs"); + t.pass("tests/trybuild/optional-and-list.rs"); + t.pass("tests/trybuild/rename.rs"); + t.pass("tests/trybuild/deny-unknown.rs"); + + t.pass("tests/trybuild/deny-duplicates.rs"); + t.compile_fail("tests/trybuild/deny-parse-fail.rs"); + + t.pass("tests/trybuild/size-limits.rs"); + t.compile_fail("tests/trybuild/size-limit-parse-fail.rs"); +} diff --git a/actix-multipart-derive/tests/trybuild/all-required.rs b/actix-multipart-derive/tests/trybuild/all-required.rs new file mode 100644 index 000000000..1b4a824d9 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/all-required.rs @@ -0,0 +1,19 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; + +#[derive(Debug, MultipartForm)] +struct ImageUpload { + description: Text, + timestamp: Text, + image: TempFile, +} + +async fn handler(_form: MultipartForm) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart-derive/tests/trybuild/deny-duplicates.rs b/actix-multipart-derive/tests/trybuild/deny-duplicates.rs new file mode 100644 index 000000000..9fcc1506c --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/deny-duplicates.rs @@ -0,0 +1,16 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::MultipartForm; + +#[derive(MultipartForm)] +#[multipart(duplicate_field = "deny")] +struct Form {} + +async fn handler(_form: MultipartForm

) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart-derive/tests/trybuild/deny-parse-fail.rs b/actix-multipart-derive/tests/trybuild/deny-parse-fail.rs new file mode 100644 index 000000000..5ea566fb0 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/deny-parse-fail.rs @@ -0,0 +1,7 @@ +use actix_multipart::form::MultipartForm; + +#[derive(MultipartForm)] +#[multipart(duplicate_field = "no")] +struct Form {} + +fn main() {} diff --git a/actix-multipart-derive/tests/trybuild/deny-parse-fail.stderr b/actix-multipart-derive/tests/trybuild/deny-parse-fail.stderr new file mode 100644 index 000000000..d25e43525 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/deny-parse-fail.stderr @@ -0,0 +1,5 @@ +error: Unknown literal value `no` + --> tests/trybuild/deny-parse-fail.rs:4:31 + | +4 | #[multipart(duplicate_field = "no")] + | ^^^^ diff --git a/actix-multipart-derive/tests/trybuild/deny-unknown.rs b/actix-multipart-derive/tests/trybuild/deny-unknown.rs new file mode 100644 index 000000000..e03460624 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/deny-unknown.rs @@ -0,0 +1,16 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::MultipartForm; + +#[derive(MultipartForm)] +#[multipart(deny_unknown_fields)] +struct Form {} + +async fn handler(_form: MultipartForm) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart-derive/tests/trybuild/optional-and-list.rs b/actix-multipart-derive/tests/trybuild/optional-and-list.rs new file mode 100644 index 000000000..deef3de59 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/optional-and-list.rs @@ -0,0 +1,18 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; + +#[derive(MultipartForm)] +struct Form { + category: Option>, + files: Vec, +} + +async fn handler(_form: MultipartForm) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart-derive/tests/trybuild/rename.rs b/actix-multipart-derive/tests/trybuild/rename.rs new file mode 100644 index 000000000..1f66bbb43 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/rename.rs @@ -0,0 +1,18 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::{tempfile::TempFile, MultipartForm}; + +#[derive(MultipartForm)] +struct Form { + #[multipart(rename = "files[]")] + files: Vec, +} + +async fn handler(_form: MultipartForm) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.rs b/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.rs new file mode 100644 index 000000000..c3d495317 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.rs @@ -0,0 +1,21 @@ +use actix_multipart::form::{text::Text, MultipartForm}; + +#[derive(MultipartForm)] +struct Form { + #[multipart(limit = "2 bytes")] + description: Text, +} + +#[derive(MultipartForm)] +struct Form2 { + #[multipart(limit = "2 megabytes")] + description: Text, +} + +#[derive(MultipartForm)] +struct Form3 { + #[multipart(limit = "four meters")] + description: Text, +} + +fn main() {} diff --git a/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.stderr b/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.stderr new file mode 100644 index 000000000..fc02a78c4 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/size-limit-parse-fail.stderr @@ -0,0 +1,17 @@ +error: Could not parse size limit `2 bytes`: invalid digit found in string + --> tests/trybuild/size-limit-parse-fail.rs:6:5 + | +6 | description: Text, + | ^^^^^^^^^^^ + +error: Could not parse size limit `2 megabytes`: invalid digit found in string + --> tests/trybuild/size-limit-parse-fail.rs:12:5 + | +12 | description: Text, + | ^^^^^^^^^^^ + +error: Could not parse size limit `four meters`: invalid digit found in string + --> tests/trybuild/size-limit-parse-fail.rs:18:5 + | +18 | description: Text, + | ^^^^^^^^^^^ diff --git a/actix-multipart-derive/tests/trybuild/size-limits.rs b/actix-multipart-derive/tests/trybuild/size-limits.rs new file mode 100644 index 000000000..92c3d0db5 --- /dev/null +++ b/actix-multipart-derive/tests/trybuild/size-limits.rs @@ -0,0 +1,21 @@ +use actix_web::{web, App, Responder}; + +use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; + +#[derive(MultipartForm)] +struct Form { + #[multipart(limit = "2 KiB")] + description: Text, + + #[multipart(limit = "512 MiB")] + files: Vec, +} + +async fn handler(_form: MultipartForm) -> impl Responder { + "Hello World!" +} + +#[actix_web::main] +async fn main() { + App::new().default_service(web::to(handler)); +} diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index ed117d7d3..53134db4f 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,11 +1,14 @@ # Changes ## Unreleased - 2022-xx-xx +- Added `MultipartForm` typed data extractor. [#2883] + +[#2883]: https://github.com/actix/actix-web/pull/2883 ## 0.5.0 - 2023-01-21 +- `Field::content_type()` now returns `Option<&mime::Mime>`. [#2885] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. -- `Field::content_type()` now returns `Option<&mime::Mime>` [#2885] [#2885]: https://github.com/actix/actix-web/pull/2885 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 8f768563c..2a14be007 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,7 +1,10 @@ [package] name = "actix-multipart" version = "0.5.0" -authors = ["Nikolay Kim "] +authors = [ + "Nikolay Kim ", + "Jacob Halsey ", +] description = "Multipart form support for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" @@ -9,26 +12,46 @@ repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" edition = "2018" +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] +all-features = true + +[features] +default = ["tempfile", "derive"] +derive = ["actix-multipart-derive"] +tempfile = ["tempfile-dep", "tokio/fs"] + [lib] name = "actix_multipart" path = "src/lib.rs" [dependencies] +actix-multipart-derive = { version = "=0.5.0", optional = true } actix-utils = "3" actix-web = { version = "4", default-features = false } bytes = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } +futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } httparse = "1.3" local-waker = "0.1" log = "0.4" -mime = "0.3" memchr = "2.5" +mime = "0.3" +serde = "1" +serde_json = "1" +serde_plain = "1" +# TODO(MSRV 1.60): replace with dep: prefix +tempfile-dep = { package = "tempfile", version = "3.4", optional = true } +tokio = { version = "1.18.5", features = ["sync"] } [dev-dependencies] -actix-rt = "2.2" actix-http = "3" +actix-multipart-rfc7578 = "0.10" +actix-rt = "2.2" +actix-test = "0.1" +awc = "3" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } tokio = { version = "1.18.5", features = ["sync"] } tokio-stream = "0.1" diff --git a/actix-multipart/src/error.rs b/actix-multipart/src/error.rs index 7d0da35e0..77b5a559f 100644 --- a/actix-multipart/src/error.rs +++ b/actix-multipart/src/error.rs @@ -1,12 +1,15 @@ //! Error and Result module -use actix_web::error::{ParseError, PayloadError}; -use actix_web::http::StatusCode; -use actix_web::ResponseError; + +use actix_web::{ + error::{ParseError, PayloadError}, + http::StatusCode, + ResponseError, +}; use derive_more::{Display, Error, From}; -/// A set of errors that can occur during parsing multipart streams -#[non_exhaustive] +/// A set of errors that can occur during parsing multipart streams. #[derive(Debug, Display, From, Error)] +#[non_exhaustive] pub enum MultipartError { /// Content-Disposition header is not found or is not equal to "form-data". /// @@ -46,12 +49,41 @@ pub enum MultipartError { /// Not consumed #[display(fmt = "Multipart stream is not consumed")] NotConsumed, + + /// An error from a field handler in a form + #[display( + fmt = "An error occurred processing field `{}`: {}", + field_name, + source + )] + Field { + field_name: String, + source: actix_web::Error, + }, + + /// Duplicate field + #[display(fmt = "Duplicate field found for: `{}`", _0)] + #[from(ignore)] + DuplicateField(#[error(not(source))] String), + + /// Missing field + #[display(fmt = "Field with name `{}` is required", _0)] + #[from(ignore)] + MissingField(#[error(not(source))] String), + + /// Unknown field + #[display(fmt = "Unsupported field `{}`", _0)] + #[from(ignore)] + UnsupportedField(#[error(not(source))] String), } /// Return `BadRequest` for `MultipartError` impl ResponseError for MultipartError { fn status_code(&self) -> StatusCode { - StatusCode::BAD_REQUEST + match &self { + MultipartError::Field { source, .. } => source.as_response_error().status_code(), + _ => StatusCode::BAD_REQUEST, + } } } diff --git a/actix-multipart/src/extractor.rs b/actix-multipart/src/extractor.rs index d45c4869c..56ed69ae4 100644 --- a/actix-multipart/src/extractor.rs +++ b/actix-multipart/src/extractor.rs @@ -9,8 +9,7 @@ use crate::server::Multipart; /// /// Content-type: multipart/form-data; /// -/// ## Server example -/// +/// # Examples /// ``` /// use actix_web::{web, HttpResponse, Error}; /// use actix_multipart::Multipart; diff --git a/actix-multipart/src/form/bytes.rs b/actix-multipart/src/form/bytes.rs new file mode 100644 index 000000000..7d64fffce --- /dev/null +++ b/actix-multipart/src/form/bytes.rs @@ -0,0 +1,53 @@ +//! Reads a field into memory. + +use actix_web::HttpRequest; +use bytes::BytesMut; +use futures_core::future::LocalBoxFuture; +use futures_util::TryStreamExt as _; +use mime::Mime; + +use crate::{ + form::{FieldReader, Limits}, + Field, MultipartError, +}; + +/// Read the field into memory. +#[derive(Debug)] +pub struct Bytes { + /// The data. + pub data: bytes::Bytes, + + /// The value of the `Content-Type` header. + pub content_type: Option, + + /// The `filename` value in the `Content-Disposition` header. + pub file_name: Option, +} + +impl<'t> FieldReader<'t> for Bytes { + type Future = LocalBoxFuture<'t, Result>; + + fn read_field( + _: &'t HttpRequest, + mut field: Field, + limits: &'t mut Limits, + ) -> Self::Future { + Box::pin(async move { + let mut buf = BytesMut::with_capacity(131_072); + + while let Some(chunk) = field.try_next().await? { + limits.try_consume_limits(chunk.len(), true)?; + buf.extend(chunk); + } + + Ok(Bytes { + data: buf.freeze(), + content_type: field.content_type().map(ToOwned::to_owned), + file_name: field + .content_disposition() + .get_filename() + .map(str::to_owned), + }) + }) + } +} diff --git a/actix-multipart/src/form/json.rs b/actix-multipart/src/form/json.rs new file mode 100644 index 000000000..9951eaaaf --- /dev/null +++ b/actix-multipart/src/form/json.rs @@ -0,0 +1,195 @@ +//! Deserializes a field as JSON. + +use std::sync::Arc; + +use actix_web::{http::StatusCode, web, Error, HttpRequest, ResponseError}; +use derive_more::{Deref, DerefMut, Display, Error}; +use futures_core::future::LocalBoxFuture; +use serde::de::DeserializeOwned; + +use crate::{ + form::{bytes::Bytes, FieldReader, Limits}, + Field, MultipartError, +}; + +use super::FieldErrorHandler; + +/// Deserialize from JSON. +#[derive(Debug, Deref, DerefMut)] +pub struct Json(pub T); + +impl Json { + pub fn into_inner(self) -> T { + self.0 + } +} + +impl<'t, T> FieldReader<'t> for Json +where + T: DeserializeOwned + 'static, +{ + type Future = LocalBoxFuture<'t, Result>; + + fn read_field(req: &'t HttpRequest, field: Field, limits: &'t mut Limits) -> Self::Future { + Box::pin(async move { + let config = JsonConfig::from_req(req); + let field_name = field.name().to_owned(); + + if config.validate_content_type { + let valid = if let Some(mime) = field.content_type() { + mime.subtype() == mime::JSON || mime.suffix() == Some(mime::JSON) + } else { + false + }; + + if !valid { + return Err(MultipartError::Field { + field_name, + source: config.map_error(req, JsonFieldError::ContentType), + }); + } + } + + let bytes = Bytes::read_field(req, field, limits).await?; + + Ok(Json(serde_json::from_slice(bytes.data.as_ref()).map_err( + |err| MultipartError::Field { + field_name, + source: config.map_error(req, JsonFieldError::Deserialize(err)), + }, + )?)) + }) + } +} + +#[derive(Debug, Display, Error)] +#[non_exhaustive] +pub enum JsonFieldError { + /// Deserialize error. + #[display(fmt = "Json deserialize error: {}", _0)] + Deserialize(serde_json::Error), + + /// Content type error. + #[display(fmt = "Content type error")] + ContentType, +} + +impl ResponseError for JsonFieldError { + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST + } +} + +/// Configuration for the [`Json`] field reader. +#[derive(Clone)] +pub struct JsonConfig { + err_handler: FieldErrorHandler, + validate_content_type: bool, +} + +const DEFAULT_CONFIG: JsonConfig = JsonConfig { + err_handler: None, + validate_content_type: true, +}; + +impl JsonConfig { + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(JsonFieldError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.err_handler = Some(Arc::new(f)); + self + } + + /// Extract payload config from app data. Check both `T` and `Data`, in that order, and fall + /// back to the default payload config. + fn from_req(req: &HttpRequest) -> &Self { + req.app_data::() + .or_else(|| req.app_data::>().map(|d| d.as_ref())) + .unwrap_or(&DEFAULT_CONFIG) + } + + fn map_error(&self, req: &HttpRequest, err: JsonFieldError) -> Error { + if let Some(err_handler) = self.err_handler.as_ref() { + (*err_handler)(err, req) + } else { + err.into() + } + } + + /// Sets whether or not the field must have a valid `Content-Type` header to be parsed. + pub fn validate_content_type(mut self, validate_content_type: bool) -> Self { + self.validate_content_type = validate_content_type; + self + } +} + +impl Default for JsonConfig { + fn default() -> Self { + DEFAULT_CONFIG + } +} + +#[cfg(test)] +mod tests { + use std::{collections::HashMap, io::Cursor}; + + use actix_multipart_rfc7578::client::multipart; + use actix_web::{http::StatusCode, web, App, HttpResponse, Responder}; + + use crate::form::{ + json::{Json, JsonConfig}, + tests::send_form, + MultipartForm, + }; + + #[derive(MultipartForm)] + struct JsonForm { + json: Json>, + } + + async fn test_json_route(form: MultipartForm) -> impl Responder { + let mut expected = HashMap::new(); + expected.insert("key1".to_owned(), "value1".to_owned()); + expected.insert("key2".to_owned(), "value2".to_owned()); + assert_eq!(&*form.json, &expected); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_json_without_content_type() { + let srv = actix_test::start(|| { + App::new() + .route("/", web::post().to(test_json_route)) + .app_data(JsonConfig::default().validate_content_type(false)) + }); + + let mut form = multipart::Form::default(); + form.add_text("json", "{\"key1\": \"value1\", \"key2\": \"value2\"}"); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } + + #[actix_rt::test] + async fn test_content_type_validation() { + let srv = actix_test::start(|| { + App::new() + .route("/", web::post().to(test_json_route)) + .app_data(JsonConfig::default().validate_content_type(true)) + }); + + // Deny because wrong content type + let bytes = Cursor::new("{\"key1\": \"value1\", \"key2\": \"value2\"}"); + let mut form = multipart::Form::default(); + form.add_reader_file_with_mime("json", bytes, "", mime::APPLICATION_OCTET_STREAM); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // Allow because correct content type + let bytes = Cursor::new("{\"key1\": \"value1\", \"key2\": \"value2\"}"); + let mut form = multipart::Form::default(); + form.add_reader_file_with_mime("json", bytes, "", mime::APPLICATION_JSON); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } +} diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs new file mode 100644 index 000000000..b0285d97e --- /dev/null +++ b/actix-multipart/src/form/mod.rs @@ -0,0 +1,744 @@ +//! Process and extract typed data from a multipart stream. + +use std::{ + any::Any, + collections::HashMap, + future::{ready, Future}, + sync::Arc, +}; + +use actix_web::{dev, error::PayloadError, web, Error, FromRequest, HttpRequest}; +use derive_more::{Deref, DerefMut}; +use futures_core::future::LocalBoxFuture; +use futures_util::{TryFutureExt as _, TryStreamExt as _}; + +use crate::{Field, Multipart, MultipartError}; + +pub mod bytes; +pub mod json; +#[cfg_attr(docsrs, doc(cfg(feature = "tempfile")))] +#[cfg(feature = "tempfile")] +pub mod tempfile; +pub mod text; + +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] +#[cfg(feature = "derive")] +pub use actix_multipart_derive::MultipartForm; + +type FieldErrorHandler = Option Error + Send + Sync>>; + +/// Trait that data types to be used in a multipart form struct should implement. +/// +/// It represents an asynchronous handler that processes a multipart field to produce `Self`. +pub trait FieldReader<'t>: Sized + Any { + /// Future that resolves to a `Self`. + type Future: Future>; + + /// The form will call this function to handle the field. + fn read_field(req: &'t HttpRequest, field: Field, limits: &'t mut Limits) -> Self::Future; +} + +/// Used to accumulate the state of the loaded fields. +#[doc(hidden)] +#[derive(Default, Deref, DerefMut)] +pub struct State(pub HashMap>); + +/// Trait that the field collection types implement, i.e. `Vec`, `Option`, or `T` itself. +#[doc(hidden)] +pub trait FieldGroupReader<'t>: Sized + Any { + type Future: Future>; + + /// The form will call this function for each matching field. + fn handle_field( + req: &'t HttpRequest, + field: Field, + limits: &'t mut Limits, + state: &'t mut State, + duplicate_field: DuplicateField, + ) -> Self::Future; + + /// Construct `Self` from the group of processed fields. + fn from_state(name: &str, state: &'t mut State) -> Result; +} + +impl<'t, T> FieldGroupReader<'t> for Option +where + T: FieldReader<'t>, +{ + type Future = LocalBoxFuture<'t, Result<(), MultipartError>>; + + fn handle_field( + req: &'t HttpRequest, + field: Field, + limits: &'t mut Limits, + state: &'t mut State, + duplicate_field: DuplicateField, + ) -> Self::Future { + if state.contains_key(field.name()) { + match duplicate_field { + DuplicateField::Ignore => return Box::pin(ready(Ok(()))), + + DuplicateField::Deny => { + return Box::pin(ready(Err(MultipartError::DuplicateField( + field.name().to_owned(), + )))) + } + + DuplicateField::Replace => {} + } + } + + Box::pin(async move { + let field_name = field.name().to_owned(); + let t = T::read_field(req, field, limits).await?; + state.insert(field_name, Box::new(t)); + Ok(()) + }) + } + + fn from_state(name: &str, state: &'t mut State) -> Result { + Ok(state.remove(name).map(|m| *m.downcast::().unwrap())) + } +} + +impl<'t, T> FieldGroupReader<'t> for Vec +where + T: FieldReader<'t>, +{ + type Future = LocalBoxFuture<'t, Result<(), MultipartError>>; + + fn handle_field( + req: &'t HttpRequest, + field: Field, + limits: &'t mut Limits, + state: &'t mut State, + _duplicate_field: DuplicateField, + ) -> Self::Future { + Box::pin(async move { + // Note: Vec GroupReader always allows duplicates + + let field_name = field.name().to_owned(); + + let vec = state + .entry(field_name) + .or_insert_with(|| Box::>::default()) + .downcast_mut::>() + .unwrap(); + + let item = T::read_field(req, field, limits).await?; + vec.push(item); + + Ok(()) + }) + } + + fn from_state(name: &str, state: &'t mut State) -> Result { + Ok(state + .remove(name) + .map(|m| *m.downcast::>().unwrap()) + .unwrap_or_default()) + } +} + +impl<'t, T> FieldGroupReader<'t> for T +where + T: FieldReader<'t>, +{ + type Future = LocalBoxFuture<'t, Result<(), MultipartError>>; + + fn handle_field( + req: &'t HttpRequest, + field: Field, + limits: &'t mut Limits, + state: &'t mut State, + duplicate_field: DuplicateField, + ) -> Self::Future { + if state.contains_key(field.name()) { + match duplicate_field { + DuplicateField::Ignore => return Box::pin(ready(Ok(()))), + + DuplicateField::Deny => { + return Box::pin(ready(Err(MultipartError::DuplicateField( + field.name().to_owned(), + )))) + } + + DuplicateField::Replace => {} + } + } + + Box::pin(async move { + let field_name = field.name().to_owned(); + let t = T::read_field(req, field, limits).await?; + state.insert(field_name, Box::new(t)); + Ok(()) + }) + } + + fn from_state(name: &str, state: &'t mut State) -> Result { + state + .remove(name) + .map(|m| *m.downcast::().unwrap()) + .ok_or_else(|| MultipartError::MissingField(name.to_owned())) + } +} + +/// Trait that allows a type to be used in the [`struct@MultipartForm`] extractor. +/// +/// You should use the [`macro@MultipartForm`] macro to derive this for your struct. +pub trait MultipartCollect: Sized { + /// An optional limit in bytes to be applied a given field name. Note this limit will be shared + /// across all fields sharing the same name. + fn limit(field_name: &str) -> Option; + + /// The extractor will call this function for each incoming field, the state can be updated + /// with the processed field data. + fn handle_field<'t>( + req: &'t HttpRequest, + field: Field, + limits: &'t mut Limits, + state: &'t mut State, + ) -> LocalBoxFuture<'t, Result<(), MultipartError>>; + + /// Once all the fields have been processed and stored in the state, this is called + /// to convert into the struct representation. + fn from_state(state: State) -> Result; +} + +#[doc(hidden)] +pub enum DuplicateField { + /// Additional fields are not processed. + Ignore, + + /// An error will be raised. + Deny, + + /// All fields will be processed, the last one will replace all previous. + Replace, +} + +/// Used to keep track of the remaining limits for the form and current field. +pub struct Limits { + pub total_limit_remaining: usize, + pub memory_limit_remaining: usize, + pub field_limit_remaining: Option, +} + +impl Limits { + pub fn new(total_limit: usize, memory_limit: usize) -> Self { + Self { + total_limit_remaining: total_limit, + memory_limit_remaining: memory_limit, + field_limit_remaining: None, + } + } + + /// This function should be called within a [`FieldReader`] when reading each chunk of a field + /// to ensure that the form limits are not exceeded. + /// + /// # Arguments + /// + /// * `bytes` - The number of bytes being read from this chunk + /// * `in_memory` - Whether to consume from the memory limits + pub fn try_consume_limits( + &mut self, + bytes: usize, + in_memory: bool, + ) -> Result<(), MultipartError> { + self.total_limit_remaining = self + .total_limit_remaining + .checked_sub(bytes) + .ok_or(MultipartError::Payload(PayloadError::Overflow))?; + + if in_memory { + self.memory_limit_remaining = self + .memory_limit_remaining + .checked_sub(bytes) + .ok_or(MultipartError::Payload(PayloadError::Overflow))?; + } + + if let Some(field_limit) = self.field_limit_remaining { + self.field_limit_remaining = Some( + field_limit + .checked_sub(bytes) + .ok_or(MultipartError::Payload(PayloadError::Overflow))?, + ); + } + + Ok(()) + } +} + +/// Typed `multipart/form-data` extractor. +/// +/// To extract typed data from a multipart stream, the inner type `T` must implement the +/// [`MultipartCollect`] trait. You should use the [`macro@MultipartForm`] macro to derive this +/// for your struct. +/// +/// Add a [`MultipartFormConfig`] to your app data to configure extraction. +#[derive(Deref, DerefMut)] +pub struct MultipartForm(pub T); + +impl MultipartForm { + /// Unwrap into inner `T` value. + pub fn into_inner(self) -> T { + self.0 + } +} + +impl FromRequest for MultipartForm +where + T: MultipartCollect, +{ + type Error = Error; + type Future = LocalBoxFuture<'static, Result>; + + #[inline] + fn from_request(req: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { + let mut payload = Multipart::new(req.headers(), payload.take()); + + let config = MultipartFormConfig::from_req(req); + let mut limits = Limits::new(config.total_limit, config.memory_limit); + + let req = req.clone(); + let req2 = req.clone(); + let err_handler = config.err_handler.clone(); + + Box::pin( + async move { + let mut state = State::default(); + // We need to ensure field limits are shared for all instances of this field name + let mut field_limits = HashMap::>::new(); + + while let Some(field) = payload.try_next().await? { + // Retrieve the limit for this field + let entry = field_limits + .entry(field.name().to_owned()) + .or_insert_with(|| T::limit(field.name())); + limits.field_limit_remaining = entry.to_owned(); + + T::handle_field(&req, field, &mut limits, &mut state).await?; + + // Update the stored limit + *entry = limits.field_limit_remaining; + } + let inner = T::from_state(state)?; + Ok(MultipartForm(inner)) + } + .map_err(move |err| { + if let Some(handler) = err_handler { + (*handler)(err, &req2) + } else { + err.into() + } + }), + ) + } +} + +type MultipartFormErrorHandler = + Option Error + Send + Sync>>; + +/// [`struct@MultipartForm`] extractor configuration. +/// +/// Add to your app data to have it picked up by [`struct@MultipartForm`] extractors. +#[derive(Clone)] +pub struct MultipartFormConfig { + total_limit: usize, + memory_limit: usize, + err_handler: MultipartFormErrorHandler, +} + +impl MultipartFormConfig { + /// Sets maximum accepted payload size for the entire form. By default this limit is 50MiB. + pub fn total_limit(mut self, total_limit: usize) -> Self { + self.total_limit = total_limit; + self + } + + /// Sets maximum accepted data that will be read into memory. By default this limit is 2MiB. + pub fn memory_limit(mut self, memory_limit: usize) -> Self { + self.memory_limit = memory_limit; + self + } + + /// Sets custom error handler. + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(MultipartError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.err_handler = Some(Arc::new(f)); + self + } + + /// Extracts payload config from app data. Check both `T` and `Data`, in that order, and fall + /// back to the default payload config. + fn from_req(req: &HttpRequest) -> &Self { + req.app_data::() + .or_else(|| req.app_data::>().map(|d| d.as_ref())) + .unwrap_or(&DEFAULT_CONFIG) + } +} + +const DEFAULT_CONFIG: MultipartFormConfig = MultipartFormConfig { + total_limit: 52_428_800, // 50 MiB + memory_limit: 2_097_152, // 2 MiB + err_handler: None, +}; + +impl Default for MultipartFormConfig { + fn default() -> Self { + DEFAULT_CONFIG + } +} + +#[cfg(test)] +mod tests { + use actix_http::encoding::Decoder; + use actix_multipart_rfc7578::client::multipart; + use actix_test::TestServer; + use actix_web::{dev::Payload, http::StatusCode, web, App, HttpResponse, Responder}; + use awc::{Client, ClientResponse}; + + use super::MultipartForm; + use crate::form::{bytes::Bytes, tempfile::TempFile, text::Text, MultipartFormConfig}; + + pub async fn send_form( + srv: &TestServer, + form: multipart::Form<'static>, + uri: &'static str, + ) -> ClientResponse> { + Client::default() + .post(srv.url(uri)) + .content_type(form.content_type()) + .send_body(multipart::Body::from(form)) + .await + .unwrap() + } + + /// Test `Option` fields. + #[derive(MultipartForm)] + struct TestOptions { + field1: Option>, + field2: Option>, + } + + async fn test_options_route(form: MultipartForm) -> impl Responder { + assert!(form.field1.is_some()); + assert!(form.field2.is_none()); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_options() { + let srv = + actix_test::start(|| App::new().route("/", web::post().to(test_options_route))); + + let mut form = multipart::Form::default(); + form.add_text("field1", "value"); + + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } + + /// Test `Vec` fields. + #[derive(MultipartForm)] + struct TestVec { + list1: Vec>, + list2: Vec>, + } + + async fn test_vec_route(form: MultipartForm) -> impl Responder { + let form = form.into_inner(); + let strings = form + .list1 + .into_iter() + .map(|s| s.into_inner()) + .collect::>(); + assert_eq!(strings, vec!["value1", "value2", "value3"]); + assert_eq!(form.list2.len(), 0); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_vec() { + let srv = actix_test::start(|| App::new().route("/", web::post().to(test_vec_route))); + + let mut form = multipart::Form::default(); + form.add_text("list1", "value1"); + form.add_text("list1", "value2"); + form.add_text("list1", "value3"); + + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } + + /// Test the `rename` field attribute. + #[derive(MultipartForm)] + struct TestFieldRenaming { + #[multipart(rename = "renamed")] + field1: Text, + #[multipart(rename = "field1")] + field2: Text, + field3: Text, + } + + async fn test_field_renaming_route( + form: MultipartForm, + ) -> impl Responder { + assert_eq!(&*form.field1, "renamed"); + assert_eq!(&*form.field2, "field1"); + assert_eq!(&*form.field3, "field3"); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_field_renaming() { + let srv = actix_test::start(|| { + App::new().route("/", web::post().to(test_field_renaming_route)) + }); + + let mut form = multipart::Form::default(); + form.add_text("renamed", "renamed"); + form.add_text("field1", "field1"); + form.add_text("field3", "field3"); + + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } + + /// Test the `deny_unknown_fields` struct attribute. + #[derive(MultipartForm)] + #[multipart(deny_unknown_fields)] + struct TestDenyUnknown {} + + #[derive(MultipartForm)] + struct TestAllowUnknown {} + + async fn test_deny_unknown_route(_: MultipartForm) -> impl Responder { + HttpResponse::Ok().finish() + } + + async fn test_allow_unknown_route(_: MultipartForm) -> impl Responder { + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_deny_unknown() { + let srv = actix_test::start(|| { + App::new() + .route("/deny", web::post().to(test_deny_unknown_route)) + .route("/allow", web::post().to(test_allow_unknown_route)) + }); + + let mut form = multipart::Form::default(); + form.add_text("unknown", "value"); + let response = send_form(&srv, form, "/deny").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + let mut form = multipart::Form::default(); + form.add_text("unknown", "value"); + let response = send_form(&srv, form, "/allow").await; + assert_eq!(response.status(), StatusCode::OK); + } + + /// Test the `duplicate_field` struct attribute. + #[derive(MultipartForm)] + #[multipart(duplicate_field = "deny")] + struct TestDuplicateDeny { + _field: Text, + } + + #[derive(MultipartForm)] + #[multipart(duplicate_field = "replace")] + struct TestDuplicateReplace { + field: Text, + } + + #[derive(MultipartForm)] + #[multipart(duplicate_field = "ignore")] + struct TestDuplicateIgnore { + field: Text, + } + + async fn test_duplicate_deny_route(_: MultipartForm) -> impl Responder { + HttpResponse::Ok().finish() + } + + async fn test_duplicate_replace_route( + form: MultipartForm, + ) -> impl Responder { + assert_eq!(&*form.field, "second_value"); + HttpResponse::Ok().finish() + } + + async fn test_duplicate_ignore_route( + form: MultipartForm, + ) -> impl Responder { + assert_eq!(&*form.field, "first_value"); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_duplicate_field() { + let srv = actix_test::start(|| { + App::new() + .route("/deny", web::post().to(test_duplicate_deny_route)) + .route("/replace", web::post().to(test_duplicate_replace_route)) + .route("/ignore", web::post().to(test_duplicate_ignore_route)) + }); + + let mut form = multipart::Form::default(); + form.add_text("_field", "first_value"); + form.add_text("_field", "second_value"); + let response = send_form(&srv, form, "/deny").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + let mut form = multipart::Form::default(); + form.add_text("field", "first_value"); + form.add_text("field", "second_value"); + let response = send_form(&srv, form, "/replace").await; + assert_eq!(response.status(), StatusCode::OK); + + let mut form = multipart::Form::default(); + form.add_text("field", "first_value"); + form.add_text("field", "second_value"); + let response = send_form(&srv, form, "/ignore").await; + assert_eq!(response.status(), StatusCode::OK); + } + + /// Test the Limits. + #[derive(MultipartForm)] + struct TestMemoryUploadLimits { + field: Bytes, + } + + #[derive(MultipartForm)] + struct TestFileUploadLimits { + field: TempFile, + } + + async fn test_upload_limits_memory( + form: MultipartForm, + ) -> impl Responder { + assert!(!form.field.data.is_empty()); + HttpResponse::Ok().finish() + } + + async fn test_upload_limits_file( + form: MultipartForm, + ) -> impl Responder { + assert!(form.field.size > 0); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_memory_limits() { + let srv = actix_test::start(|| { + App::new() + .route("/text", web::post().to(test_upload_limits_memory)) + .route("/file", web::post().to(test_upload_limits_file)) + .app_data( + MultipartFormConfig::default() + .memory_limit(20) + .total_limit(usize::MAX), + ) + }); + + // Exceeds the 20 byte memory limit + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/text").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // Memory limit should not apply when the data is being streamed to disk + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/file").await; + assert_eq!(response.status(), StatusCode::OK); + } + + #[actix_rt::test] + async fn test_total_limit() { + let srv = actix_test::start(|| { + App::new() + .route("/text", web::post().to(test_upload_limits_memory)) + .route("/file", web::post().to(test_upload_limits_file)) + .app_data( + MultipartFormConfig::default() + .memory_limit(usize::MAX) + .total_limit(20), + ) + }); + + // Within the 20 byte limit + let mut form = multipart::Form::default(); + form.add_text("field", "7 bytes"); + let response = send_form(&srv, form, "/text").await; + assert_eq!(response.status(), StatusCode::OK); + + // Exceeds the 20 byte overall limit + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/text").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // Exceeds the 20 byte overall limit + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/file").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + } + + #[derive(MultipartForm)] + struct TestFieldLevelLimits { + #[multipart(limit = "30B")] + field: Vec, + } + + async fn test_field_level_limits_route( + form: MultipartForm, + ) -> impl Responder { + assert!(!form.field.is_empty()); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_field_level_limits() { + let srv = actix_test::start(|| { + App::new() + .route("/", web::post().to(test_field_level_limits_route)) + .app_data( + MultipartFormConfig::default() + .memory_limit(usize::MAX) + .total_limit(usize::MAX), + ) + }); + + // Within the 30 byte limit + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + + // Exceeds the the 30 byte limit + let mut form = multipart::Form::default(); + form.add_text("field", "this string is more than 30 bytes long"); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // Total of values (14 bytes) is within 30 byte limit for "field" + let mut form = multipart::Form::default(); + form.add_text("field", "7 bytes"); + form.add_text("field", "7 bytes"); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + + // Total of values exceeds 30 byte limit for "field" + let mut form = multipart::Form::default(); + form.add_text("field", "this string is 28 bytes long"); + form.add_text("field", "this string is 28 bytes long"); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + } +} diff --git a/actix-multipart/src/form/tempfile.rs b/actix-multipart/src/form/tempfile.rs new file mode 100644 index 000000000..3c637e717 --- /dev/null +++ b/actix-multipart/src/form/tempfile.rs @@ -0,0 +1,206 @@ +//! Writes a field to a temporary file on disk. + +use std::{ + io, + path::{Path, PathBuf}, + sync::Arc, +}; + +use actix_web::{http::StatusCode, web, Error, HttpRequest, ResponseError}; +use derive_more::{Display, Error}; +use futures_core::future::LocalBoxFuture; +use futures_util::TryStreamExt as _; +use mime::Mime; +use tempfile_dep::NamedTempFile; +use tokio::io::AsyncWriteExt; + +use super::FieldErrorHandler; +use crate::{ + form::{FieldReader, Limits}, + Field, MultipartError, +}; + +/// Write the field to a temporary file on disk. +#[derive(Debug)] +pub struct TempFile { + /// The temporary file on disk. + pub file: NamedTempFile, + + /// The value of the `content-type` header. + pub content_type: Option, + + /// The `filename` value in the `content-disposition` header. + pub file_name: Option, + + /// The size in bytes of the file. + pub size: usize, +} + +impl<'t> FieldReader<'t> for TempFile { + type Future = LocalBoxFuture<'t, Result>; + + fn read_field( + req: &'t HttpRequest, + mut field: Field, + limits: &'t mut Limits, + ) -> Self::Future { + Box::pin(async move { + let config = TempFileConfig::from_req(req); + let field_name = field.name().to_owned(); + let mut size = 0; + + let file = config.create_tempfile().map_err(|err| { + config.map_error(req, &field_name, TempFileError::FileIo(err)) + })?; + + let mut file_async = tokio::fs::File::from_std(file.reopen().map_err(|err| { + config.map_error(req, &field_name, TempFileError::FileIo(err)) + })?); + + while let Some(chunk) = field.try_next().await? { + limits.try_consume_limits(chunk.len(), false)?; + size += chunk.len(); + file_async.write_all(chunk.as_ref()).await.map_err(|err| { + config.map_error(req, &field_name, TempFileError::FileIo(err)) + })?; + } + + file_async.flush().await.map_err(|err| { + config.map_error(req, &field_name, TempFileError::FileIo(err)) + })?; + + Ok(TempFile { + file, + content_type: field.content_type().map(ToOwned::to_owned), + file_name: field + .content_disposition() + .get_filename() + .map(str::to_owned), + size, + }) + }) + } +} + +#[derive(Debug, Display, Error)] +#[non_exhaustive] +pub enum TempFileError { + /// File I/O Error + #[display(fmt = "File I/O error: {}", _0)] + FileIo(std::io::Error), +} + +impl ResponseError for TempFileError { + fn status_code(&self) -> StatusCode { + StatusCode::INTERNAL_SERVER_ERROR + } +} + +/// Configuration for the [`TempFile`] field reader. +#[derive(Clone)] +pub struct TempFileConfig { + err_handler: FieldErrorHandler, + directory: Option, +} + +impl TempFileConfig { + fn create_tempfile(&self) -> io::Result { + if let Some(ref dir) = self.directory { + NamedTempFile::new_in(dir) + } else { + NamedTempFile::new() + } + } +} + +impl TempFileConfig { + /// Sets custom error handler. + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(TempFileError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.err_handler = Some(Arc::new(f)); + self + } + + /// Extracts payload config from app data. Check both `T` and `Data`, in that order, and fall + /// back to the default payload config. + fn from_req(req: &HttpRequest) -> &Self { + req.app_data::() + .or_else(|| req.app_data::>().map(|d| d.as_ref())) + .unwrap_or(&DEFAULT_CONFIG) + } + + fn map_error( + &self, + req: &HttpRequest, + field_name: &str, + err: TempFileError, + ) -> MultipartError { + let source = if let Some(ref err_handler) = self.err_handler { + (err_handler)(err, req) + } else { + err.into() + }; + + MultipartError::Field { + field_name: field_name.to_owned(), + source, + } + } + + /// Sets the directory that temp files will be created in. + /// + /// The default temporary file location is platform dependent. + pub fn directory(mut self, dir: impl AsRef) -> Self { + self.directory = Some(dir.as_ref().to_owned()); + self + } +} + +const DEFAULT_CONFIG: TempFileConfig = TempFileConfig { + err_handler: None, + directory: None, +}; + +impl Default for TempFileConfig { + fn default() -> Self { + DEFAULT_CONFIG + } +} + +#[cfg(test)] +mod tests { + use std::io::{Cursor, Read}; + + use actix_multipart_rfc7578::client::multipart; + use actix_web::{http::StatusCode, web, App, HttpResponse, Responder}; + + use crate::form::{tempfile::TempFile, tests::send_form, MultipartForm}; + + #[derive(MultipartForm)] + struct FileForm { + file: TempFile, + } + + async fn test_file_route(form: MultipartForm) -> impl Responder { + let mut form = form.into_inner(); + let mut contents = String::new(); + form.file.file.read_to_string(&mut contents).unwrap(); + assert_eq!(contents, "Hello, world!"); + assert_eq!(form.file.file_name.unwrap(), "testfile.txt"); + assert_eq!(form.file.content_type.unwrap(), mime::TEXT_PLAIN); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_file_upload() { + let srv = actix_test::start(|| App::new().route("/", web::post().to(test_file_route))); + + let mut form = multipart::Form::default(); + let bytes = Cursor::new("Hello, world!"); + form.add_reader_file_with_mime("file", bytes, "testfile.txt", mime::TEXT_PLAIN); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } +} diff --git a/actix-multipart/src/form/text.rs b/actix-multipart/src/form/text.rs new file mode 100644 index 000000000..83e211524 --- /dev/null +++ b/actix-multipart/src/form/text.rs @@ -0,0 +1,196 @@ +//! Deserializes a field from plain text. + +use std::{str, sync::Arc}; + +use actix_web::{http::StatusCode, web, Error, HttpRequest, ResponseError}; +use derive_more::{Deref, DerefMut, Display, Error}; +use futures_core::future::LocalBoxFuture; +use serde::de::DeserializeOwned; + +use super::FieldErrorHandler; +use crate::{ + form::{bytes::Bytes, FieldReader, Limits}, + Field, MultipartError, +}; + +/// Deserialize from plain text. +/// +/// Internally this uses [`serde_plain`] for deserialization, which supports primitive types +/// including strings, numbers, and simple enums. +#[derive(Debug, Deref, DerefMut)] +pub struct Text(pub T); + +impl Text { + /// Unwraps into inner value. + pub fn into_inner(self) -> T { + self.0 + } +} + +impl<'t, T> FieldReader<'t> for Text +where + T: DeserializeOwned + 'static, +{ + type Future = LocalBoxFuture<'t, Result>; + + fn read_field(req: &'t HttpRequest, field: Field, limits: &'t mut Limits) -> Self::Future { + Box::pin(async move { + let config = TextConfig::from_req(req); + let field_name = field.name().to_owned(); + + if config.validate_content_type { + let valid = if let Some(mime) = field.content_type() { + mime.subtype() == mime::PLAIN || mime.suffix() == Some(mime::PLAIN) + } else { + // https://datatracker.ietf.org/doc/html/rfc7578#section-4.4 + // content type defaults to text/plain, so None should be considered valid + true + }; + + if !valid { + return Err(MultipartError::Field { + field_name, + source: config.map_error(req, TextError::ContentType), + }); + } + } + + let bytes = Bytes::read_field(req, field, limits).await?; + + let text = str::from_utf8(&bytes.data).map_err(|err| MultipartError::Field { + field_name: field_name.clone(), + source: config.map_error(req, TextError::Utf8Error(err)), + })?; + + Ok(Text(serde_plain::from_str(text).map_err(|err| { + MultipartError::Field { + field_name, + source: config.map_error(req, TextError::Deserialize(err)), + } + })?)) + }) + } +} + +#[derive(Debug, Display, Error)] +#[non_exhaustive] +pub enum TextError { + /// UTF-8 decoding error. + #[display(fmt = "UTF-8 decoding error: {}", _0)] + Utf8Error(str::Utf8Error), + + /// Deserialize error. + #[display(fmt = "Plain text deserialize error: {}", _0)] + Deserialize(serde_plain::Error), + + /// Content type error. + #[display(fmt = "Content type error")] + ContentType, +} + +impl ResponseError for TextError { + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST + } +} + +/// Configuration for the [`Text`] field reader. +#[derive(Clone)] +pub struct TextConfig { + err_handler: FieldErrorHandler, + validate_content_type: bool, +} + +impl TextConfig { + /// Sets custom error handler. + pub fn error_handler(mut self, f: F) -> Self + where + F: Fn(TextError, &HttpRequest) -> Error + Send + Sync + 'static, + { + self.err_handler = Some(Arc::new(f)); + self + } + + /// Extracts payload config from app data. Check both `T` and `Data`, in that order, and fall + /// back to the default payload config. + fn from_req(req: &HttpRequest) -> &Self { + req.app_data::() + .or_else(|| req.app_data::>().map(|d| d.as_ref())) + .unwrap_or(&DEFAULT_CONFIG) + } + + fn map_error(&self, req: &HttpRequest, err: TextError) -> Error { + if let Some(ref err_handler) = self.err_handler { + (err_handler)(err, req) + } else { + err.into() + } + } + + /// Sets whether or not the field must have a valid `Content-Type` header to be parsed. + /// + /// Note that an empty `Content-Type` is also accepted, as the multipart specification defines + /// `text/plain` as the default for text fields. + pub fn validate_content_type(mut self, validate_content_type: bool) -> Self { + self.validate_content_type = validate_content_type; + self + } +} + +const DEFAULT_CONFIG: TextConfig = TextConfig { + err_handler: None, + validate_content_type: true, +}; + +impl Default for TextConfig { + fn default() -> Self { + DEFAULT_CONFIG + } +} + +#[cfg(test)] +mod tests { + use std::io::Cursor; + + use actix_multipart_rfc7578::client::multipart; + use actix_web::{http::StatusCode, web, App, HttpResponse, Responder}; + + use crate::form::{ + tests::send_form, + text::{Text, TextConfig}, + MultipartForm, + }; + + #[derive(MultipartForm)] + struct TextForm { + number: Text, + } + + async fn test_text_route(form: MultipartForm) -> impl Responder { + assert_eq!(*form.number, 1025); + HttpResponse::Ok().finish() + } + + #[actix_rt::test] + async fn test_content_type_validation() { + let srv = actix_test::start(|| { + App::new() + .route("/", web::post().to(test_text_route)) + .app_data(TextConfig::default().validate_content_type(true)) + }); + + // Deny because wrong content type + let bytes = Cursor::new("1025"); + let mut form = multipart::Form::default(); + form.add_reader_file_with_mime("number", bytes, "", mime::APPLICATION_OCTET_STREAM); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + + // Allow because correct content type + let bytes = Cursor::new("1025"); + let mut form = multipart::Form::default(); + form.add_reader_file_with_mime("number", bytes, "", mime::TEXT_PLAIN); + let response = send_form(&srv, form, "/").await; + assert_eq!(response.status(), StatusCode::OK); + } +} diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index 37d03db49..c8fba77d0 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -3,10 +3,17 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] #![allow(clippy::borrow_interior_mutable_const, clippy::uninlined_format_args)] +#![cfg_attr(docsrs, feature(doc_cfg))] + +// This allows us to use the actix_multipart_derive within this crate's tests +#[cfg(test)] +extern crate self as actix_multipart; mod error; mod extractor; mod server; +pub mod form; + pub use self::error::MultipartError; pub use self::server::{Field, Multipart}; diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index 9e0becd5c..6726bc9d3 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -270,7 +270,9 @@ impl InnerMultipart { match field.borrow_mut().poll(safety) { Poll::Pending => return Poll::Pending, Poll::Ready(Some(Ok(_))) => continue, - Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))), + Poll::Ready(Some(Err(err))) => { + return Poll::Ready(Some(Err(err))) + } Poll::Ready(None) => true, } } @@ -658,7 +660,7 @@ impl InnerField { match res { Poll::Pending => return Poll::Pending, Poll::Ready(Some(Ok(bytes))) => return Poll::Ready(Some(Ok(bytes))), - Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(e))), + Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))), Poll::Ready(None) => self.eof = true, } } @@ -673,7 +675,7 @@ impl InnerField { } Poll::Ready(None) } - Err(e) => Poll::Ready(Some(Err(e))), + Err(err) => Poll::Ready(Some(Err(err))), } } else { Poll::Pending @@ -794,7 +796,7 @@ impl PayloadBuffer { loop { match Pin::new(&mut self.stream).poll_next(cx) { Poll::Ready(Some(Ok(data))) => self.buf.extend_from_slice(&data), - Poll::Ready(Some(Err(e))) => return Err(e), + Poll::Ready(Some(Err(err))) => return Err(err), Poll::Ready(None) => { self.eof = true; return Ok(()); @@ -860,19 +862,22 @@ impl PayloadBuffer { #[cfg(test)] mod tests { - use super::*; + use std::time::Duration; - use actix_http::h1::Payload; - use actix_web::http::header::{DispositionParam, DispositionType}; - use actix_web::rt; - use actix_web::test::TestRequest; - use actix_web::FromRequest; + use actix_http::h1; + use actix_web::{ + http::header::{DispositionParam, DispositionType}, + rt, + test::TestRequest, + FromRequest, + }; use bytes::Bytes; use futures_util::{future::lazy, StreamExt as _}; - use std::time::Duration; use tokio::sync::mpsc; use tokio_stream::wrappers::UnboundedReceiverStream; + use super::*; + #[actix_rt::test] async fn test_boundary() { let headers = HeaderMap::new(); @@ -1119,7 +1124,7 @@ mod tests { #[actix_rt::test] async fn test_basic() { - let (_, payload) = Payload::create(false); + let (_, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); assert_eq!(payload.buf.len(), 0); @@ -1129,7 +1134,7 @@ mod tests { #[actix_rt::test] async fn test_eof() { - let (mut sender, payload) = Payload::create(false); + let (mut sender, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); assert_eq!(None, payload.read_max(4).unwrap()); @@ -1145,7 +1150,7 @@ mod tests { #[actix_rt::test] async fn test_err() { - let (mut sender, payload) = Payload::create(false); + let (mut sender, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); assert_eq!(None, payload.read_max(1).unwrap()); sender.set_error(PayloadError::Incomplete(None)); @@ -1154,7 +1159,7 @@ mod tests { #[actix_rt::test] async fn test_readmax() { - let (mut sender, payload) = Payload::create(false); + let (mut sender, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); sender.feed_data(Bytes::from("line1")); @@ -1171,7 +1176,7 @@ mod tests { #[actix_rt::test] async fn test_readexactly() { - let (mut sender, payload) = Payload::create(false); + let (mut sender, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); assert_eq!(None, payload.read_exact(2)); @@ -1189,7 +1194,7 @@ mod tests { #[actix_rt::test] async fn test_readuntil() { - let (mut sender, payload) = Payload::create(false); + let (mut sender, payload) = h1::Payload::create(false); let mut payload = PayloadBuffer::new(payload); assert_eq!(None, payload.read_until(b"ne").unwrap()); @@ -1230,7 +1235,7 @@ mod tests { #[actix_rt::test] async fn test_multipart_payload_consumption() { // with sample payload and HttpRequest with no headers - let (_, inner_payload) = Payload::create(false); + let (_, inner_payload) = h1::Payload::create(false); let mut payload = actix_web::dev::Payload::from(inner_payload); let req = TestRequest::default().to_http_request(); diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 44755035c..6cb86bbdd 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -103,7 +103,7 @@ actix-test = { version = "0.1", features = ["openssl", "rustls"] } awc = { version = "3", features = ["openssl"] } brotli = "3.3.3" -const-str = "0.4" +const-str = "0.3" criterion = { version = "0.4", features = ["html_reports"] } env_logger = "0.9" flate2 = "1.0.13" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index a69a07d67..00c3c87c5 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -99,7 +99,7 @@ actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } brotli = "3.3.3" -const-str = "0.4" +const-str = "0.3" env_logger = "0.9" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } From e2fed91efd9c4a6e89b4ee5f7e977aa612c3100b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 00:55:57 +0000 Subject: [PATCH 024/314] format markdown with prettier --- .github/ISSUE_TEMPLATE/bug_report.md | 10 +- .github/PULL_REQUEST_TEMPLATE.md | 7 +- .prettierrc.json | 3 - .prettierrc.yaml | 1 + actix-files/CHANGES.md | 87 +++--- actix-files/README.md | 2 +- actix-http-test/CHANGES.md | 60 ++-- actix-http-test/README.md | 2 +- actix-http/CHANGES.md | 338 +++++++++++++++------- actix-http/README.md | 17 +- actix-multipart/CHANGES.md | 39 +-- actix-multipart/README.md | 2 +- actix-router/CHANGES.md | 54 ++-- actix-test/CHANGES.md | 29 +- actix-web-actors/CHANGES.md | 41 ++- actix-web-actors/README.md | 2 +- actix-web-codegen/CHANGES.md | 51 ++-- actix-web-codegen/README.md | 2 +- actix-web/CHANGES.md | 304 ++++++++++--------- actix-web/MIGRATION-0.x.md | 54 ++-- actix-web/MIGRATION-1.0.md | 21 +- actix-web/MIGRATION-2.0.md | 15 +- actix-web/MIGRATION-3.0.md | 26 +- actix-web/MIGRATION-4.0.md | 2 +- actix-web/README.md | 11 +- actix-web/examples/uds.rs | 2 +- actix-web/src/middleware/authors-guide.md | 1 + awc/CHANGES.md | 122 ++++---- awc/README.md | 2 +- scripts/bump | 12 +- 30 files changed, 721 insertions(+), 598 deletions(-) delete mode 100644 .prettierrc.json create mode 100644 .prettierrc.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index fa06a137a..a26842245 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -3,34 +3,40 @@ name: Bug Report about: Create a bug report. --- -Your issue may already be reported! -Please search on the [Actix Web issue tracker](https://github.com/actix/actix-web/issues) before creating one. +Your issue may already be reported! Please search on the [Actix Web issue tracker](https://github.com/actix/actix-web/issues) before creating one. ## Expected Behavior + ## Current Behavior + ## Possible Solution + ## Steps to Reproduce (for bugs) + + 1. 2. 3. 4. ## Context + ## Your Environment + - Rust Version (I.e, output of `rustc -V`): diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d617cf708..e0d17fb27 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,12 +2,14 @@ ## PR Type + + PR_TYPE - ## PR Checklist + @@ -17,11 +19,10 @@ PR_TYPE - [ ] Format code with the latest stable rustfmt. - [ ] (Team) Label with affected crates and semver status. - ## Overview + - diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 677ba8ef2..000000000 --- a/.prettierrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "proseWrap": "never" -} diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 000000000..7b5590248 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1 @@ +proseWrap: never diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 60d3ceb96..b4b2fd8c1 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,8 +2,8 @@ ## Unreleased - 2022-xx-xx - ## 0.6.3 - 2023-01-21 + - XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. - Update `tokio-uring` dependency to `0.4`. @@ -11,13 +11,14 @@ [#2903]: https://github.com/actix/actix-web/pull/2903 ## 0.6.2 - 2022-07-23 + - Allow partial range responses for video content to start streaming sooner. [#2817] - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. [#2817]: https://github.com/actix/actix-web/pull/2817 - ## 0.6.1 - 2022-06-11 + - Add `NamedFile::{modified, metadata, content_type, content_disposition, encoding}()` getters. [#2021] - Update `tokio-uring` dependency to `0.3`. - Audio files now use `Content-Disposition: inline` instead of `attachment`. [#2645] @@ -26,46 +27,46 @@ [#2021]: https://github.com/actix/actix-web/pull/2021 [#2645]: https://github.com/actix/actix-web/pull/2645 - ## 0.6.0 - 2022-02-25 + - No significant changes since `0.6.0-beta.16`. - ## 0.6.0-beta.16 - 2022-01-31 + - No significant changes since `0.6.0-beta.15`. - ## 0.6.0-beta.15 - 2022-01-21 + - No significant changes since `0.6.0-beta.14`. - ## 0.6.0-beta.14 - 2022-01-14 + - The `prefer_utf8` option introduced in `0.4.0` is now true by default. [#2583] [#2583]: https://github.com/actix/actix-web/pull/2583 - ## 0.6.0-beta.13 - 2022-01-04 + - The `Files` service now rejects requests with URL paths that include `%2F` (decoded: `/`). [#2398] - The `Files` service now correctly decodes `%25` in the URL path to `%` for the file path. [#2398] - Minimum supported Rust version (MSRV) is now 1.54. [#2398]: https://github.com/actix/actix-web/pull/2398 - ## 0.6.0-beta.12 - 2021-12-29 + - No significant changes since `0.6.0-beta.11`. - ## 0.6.0-beta.11 - 2021-12-27 + - No significant changes since `0.6.0-beta.10`. - ## 0.6.0-beta.10 - 2021-12-11 + - No significant changes since `0.6.0-beta.9`. - ## 0.6.0-beta.9 - 2021-11-22 + - Add crate feature `experimental-io-uring`, enabling async file I/O to be utilized. This feature is only available on Linux OSes with recent kernel versions. This feature is semver-exempt. [#2408] - Add `NamedFile::open_async`. [#2408] - Fix 304 Not Modified responses to omit the Content-Length header, as per the spec. [#2453] @@ -76,24 +77,24 @@ [#2408]: https://github.com/actix/actix-web/pull/2408 [#2453]: https://github.com/actix/actix-web/pull/2453 - ## 0.6.0-beta.8 - 2021-10-20 + - Minimum supported Rust version (MSRV) is now 1.52. - ## 0.6.0-beta.7 - 2021-09-09 + - Minimum supported Rust version (MSRV) is now 1.51. - ## 0.6.0-beta.6 - 2021-06-26 + - Added `Files::path_filter()`. [#2274] - `Files::show_files_listing()` can now be used with `Files::index_file()` to show files listing as a fallback when the index file is not found. [#2228] [#2274]: https://github.com/actix/actix-web/pull/2274 [#2228]: https://github.com/actix/actix-web/pull/2228 - ## 0.6.0-beta.5 - 2021-06-17 + - `NamedFile` now implements `ServiceFactory` and `HttpServiceFactory` making it much more useful in routing. For example, it can be used directly as a default service. [#2135] - For symbolic links, `Content-Disposition` header no longer shows the filename of the original file. [#2156] - `Files::redirect_to_slash_directory()` now works as expected when used with `Files::show_files_listing()`. [#2225] @@ -104,58 +105,58 @@ [#2225]: https://github.com/actix/actix-web/pull/2225 [#2257]: https://github.com/actix/actix-web/pull/2257 - ## 0.6.0-beta.4 - 2021-04-02 + - Add support for `.guard` in `Files` to selectively filter `Files` services. [#2046] [#2046]: https://github.com/actix/actix-web/pull/2046 - ## 0.6.0-beta.3 - 2021-03-09 + - No notable changes. - ## 0.6.0-beta.2 - 2021-02-10 + - Fix If-Modified-Since and If-Unmodified-Since to not compare using sub-second timestamps. [#1887] - Replace `v_htmlescape` with `askama_escape`. [#1953] [#1887]: https://github.com/actix/actix-web/pull/1887 [#1953]: https://github.com/actix/actix-web/pull/1953 - ## 0.6.0-beta.1 - 2021-01-07 + - `HttpRange::parse` now has its own error type. - Update `bytes` to `1.0`. [#1813] [#1813]: https://github.com/actix/actix-web/pull/1813 - ## 0.5.0 - 2020-12-26 + - Optionally support hidden files/directories. [#1811] [#1811]: https://github.com/actix/actix-web/pull/1811 - ## 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] [#1714]: https://github.com/actix/actix-web/pull/1714 - ## 0.3.0 - 2020-09-11 + - No significant changes from 0.3.0-beta.1. - ## 0.3.0-beta.1 - 2020-07-15 + - Update `v_htmlescape` to 0.10 - Update `actix-web` and `actix-http` dependencies to beta.1 - ## 0.3.0-alpha.1 - 2020-05-23 + - Update `actix-web` and `actix-http` dependencies to alpha - Fix some typos in the docs - Bump minimum supported Rust version to 1.40 @@ -163,73 +164,73 @@ [#1384]: https://github.com/actix/actix-web/pull/1384 - ## 0.2.1 - 2019-12-22 + - Use the same format for file URLs regardless of platforms - ## 0.2.0 - 2019-12-20 + - Fix BodyEncoding trait import #1220 - ## 0.2.0-alpha.1 - 2019-12-07 + - Migrate to `std::future` - ## 0.1.7 - 2019-11-06 -- Add an additional `filename*` param in the `Content-Disposition` header of - `actix_files::NamedFile` to be more compatible. (#1151) + +- Add an additional `filename*` param in the `Content-Disposition` header of `actix_files::NamedFile` to be more compatible. (#1151) ## 0.1.6 - 2019-10-14 + - Add option to redirect to a slash-ended path `Files` #1132 - ## 0.1.5 - 2019-10-08 + - Bump up `mime_guess` crate version to 2.0.1 - Bump up `percent-encoding` crate version to 2.1 - Allow user defined request guards for `Files` #1113 - ## 0.1.4 - 2019-07-20 + - Allow to disable `Content-Disposition` header #686 - ## 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 - Fix ring dependency from actix-web default features for #741 - ## 0.1.1 - 2019-06-01 + - Static files are incorrectly served as both chunked and with length #812 - ## 0.1.0 - 2019-05-25 + - NamedFile last-modified check always fails due to nano-seconds in file modified date #820 - ## 0.1.0-beta.4 - 2019-05-12 + - Update actix-web to beta.4 - ## 0.1.0-beta.1 - 2019-04-20 + - Update actix-web to beta.1 - ## 0.1.0-alpha.6 - 2019-04-14 + - Update actix-web to alpha6 - ## 0.1.0-alpha.4 - 2019-04-08 + - Update actix-web to alpha4 - ## 0.1.0-alpha.2 - 2019-04-02 + - Add default handler support - ## 0.1.0-alpha.1 - 2019-03-28 + - Initial impl diff --git a/actix-files/README.md b/actix-files/README.md index 9a7e6e722..8869ca436 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -15,4 +15,4 @@ - [API Documentation](https://docs.rs/actix-files) - [Example Project](https://github.com/actix/examples/tree/master/basics/static-files) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index 0eeb80454..e56883c19 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,12 +2,12 @@ ## Unreleased - 2022-xx-xx - ## 3.1.0 - 2023-01-21 + - Minimum supported Rust version (MSRV) is now 1.59. - ## 3.0.0 - 2022-07-24 + - `TestServer::stop` is now async and will wait for the server and system to shutdown. [#2442] - Added `TestServer::client_headers` method. [#2097] - Update `actix-server` dependency to `2`. @@ -19,71 +19,71 @@ [#2097]: https://github.com/actix/actix-web/pull/2097 [#1813]: https://github.com/actix/actix-web/pull/1813 -
3.0.0 Pre-Releases ## 3.0.0-beta.13 - 2022-02-16 + - No significant changes since `3.0.0-beta.12`. - ## 3.0.0-beta.12 - 2022-01-31 + - No significant changes since `3.0.0-beta.11`. - ## 3.0.0-beta.11 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 3.0.0-beta.10 - 2021-12-27 + - Update `actix-server` to `2.0.0-rc.2`. [#2550] [#2550]: https://github.com/actix/actix-web/pull/2550 - ## 3.0.0-beta.9 - 2021-12-11 + - No significant changes since `3.0.0-beta.8`. - ## 3.0.0-beta.8 - 2021-11-30 + - Update `actix-tls` to `3.0.0-rc.1`. [#2474] [#2474]: https://github.com/actix/actix-web/pull/2474 - ## 3.0.0-beta.7 - 2021-11-22 + - Fix compatibility with experimental `io-uring` feature of `actix-rt`. [#2408] [#2408]: https://github.com/actix/actix-web/pull/2408 - ## 3.0.0-beta.6 - 2021-11-15 + - `TestServer::stop` is now async and will wait for the server and system to shutdown. [#2442] - Update `actix-server` to `2.0.0-beta.9`. [#2442] - Minimum supported Rust version (MSRV) is now 1.52. [#2442]: https://github.com/actix/actix-web/pull/2442 - ## 3.0.0-beta.5 - 2021-09-09 + - Minimum supported Rust version (MSRV) is now 1.51. - ## 3.0.0-beta.4 - 2021-04-02 + - Added `TestServer::client_headers` method. [#2097] [#2097]: https://github.com/actix/actix-web/pull/2097 - ## 3.0.0-beta.3 - 2021-03-09 -- No notable changes. +- No notable changes. ## 3.0.0-beta.2 - 2021-02-10 + - No notable changes. - ## 3.0.0-beta.1 - 2021-01-07 + - Update `bytes` to `1.0`. [#1813] [#1813]: https://github.com/actix/actix-web/pull/1813 @@ -91,6 +91,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] @@ -98,12 +99,12 @@ [#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 - Make `test_server` `async` fn. @@ -113,55 +114,56 @@ - Update `env_logger` dependency to 0.7 ## 1.0.0 - 2019-12-13 + - Replaced `TestServer::start()` with `test_server()` - ## 1.0.0-alpha.3 - 2019-12-07 + - Migrate to `std::future` - ## 0.2.5 - 2019-09-17 + - Update serde_urlencoded to "0.6.1" - Increase TestServerRuntime timeouts from 500ms to 3000ms - Do not override current `System` - ## 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` - ## 0.2.2 - 2019-06-16 + - Add .put() and .sput() methods - ## 0.2.1 - 2019-06-05 + - Add license files - ## 0.2.0 - 2019-05-12 + - Update awc and actix-http deps - ## 0.1.1 - 2019-04-24 + - Always make new connection for http client - ## 0.1.0 - 2019-04-16 + - No changes - ## 0.1.0-alpha.3 - 2019-04-02 + - Request functions accept path #743 - ## 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 + - Initial impl diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 910b5649d..94f0e88a5 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http-test) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 6a45e79dd..033cd994c 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,9 +2,10 @@ ## Unreleased - 2022-xx-xx - ## 3.3.0 - 2023-01-21 + ### Added + - Implement `MessageBody` for `Cow<'static, str>` and `Cow<'static, [u8]>`. [#2959] - Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868] - Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868] @@ -21,9 +22,11 @@ - `X_FORWARDED_PROTO` ### Fixed + - Fix non-empty body of HTTP/2 HEAD responses. [#2920] ### Performance + - Improve overall performance of operations on `Extensions`. [#2890] [#2959]: https://github.com/actix/actix-web/pull/2959 @@ -35,74 +38,86 @@ [#2956]: https://github.com/actix/actix-web/pull/2956 [#2968]: https://github.com/actix/actix-web/pull/2968 - ## 3.2.2 - 2022-09-11 + ### Changed + - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. ### Fixed + - Avoid possibility of dispatcher getting stuck while back-pressuring I/O. [#2369] [#2369]: https://github.com/actix/actix-web/pull/2369 - ## 3.2.1 - 2022-07-02 + ### Fixed + - Fix parsing ambiguity in Transfer-Encoding and Content-Length headers for HTTP/1.0 requests. [#2794] [#2794]: https://github.com/actix/actix-web/pull/2794 - ## 3.2.0 - 2022-06-30 + ### Changed + - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. ### Fixed + - Websocket parser no longer throws endless overflow errors after receiving an oversized frame. [#2790] - Retain previously set Vary headers when using compression encoder. [#2798] [#2790]: https://github.com/actix/actix-web/pull/2790 [#2798]: https://github.com/actix/actix-web/pull/2798 - ## 3.1.0 - 2022-06-11 + ### Changed + - Minimum supported Rust version (MSRV) is now 1.56 due to transitive `hashbrown` dependency. ### Fixed + - Revert broken fix in [#2624] that caused erroneous 500 error responses. Temporarily re-introduces [#2357] bug. [#2779] [#2624]: https://github.com/actix/actix-web/pull/2624 [#2357]: https://github.com/actix/actix-web/issues/2357 [#2779]: https://github.com/actix/actix-web/pull/2779 - ## 3.0.4 - 2022-03-09 + ### Fixed + - Document on docs.rs with `ws` feature enabled. - ## 3.0.3 - 2022-03-08 + ### Fixed + - Allow spaces between header name and colon when parsing responses. [#2684] [#2684]: https://github.com/actix/actix-web/pull/2684 - ## 3.0.2 - 2022-03-05 + ### Fixed + - Fix encoding camel-case header names with more than one hyphen. [#2683] [#2683]: https://github.com/actix/actix-web/pull/2683 - ## 3.0.1 - 2022-03-04 + - Fix panic in H1 dispatcher when pipelining is used with keep-alive. [#2678] [#2678]: https://github.com/actix/actix-web/issues/2678 ## 3.0.0 - 2022-02-25 + ### Dependencies + - Updated `actix-*` to Tokio v1-based versions. [#1813] - Updated `bytes` to `1.0`. [#1813] - Updated `h2` to `0.3`. [#1813] @@ -111,6 +126,7 @@ - Updated `tokio` to `1`. ### Added + - Crate Features: - `ws`; disabled by default. [#2618] - `http2`; disabled by default. [#2618] @@ -179,6 +195,7 @@ - `#[must_use]` for `ws::Codec` to prevent subtle bugs. [#1920] ### Changed + - Traits: - Rename `IntoHeaderValue => TryIntoHeaderValue`. [#2510] - `MessageBody` now has an associated `Error` type. [#2183] @@ -234,6 +251,7 @@ - Minimum supported Rust version (MSRV) is now 1.54. ### Fixed + - A `Vary` header is now correctly sent along with compressed content. [#2501] - HTTP/1.1 dispatcher correctly uses client request timeout. [#2611] - Fixed issue where handlers that took payload but then dropped without reading it to EOF it would cause keep-alive connections to become stuck. [#2624] @@ -246,6 +264,7 @@ - Fixed quality parse error in Accept-Encoding header. [#2344] ### Removed + - Crate Features: - `compress` feature. [#2065] - `cookies` feature. [#2065] @@ -308,7 +327,6 @@ - `downcast` and `downcast_get_type_id` macros. [#2291] - Down-casting for `MessageBody` types; use standard `Any` trait. [#2183] - [#1813]: https://github.com/actix/actix-web/pull/1813 [#1845]: https://github.com/actix/actix-web/pull/1845 [#1857]: https://github.com/actix/actix-web/pull/1857 @@ -381,37 +399,42 @@ [#2660]: https://github.com/actix/actix-web/pull/2660 [00ba8d55]: https://github.com/actix/actix-web/commit/00ba8d55492284581695d824648590715a8bd386 -
3.0.0 Pre-Releases ## 3.0.0-rc.4 - 2022-02-22 + ### Fixed + - Fix h1 dispatcher panic. [1ce58ecb] [1ce58ecb]: https://github.com/actix/actix-web/commit/1ce58ecb305c60e51db06e6c913b7a1344e229ca - ## 3.0.0-rc.3 - 2022-02-16 + - No significant changes since `3.0.0-rc.2`. - ## 3.0.0-rc.2 - 2022-02-08 + ### Added + - Implement `From>` for `Response>`. [#2625] ### Changed + - `error::DispatcherError` enum is now marked `#[non_exhaustive]`. [#2624] ### Fixed + - Issue where handlers that took payload but then dropped without reading it to EOF it would cause keep-alive connections to become stuck. [#2624] [#2624]: https://github.com/actix/actix-web/pull/2624 [#2625]: https://github.com/actix/actix-web/pull/2625 - ## 3.0.0-rc.1 - 2022-01-31 + ### Added + - Implement `Default` for `KeepAlive`. [#2611] - Implement `From` for `KeepAlive`. [#2611] - Implement `From>` for `KeepAlive`. [#2611] @@ -420,6 +443,7 @@ - Crate `http2` feature flag, disabled by default. [#2618] ### Changed + - Rename `ServiceConfig::{client_timer_expire => client_request_deadline}`. [#2611] - Rename `ServiceConfig::{client_disconnect_timer => client_disconnect_deadline}`. [#2611] - Deadline methods in `ServiceConfig` now return `std::time::Instant`s instead of Tokio's wrapper type. [#2611] @@ -430,9 +454,11 @@ - `ServiceConfig::keep_alive` now returns a `KeepAlive`. [#2611] ### Fixed + - HTTP/1.1 dispatcher correctly uses client request timeout. [#2611] ### Removed + - `ServiceConfig::{client_timer, keep_alive_timer}`. [#2611] - `impl From for KeepAlive`; use `Duration`s instead. [#2611] - `impl From> for KeepAlive`; use `Duration`s instead. [#2611] @@ -441,16 +467,19 @@ [#2611]: https://github.com/actix/actix-web/pull/2611 [#2618]: https://github.com/actix/actix-web/pull/2618 - ## 3.0.0-beta.19 - 2022-01-21 + ### Added + - Response headers can be sent as camel case using `res.head_mut().set_camel_case_headers(true)`. [#2587] - `ResponseHead` now implements `Clone`. [#2585] ### Changed + - Brotli (de)compression support is now provided by the `brotli` crate. [#2538] ### Removed + - `ResponseHead::extensions[_mut]()`. [#2585] - `ResponseBuilder::extensions[_mut]()`. [#2585] @@ -458,9 +487,10 @@ [#2585]: https://github.com/actix/actix-web/pull/2585 [#2587]: https://github.com/actix/actix-web/pull/2587 - ## 3.0.0-beta.18 - 2022-01-04 + ### Added + - `impl Eq` for `header::ContentEncoding`. [#2501] - `impl Copy` for `QualityItem` where `T: Copy`. [#2501] - `Quality::ZERO` equivalent to `q=0`. [#2501] @@ -468,6 +498,7 @@ - `ContentEncoding::to_header_value()`. [#2501] ### Changed + - `Quality::MIN` is now the smallest non-zero value. [#2501] - `QualityItem::min` semantics changed with `QualityItem::MIN`. [#2501] - Rename `ContentEncoding::{Br => Brotli}`. [#2501] @@ -475,19 +506,22 @@ - Minimum supported Rust version (MSRV) is now 1.54. ### Fixed + - `ContentEncoding::Identity` can now be parsed from a string. [#2501] - A `Vary` header is now correctly sent along with compressed content. [#2501] ### Removed + - `ContentEncoding::Auto` variant. [#2501] - `ContentEncoding::is_compression()`. [#2501] [#2501]: https://github.com/actix/actix-web/pull/2501 [#2565]: https://github.com/actix/actix-web/pull/2565 - ## 3.0.0-beta.17 - 2021-12-27 + ### Changed + - `HeaderMap::get_all` now returns a `std::slice::Iter`. [#2527] - `Payload` inner fields are now named. [#2545] - `impl Stream` for `Payload` no longer requires the `Stream` variant be `Unpin`. [#2545] @@ -496,30 +530,35 @@ - Rename `PayloadStream` to `BoxedPayloadStream`. [#2545] ### Removed + - `h1::Payload::readany`. [#2545] [#2527]: https://github.com/actix/actix-web/pull/2527 [#2545]: https://github.com/actix/actix-web/pull/2545 - ## 3.0.0-beta.16 - 2021-12-17 + ### Added + - New method on `MessageBody` trait, `try_into_bytes`, with default implementation, for optimizations on body types that complete in exactly one poll. Replaces `is_complete_body` and `take_complete_body`. [#2522] ### Changed + - Rename trait `IntoHeaderPair => TryIntoHeaderPair`. [#2510] - Rename `TryIntoHeaderPair::{try_into_header_pair => try_into_pair}`. [#2510] - Rename trait `IntoHeaderValue => TryIntoHeaderValue`. [#2510] ### Removed + - `MessageBody::{is_complete_body,take_complete_body}`. [#2522] [#2510]: https://github.com/actix/actix-web/pull/2510 [#2522]: https://github.com/actix/actix-web/pull/2522 - ## 3.0.0-beta.15 - 2021-12-11 + ### Added + - Add timeout for canceling HTTP/2 server side connection handshake. Default to 5 seconds. [#2483] - HTTP/2 handshake timeout can be configured with `ServiceConfig::client_timeout`. [#2483] - `Response::map_into_boxed_body`. [#2468] @@ -540,6 +579,7 @@ - New `boxed` method on `MessageBody` trait for wrapping body type. [#2520] ### Changed + - Rename `body::BoxBody::{from_body => new}`. [#2468] - Body type for `Responses` returned from `Response::{new, ok, etc...}` is now `BoxBody`. [#2468] - The `Error` associated type on `MessageBody` type now requires `impl Error` (or similar). [#2468] @@ -549,6 +589,7 @@ - `ResponseBuilder::finish()` now returns `Response>`. [#2468] ### Removed + - `ResponseBuilder::streaming`. [#2468] - `impl Future` for `ResponseBuilder`. [#2468] - Remove unnecessary `MessageBody` bound on types passed to `body::AnyBody::new`. [#2468] @@ -568,9 +609,10 @@ [#2497]: https://github.com/actix/actix-web/pull/2497 [#2520]: https://github.com/actix/actix-web/pull/2520 - ## 3.0.0-beta.14 - 2021-11-30 + ### Changed + - Guarantee ordering of `header::GetAll` iterator to be same as insertion order. [#2467] - Expose `header::map` module. [#2467] - Implement `ExactSizeIterator` and `FusedIterator` for all `HeaderMap` iterators. [#2470] @@ -580,15 +622,17 @@ [#2470]: https://github.com/actix/actix-web/pull/2470 [#2474]: https://github.com/actix/actix-web/pull/2474 - ## 3.0.0-beta.13 - 2021-11-22 + ### Added + - `body::AnyBody::empty` for quickly creating an empty body. [#2446] - `body::AnyBody::none` for quickly creating a "none" body. [#2456] - `impl Clone` for `body::AnyBody where S: Clone`. [#2448] - `body::AnyBody::into_boxed` for quickly converting to a type-erased, boxed body type. [#2448] ### Changed + - Rename `body::AnyBody::{Message => Body}`. [#2446] - Rename `body::AnyBody::{from_message => new_boxed}`. [#2448] - Rename `body::AnyBody::{from_slice => copy_from_slice}`. [#2448] @@ -597,6 +641,7 @@ - `Encoder::response` now returns `AnyBody>`. [#2448] ### Removed + - `body::AnyBody::Empty`; an empty body can now only be represented as a zero-length `Bytes` variant. [#2446] - `body::BodySize::Empty`; an empty body can now only be represented as a `Sized(0)` variant. [#2446] - `EncoderError::Boxed`; it is no longer required. [#2446] @@ -606,33 +651,38 @@ [#2448]: https://github.com/actix/actix-web/pull/2448 [#2456]: https://github.com/actix/actix-web/pull/2456 - ## 3.0.0-beta.12 - 2021-11-15 + ### Changed + - Update `actix-server` to `2.0.0-beta.9`. [#2442] ### Removed + - `client` module. [#2425] - `trust-dns` feature. [#2425] [#2425]: https://github.com/actix/actix-web/pull/2425 [#2442]: https://github.com/actix/actix-web/pull/2442 - ## 3.0.0-beta.11 - 2021-10-20 + ### Changed + - Updated rustls to v0.20. [#2414] - Minimum supported Rust version (MSRV) is now 1.52. [#2414]: https://github.com/actix/actix-web/pull/2414 - ## 3.0.0-beta.10 - 2021-09-09 + ### Changed + - `ContentEncoding` is now marked `#[non_exhaustive]`. [#2377] - Minimum supported Rust version (MSRV) is now 1.51. ### Fixed + - Remove slice creation pointing to potential uninitialized data on h1 encoder. [#2364] - Remove `Into` bound on `Encoder` body types. [#2375] - Fix quality parse error in Accept-Encoding header. [#2344] @@ -642,25 +692,29 @@ [#2344]: https://github.com/actix/actix-web/pull/2344 [#2377]: https://github.com/actix/actix-web/pull/2377 - ## 3.0.0-beta.9 - 2021-08-09 + ### Fixed + - Potential HTTP request smuggling vulnerabilities. [RUSTSEC-2021-0081](https://github.com/rustsec/advisory-db/pull/977) - ## 3.0.0-beta.8 - 2021-06-26 + ### Changed + - Change compression algorithm features flags. [#2250] ### Removed + - `downcast` and `downcast_get_type_id` macros. [#2291] [#2291]: https://github.com/actix/actix-web/pull/2291 [#2250]: https://github.com/actix/actix-web/pull/2250 - ## 3.0.0-beta.7 - 2021-06-17 + ### Added + - Alias `body::Body` as `body::AnyBody`. [#2215] - `BoxAnyBody`: a boxed message body with boxed errors. [#2183] - Re-export `http` crate's `Error` type as `error::HttpError`. [#2171] @@ -671,6 +725,7 @@ - Add zstd support for `ContentEncoding`. [#2244] ### Changed + - The `MessageBody` trait now has an associated `Error` type. [#2183] - All error trait bounds in server service builders have changed from `Into` to `Into>`. [#2253] - All error trait bounds in message body and stream impls changed from `Into` to `Into>`. [#2253] @@ -684,6 +739,7 @@ - `HttpServer::{listen_rustls(), bind_rustls()}` now honor the ALPN protocols in the configuration parameter. [#2226] ### Removed + - Stop re-exporting `http` crate's `HeaderMap` types in addition to ours. [#2171] - Down-casting for `MessageBody` types. [#2183] - `error::Result` alias. [#2201] @@ -702,21 +758,23 @@ [#2253]: https://github.com/actix/actix-web/pull/2253 [#2244]: https://github.com/actix/actix-web/pull/2244 - - ## 3.0.0-beta.6 - 2021-04-17 + ### Added + - `impl MessageBody for Pin>`. [#2152] - `Response::{ok, bad_request, not_found, internal_server_error}`. [#2159] - Helper `body::to_bytes` for async collecting message body into Bytes. [#2158] ### Changed + - The type parameter of `Response` no longer has a default. [#2152] - The `Message` variant of `body::Body` is now `Pin>`. [#2152] - `BodyStream` and `SizedStream` are no longer restricted to Unpin types. [#2152] - Error enum types are marked `#[non_exhaustive]`. [#2161] ### Removed + - `cookies` feature flag. [#2065] - Top-level `cookies` mod (re-export). [#2065] - `HttpMessage` trait loses the `cookies` and `cookie` methods. [#2065] @@ -735,17 +793,20 @@ [#2158]: https://github.com/actix/actix-web/pull/2158 [#2161]: https://github.com/actix/actix-web/pull/2161 - ## 3.0.0-beta.5 - 2021-04-02 + ### Added + - `client::Connector::handshake_timeout` method for customizing TLS connection handshake timeout. [#2081] - `client::ConnectorService` as `client::Connector::finish` method's return type [#2081] - `client::ConnectionIo` trait alias [#2081] ### Changed + - `client::Connector` type now only have one generic type for `actix_service::Service`. [#2063] ### Removed + - Common typed HTTP headers were moved to actix-web. [2094] - `ResponseError` impl for `actix_utils::timeout::TimeoutError`. [#2127] @@ -754,14 +815,16 @@ [#2094]: https://github.com/actix/actix-web/pull/2094 [#2127]: https://github.com/actix/actix-web/pull/2127 - ## 3.0.0-beta.4 - 2021-03-08 + ### Changed + - Feature `cookies` is now optional and disabled by default. [#1981] - `ws::hash_key` now returns array. [#2035] - `ResponseBuilder::json` now takes `impl Serialize`. [#2052] ### Removed + - Re-export of `futures_channel::oneshot::Canceled` is removed from `error` mod. [#1994] - `ResponseError` impl for `futures_channel::oneshot::Canceled` is removed. [#1994] @@ -770,13 +833,14 @@ [#2035]: https://github.com/actix/actix-web/pull/2035 [#2052]: https://github.com/actix/actix-web/pull/2052 - ## 3.0.0-beta.3 - 2021-02-10 + - No notable changes. - ## 3.0.0-beta.2 - 2021-02-10 + ### Added + - `TryIntoHeaderPair` trait that allows using typed and untyped headers in the same methods. [#1869] - `ResponseBuilder::insert_header` method which allows using typed headers. [#1869] - `ResponseBuilder::append_header` method which allows using typed headers. [#1869] @@ -788,22 +852,21 @@ - `trust-dns` optional feature to enable `trust-dns-resolver` as client dns resolver. [#1969] ### Changed -- `ResponseBuilder::content_type` now takes an `impl TryIntoHeaderValue` to support using typed - `mime` types. [#1894] -- Renamed `TryIntoHeaderValue::{try_into => try_into_value}` to avoid ambiguity with std - `TryInto` trait. [#1894] + +- `ResponseBuilder::content_type` now takes an `impl TryIntoHeaderValue` to support using typed `mime` types. [#1894] +- Renamed `TryIntoHeaderValue::{try_into => try_into_value}` to avoid ambiguity with std `TryInto` trait. [#1894] - `Extensions::insert` returns Option of replaced item. [#1904] - Remove `HttpResponseBuilder::json2()`. [#1903] - Enable `HttpResponseBuilder::json()` to receive data by value and reference. [#1903] - `client::error::ConnectError` Resolver variant contains `Box` type. [#1905] - `client::ConnectorConfig` default timeout changed to 5 seconds. [#1905] -- Simplify `BlockingError` type to a unit struct. It's now only triggered when blocking thread pool - is dead. [#1957] +- Simplify `BlockingError` type to a unit struct. It's now only triggered when blocking thread pool is dead. [#1957] - `HeaderMap::len` now returns number of values instead of number of keys. [#1964] - `HeaderMap::insert` now returns iterator of removed values. [#1964] - `HeaderMap::remove` now returns iterator of removed values. [#1964] ### Removed + - `ResponseBuilder::set`; use `ResponseBuilder::insert_header`. [#1869] - `ResponseBuilder::set_header`; use `ResponseBuilder::insert_header`. [#1869] - `ResponseBuilder::header`; use `ResponseBuilder::append_header`. [#1869] @@ -813,6 +876,7 @@ - `ResponseError` impl for `actix::MailboxError`. [#1969] ### Documentation + - Vastly improve docs and add examples for `HeaderMap`. [#1964] [#1869]: https://github.com/actix/actix-web/pull/1869 @@ -825,12 +889,14 @@ [#1964]: https://github.com/actix/actix-web/pull/1964 [#1969]: https://github.com/actix/actix-web/pull/1969 - ## 3.0.0-beta.1 - 2021-01-07 + ### Added + - Add `Http3` to `Protocol` enum for future compatibility and also mark `#[non_exhaustive]`. ### Changed + - Update `actix-*` dependencies to tokio `1.0` based versions. [#1813] - Bumped `rand` to `0.8`. - Update `bytes` to `1.0`. [#1813] @@ -838,16 +904,11 @@ - The `ws::Message::Text` enum variant now contains a `bytestring::ByteString`. [#1864] ### Removed -- Deprecated `on_connect` methods have been removed. Prefer the new - `on_connect_ext` technique. [#1857] -- Remove `ResponseError` impl for `actix::actors::resolver::ResolverError` - due to deprecate of resolver actor. [#1813] -- Remove `ConnectError::SslHandshakeError` and re-export of `HandshakeError`. - due to the removal of this type from `tokio-openssl` crate. openssl handshake - error would return as `ConnectError::SslError`. [#1813] -- Remove `actix-threadpool` dependency. Use `actix_rt::task::spawn_blocking`. - Due to this change `actix_threadpool::BlockingError` type is moved into - `actix_http::error` module. [#1878] + +- Deprecated `on_connect` methods have been removed. Prefer the new `on_connect_ext` technique. [#1857] +- Remove `ResponseError` impl for `actix::actors::resolver::ResolverError` due to deprecate of resolver actor. [#1813] +- Remove `ConnectError::SslHandshakeError` and re-export of `HandshakeError`. due to the removal of this type from `tokio-openssl` crate. openssl handshake error would return as `ConnectError::SslError`. [#1813] +- Remove `actix-threadpool` dependency. Use `actix_rt::task::spawn_blocking`. Due to this change `actix_threadpool::BlockingError` type is moved into `actix_http::error` module. [#1878] [#1813]: https://github.com/actix/actix-web/pull/1813 [#1857]: https://github.com/actix/actix-web/pull/1857 @@ -856,29 +917,34 @@
- ## 2.2.2 - 2022-01-21 + ### Changed + - Migrate to `brotli` crate. [ad7e3c06] [ad7e3c06]: https://github.com/actix/actix-web/commit/ad7e3c06 - ## 2.2.1 - 2021-08-09 + ### Fixed + - Potential HTTP request smuggling vulnerabilities. [RUSTSEC-2021-0081](https://github.com/rustsec/advisory-db/pull/977) - ## 2.2.0 - 2020-11-25 + ### 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] ### Changed + - Upgrade `serde_urlencoded` to `0.7`. [#1773] [#1773]: https://github.com/actix/actix-web/pull/1773 @@ -887,12 +953,14 @@ [#1793]: https://github.com/actix/actix-web/pull/1793 [#1797]: https://github.com/actix/actix-web/pull/1797 - ## 2.1.0 - 2020-10-30 + ### Added + - Added more flexible `on_connect_ext` methods for on-connect handling. [#1754] ### Changed + - Upgrade `base64` to `0.13`. [#1744] - Upgrade `pin-project` to `1.0`. [#1733] - Deprecate `ResponseBuilder::{if_some, if_true}`. [#1760] @@ -902,37 +970,42 @@ [#1733]: https://github.com/actix/actix-web/pull/1733 [#1744]: https://github.com/actix/actix-web/pull/1744 - ## 2.0.0 - 2020-09-11 + - No significant changes from `2.0.0-beta.4`. - ## 2.0.0-beta.4 - 2020-09-09 + ### Changed + - Update actix-codec and actix-utils dependencies. - Update actix-connect and actix-tls dependencies. - ## 2.0.0-beta.3 - 2020-08-14 + ### Fixed + - Memory leak of `client::pool::ConnectorPoolSupport`. [#1626] [#1626]: https://github.com/actix/actix-web/pull/1626 - ## 2.0.0-beta.2 - 2020-07-21 + ### Fixed + - Potential UB in h1 decoder using uninitialized memory. [#1614] ### Changed + - Fix illegal chunked encoding. [#1615] [#1614]: https://github.com/actix/actix-web/pull/1614 [#1615]: https://github.com/actix/actix-web/pull/1615 - ## 2.0.0-beta.1 - 2020-07-11 + ### Changed + - Migrate cookie handling to `cookie` crate. [#1558] - Update `sha-1` to 0.9. [#1586] - Fix leak in client pool. [#1580] @@ -942,278 +1015,319 @@ [#1586]: https://github.com/actix/actix-web/pull/1586 [#1580]: https://github.com/actix/actix-web/pull/1580 - ## 2.0.0-alpha.4 - 2020-05-21 + ### Changed + - Bump minimum supported Rust version to 1.40 -- content_length function is removed, and you can set Content-Length by calling - no_chunking function [#1439] -- `BodySize::Sized64` variant has been removed. `BodySize::Sized` now receives a - `u64` instead of a `usize`. +- content_length function is removed, and you can set Content-Length by calling no_chunking function [#1439] +- `BodySize::Sized64` variant has been removed. `BodySize::Sized` now receives a `u64` instead of a `usize`. - Update `base64` dependency to 0.12 ### Fixed + - Support parsing of `SameSite=None` [#1503] [#1439]: https://github.com/actix/actix-web/pull/1439 [#1503]: https://github.com/actix/actix-web/pull/1503 - ## 2.0.0-alpha.3 - 2020-05-08 + ### Fixed + - Correct spelling of ConnectError::Unresolved [#1487] -- Fix a mistake in the encoding of websocket continuation messages wherein - Item::FirstText and Item::FirstBinary are each encoded as the other. +- Fix a mistake in the encoding of websocket continuation messages wherein Item::FirstText and Item::FirstBinary are each encoded as the other. ### Changed + - Implement `std::error::Error` for our custom errors [#1422] -- Remove `failure` support for `ResponseError` since that crate - will be deprecated in the near future. +- Remove `failure` support for `ResponseError` since that crate will be deprecated in the near future. [#1422]: https://github.com/actix/actix-web/pull/1422 [#1487]: https://github.com/actix/actix-web/pull/1487 - ## 2.0.0-alpha.2 - 2020-03-07 + ### Changed + - Update `actix-connect` and `actix-tls` dependency to 2.0.0-alpha.1. [#1395] -- Change default initial window size and connection window size for HTTP2 to 2MB and 1MB - respectively to improve download speed for awc when downloading large objects. [#1394] -- client::Connector accepts initial_window_size and initial_connection_window_size - HTTP2 configuration. [#1394] +- Change default initial window size and connection window size for HTTP2 to 2MB and 1MB respectively to improve download speed for awc when downloading large objects. [#1394] +- client::Connector accepts initial_window_size and initial_connection_window_size HTTP2 configuration. [#1394] - client::Connector allowing to set max_http_version to limit HTTP version to be used. [#1394] [#1394]: https://github.com/actix/actix-web/pull/1394 [#1395]: https://github.com/actix/actix-web/pull/1395 - ## 2.0.0-alpha.1 - 2020-02-27 + ### Changed + - Update the `time` dependency to 0.2.7. - Moved actors messages support from actix crate, enabled with feature `actors`. -- Breaking change: trait MessageBody requires Unpin and accepting `Pin<&mut Self>` instead of - `&mut self` in the poll_next(). +- Breaking change: trait MessageBody requires Unpin and accepting `Pin<&mut Self>` instead of `&mut self` in the poll_next(). - MessageBody is not implemented for &'static [u8] anymore. ### Fixed + - Allow `SameSite=None` cookies to be sent in a response. - ## 1.0.1 - 2019-12-20 + ### Fixed + - Poll upgrade service's readiness from HTTP service handlers - Replace brotli with brotli2 #1224 - ## 1.0.0 - 2019-12-13 + ### Added + - Add websockets continuation frame support ### Changed + - Replace `flate2-xxx` features with `compress` - ## 1.0.0-alpha.5 - 2019-12-09 + ### Fixed + - Check `Upgrade` service readiness before calling it - Fix buffer remaining capacity calculation ### Changed + - Websockets: Ping and Pong should have binary data #1049 - ## 1.0.0-alpha.4 - 2019-12-08 + ### Added + - Add impl ResponseBuilder for Error ### Changed + - Use rust based brotli compression library ## 1.0.0-alpha.3 - 2019-12-07 + ### Changed + - Migrate to tokio 0.2 - Migrate to `std::future` - ## 0.2.11 - 2019-11-06 + ### Added + - Add support for serde_json::Value to be passed as argument to ResponseBuilder.body() -- Add an additional `filename*` param in the `Content-Disposition` header of - `actix_files::NamedFile` to be more compatible. (#1151) +- Add an additional `filename*` param in the `Content-Disposition` header of `actix_files::NamedFile` to be more compatible. (#1151) - Allow to use `std::convert::Infallible` as `actix_http::error::Error` ### Fixed -- To be compatible with non-English error responses, `ResponseError` rendered with `text/plain; - charset=utf-8` header [#1118] + +- To be compatible with non-English error responses, `ResponseError` rendered with `text/plain; charset=utf-8` header [#1118] [#1878]: https://github.com/actix/actix-web/pull/1878 - ## 0.2.10 - 2019-09-11 + ### Added -- Add support for sending HTTP requests with `Rc` in addition to sending HTTP requests - with `RequestHead` + +- Add support for sending HTTP requests with `Rc` in addition to sending HTTP requests with `RequestHead` ### Fixed + - h2 will use error response #1080 - on_connect result isn't added to request extensions for http2 requests #1009 - ## 0.2.9 - 2019-08-13 + ### Changed + - Dropped the `byteorder`-dependency in favor of `stdlib`-implementation - Update percent-encoding to 2.1 - Update serde_urlencoded to 0.6.1 ### Fixed + - Fixed a panic in the HTTP2 handshake in client HTTP requests (#1031) - ## 0.2.8 - 2019-08-01 + ### Added + - Add `rustls` support - Add `Clone` impl for `HeaderMap` ### Fixed -- awc client panic #1016 -- Invalid response with compression middleware enabled, but compression-related features - disabled #997 +- awc client panic #1016 +- Invalid response with compression middleware enabled, but compression-related features disabled #997 ## 0.2.7 - 2019-07-18 + ### Added + - Add support for downcasting response errors #986 - ## 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 + - Add `on-connect` callback, `HttpServiceBuilder::on_connect()` #946 ### Changed + - Use `encoding_rs` crate instead of unmaintained `encoding` crate - Add `Copy` and `Clone` impls for `ws::Codec` - ## 0.2.4 - 2019-06-16 + ### Fixed + - Do not compress NoContent (204) responses #918 - ## 0.2.3 - 2019-06-02 + ### Added + - Debug impl for ResponseBuilder - From SizedStream and BodyStream for Body ### Changed + - SizedStream uses u64 - ## 0.2.2 - 2019-05-29 + ### Fixed + - Parse incoming stream before closing stream on disconnect #868 - ## 0.2.1 - 2019-05-25 + ### Fixed + - Handle socket read disconnect - ## 0.2.0 - 2019-05-12 + ### Changed + - Update actix-service to 0.4 - Expect and upgrade services accept `ServerConfig` config. ### Deleted + - `OneRequest` service - ## 0.1.5 - 2019-05-04 + ### Fixed + - Clean up response extensions in response pool #817 - ## 0.1.4 - 2019-04-24 + ### Added + - Allow to render h1 request headers in `Camel-Case` ### Fixed + - Read until eof for http/1.0 responses #771 - ## 0.1.3 - 2019-04-23 + ### Fixed + - Fix http client pool management - Fix http client wait queue management #794 - ## 0.1.2 - 2019-04-23 + ### Fixed + - Fix BorrowMutError panic in client connector #793 - ## 0.1.1 - 2019-04-19 + ### Changed + - Cookie::max_age() accepts value in seconds - Cookie::max_age_time() accepts value in time::Duration - Allow to specify server address for client connector - ## 0.1.0 - 2019-04-16 + ### Added + - Expose peer addr via `Request::peer_addr()` and `RequestHead::peer_addr` ### Changed + - `actix_http::encoding` always available - use trust-dns-resolver 0.11.0 - ## 0.1.0-alpha.5 - 2019-04-12 + ### Added + - Allow to use custom service for upgrade requests - Added `h1::SendResponse` future. ### Changed + - MessageBody::length() renamed to MessageBody::size() for consistency - ws handshake verification functions take RequestHead instead of Request - ## 0.1.0-alpha.4 - 2019-04-08 + ### Added + - Allow to use custom `Expect` handler - Add minimal `std::error::Error` impl for `Error` ### Changed + - Export IntoHeaderValue - Render error and return as response body - Use thread pool for response body compression ### Deleted + - Removed PayloadBuffer - ## 0.1.0-alpha.3 - 2019-04-02 + ### Added + - Warn when an unsealed private cookie isn't valid UTF-8 ### Fixed + - Rust 1.31.0 compatibility - Preallocate read buffer for h1 codec - Detect socket disconnection during protocol selection - ## 0.1.0-alpha.2 - 2019-03-29 + ### Added + - Added ws::Message::Nop, no-op websockets message ### Changed + - Do not use thread pool for decompression if chunk size is smaller than 2048. - ## 0.1.0-alpha.1 - 2019-03-28 + - Initial impl diff --git a/actix-http/README.md b/actix-http/README.md index 2dd2d248f..aa98f953f 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 ## Example @@ -49,18 +49,3 @@ async fn main() -> io::Result<()> { .await } ``` - -## License - -This project is licensed under either of - -- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) -- MIT license ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT)) - -at your option. - -## Code of Conduct - -Contribution to the actix-http crate is organized under the terms of the -Contributor Covenant, the maintainer of actix-http, @fafhrd91, promises to -intervene to uphold that code of conduct. diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 53134db4f..3d93a4921 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,45 +1,46 @@ # Changes ## Unreleased - 2022-xx-xx + - Added `MultipartForm` typed data extractor. [#2883] [#2883]: https://github.com/actix/actix-web/pull/2883 - ## 0.5.0 - 2023-01-21 + - `Field::content_type()` now returns `Option<&mime::Mime>`. [#2885] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2885]: https://github.com/actix/actix-web/pull/2885 - ## 0.4.0 - 2022-02-25 + - No significant changes since `0.4.0-beta.13`. - ## 0.4.0-beta.13 - 2022-01-31 + - No significant changes since `0.4.0-beta.12`. - ## 0.4.0-beta.12 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 0.4.0-beta.11 - 2021-12-27 + - No significant changes since `0.4.0-beta.10`. - ## 0.4.0-beta.10 - 2021-12-11 + - No significant changes since `0.4.0-beta.9`. - ## 0.4.0-beta.9 - 2021-12-01 + - Polling `Field` after dropping `Multipart` now fails immediately instead of hanging forever. [#2463] [#2463]: https://github.com/actix/actix-web/pull/2463 - ## 0.4.0-beta.8 - 2021-11-22 + - Ensure a correct Content-Disposition header is included in every part of a multipart message. [#2451] - Added `MultipartError::NoContentDisposition` variant. [#2451] - Since Content-Disposition is now ensured, `Field::content_disposition` is now infallible. [#2451] @@ -49,52 +50,52 @@ [#2451]: https://github.com/actix/actix-web/pull/2451 - ## 0.4.0-beta.7 - 2021-10-20 + - Minimum supported Rust version (MSRV) is now 1.52. - ## 0.4.0-beta.6 - 2021-09-09 + - Minimum supported Rust version (MSRV) is now 1.51. - ## 0.4.0-beta.5 - 2021-06-17 -- No notable changes. +- No notable changes. ## 0.4.0-beta.4 - 2021-04-02 -- No notable changes. +- No notable changes. ## 0.4.0-beta.3 - 2021-03-09 -- No notable changes. +- No notable changes. ## 0.4.0-beta.2 - 2021-02-10 + - No notable changes. - ## 0.4.0-beta.1 - 2021-01-07 + - Fix multipart consuming payload before header checks. [#1513] - Update `bytes` to `1.0`. [#1813] [#1813]: https://github.com/actix/actix-web/pull/1813 [#1513]: https://github.com/actix/actix-web/pull/1513 - ## 0.3.0 - 2020-09-11 + - No significant changes from `0.3.0-beta.2`. - ## 0.3.0-beta.2 - 2020-09-10 + - Update `actix-*` dependencies to latest versions. - ## 0.3.0-beta.1 - 2020-07-15 + - Update `actix-web` to 3.0.0-beta.1 - ## 0.3.0-alpha.1 - 2020-05-25 + - Update `actix-web` to 3.0.0-alpha.3 - Bump minimum supported Rust version to 1.40 - Minimize `futures` dependencies diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 82587ffc0..23c7aa4f5 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 51e7cbc10..b3a85d3fe 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,16 +2,17 @@ ## Unreleased - 2022-xx-xx - ## 0.5.1 - 2022-09-19 + - Correct typo in error string for `i32` deserialization. [#2876] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2876]: https://github.com/actix/actix-web/pull/2876 - ## 0.5.0 - 2022-02-22 + ### Added + - Add `Path::as_str`. [#2590] - Add `ResourceDef::set_name`. [#373][net#373] - Add `RouterBuilder::push`. [#2612] @@ -23,6 +24,7 @@ - Support multi-pattern prefixes and joins. [#2356] ### Changed + - Change signature of `ResourceDef::capture_match_info_fn` to remove `user_data` parameter. [#2612] - Deprecate `Path::path`. [#2590] - Disallow prefix routes with tail segments. [#379][net#379] @@ -47,6 +49,7 @@ - Return type of `ResourceDef::pattern` is now `Option<&str>`. [#373][net#373] ### Fixed + - Fix `ResourceDef`'s `PartialEq` implementation. [#373][net#373] - Fix segment interpolation leaving `Path` in unintended state after matching. [#368][net#368] - Improve malformed path error message. [#384][net#384] @@ -55,6 +58,7 @@ - Static patterns in multi-patterns are no longer interpreted as regex. [#366][net#366] ### Removed + - `ResourceDef::name_mut`. [#373][net#373] - Unused `ResourceInfo`. [#2612] @@ -77,11 +81,11 @@ [net#380]: https://github.com/actix/actix-net/pull/380 [net#384]: https://github.com/actix/actix-net/pull/384 -
0.5.0 Pre-Releases ## 0.5.0-rc.3 - 2022-01-31 + - Remove unused `ResourceInfo`. [#2612] - Add `RouterBuilder::push`. [#2612] - Change signature of `ResourceDef::capture_match_info_fn` to remove `user_data` parameter. [#2612] @@ -92,33 +96,33 @@ [#2612]: https://github.com/actix/actix-web/pull/2612 [#2613]: https://github.com/actix/actix-web/pull/2613 - ## 0.5.0-rc.2 - 2022-01-21 + - Add `Path::as_str`. [#2590] - Deprecate `Path::path`. [#2590] [#2590]: https://github.com/actix/actix-web/pull/2590 - ## 0.5.0-rc.1 - 2022-01-14 + - `Resource` trait now have an associated type, `Path`, instead of the generic parameter. [#2568] - `Resource` is now implemented for `&mut Path<_>` and `RefMut>`. [#2568] [#2568]: https://github.com/actix/actix-web/pull/2568 - ## 0.5.0-beta.4 - 2022-01-04 + - `PathDeserializer` now decodes all percent encoded characters in dynamic segments. [#2566] - Minimum supported Rust version (MSRV) is now 1.54. [#2566]: https://github.com/actix/actix-net/pull/2566 - ## 0.5.0-beta.3 - 2021-12-17 + - Minimum supported Rust version (MSRV) is now 1.52. - ## 0.5.0-beta.2 - 2021-09-09 + - Introduce `ResourceDef::join`. [#380][net#380] - Disallow prefix routes with tail segments. [#379][net#379] - Enforce path separators on dynamic prefixes. [#378][net#378] @@ -137,8 +141,8 @@ [#2355]: https://github.com/actix/actix-web/pull/2355 [#2356]: https://github.com/actix/actix-web/pull/2356 - ## 0.5.0-beta.1 - 2021-07-20 + - Fix a bug in multi-patterns where static patterns are interpreted as regex. [#366][net#366] - Introduce `ResourceDef::pattern_iter` to get an iterator over all patterns in a multi-pattern resource. [#373][net#373] - Fix segment interpolation leaving `Path` in unintended state after matching. [#368][net#368] @@ -167,8 +171,8 @@
- ## 0.4.0 - 2021-06-06 + - When matching path parameters, `%25` is now kept in the percent-encoded form; no longer decoded to `%`. [#357][net#357] - Path tail patterns now match new lines (`\n`) in request URL. [#360][net#360] - Fixed a safety bug where `Path` could return a malformed string after percent decoding. [#359][net#359] @@ -179,70 +183,70 @@ [net#359]: https://github.com/actix/actix-net/pull/359 [net#360]: https://github.com/actix/actix-net/pull/360 - ## 0.3.0 - 2019-12-31 + - Version was yanked previously. See https://crates.io/crates/actix-router/0.3.0 - ## 0.2.7 - 2021-02-06 + - Add `Router::recognize_checked` [#247][net#247] [net#247]: https://github.com/actix/actix-net/pull/247 - ## 0.2.6 - 2021-01-09 + - Use `bytestring` version range compatible with Bytes v1.0. [#246][net#246] [net#246]: https://github.com/actix/actix-net/pull/246 - ## 0.2.5 - 2020-09-20 + - Fix `from_hex()` method - ## 0.2.4 - 2019-12-31 + - Add `ResourceDef::resource_path_named()` path generation method - ## 0.2.3 - 2019-12-25 + - Add impl `IntoPattern` for `&String` - ## 0.2.2 - 2019-12-25 + - Use `IntoPattern` for `RouterBuilder::path()` - ## 0.2.1 - 2019-12-25 + - Add `IntoPattern` trait - Add multi-pattern resources - ## 0.2.0 - 2019-12-07 + - Update http to 0.2 - Update regex to 1.3 - Use bytestring instead of string - ## 0.1.5 - 2019-05-15 + - Remove debug prints - ## 0.1.4 - 2019-05-15 + - Fix checked resource match - ## 0.1.3 - 2019-04-22 -- Added support for `remainder match` (i.e "/path/{tail}*") +- Added support for `remainder match` (i.e "/path/{tail}\*") ## 0.1.2 - 2019-04-07 + - Export `Quoter` type - Allow to reset `Path` instance - ## 0.1.1 - 2019-04-03 + - Get dynamic segment by name instead of iterator. - ## 0.1.0 - 2019-03-09 + - Initial release diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index c8fe54203..23f4b4db1 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -1,72 +1,73 @@ # Changes ## Unreleased - 2022-xx-xx + - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. - ## 0.1.0 - 2022-07-24 + - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. - ## 0.1.0-beta.13 - 2022-02-16 + - No significant changes since `0.1.0-beta.12`. - ## 0.1.0-beta.12 - 2022-01-31 + - Rename `TestServerConfig::{client_timeout => client_request_timeout}`. [#2611] [#2611]: https://github.com/actix/actix-web/pull/2611 - ## 0.1.0-beta.11 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 0.1.0-beta.10 - 2021-12-27 + - No significant changes since `0.1.0-beta.9`. - ## 0.1.0-beta.9 - 2021-12-17 + - Re-export `actix_http::body::to_bytes`. [#2518] - Update `actix_web::test` re-exports. [#2518] [#2518]: https://github.com/actix/actix-web/pull/2518 - ## 0.1.0-beta.8 - 2021-12-11 + - No significant changes since `0.1.0-beta.7`. - ## 0.1.0-beta.7 - 2021-11-22 + - Fix compatibility with experimental `io-uring` feature of `actix-rt`. [#2408] [#2408]: https://github.com/actix/actix-web/pull/2408 - ## 0.1.0-beta.6 - 2021-11-15 + - No significant changes from `0.1.0-beta.5`. - ## 0.1.0-beta.5 - 2021-10-20 + - Updated rustls to v0.20. [#2414] - Minimum supported Rust version (MSRV) is now 1.52. [#2414]: https://github.com/actix/actix-web/pull/2414 - ## 0.1.0-beta.4 - 2021-09-09 + - Minimum supported Rust version (MSRV) is now 1.51. - ## 0.1.0-beta.3 - 2021-06-20 + - No significant changes from `0.1.0-beta.2`. - ## 0.1.0-beta.2 - 2021-04-17 + - No significant changes from `0.1.0-beta.1`. - ## 0.1.0-beta.1 - 2021-04-02 + - Move integration testing structs from `actix-web`. [#2112] [#2112]: https://github.com/actix/actix-web/pull/2112 diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index c66c04d37..480470bee 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,72 +2,72 @@ ## Unreleased - 2022-xx-xx - ## 4.2.0 - 2023-01-21 + - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. - ## 4.1.0 - 2022-03-02 + - Add support for `actix` version `0.13`. [#2675] [#2675]: https://github.com/actix/actix-web/pull/2675 - ## 4.0.0 - 2022-02-25 + - No significant changes since `4.0.0-beta.12`. - ## 4.0.0-beta.12 - 2022-02-16 + - No significant changes since `4.0.0-beta.11`. - ## 4.0.0-beta.11 - 2022-01-31 + - No significant changes since `4.0.0-beta.10`. - ## 4.0.0-beta.10 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 4.0.0-beta.9 - 2021-12-27 + - No significant changes since `4.0.0-beta.8`. - ## 4.0.0-beta.8 - 2021-12-11 + - Add `ws:WsResponseBuilder` for building WebSocket session response. [#1920] - Deprecate `ws::{start_with_addr, start_with_protocols}`. [#1920] - Minimum supported Rust version (MSRV) is now 1.52. [#1920]: https://github.com/actix/actix-web/pull/1920 - ## 4.0.0-beta.7 - 2021-09-09 + - Minimum supported Rust version (MSRV) is now 1.51. - ## 4.0.0-beta.6 - 2021-06-26 + - Update `actix` to `0.12`. [#2277] [#2277]: https://github.com/actix/actix-web/pull/2277 - ## 4.0.0-beta.5 - 2021-06-17 -- No notable changes. +- No notable changes. ## 4.0.0-beta.4 - 2021-04-02 -- No notable changes. +- No notable changes. ## 4.0.0-beta.3 - 2021-03-09 -- No notable changes. +- No notable changes. ## 4.0.0-beta.2 - 2021-02-10 + - No notable changes. - ## 4.0.0-beta.1 - 2021-01-07 + - Update `pin-project` to `1.0`. - Update `bytes` to `1.0`. [#1813] - `WebsocketContext::text` now takes an `Into`. [#1864] @@ -75,21 +75,21 @@ [#1813]: https://github.com/actix/actix-web/pull/1813 [#1864]: https://github.com/actix/actix-web/pull/1864 - ## 3.0.0 - 2020-09-11 + - No significant changes from `3.0.0-beta.2`. - ## 3.0.0-beta.2 - 2020-09-10 + - Update `actix-*` dependencies to latest versions. - ## [3.0.0-beta.1] - 2020-xx-xx + - Update `actix-web` & `actix-http` dependencies to beta.1 - Bump minimum supported Rust version to 1.40 - ## [3.0.0-alpha.1] - 2020-05-08 + - Update the actix-web dependency to 3.0.0-alpha.1 - Update the actix dependency to 0.10.0-alpha.2 - Update the actix-http dependency to 2.0.0-alpha.3 @@ -112,8 +112,7 @@ ## [1.0.2] - 2019-07-20 -- Add `ws::start_with_addr()`, returning the address of the created actor, along - with the `HttpResponse`. +- Add `ws::start_with_addr()`, returning the address of the created actor, along with the `HttpResponse`. - Add support for specifying protocols on websocket handshake #835 diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index 29d766eab..dce91f503 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-actors) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index ffa2cd252..008e4c170 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,47 +1,48 @@ # Changes ## Unreleased - 2022-xx-xx + - Add support for Custom Methods with `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 - ## 4.1.0 - 2022-09-11 + - Add `#[routes]` macro to support multiple paths for one handler. [#2718] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2718]: https://github.com/actix/actix-web/pull/2718 - ## 4.0.1 - 2022-06-11 + - Fix support for guard paths in route handler macros. [#2771] - Minimum supported Rust version (MSRV) is now 1.56 due to transitive `hashbrown` dependency. [#2771]: https://github.com/actix/actix-web/pull/2771 - ## 4.0.0 - 2022-02-24 + - Version aligned with `actix-web` and will remain in sync going forward. - No significant changes since `0.5.0`. - ## 0.5.0 - 2022-02-24 + - No significant changes since `0.5.0-rc.2`. - ## 0.5.0-rc.2 - 2022-02-01 + - No significant changes since `0.5.0-rc.1`. - ## 0.5.0-rc.1 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 0.5.0-beta.6 - 2021-12-11 + - No significant changes since `0.5.0-beta.5`. - ## 0.5.0-beta.5 - 2021-10-20 + - Improve error recovery potential when macro input is invalid. [#2410] - Add `#[actix_web::test]` macro for setting up tests with a runtime. [#2409] - Minimum supported Rust version (MSRV) is now 1.52. @@ -49,90 +50,90 @@ [#2410]: https://github.com/actix/actix-web/pull/2410 [#2409]: https://github.com/actix/actix-web/pull/2409 - ## 0.5.0-beta.4 - 2021-09-09 + - In routing macros, paths are now validated at compile time. [#2350] - Minimum supported Rust version (MSRV) is now 1.51. [#2350]: https://github.com/actix/actix-web/pull/2350 - ## 0.5.0-beta.3 - 2021-06-17 + - No notable changes. - ## 0.5.0-beta.2 - 2021-03-09 + - Preserve doc comments when using route macros. [#2022] - Add `name` attribute to `route` macro. [#1934] [#2022]: https://github.com/actix/actix-web/pull/2022 [#1934]: https://github.com/actix/actix-web/pull/1934 - ## 0.5.0-beta.1 - 2021-02-10 + - Use new call signature for `System::new`. - ## 0.4.0 - 2020-09-20 + - Added compile success and failure testing. [#1677] - Add `route` macro for supporting multiple HTTP methods guards. [#1674] [#1677]: https://github.com/actix/actix-web/pull/1677 [#1674]: https://github.com/actix/actix-web/pull/1674 - ## 0.3.0 - 2020-09-11 + - No significant changes from `0.3.0-beta.1`. - ## 0.3.0-beta.1 - 2020-07-14 + - Add main entry-point macro that uses re-exported runtime. [#1559] [#1559]: https://github.com/actix/actix-web/pull/1559 - ## 0.2.2 - 2020-05-23 + - Add resource middleware on actix-web-codegen [#1467] [#1467]: https://github.com/actix/actix-web/pull/1467 - ## 0.2.1 - 2020-02-25 + - Add `#[allow(missing_docs)]` attribute to generated structs [#1368] - Allow the handler function to be named as `config` [#1290] [#1368]: https://github.com/actix/actix-web/issues/1368 [#1290]: https://github.com/actix/actix-web/issues/1290 - ## 0.2.0 - 2019-12-13 + - Generate code for actix-web 2.0 - ## 0.1.3 - 2019-10-14 + - Bump up `syn` & `quote` to 1.0 - Provide better error message - ## 0.1.2 - 2019-06-04 + - Add macros for head, options, trace, connect and patch http methods - ## 0.1.1 - 2019-06-01 + - Add syn "extra-traits" feature - ## 0.1.0 - 2019-05-18 + - Release - ## 0.1.0-beta.1 - 2019-04-20 + - Gen code for actix-web 1.0.0-beta.1 - ## 0.1.0-alpha.6 - 2019-04-14 + - Gen code for actix-web 1.0.0-alpha.6 - ## 0.1.0-alpha.1 - 2019-03-28 + - Initial impl diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 821236e47..b5eda863c 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-codegen) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 ## Compile Testing diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 1e6a953f5..2d4b2db51 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -3,7 +3,9 @@ ## Unreleased - 2022-xx-xx ## 4.3.0 - 2023-01-21 + ### Added + - Add `ContentDisposition::attachment()` constructor. [#2867] - Add `ErrorHandlers::default_handler()` (as well as `default_handler_{server, client}()`) to make registering handlers for groups of response statuses easier. [#2784] - Add `Logger::custom_response_replace()`. [#2631] @@ -12,6 +14,7 @@ - Add fallible versions of `test` helpers: `try_call_service()`, `try_call_and_read_body_json()`, `try_read_body()`, and `try_read_body_json()`. [#2961] ### Fixed + - Add `Allow` header to `Resource`'s default responses when no routes are matched. [#2949] [#1961]: https://github.com/actix/actix-web/pull/1961 @@ -22,39 +25,45 @@ [#2949]: https://github.com/actix/actix-web/pull/2949 [#2961]: https://github.com/actix/actix-web/pull/2961 - ## 4.2.1 - 2022-09-12 + ### Fixed + - Bump minimum version of `actix-http` dependency to fix compatibility issue. [#2871] [#2871]: https://github.com/actix/actix-web/pull/2871 - ## 4.2.0 - 2022-09-11 + ### Added + - Add `#[routes]` macro to support multiple paths for one handler. [#2718] - Add `ServiceRequest::{parts, request}()` getter methods. [#2786] - Add configuration options for TLS handshake timeout via `HttpServer::{rustls, openssl}_with_config` methods. [#2752] ### Changed + - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2718]: https://github.com/actix/actix-web/pull/2718 [#2752]: https://github.com/actix/actix-web/pull/2752 [#2786]: https://github.com/actix/actix-web/pull/2786 - ## 4.1.0 - 2022-06-11 + ### Added + - Add `ServiceRequest::extract()` to make it easier to use extractors when writing middlewares. [#2647] - Add `Route::wrap()` to allow individual routes to use middleware. [#2725] - Add `ServiceConfig::default_service()`. [#2338] [#2743] - Implement `ResponseError` for `std::convert::Infallible` ### Changed + - Minimum supported Rust version (MSRV) is now 1.56 due to transitive `hashbrown` dependency. ### Fixed + - Clear connection-level data on `HttpRequest` drop. [#2742] [#2338]: https://github.com/actix/actix-web/pull/2338 @@ -63,14 +72,16 @@ [#2742]: https://github.com/actix/actix-web/pull/2742 [#2743]: https://github.com/actix/actix-web/pull/2743 - ## 4.0.1 - 2022-02-25 + ### Fixed + - Use stable version in readme example. - ## 4.0.0 - 2022-02-25 + ### Dependencies + - Updated `actix-*` to Tokio v1-based versions. [#1813] - Updated `actix-web-codegen` to `4.0.0`. - Updated `cookie` to `0.16`. [#2555] @@ -80,6 +91,7 @@ - Updated `tokio` to `1`. ### Added + - Crate Features: - `cookies`; enabled by default. [#2619] - `compress-brotli`; enabled by default. [#2618] @@ -126,6 +138,7 @@ - Connection data set through the `HttpServer::on_connect` callback is now accessible only from the new `HttpRequest::conn_data()` and `ServiceRequest::conn_data()` methods. [#2491] ### Changed + - Functions: - `guard::fn_guard` functions now receives a `&GuardContext`. [#2552] - `guard::Not` is now generic over the type of guard it wraps. [#2552] @@ -191,6 +204,7 @@ - Minimum supported Rust version (MSRV) is now 1.54. ### Fixed + - Auto-negotiation of content encoding is more fault-tolerant when using the `Compress` middleware. [#2501] - Scope and Resource middleware can access data items set on their own layer. [#2288] - Multiple calls to `App::data()` with the same type now keeps the latest call's data. [#1906] @@ -204,11 +218,13 @@ - Added the underlying parse error to `test::read_body_json`'s panic message. [#1812] ### Security + - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html ### Removed + - Crate Features: - `compress` feature. [#2065] - Functions: @@ -337,50 +353,58 @@ [#2663]: https://github.com/actix/actix-web/pull/2663 [871ca5e4]: https://github.com/actix/actix-web/commit/871ca5e4ae2bdc22d1ea02701c2992fa8d04aed7 -
4.0.0 Pre-Releases ## 4.0.0-rc.3 - 2022-02-08 + ### Changed + - `middleware::Condition` gained a broader compatibility; `Compat` is needed in fewer cases. [#2635] ### Added + - Implement `Responder` for `Vec`. [#2625] - Re-export `KeepAlive` in `http` mod. [#2625] [#2625]: https://github.com/actix/actix-web/pull/2625 [#2635]: https://github.com/actix/actix-web/pull/2635 - ## 4.0.0-rc.2 - 2022-02-02 + ### Added + - On-by-default `macros` feature flag to enable routing and runtime macros. [#2619] ### Removed + - `rt::{Arbiter, ArbiterHandle}` re-exports. [#2619] [#2619]: https://github.com/actix/actix-web/pull/2619 - ## 4.0.0-rc.1 - 2022-01-31 + ### Changed + - Rename `HttpServer::{client_timeout => client_request_timeout}`. [#2611] - Rename `HttpServer::{client_shutdown => client_disconnect_timeout}`. [#2611] ### Removed + - `impl Future for HttpResponse`. [#2601] [#2601]: https://github.com/actix/actix-web/pull/2601 [#2611]: https://github.com/actix/actix-web/pull/2611 - ## 4.0.0-beta.21 - 2022-01-21 + ### Added + - `HttpResponse::add_removal_cookie`. [#2586] - `Logger::log_target`. [#2594] ### Removed + - `HttpRequest::req_data[_mut]()`; request-local data is still available through `.extensions()`. [#2585] - `HttpRequestBuilder::del_cookie`. [#2591] @@ -389,13 +413,15 @@ [#2591]: https://github.com/actix/actix-web/pull/2591 [#2594]: https://github.com/actix/actix-web/pull/2594 - ## 4.0.0-beta.20 - 2022-01-14 + ### Added + - `GuardContext::header` [#2569] - `ServiceConfig::configure` to allow easy nesting of configuration functions. [#1988] ### Changed + - `HttpResponse` can now be used as a `Responder` with any body type. [#2567] - `Result` extractor wrapper can now convert error types. [#2581] - Associated types in `FromRequest` impl for `Option` and `Result` has changed. [#2581] @@ -409,52 +435,61 @@ [#2582]: https://github.com/actix/actix-web/pull/2582 [#2584]: https://github.com/actix/actix-web/pull/2584 - ## 4.0.0-beta.19 - 2022-01-04 + ### Added + - `impl Hash` for `http::header::Encoding`. [#2501] - `AcceptEncoding::negotiate()`. [#2501] ### Changed + - `AcceptEncoding::preference` now returns `Option>`. [#2501] - Rename methods `BodyEncoding::{encoding => encode_with, get_encoding => preferred_encoding}`. [#2501] - `http::header::Encoding` now only represents `Content-Encoding` types. [#2501] ### Fixed + - Auto-negotiation of content encoding is more fault-tolerant when using the `Compress` middleware. [#2501] ### Removed + - `Compress::new`; restricting compression algorithm is done through feature flags. [#2501] - `BodyEncoding` trait; signalling content encoding is now only done via the `Content-Encoding` header. [#2565] [#2501]: https://github.com/actix/actix-web/pull/2501 [#2565]: https://github.com/actix/actix-web/pull/2565 - ## 4.0.0-beta.18 - 2021-12-29 + ### Changed + - Update `cookie` dependency (re-exported) to `0.16`. [#2555] - Minimum supported Rust version (MSRV) is now 1.54. ### Security + - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [#2555]: https://github.com/actix/actix-web/pull/2555 [`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html - ## 4.0.0-beta.17 - 2021-12-29 + ### Added + - `guard::GuardContext` for use with the `Guard` trait. [#2552] - `ServiceRequest::guard_ctx` for obtaining a guard context. [#2552] ### Changed + - `Guard` trait now receives a `&GuardContext`. [#2552] - `guard::fn_guard` functions now receives a `&GuardContext`. [#2552] - Some guards now return `impl Guard` and their concrete types are made private: `guard::Header` and all the method guards. [#2552] - The `Not` guard is now generic over the type of guard it wraps. [#2552] ### Fixed + - Rename `ConnectionInfo::{remote_addr => peer_addr}`, deprecating the old name. [#2554] - `ConnectionInfo::peer_addr` will not return the port number. [#2554] - `ConnectionInfo::realip_remote_addr` will not return the port number if sourcing the IP from the peer's socket address. [#2554] @@ -462,22 +497,25 @@ [#2552]: https://github.com/actix/actix-web/pull/2552 [#2554]: https://github.com/actix/actix-web/pull/2554 - ## 4.0.0-beta.16 - 2021-12-27 + ### Changed + - No longer require `Scope` service body type to be boxed. [#2523] - No longer require `Resource` service body type to be boxed. [#2526] [#2523]: https://github.com/actix/actix-web/pull/2523 [#2526]: https://github.com/actix/actix-web/pull/2526 - ## 4.0.0-beta.15 - 2021-12-17 + ### Added + - Method on `Responder` trait (`customize`) for customizing responders and `CustomizeResponder` struct. [#2510] - Implement `Debug` for `DefaultHeaders`. [#2510] ### Changed + - Align `DefaultHeader` method terminology, deprecating previous methods. [#2510] - Response service types in `ErrorHandlers` middleware now use `ServiceResponse>` to allow changing the body type. [#2515] - Both variants in `ErrorHandlerResponse` now use `ServiceResponse>`. [#2515] @@ -487,6 +525,7 @@ - Relax body type and error bounds on test utilities. [#2518] ### Removed + - Top-level `EitherExtractError` export. [#2510] - Conversion implementations for `either` crate. [#2516] - `test::load_stream` and `test::load_body`; replace usage with `body::to_bytes`. [#2518] @@ -496,9 +535,10 @@ [#2516]: https://github.com/actix/actix-web/pull/2516 [#2518]: https://github.com/actix/actix-web/pull/2518 - ## 4.0.0-beta.14 - 2021-12-11 + ### Added + - Methods on `AcceptLanguage`: `ranked` and `preference`. [#2480] - `AcceptEncoding` typed header. [#2482] - `Range` typed header. [#2485] @@ -509,6 +549,7 @@ - `ServiceResponse::into_parts`. [#2499] ### Changed + - Rename `Accept::{mime_precedence => ranked}`. [#2480] - Rename `Accept::{mime_preference => preference}`. [#2480] - Un-deprecate `App::data_factory`. [#2484] @@ -518,11 +559,13 @@ - Request-local data container is no longer part of a `RequestHead`. Instead it is a distinct part of a `Request`. [#2487] ### Fixed + - Accept wildcard `*` items in `AcceptLanguage`. [#2480] - Re-exports `dev::{BodySize, MessageBody, SizedStream}`. They are exposed through the `body` module. [#2468] - Typed headers containing lists that require one or more items now enforce this minimum. [#2482] ### Removed + - `ConnectionInfo::get`. [#2487] [#2430]: https://github.com/actix/actix-web/pull/2430 @@ -537,46 +580,54 @@ [#2493]: https://github.com/actix/actix-web/pull/2493 [#2499]: https://github.com/actix/actix-web/pull/2499 - ## 4.0.0-beta.13 - 2021-11-30 + ### Changed + - Update `actix-tls` to `3.0.0-rc.1`. [#2474] [#2474]: https://github.com/actix/actix-web/pull/2474 - ## 4.0.0-beta.12 - 2021-11-22 + ### Changed + - Compress middleware's response type is now `AnyBody>`. [#2448] ### Fixed + - Relax `Unpin` bound on `S` (stream) parameter of `HttpResponseBuilder::streaming`. [#2448] ### Removed + - `dev::ResponseBody` re-export; is function is replaced by the new `dev::AnyBody` enum. [#2446] [#2446]: https://github.com/actix/actix-web/pull/2446 [#2448]: https://github.com/actix/actix-web/pull/2448 - ## 4.0.0-beta.11 - 2021-11-15 + ### Added + - Re-export `dev::ServerHandle` from `actix-server`. [#2442] ### Changed + - `ContentType::html` now produces `text/html; charset=utf-8` instead of `text/html`. [#2423] - Update `actix-server` to `2.0.0-beta.9`. [#2442] [#2423]: https://github.com/actix/actix-web/pull/2423 [#2442]: https://github.com/actix/actix-web/pull/2442 - ## 4.0.0-beta.10 - 2021-10-20 + ### Added + - Option to allow `Json` extractor to work without a `Content-Type` header present. [#2362] - `#[actix_web::test]` macro for setting up tests with a runtime. [#2409] ### Changed + - Associated type `FromRequest::Config` was removed. [#2233] - Inner field made private on `web::Payload`. [#2384] - `Data::into_inner` and `Data::get_ref` no longer requires `T: Sized`. [#2403] @@ -584,6 +635,7 @@ - Minimum supported Rust version (MSRV) is now 1.52. ### Removed + - Useless `ServiceResponse::checked_expr` method. [#2401] [#2233]: https://github.com/actix/actix-web/pull/2233 @@ -594,18 +646,21 @@ [#2409]: https://github.com/actix/actix-web/pull/2409 [#2414]: https://github.com/actix/actix-web/pull/2414 - ## 4.0.0-beta.9 - 2021-09-09 + ### Added + - Re-export actix-service `ServiceFactory` in `dev` module. [#2325] ### Changed + - Compress middleware will return 406 Not Acceptable when no content encoding is acceptable to the client. [#2344] - Move `BaseHttpResponse` to `dev::Response`. [#2379] - Enable `TestRequest::param` to accept more than just static strings. [#2172] - Minimum supported Rust version (MSRV) is now 1.51. ### Fixed + - Fix quality parse error in Accept-Encoding header. [#2344] - Re-export correct type at `web::HttpResponse`. [#2379] @@ -614,20 +669,23 @@ [#2344]: https://github.com/actix/actix-web/pull/2344 [#2379]: https://github.com/actix/actix-web/pull/2379 - ## 4.0.0-beta.8 - 2021-06-26 + ### Added + - Add `ServiceRequest::parts_mut`. [#2177] - Add extractors for `Uri` and `Method`. [#2263] - Add extractors for `ConnectionInfo` and `PeerAddr`. [#2263] - Add `Route::service` for using hand-written services as handlers. [#2262] ### Changed + - Change compression algorithm features flags. [#2250] - Deprecate `App::data` and `App::data_factory`. [#2271] - Smarter extraction of `ConnectionInfo` parts. [#2282] ### Fixed + - Scope and Resource middleware can access data items set on their own layer. [#2288] [#2177]: https://github.com/actix/actix-web/pull/2177 @@ -638,12 +696,14 @@ [#2282]: https://github.com/actix/actix-web/pull/2282 [#2288]: https://github.com/actix/actix-web/pull/2288 - ## 4.0.0-beta.7 - 2021-06-17 + ### Added + - `HttpServer::worker_max_blocking_threads` for setting block thread pool. [#2200] ### Changed + - Adjusted default JSON payload limit to 2MB (from 32kb) and included size and limits in the `JsonPayloadError::Overflow` error variant. [#2162] - `ServiceResponse::error_response` now uses body type of `Body`. [#2201] - `ServiceResponse::checked_expr` now returns a `Result`. [#2201] @@ -656,6 +716,7 @@ - `middleware::normalize` now will not try to normalize URIs with no valid path [#2246] ### Removed + - `HttpResponse::take_body` and old `HttpResponse::into_body` method that casted body type. [#2201] [#2162]: https://github.com/actix/actix-web/pull/2162 @@ -664,36 +725,39 @@ [#2253]: https://github.com/actix/actix-web/pull/2253 [#2246]: https://github.com/actix/actix-web/pull/2246 - ## 4.0.0-beta.6 - 2021-04-17 + ### Added + - `HttpResponse` and `HttpResponseBuilder` types. [#2065] ### Changed + - Most error types are now marked `#[non_exhaustive]`. [#2148] - Methods on `ContentDisposition` that took `T: AsRef` now take `impl AsRef`. [#2065]: https://github.com/actix/actix-web/pull/2065 [#2148]: https://github.com/actix/actix-web/pull/2148 - ## 4.0.0-beta.5 - 2021-04-02 + ### Added + - `Header` extractor for extracting common HTTP headers in handlers. [#2094] - Added `TestServer::client_headers` method. [#2097] ### Changed -- `CustomResponder` would return error as `HttpResponse` when `CustomResponder::with_header` failed - instead of skipping. (Only the first error is kept when multiple error occur) [#2093] + +- `CustomResponder` would return error as `HttpResponse` when `CustomResponder::with_header` failed instead of skipping. (Only the first error is kept when multiple error occur) [#2093] ### Fixed + - Double ampersand in Logger format is escaped correctly. [#2067] ### Removed -- The `client` mod was removed. Clients should now use `awc` directly. - [871ca5e4](https://github.com/actix/actix-web/commit/871ca5e4ae2bdc22d1ea02701c2992fa8d04aed7) -- Integration testing was moved to new `actix-test` crate. Namely these items from the `test` - module: `TestServer`, `TestServerConfig`, `start`, `start_with`, and `unused_addr`. [#2112] + +- The `client` mod was removed. Clients should now use `awc` directly. [871ca5e4](https://github.com/actix/actix-web/commit/871ca5e4ae2bdc22d1ea02701c2992fa8d04aed7) +- Integration testing was moved to new `actix-test` crate. Namely these items from the `test` module: `TestServer`, `TestServerConfig`, `start`, `start_with`, and `unused_addr`. [#2112] [#2067]: https://github.com/actix/actix-web/pull/2067 [#2093]: https://github.com/actix/actix-web/pull/2093 @@ -701,50 +765,48 @@ [#2097]: https://github.com/actix/actix-web/pull/2097 [#2112]: https://github.com/actix/actix-web/pull/2112 - ## 4.0.0-beta.4 - 2021-03-09 + ### Changed + - Feature `cookies` is now optional and enabled by default. [#1981] -- `JsonBody::new` returns a default limit of 32kB to be consistent with `JsonConfig` and the default - behaviour of the `web::Json` extractor. [#2010] +- `JsonBody::new` returns a default limit of 32kB to be consistent with `JsonConfig` and the default behaviour of the `web::Json` extractor. [#2010] [#1981]: https://github.com/actix/actix-web/pull/1981 [#2010]: https://github.com/actix/actix-web/pull/2010 - ## 4.0.0-beta.3 - 2021-02-10 + - Update `actix-web-codegen` to `0.5.0-beta.1`. - ## 4.0.0-beta.2 - 2021-02-10 + ### Added -- The method `Either, web::Form>::into_inner()` which returns the inner type for - whichever variant was created. Also works for `Either, web::Json>`. [#1894] + +- The method `Either, web::Form>::into_inner()` which returns the inner type for whichever variant was created. Also works for `Either, web::Json>`. [#1894] - Add `services!` macro for helping register multiple services to `App`. [#1933] - Enable registering a vec of services of the same type to `App` [#1933] ### Changed -- Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly. - Making it simpler and more performant. [#1891] + +- Rework `Responder` trait to be sync and returns `Response`/`HttpResponse` directly. Making it simpler and more performant. [#1891] - `ServiceRequest::into_parts` and `ServiceRequest::from_parts` can no longer fail. [#1893] - `ServiceRequest::from_request` can no longer fail. [#1893] - Our `Either` type now uses `Left`/`Right` variants (instead of `A`/`B`) [#1894] -- `test::{call_service, read_response, read_response_json, send_request}` take `&Service` - in argument [#1905] -- `App::wrap_fn`, `Resource::wrap_fn` and `Scope::wrap_fn` provide `&Service` in closure - argument. [#1905] +- `test::{call_service, read_response, read_response_json, send_request}` take `&Service` in argument [#1905] +- `App::wrap_fn`, `Resource::wrap_fn` and `Scope::wrap_fn` provide `&Service` in closure argument. [#1905] - `web::block` no longer requires the output is a Result. [#1957] ### Fixed + - Multiple calls to `App::data` with the same type now keeps the latest call's data. [#1906] ### Removed + - Public field of `web::Path` has been made private. [#1894] - Public field of `web::Query` has been made private. [#1894] - `TestRequest::with_header`; use `TestRequest::default().insert_header()`. [#1869] -- `AppService::set_service_data`; for custom HTTP service factories adding application data, use the - layered data model by calling `ServiceRequest::add_data_container` when handling - requests instead. [#1906] +- `AppService::set_service_data`; for custom HTTP service factories adding application data, use the layered data model by calling `ServiceRequest::add_data_container` when handling requests instead. [#1906] [#1891]: https://github.com/actix/actix-web/pull/1891 [#1893]: https://github.com/actix/actix-web/pull/1893 @@ -755,30 +817,30 @@ [#1933]: https://github.com/actix/actix-web/pull/1933 [#1957]: https://github.com/actix/actix-web/pull/1957 - ## 4.0.0-beta.1 - 2021-01-07 + ### Added -- `Compat` middleware enabling generic response body/error type of middlewares like `Logger` and - `Compress` to be used in `middleware::Condition` and `Resource`, `Scope` services. [#1865] + +- `Compat` middleware enabling generic response body/error type of middlewares like `Logger` and `Compress` to be used in `middleware::Condition` and `Resource`, `Scope` services. [#1865] ### Changed + - Update `actix-*` dependencies to tokio `1.0` based versions. [#1813] - Bumped `rand` to `0.8`. - Update `rust-tls` to `0.19`. [#1813] - Rename `Handler` to `HandlerService` and rename `Factory` to `Handler`. [#1852] -- The default `TrailingSlash` is now `Trim`, in line with existing documentation. See migration - guide for implications. [#1875] +- The default `TrailingSlash` is now `Trim`, in line with existing documentation. See migration guide for implications. [#1875] - Rename `DefaultHeaders::{content_type => add_content_type}`. [#1875] - MSRV is now 1.46.0. ### Fixed + - Added the underlying parse error to `test::read_body_json`'s panic message. [#1812] ### Removed -- Public modules `middleware::{normalize, err_handlers}`. All necessary middleware types are now - exposed directly by the `middleware` module. -- Remove `actix-threadpool` as dependency. `actix_threadpool::BlockingError` error type can be imported - from `actix_web::error` module. [#1878] + +- Public modules `middleware::{normalize, err_handlers}`. All necessary middleware types are now exposed directly by the `middleware` module. +- Remove `actix-threadpool` as dependency. `actix_threadpool::BlockingError` error type can be imported from `actix_web::error` module. [#1878] [#1812]: https://github.com/actix/actix-web/pull/1812 [#1813]: https://github.com/actix/actix-web/pull/1813 @@ -790,14 +852,17 @@
## 3.3.3 - 2021-12-18 + ### Changed + - Soft-deprecate `NormalizePath::default()`, noting upcoming behavior change in v4. [#2529] [#2529]: https://github.com/actix/actix-web/pull/2529 - ## 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] @@ -806,24 +871,27 @@ [#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 + ### Added + - Add `Either` extractor helper. [#1788] ### Changed + - 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 - ## 3.2.0 - 2020-10-30 + ### Added + - Implement `exclude_regex` for Logger middleware. [#1723] - Add request-local data extractor `web::ReqData`. [#1748] - Add ability to register closure for request middleware logging. [#1749] @@ -831,6 +899,7 @@ - Expose `on_connect` for access to the connection stream before request is handled. [#1754] ### Changed + - Updated actix-web-codegen dependency for access to new `#[route(...)]` multi-method macro. - Print non-configured `Data` type when attempting extraction. [#1743] - Re-export bytes::Buf{Mut} in web module. [#1750] @@ -843,52 +912,53 @@ [#1754]: https://github.com/actix/actix-web/pull/1754 [#1749]: https://github.com/actix/actix-web/pull/1749 - ## 3.1.0 - 2020-09-29 + ### Changed -- Add `TrailingSlash::MergeOnly` behaviour to `NormalizePath`, which allows `NormalizePath` - to retain any trailing slashes. [#1695] -- Remove bound `std::marker::Sized` from `web::Data` to support storing `Arc` - via `web::Data::from` [#1710] + +- Add `TrailingSlash::MergeOnly` behaviour to `NormalizePath`, which allows `NormalizePath` to retain any trailing slashes. [#1695] +- Remove bound `std::marker::Sized` from `web::Data` to support storing `Arc` via `web::Data::from` [#1710] ### Fixed + - `ResourceMap` debug printing is no longer infinitely recursive. [#1708] [#1695]: https://github.com/actix/actix-web/pull/1695 [#1708]: https://github.com/actix/actix-web/pull/1708 [#1710]: https://github.com/actix/actix-web/pull/1710 - ## 3.0.2 - 2020-09-15 + ### Fixed + - `NormalizePath` when used with `TrailingSlash::Trim` no longer trims the root path "/". [#1678] [#1678]: https://github.com/actix/actix-web/pull/1678 - ## 3.0.1 - 2020-09-13 + ### Changed + - `middleware::normalize::TrailingSlash` enum is now accessible. [#1673] [#1673]: https://github.com/actix/actix-web/pull/1673 - ## 3.0.0 - 2020-09-11 + - No significant changes from `3.0.0-beta.4`. - ## 3.0.0-beta.4 - 2020-09-09 + ### Added -- `middleware::NormalizePath` now has configurable behavior for either always having a trailing - slash, or as the new addition, always trimming trailing slashes. [#1639] + +- `middleware::NormalizePath` now has configurable behavior for either always having a trailing slash, or as the new addition, always trimming trailing slashes. [#1639] ### Changed + - Update actix-codec and actix-utils dependencies. [#1634] -- `FormConfig` and `JsonConfig` configurations are now also considered when set - using `App::data`. [#1641] +- `FormConfig` and `JsonConfig` configurations are now also considered when set using `App::data`. [#1641] - `HttpServer::maxconn` is renamed to the more expressive `HttpServer::max_connections`. [#1655] -- `HttpServer::maxconnrate` is renamed to the more expressive - `HttpServer::max_connection_rate`. [#1655] +- `HttpServer::maxconnrate` is renamed to the more expressive `HttpServer::max_connection_rate`. [#1655] [#1639]: https://github.com/actix/actix-web/pull/1639 [#1641]: https://github.com/actix/actix-web/pull/1641 @@ -896,22 +966,23 @@ [#1655]: https://github.com/actix/actix-web/pull/1655 ## 3.0.0-beta.3 - 2020-08-17 + ### Changed + - Update `rustls` to 0.18 - ## 3.0.0-beta.2 - 2020-08-17 + ### Changed -- `PayloadConfig` is now also considered in `Bytes` and `String` extractors when set - using `App::data`. [#1610] -- `web::Path` now has a public representation: `web::Path(pub T)` that enables - destructuring. [#1594] -- `ServiceRequest::app_data` allows retrieval of non-Data data without splitting into parts to - access `HttpRequest` which already allows this. [#1618] + +- `PayloadConfig` is now also considered in `Bytes` and `String` extractors when set using `App::data`. [#1610] +- `web::Path` now has a public representation: `web::Path(pub T)` that enables destructuring. [#1594] +- `ServiceRequest::app_data` allows retrieval of non-Data data without splitting into parts to access `HttpRequest` which already allows this. [#1618] - Re-export all error types from `awc`. [#1621] - MSRV is now 1.42.0. ### Fixed + - Memory leak of app data in pooled requests. [#1609] [#1594]: https://github.com/actix/actix-web/pull/1594 @@ -920,28 +991,32 @@ [#1618]: https://github.com/actix/actix-web/pull/1618 [#1621]: https://github.com/actix/actix-web/pull/1621 - ## 3.0.0-beta.1 - 2020-07-13 + ### Added + - Re-export `actix_rt::main` as `actix_web::main`. -- `HttpRequest::match_pattern` and `ServiceRequest::match_pattern` for extracting the matched - resource pattern. +- `HttpRequest::match_pattern` and `ServiceRequest::match_pattern` for extracting the matched resource pattern. - `HttpRequest::match_name` and `ServiceRequest::match_name` for extracting matched resource name. ### Changed + - Fix actix_http::h1::dispatcher so it returns when HW_BUFFER_SIZE is reached. Should reduce peak memory consumption during large uploads. [#1550] - Migrate cookie handling to `cookie` crate. Actix-web no longer requires `ring` dependency. - MSRV is now 1.41.1 ### Fixed + - `NormalizePath` improved consistency when path needs slashes added _and_ removed. - ## 3.0.0-alpha.3 - 2020-05-21 + ### Added + - Add option to create `Data` from `Arc` [#1509] ### Changed + - Resources and Scopes can now access non-overridden data types set on App (or containing scopes) when setting their own data. [#1486] - Fix audit issue logging by default peer address [#1485] - Bump minimum supported Rust version to 1.40 @@ -964,7 +1039,6 @@ [#1452]: https://github.com/actix/actix-web/pull/1452 [#1486]: https://github.com/actix/actix-web/pull/1486 - ## [3.0.0-alpha.1] - 2020-03-11 ### Added @@ -1010,7 +1084,6 @@ - Fix `AppConfig::secure()` is always false. #1202 - ## [2.0.0-alpha.6] - 2019-12-15 ### Fixed @@ -1035,7 +1108,6 @@ - Migrate to tokio 0.2 - ## [2.0.0-alpha.1] - 2019-11-22 ### Changed @@ -1044,7 +1116,6 @@ - Remove implementation of `Responder` for `()`. (#1167) - ## [1.0.9] - 2019-11-14 ### Added @@ -1055,20 +1126,17 @@ - Support `Host` guards when the `Host` header is unset (e.g. HTTP/2 requests) (#1129) - ## [1.0.8] - 2019-09-25 ### Added -- Add `Scope::register_data` and `Resource::register_data` methods, parallel to - `App::register_data`. +- Add `Scope::register_data` and `Resource::register_data` methods, parallel to `App::register_data`. - Add `middleware::Condition` that conditionally enables another middleware - Allow to re-construct `ServiceRequest` from `HttpRequest` and `Payload` -- Add `HttpServer::listen_uds` for ability to listen on UDS FD rather than path, - which is useful for example with systemd. +- Add `HttpServer::listen_uds` for ability to listen on UDS FD rather than path, which is useful for example with systemd. ### Changed @@ -1076,14 +1144,12 @@ - Use actix-testing for testing utils - ## [1.0.7] - 2019-08-29 ### Fixed - Request Extensions leak #1062 - ## [1.0.6] - 2019-08-28 ### Added @@ -1094,8 +1160,7 @@ - Add `into_inner` to `Data` -- Add `test::TestRequest::set_form()` convenience method to automatically serialize data and set - the header in test requests. +- Add `test::TestRequest::set_form()` convenience method to automatically serialize data and set the header in test requests. ### Changed @@ -1107,35 +1172,30 @@ - Update url to 2.1 - ## [1.0.5] - 2019-07-18 ### Added - Unix domain sockets (HttpServer::bind_uds) #92 -- Actix now logs errors resulting in "internal server error" responses always, with the `error` - logging level +- 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 - 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. +- 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 @@ -1144,8 +1204,7 @@ ### Changed -- Use `encoding_rs` crate instead of unmaintained `encoding` crate - +- Use `encoding_rs` crate instead of unmaintained `encoding` crate ## [1.0.2] - 2019-06-17 @@ -1155,7 +1214,6 @@ - Move identity middleware to `actix-identity` crate. - ## [1.0.1] - 2019-06-17 ### Added @@ -1180,7 +1238,6 @@ - HttpRequest::url_for is broken with nested scopes #915 - ## [1.0.0] - 2019-06-05 ### Added @@ -1189,8 +1246,7 @@ - Add `ServiceRequest::set_payload()` method. -- Add `test::TestRequest::set_json()` convenience method to automatically - serialize data and set header in test requests. +- Add `test::TestRequest::set_json()` convenience method to automatically serialize data and set header in test requests. - Add macros for head, options, trace, connect and patch http methods @@ -1204,7 +1260,6 @@ - Clear http requests pool on app service drop #860 - ## [1.0.0-rc] - 2019-05-18 ### Added @@ -1220,7 +1275,6 @@ - Codegen with parameters in the path only resolves the first registered endpoint #841 - ## [1.0.0-beta.4] - 2019-05-12 ### Added @@ -1232,7 +1286,6 @@ - `App::configure` take an `FnOnce` instead of `Fn` - Upgrade actix-net crates - ## [1.0.0-beta.3] - 2019-05-04 ### Added @@ -1241,11 +1294,9 @@ ### Changed -- Extractor configuration could be registered with `App::data()` - or with `Resource::data()` #775 +- Extractor configuration could be registered with `App::data()` or with `Resource::data()` #775 -- Route data is unified with app data, `Route::data()` moved to resource - level to `Resource::data()` +- Route data is unified with app data, `Route::data()` moved to resource level to `Resource::data()` - CORS handling without headers #702 @@ -1259,7 +1310,6 @@ - `App::data_factory()` is deleted. - ## [1.0.0-beta.2] - 2019-04-24 ### Added @@ -1268,7 +1318,7 @@ - Add helper functions for reading response body `test::read_body()` -- Add support for `remainder match` (i.e "/path/{tail}*") +- Add support for `remainder match` (i.e "/path/{tail}\*") - Extend `Responder` trait, allow to override status code and headers. @@ -1282,13 +1332,11 @@ - Fix async web::Data factory handling - ## [1.0.0-beta.1] - 2019-04-20 ### Added -- Add helper functions for reading test response body, - `test::read_response()` and test::read_response_json()` +- Add helper functions for reading test response body, `test::read_response()` and test::read_response_json()` - Add `.peer_addr()` #744 @@ -1308,7 +1356,6 @@ - Fixed `TestRequest::app_data()` - ## [1.0.0-alpha.6] - 2019-04-14 ### Changed @@ -1317,12 +1364,10 @@ - Remove generic type for request payload, always use default. -- Removed `Decompress` middleware. Bytes, String, Json, Form extractors - automatically decompress payload. +- Removed `Decompress` middleware. Bytes, String, Json, Form extractors automatically decompress payload. - Make extractor config type explicit. Add `FromRequest::Config` associated type. - ## [1.0.0-alpha.5] - 2019-04-12 ### Added @@ -1333,7 +1378,6 @@ - Removed native-tls support - ## [1.0.0-alpha.4] - 2019-04-08 ### Added @@ -1356,7 +1400,6 @@ - Fix body propagation in Response::from_error. #760 - ## [1.0.0-alpha.3] - 2019-04-02 ### Changed @@ -1371,7 +1414,6 @@ - Removed unused `actix_web::web::md()` - ## [1.0.0-alpha.2] - 2019-03-29 ### Added diff --git a/actix-web/MIGRATION-0.x.md b/actix-web/MIGRATION-0.x.md index 1b60c36d1..6af514642 100644 --- a/actix-web/MIGRATION-0.x.md +++ b/actix-web/MIGRATION-0.x.md @@ -1,7 +1,6 @@ # 0.7.15 -- The `' '` character is not percent decoded anymore before matching routes. If you need to use it in - your routes, you should use `%20`. +- The `' '` character is not percent decoded anymore before matching routes. If you need to use it in your routes, you should use `%20`. instead of @@ -29,13 +28,11 @@ fn main() { # 0.7.4 -- `Route::with_config()`/`Route::with_async_config()` always passes configuration objects as tuple - even for handler with one parameter. +- `Route::with_config()`/`Route::with_async_config()` always passes configuration objects as tuple even for handler with one parameter. # 0.7 -- `HttpRequest` does not implement `Stream` anymore. If you need to read request payload - use `HttpMessage::payload()` method. +- `HttpRequest` does not implement `Stream` anymore. If you need to read request payload use `HttpMessage::payload()` method. instead of @@ -60,8 +57,7 @@ fn index(req: HttpRequest) -> impl Responder { } ``` -- [Middleware](https://actix.rs/actix-web/actix_web/middleware/trait.Middleware.html) - trait uses `&HttpRequest` instead of `&mut HttpRequest`. +- [Middleware](https://actix.rs/actix-web/actix_web/middleware/trait.Middleware.html) trait uses `&HttpRequest` instead of `&mut HttpRequest`. - Removed `Route::with2()` and `Route::with3()` use tuple of extractors instead. @@ -81,14 +77,11 @@ fn index((query, json): (Query<..>, Json impl Responder {} - `Handler::handle()` accepts reference to `HttpRequest<_>` instead of value -- Removed deprecated `HttpServer::threads()`, use - [HttpServer::workers()](https://actix.rs/actix-web/actix_web/server/struct.HttpServer.html#method.workers) instead. +- Removed deprecated `HttpServer::threads()`, use [HttpServer::workers()](https://actix.rs/actix-web/actix_web/server/struct.HttpServer.html#method.workers) instead. -- Renamed `client::ClientConnectorError::Connector` to - `client::ClientConnectorError::Resolver` +- Renamed `client::ClientConnectorError::Connector` to `client::ClientConnectorError::Resolver` -- `Route::with()` does not return `ExtractorConfig`, to configure - extractor use `Route::with_config()` +- `Route::with()` does not return `ExtractorConfig`, to configure extractor use `Route::with_config()` instead of @@ -116,23 +109,19 @@ fn main() { } ``` -- `Route::with_async()` does not return `ExtractorConfig`, to configure - extractor use `Route::with_async_config()` +- `Route::with_async()` does not return `ExtractorConfig`, to configure extractor use `Route::with_async_config()` # 0.6 - `Path` extractor return `ErrorNotFound` on failure instead of `ErrorBadRequest` -- `ws::Message::Close` now includes optional close reason. - `ws::CloseCode::Status` and `ws::CloseCode::Empty` have been removed. +- `ws::Message::Close` now includes optional close reason. `ws::CloseCode::Status` and `ws::CloseCode::Empty` have been removed. - `HttpServer::threads()` renamed to `HttpServer::workers()`. -- `HttpServer::start_ssl()` and `HttpServer::start_tls()` deprecated. - Use `HttpServer::bind_ssl()` and `HttpServer::bind_tls()` instead. +- `HttpServer::start_ssl()` and `HttpServer::start_tls()` deprecated. Use `HttpServer::bind_ssl()` and `HttpServer::bind_tls()` instead. -- `HttpRequest::extensions()` returns read only reference to the request's Extension - `HttpRequest::extensions_mut()` returns mutable reference. +- `HttpRequest::extensions()` returns read only reference to the request's Extension `HttpRequest::extensions_mut()` returns mutable reference. - Instead of @@ -146,8 +135,7 @@ fn main() { - `FromRequest::Result` has to implement `Into>` -- [`Responder::respond_to()`](https://actix.rs/actix-web/actix_web/trait.Responder.html#tymethod.respond_to) - is generic over `S` +- [`Responder::respond_to()`](https://actix.rs/actix-web/actix_web/trait.Responder.html#tymethod.respond_to) is generic over `S` - Use `Query` extractor instead of HttpRequest::query()`. @@ -163,23 +151,19 @@ or let q = Query::>::extract(req); ``` -- Websocket operations are implemented as `WsWriter` trait. - you need to use `use actix_web::ws::WsWriter` +- Websocket operations are implemented as `WsWriter` trait. you need to use `use actix_web::ws::WsWriter` # 0.5 -- `HttpResponseBuilder::body()`, `.finish()`, `.json()` - methods return `HttpResponse` instead of `Result` +- `HttpResponseBuilder::body()`, `.finish()`, `.json()` methods return `HttpResponse` instead of `Result` -- `actix_web::Method`, `actix_web::StatusCode`, `actix_web::Version` - moved to `actix_web::http` module +- `actix_web::Method`, `actix_web::StatusCode`, `actix_web::Version` moved to `actix_web::http` module - `actix_web::header` moved to `actix_web::http::header` - `NormalizePath` moved to `actix_web::http` module -- `HttpServer` moved to `actix_web::server`, added new `actix_web::server::new()` function, - shortcut for `actix_web::server::HttpServer::new()` +- `HttpServer` moved to `actix_web::server`, added new `actix_web::server::new()` function, shortcut for `actix_web::server::HttpServer::new()` - `DefaultHeaders` middleware does not use separate builder, all builder methods moved to type itself @@ -187,11 +171,9 @@ let q = Query::>::extract(req); - `CookieSessionBackendBuilder` removed, all methods moved to `CookieSessionBackend` type -- `actix_web::httpcodes` module is deprecated, `HttpResponse::Ok()`, `HttpResponse::Found()` and other `HttpResponse::XXX()` - functions should be used instead +- `actix_web::httpcodes` module is deprecated, `HttpResponse::Ok()`, `HttpResponse::Found()` and other `HttpResponse::XXX()` functions should be used instead -- `ClientRequestBuilder::body()` returns `Result<_, actix_web::Error>` - instead of `Result<_, http::Error>` +- `ClientRequestBuilder::body()` returns `Result<_, actix_web::Error>` instead of `Result<_, http::Error>` - `Application` renamed to a `App` diff --git a/actix-web/MIGRATION-1.0.md b/actix-web/MIGRATION-1.0.md index 94c6321ac..d72bb63b6 100644 --- a/actix-web/MIGRATION-1.0.md +++ b/actix-web/MIGRATION-1.0.md @@ -88,8 +88,7 @@ ) ``` -- Resource registration. 1.0 version uses generalized resource - registration via `.service()` method. +- Resource registration. 1.0 version uses generalized resource registration via `.service()` method. instead of @@ -97,9 +96,7 @@ App.new().resource("/welcome", |r| r.f(welcome)) ``` - use App's or Scope's `.service()` method. `.service()` method accepts - object that implements `HttpServiceFactory` trait. By default - actix-web provides `Resource` and `Scope` services. + use App's or Scope's `.service()` method. `.service()` method accepts object that implements `HttpServiceFactory` trait. By default actix-web provides `Resource` and `Scope` services. ```rust App.new().service( @@ -164,9 +161,7 @@ } ``` -- `.f()`, `.a()` and `.h()` handler registration methods have been removed. - Use `.to()` for handlers and `.to_async()` for async handlers. Handler function - must use extractors. +- `.f()`, `.a()` and `.h()` handler registration methods have been removed. Use `.to()` for handlers and `.to_async()` for async handlers. Handler function must use extractors. instead of @@ -210,9 +205,7 @@ } ``` -- `State` is now `Data`. You register Data during the App initialization process - and then access it from handlers either using a Data extractor or using - HttpRequest's api. +- `State` is now `Data`. You register Data during the App initialization process and then access it from handlers either using a Data extractor or using HttpRequest's api. instead of @@ -277,8 +270,7 @@ .route("/index.html", web::get().to(index)); ``` -- `HttpRequest::body()`, `HttpRequest::urlencoded()`, `HttpRequest::json()`, `HttpRequest::multipart()` - method have been removed. Use `Bytes`, `String`, `Form`, `Json`, `Multipart` extractors instead. +- `HttpRequest::body()`, `HttpRequest::urlencoded()`, `HttpRequest::json()`, `HttpRequest::multipart()` method have been removed. Use `Bytes`, `String`, `Form`, `Json`, `Multipart` extractors instead. instead of @@ -317,8 +309,7 @@ use `use actix_multipart::Multipart` -- Response compression is not enabled by default. - To enable, use `Compress` middleware, `App::new().wrap(Compress::default())`. +- Response compression is not enabled by default. To enable, use `Compress` middleware, `App::new().wrap(Compress::default())`. - Session middleware moved to actix-session crate diff --git a/actix-web/MIGRATION-2.0.md b/actix-web/MIGRATION-2.0.md index 3af5f6e1a..41e6104b9 100644 --- a/actix-web/MIGRATION-2.0.md +++ b/actix-web/MIGRATION-2.0.md @@ -1,21 +1,16 @@ # Migrating to 2.0.0 -- `HttpServer::start()` renamed to `HttpServer::run()`. It also possible to - `.await` on `run` method result, in that case it awaits server exit. +- `HttpServer::start()` renamed to `HttpServer::run()`. It also possible to `.await` on `run` method result, in that case it awaits server exit. -- `App::register_data()` renamed to `App::app_data()` and accepts any type `T: 'static`. - Stored data is available via `HttpRequest::app_data()` method at runtime. +- `App::register_data()` renamed to `App::app_data()` and accepts any type `T: 'static`. Stored data is available via `HttpRequest::app_data()` method at runtime. - Extractor configuration must be registered with `App::app_data()` instead of `App::data()` -- Sync handlers has been removed. `.to_async()` method has been renamed to `.to()` - replace `fn` with `async fn` to convert sync handler to async +- Sync handlers has been removed. `.to_async()` method has been renamed to `.to()` replace `fn` with `async fn` to convert sync handler to async -- `actix_http_test::TestServer` moved to `actix_web::test` module. To start - test server use `test::start()` or `test_start_with_config()` methods +- `actix_http_test::TestServer` moved to `actix_web::test` module. To start test server use `test::start()` or `test_start_with_config()` methods -- `ResponseError` trait has been refactored. `ResponseError::error_response()` renders - http response. +- `ResponseError` trait has been refactored. `ResponseError::error_response()` renders http response. - Feature `rust-tls` renamed to `rustls` diff --git a/actix-web/MIGRATION-3.0.md b/actix-web/MIGRATION-3.0.md index 54bcd58bd..89255e434 100644 --- a/actix-web/MIGRATION-3.0.md +++ b/actix-web/MIGRATION-3.0.md @@ -1,31 +1,23 @@ # Migrating to 3.0.0 -- The return type for `ServiceRequest::app_data::()` was changed from returning a `Data` to - simply a `T`. To access a `Data` use `ServiceRequest::app_data::>()`. +- The return type for `ServiceRequest::app_data::()` was changed from returning a `Data` to simply a `T`. To access a `Data` use `ServiceRequest::app_data::>()`. - Cookie handling has been offloaded to the `cookie` crate: - `USERINFO_ENCODE_SET` is no longer exposed. Percent-encoding is still supported; check docs. - Some types now require lifetime parameters. -- The time crate was updated to `v0.2`, a major breaking change to the time crate, which affects - any `actix-web` method previously expecting a time v0.1 input. +- The time crate was updated to `v0.2`, a major breaking change to the time crate, which affects any `actix-web` method previously expecting a time v0.1 input. -- Setting a cookie's SameSite property, explicitly, to `SameSite::None` will now - result in `SameSite=None` being sent with the response Set-Cookie header. - To create a cookie without a SameSite attribute, remove any calls setting same_site. +- Setting a cookie's SameSite property, explicitly, to `SameSite::None` will now result in `SameSite=None` being sent with the response Set-Cookie header. To create a cookie without a SameSite attribute, remove any calls setting same_site. -- actix-http support for Actors messages was moved to actix-http crate and is enabled - with feature `actors` +- actix-http support for Actors messages was moved to actix-http crate and is enabled with feature `actors` -- content_length function is removed from actix-http. - You can set Content-Length by normally setting the response body or calling no_chunking function. +- content_length function is removed from actix-http. You can set Content-Length by normally setting the response body or calling no_chunking function. -- `BodySize::Sized64` variant has been removed. `BodySize::Sized` now receives a - `u64` instead of a `usize`. +- `BodySize::Sized64` variant has been removed. `BodySize::Sized` now receives a `u64` instead of a `usize`. -- Code that was using `path.` to access a `web::Path<(A, B, C)>`s elements now needs to use - destructuring or `.into_inner()`. For example: +- Code that was using `path.` to access a `web::Path<(A, B, C)>`s elements now needs to use destructuring or `.into_inner()`. For example: ```rust // Previously: @@ -44,9 +36,7 @@ } ``` -- `middleware::NormalizePath` can now also be configured to trim trailing slashes instead of always keeping one. - It will need `middleware::normalize::TrailingSlash` when being constructed with `NormalizePath::new(...)`, - or for an easier migration you can replace `wrap(middleware::NormalizePath)` with `wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly))`. +- `middleware::NormalizePath` can now also be configured to trim trailing slashes instead of always keeping one. It will need `middleware::normalize::TrailingSlash` when being constructed with `NormalizePath::new(...)`, or for an easier migration you can replace `wrap(middleware::NormalizePath)` with `wrap(middleware::NormalizePath::new(TrailingSlash::MergeOnly))`. - `HttpServer::maxconn` is renamed to the more expressive `HttpServer::max_connections`. diff --git a/actix-web/MIGRATION-4.0.md b/actix-web/MIGRATION-4.0.md index fbeae0680..7b1cfc03b 100644 --- a/actix-web/MIGRATION-4.0.md +++ b/actix-web/MIGRATION-4.0.md @@ -31,7 +31,7 @@ Headings marked with :warning: are **breaking behavioral changes**. They will pr - [Returning `HttpResponse` synchronously](#returning-httpresponse-synchronously) - [`#[actix_web::main]` and `#[tokio::main]`](#actix_webmain-and-tokiomain) - [`web::block`](#webblock) -- +- ## MSRV diff --git a/actix-web/README.md b/actix-web/README.md index 20ca66fad..a92837c3b 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -5,16 +5,7 @@

-[![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=4.3.0)](https://docs.rs/actix-web/4.3.0) -![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) -![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.3.0/status.svg)](https://deps.rs/crate/actix-web/4.3.0) -
-[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) -[![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) -![downloads](https://img.shields.io/crates/d/actix-web.svg) -[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) +[![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=4.3.0)](https://docs.rs/actix-web/4.3.0) ![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.0/status.svg)](https://deps.rs/crate/actix-web/4.3.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

diff --git a/actix-web/examples/uds.rs b/actix-web/examples/uds.rs index ba4b25a29..15e28ba1d 100644 --- a/actix-web/examples/uds.rs +++ b/actix-web/examples/uds.rs @@ -41,7 +41,7 @@ async fn main() -> std::io::Result<()> { ) .service(web::resource("/test1.html").to(|| async { "Test\r\n" })) }) - .bind_uds("/Users/fafhrd91/uds-test")? + .bind_uds("/Users/me/uds-test")? .workers(1) .run() .await diff --git a/actix-web/src/middleware/authors-guide.md b/actix-web/src/middleware/authors-guide.md index a8d1edea4..64bad15c2 100644 --- a/actix-web/src/middleware/authors-guide.md +++ b/actix-web/src/middleware/authors-guide.md @@ -13,4 +13,5 @@ ## When To (Not) Use Middleware ## Author's References + - `EitherBody` + when is middleware appropriate: https://discord.com/channels/771444961383153695/952016890723729428 diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 6d313ea2f..ad5cd9996 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,27 +1,33 @@ # Changes ## Unreleased - 2023-xx-xx + ### Changed + - `client::Connect` is now public to allow tunneling connection with `client::Connector`. - ## 3.1.0 - 2023-01-21 + ### Changed + - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. - ## 3.0.1 - 2022-08-25 + ### Changed + - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. ### Fixed + - Fixed handling of redirection requests that begin with `//`. [#2840] [#2840]: https://github.com/actix/actix-web/pull/2840 - ## 3.0.0 - 2022-03-07 + ### Dependencies + - Updated `actix-*` to Tokio v1-based versions. [#1813] - Updated `bytes` to `1.0`. [#1813] - Updated `cookie` to `0.16`. [#2555] @@ -30,6 +36,7 @@ - Updated `tokio` to `1`. ### Added + - `trust-dns` crate feature to enable `trust-dns-resolver` as client DNS resolver; disabled by default. [#1969] - `cookies` crate feature; enabled by default. [#2619] - `compress-brotli` crate feature; enabled by default. [#2250] @@ -46,6 +53,7 @@ - `ClientBuilder::add_default_header()` (and deprecate `ClientBuilder::header()`). [#2510] ### Changed + - `client::Connector` type now only has one generic type for `actix_service::Service`. [#2063] - `client::error::ConnectError` Resolver variant contains `Box` type. [#1905] - `client::ConnectorConfig` default timeout changed to 5 seconds. [#1905] @@ -63,6 +71,7 @@ - Minimum supported Rust version (MSRV) is now 1.54. ### Fixed + - Send headers along with redirected requests. [#2310] - Improve `Client` instantiation efficiency when using `openssl` by only building connectors once. [#2503] - Remove unnecessary `Unpin` bounds on `*::send_stream`. [#2553] @@ -71,6 +80,7 @@ - `impl Stream` for `ClientResponse` no longer requires the body type be `Unpin`. [#2546] ### Removed + - `compress` crate feature. [#2250] - `ClientRequest::set`; use `ClientRequest::insert_header`. [#1869] - `ClientRequest::set_header`; use `ClientRequest::insert_header`. [#1869] @@ -80,10 +90,10 @@ - `ClientBuilder::default` function [#2008] ### Security + - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html - [#1813]: https://github.com/actix/actix-web/pull/1813 [#1869]: https://github.com/actix/actix-web/pull/1869 [#1905]: https://github.com/actix/actix-web/pull/1905 @@ -113,46 +123,48 @@ [#2553]: https://github.com/actix/actix-web/pull/2553 [#2555]: https://github.com/actix/actix-web/pull/2555 -
3.0.0 Pre-Releases ## 3.0.0-beta.21 - 2022-02-16 + - No significant changes since `3.0.0-beta.20`. - ## 3.0.0-beta.20 - 2022-01-31 + - No significant changes since `3.0.0-beta.19`. - ## 3.0.0-beta.19 - 2022-01-21 + - No significant changes since `3.0.0-beta.18`. - ## 3.0.0-beta.18 - 2022-01-04 + - Minimum supported Rust version (MSRV) is now 1.54. - ## 3.0.0-beta.17 - 2021-12-29 + ### Changed + - Update `cookie` dependency (re-exported) to `0.16`. [#2555] ### Security + - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [#2555]: https://github.com/actix/actix-web/pull/2555 [`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html - ## 3.0.0-beta.16 - 2021-12-29 + - `*::send_json` and `*::send_form` methods now receive `impl Serialize`. [#2553] - `FrozenClientRequest::extra_header` now uses receives an `impl TryIntoHeaderPair`. [#2553] - Remove unnecessary `Unpin` bounds on `*::send_stream`. [#2553] [#2553]: https://github.com/actix/actix-web/pull/2553 - ## 3.0.0-beta.15 - 2021-12-27 + - Rename `Connector::{ssl => openssl}`. [#2503] - Improve `Client` instantiation efficiency when using `openssl` by only building connectors once. [#2503] - `ClientRequest::send_body` now takes an `impl MessageBody`. [#2546] @@ -164,89 +176,96 @@ [#2503]: https://github.com/actix/actix-web/pull/2503 [#2546]: https://github.com/actix/actix-web/pull/2546 - ## 3.0.0-beta.14 - 2021-12-17 + - Add `ClientBuilder::add_default_header` and deprecate `ClientBuilder::header`. [#2510] [#2510]: https://github.com/actix/actix-web/pull/2510 - ## 3.0.0-beta.13 - 2021-12-11 + - No significant changes since `3.0.0-beta.12`. - ## 3.0.0-beta.12 - 2021-11-30 + - Update `actix-tls` to `3.0.0-rc.1`. [#2474] [#2474]: https://github.com/actix/actix-web/pull/2474 - ## 3.0.0-beta.11 - 2021-11-22 + - No significant changes from `3.0.0-beta.10`. - ## 3.0.0-beta.10 - 2021-11-15 + - No significant changes from `3.0.0-beta.9`. - ## 3.0.0-beta.9 - 2021-10-20 + - Updated rustls to v0.20. [#2414] [#2414]: https://github.com/actix/actix-web/pull/2414 - ## 3.0.0-beta.8 - 2021-09-09 + ### Changed + - Send headers within the redirect requests. [#2310] [#2310]: https://github.com/actix/actix-web/pull/2310 - ## 3.0.0-beta.7 - 2021-06-26 + ### Changed + - Change compression algorithm features flags. [#2250] [#2250]: https://github.com/actix/actix-web/pull/2250 - ## 3.0.0-beta.6 - 2021-06-17 + - No significant changes since 3.0.0-beta.5. - ## 3.0.0-beta.5 - 2021-04-17 + ### Removed + - Deprecated methods on `ClientRequest`: `if_true`, `if_some`. [#2148] [#2148]: https://github.com/actix/actix-web/pull/2148 - ## 3.0.0-beta.4 - 2021-04-02 + ### Added + - Add `Client::headers` to get default mut reference of `HeaderMap` of client object. [#2114] ### Changed + - `ConnectorService` type is renamed to `BoxConnectorService`. [#2081] - Fix http/https encoding when enabling `compress` feature. [#2116] -- Rename `TestResponse::header` to `append_header`, `set` to `insert_header`. `TestResponse` header - methods now take `TryIntoHeaderPair` tuples. [#2094] +- Rename `TestResponse::header` to `append_header`, `set` to `insert_header`. `TestResponse` header methods now take `TryIntoHeaderPair` tuples. [#2094] [#2081]: https://github.com/actix/actix-web/pull/2081 [#2094]: https://github.com/actix/actix-web/pull/2094 [#2114]: https://github.com/actix/actix-web/pull/2114 [#2116]: https://github.com/actix/actix-web/pull/2116 - ## 3.0.0-beta.3 - 2021-03-08 + ### Added + - `ClientResponse::timeout` for set the timeout of collecting response body. [#1931] - `ClientBuilder::local_address` for bind to a local ip address for this client. [#2024] ### Changed + - Feature `cookies` is now optional and enabled by default. [#1981] - `ClientBuilder::connector` method would take `actix_http::client::Connector` type. [#2008] - Basic auth password now takes blank passwords as an empty string instead of Option. [#2050] ### Removed + - `ClientBuilder::default` function [#2008] [#1931]: https://github.com/actix/actix-web/pull/1931 @@ -255,17 +274,20 @@ [#2024]: https://github.com/actix/actix-web/pull/2024 [#2050]: https://github.com/actix/actix-web/pull/2050 - ## 3.0.0-beta.2 - 2021-02-10 + ### Added + - `ClientRequest::insert_header` method which allows using typed headers. [#1869] - `ClientRequest::append_header` method which allows using typed headers. [#1869] - `trust-dns` optional feature to enable `trust-dns-resolver` as client dns resolver. [#1969] ### Changed + - Relax default timeout for `Connector` to 5 seconds(original 1 second). [#1905] ### Removed + - `ClientRequest::set`; use `ClientRequest::insert_header`. [#1869] - `ClientRequest::set_header`; use `ClientRequest::insert_header`. [#1869] - `ClientRequest::set_header_if_none`; use `ClientRequest::insert_header_if_none`. [#1869] @@ -275,9 +297,10 @@ [#1905]: https://github.com/actix/actix-web/pull/1905 [#1969]: https://github.com/actix/actix-web/pull/1969 - ## 3.0.0-beta.1 - 2021-01-07 + ### Changed + - Update `rand` to `0.8` - Update `bytes` to `1.0`. [#1813] - Update `rust-tls` to `0.19`. [#1813] @@ -287,53 +310,62 @@
## 2.0.3 - 2020-11-29 + ### Fixed + - Ensure `actix-http` dependency uses same `serde_urlencoded`. - ## 2.0.2 - 2020-11-25 + ### Changed + - Upgrade `serde_urlencoded` to `0.7`. [#1773] [#1773]: https://github.com/actix/actix-web/pull/1773 - ## 2.0.1 - 2020-10-30 + ### Changed + - Upgrade `base64` to `0.13`. [#1744] - Deprecate `ClientRequest::{if_some, if_true}`. [#1760] ### Fixed -- Use `Accept-Encoding: identity` instead of `Accept-Encoding: br` when no compression feature - is enabled [#1737] + +- Use `Accept-Encoding: identity` instead of `Accept-Encoding: br` when no compression feature is enabled [#1737] [#1737]: https://github.com/actix/actix-web/pull/1737 [#1760]: https://github.com/actix/actix-web/pull/1760 [#1744]: https://github.com/actix/actix-web/pull/1744 - ## 2.0.0 - 2020-09-11 + ### Changed + - `Client::build` was renamed to `Client::builder`. - ## 2.0.0-beta.4 - 2020-09-09 + ### Changed + - Update actix-codec & actix-tls dependencies. - ## 2.0.0-beta.3 - 2020-08-17 + ### Changed + - Update `rustls` to 0.18 - ## 2.0.0-beta.2 - 2020-07-21 + ### Changed + - Update `actix-http` dependency to 2.0.0-beta.2 - ## [2.0.0-beta.1] - 2020-07-14 + ### Changed + - Update `actix-http` dependency to 2.0.0-beta.1 ## [2.0.0-alpha.2] - 2020-05-21 @@ -365,26 +397,22 @@ - Migrate to `std::future` - ## [0.2.8] - 2019-11-06 - Add support for setting query from Serialize type for client request. - ## [0.2.7] - 2019-09-25 ### Added - Remaining getter methods for `ClientRequest`'s private `head` field #1101 - ## [0.2.6] - 2019-09-12 ### Added - Export frozen request related types. - ## [0.2.5] - 2019-09-11 ### Added @@ -395,7 +423,6 @@ - Ensure that the `Host` header is set when initiating a WebSocket client connection. - ## [0.2.4] - 2019-08-13 ### Changed @@ -404,14 +431,12 @@ - Update serde_urlencoded to "0.6.1" - ## [0.2.3] - 2019-08-01 ### Added - Add `rustls` support - ## [0.2.2] - 2019-07-01 ### Changed @@ -420,7 +445,6 @@ - Upgrade `rand` dependency version to 0.7 - ## [0.2.1] - 2019-06-05 ### Added @@ -437,7 +461,6 @@ - Upgrade actix-http dependency. - ## [0.1.1] - 2019-04-19 ### Added @@ -448,19 +471,16 @@ - `ClientRequest::if_true()` and `ClientRequest::if_some()` use instance instead of ref - ## [0.1.0] - 2019-04-16 - No changes - ## [0.1.0-alpha.6] - 2019-04-14 ### Changed - Do not set default headers for websocket request - ## [0.1.0-alpha.5] - 2019-04-12 ### Changed @@ -471,14 +491,12 @@ - Add Debug impl for BoxedSocket - ## [0.1.0-alpha.4] - 2019-04-08 ### Changed - Update actix-http dependency - ## [0.1.0-alpha.3] - 2019-04-02 ### Added @@ -487,7 +505,6 @@ - `ClientResponse::json()` - Loads and parse `application/json` encoded body - ### Changed - `ClientRequest::json()` accepts reference instead of object. @@ -496,7 +513,6 @@ - Renamed `ClientRequest::close_connection()` to `ClientRequest::force_close()` - ## [0.1.0-alpha.2] - 2019-03-29 ### Added @@ -509,14 +525,12 @@ - Re-export `actix_http::client::Connector`. - ### Changed - Allow to override request's uri - Export `ws` sub-module with websockets related types - ## [0.1.0-alpha.1] - 2019-03-28 - Initial impl diff --git a/awc/README.md b/awc/README.md index cbe9af26a..99b845eac 100644 --- a/awc/README.md +++ b/awc/README.md @@ -12,7 +12,7 @@ - [API Documentation](https://docs.rs/awc) - [Example Project](https://github.com/actix/examples/tree/master/https-tls/awc-https) -- Minimum Supported Rust Version (MSRV): 1.54 +- Minimum Supported Rust Version (MSRV): 1.59 ## Example diff --git a/scripts/bump b/scripts/bump index 33ea52010..87fd50856 100755 --- a/scripts/bump +++ b/scripts/bump @@ -51,7 +51,6 @@ cat "$CHANGELOG_FILE" | if [ "$(wc -w "$CHANGE_CHUNK_FILE" | awk '{ print $1 }')" = "0" ]; then echo "- No significant changes since \`$CURRENT_VERSION\`." >"$CHANGE_CHUNK_FILE" echo >>"$CHANGE_CHUNK_FILE" - echo >>"$CHANGE_CHUNK_FILE" fi if [ -n "${2-}" ]; then @@ -82,14 +81,17 @@ sed -i.bak -E "s/^version ?= ?\"[^\"]+\"$/version = \"$NEW_VERSION\"/" "$CARGO_M ( sed '/Unreleased/ q' "$CHANGELOG_FILE" # up to unreleased heading echo # blank line - echo # blank line echo "## $NEW_VERSION - $DATE" # new version heading + echo # blank line cat "$CHANGE_CHUNK_FILE" # previously unreleased changes sed "/$CURRENT_VERSION/ q" "$CHANGELOG_FILE" | tail -n 1 # the previous version heading sed "1,/$CURRENT_VERSION/ d" "$CHANGELOG_FILE" # everything after previous version heading ) >"$CHANGELOG_FILE.bak" mv "$CHANGELOG_FILE.bak" "$CHANGELOG_FILE" +# format CHANGELOG file according to prettier +npx -y prettier --write "$CHANGELOG_FILE" || true + # done; remove backup files rm -f $CARGO_MANIFEST.bak rm -f $CHANGELOG_FILE.bak @@ -139,12 +141,14 @@ GIT_TAG="$(echo $SHORT_PACKAGE_NAME-v$NEW_VERSION)" RELEASE_TITLE="$(echo $PACKAGE_NAME: v$NEW_VERSION)" if [ "$(echo $NEW_VERSION | grep beta)" ] || [ "$(echo $NEW_VERSION | grep rc)" ] || [ "$(echo $NEW_VERSION | grep alpha)" ]; then - PRERELEASE="--prerelease" + FLAGS="--prerelease" +else + FLAGS="--latest" fi echo echo "GitHub release command:" -GH_CMD="gh release create \"$GIT_TAG\" --draft --title \"$RELEASE_TITLE\" --notes-file \"$CHANGE_CHUNK_FILE\" ${PRERELEASE:-}" +GH_CMD="gh release create \"$GIT_TAG\" --draft --title \"$RELEASE_TITLE\" --notes-file \"$CHANGE_CHUNK_FILE\" ${FLAGS:-}" echo "$GH_CMD" read -p "Submit draft GH release: (y/N) " GH_RELEASE From 115701eb862aa8f3f764735aefe6ad687f8102b5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 03:34:47 +0000 Subject: [PATCH 025/314] prepare awc release 3.1.1 --- actix-http/src/h1/dispatcher_tests.rs | 1 - awc/CHANGES.md | 6 ++++-- awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/actix-http/src/h1/dispatcher_tests.rs b/actix-http/src/h1/dispatcher_tests.rs index d39c5bd69..db46cdefc 100644 --- a/actix-http/src/h1/dispatcher_tests.rs +++ b/actix-http/src/h1/dispatcher_tests.rs @@ -932,7 +932,6 @@ fn http_msg(msg: impl AsRef) -> BytesMut { .as_ref() .trim() .split('\n') - .into_iter() .map(|line| [line.trim_start(), "\r"].concat()) .collect::>() .join("\n"); diff --git a/awc/CHANGES.md b/awc/CHANGES.md index ad5cd9996..03cbf61d4 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +## 3.1.1 - 2023-02-26 + ### Changed - `client::Connect` is now public to allow tunneling connection with `client::Connector`. @@ -93,7 +95,7 @@ - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. -[`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html +[`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html [#1813]: https://github.com/actix/actix-web/pull/1813 [#1869]: https://github.com/actix/actix-web/pull/1869 [#1905]: https://github.com/actix/actix-web/pull/1905 @@ -153,7 +155,7 @@ - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [#2555]: https://github.com/actix/actix-web/pull/2555 -[`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html +[`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html ## 3.0.0-beta.16 - 2021-12-29 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 00c3c87c5..c3dab92b0 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.1.0" +version = "3.1.1" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 99b845eac..a9d411067 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=3.1.0)](https://docs.rs/awc/3.1.0) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.1.1)](https://docs.rs/awc/3.1.1) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.1.0/status.svg)](https://deps.rs/crate/awc/3.1.0) +[![Dependency Status](https://deps.rs/crate/awc/3.1.1/status.svg)](https://deps.rs/crate/awc/3.1.1) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) ## Documentation & Resources From 35006e9cae904ac28ffe81e62ac2e0110346121d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 03:42:27 +0000 Subject: [PATCH 026/314] prepare actix-web-codegen release 4.2.0 --- actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 ++-- actix-web/CHANGES.md | 6 +++++- actix-web/Cargo.toml | 2 +- scripts/bump | 1 - 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 008e4c170..eb955afcf 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2022-xx-xx +## 4.2.0 - 2023-02-26 + - Add support for Custom Methods with `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index da5577445..51cb0dfef 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "4.1.0" +version = "4.2.0" description = "Routing and runtime macros for Actix Web" homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index b5eda863c..8dd3e986e 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -3,11 +3,11 @@ > Routing and runtime macros for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) -[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.1.0)](https://docs.rs/actix-web-codegen/4.1.0) +[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.0)](https://docs.rs/actix-web-codegen/4.2.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
-[![dependency status](https://deps.rs/crate/actix-web-codegen/4.1.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.1.0) +[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.0) [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 2d4b2db51..813739520 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased - 2022-xx-xx +- Add support for custom methods with the `#[route]` macro. [#2969] + +[#2969]: https://github.com/actix/actix-web/pull/2969 + ## 4.3.0 - 2023-01-21 ### Added @@ -472,7 +476,7 @@ - `cookie` upgrade addresses [`RUSTSEC-2020-0071`]. [#2555]: https://github.com/actix/actix-web/pull/2555 -[`RUSTSEC-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html +[`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html ## 4.0.0-beta.17 - 2021-12-29 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 6cb86bbdd..c0bb430ad 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -70,7 +70,7 @@ actix-tls = { version = "3", default-features = false, optional = true } actix-http = { version = "3.3", features = ["http2", "ws"] } actix-router = "0.5" -actix-web-codegen = { version = "4.1", optional = true } +actix-web-codegen = { version = "4.2", optional = true } ahash = "0.7" bytes = "1" diff --git a/scripts/bump b/scripts/bump index 87fd50856..40d43d429 100755 --- a/scripts/bump +++ b/scripts/bump @@ -82,7 +82,6 @@ sed -i.bak -E "s/^version ?= ?\"[^\"]+\"$/version = \"$NEW_VERSION\"/" "$CARGO_M sed '/Unreleased/ q' "$CHANGELOG_FILE" # up to unreleased heading echo # blank line echo "## $NEW_VERSION - $DATE" # new version heading - echo # blank line cat "$CHANGE_CHUNK_FILE" # previously unreleased changes sed "/$CURRENT_VERSION/ q" "$CHANGELOG_FILE" | tail -n 1 # the previous version heading sed "1,/$CURRENT_VERSION/ d" "$CHANGELOG_FILE" # everything after previous version heading From e35ec28cd27e34bd4cc76d843975c24231db2b59 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 03:44:34 +0000 Subject: [PATCH 027/314] prepare actix-web release 4.3.1 --- actix-web-codegen/CHANGES.md | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index eb955afcf..5bc510273 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -4,7 +4,7 @@ ## 4.2.0 - 2023-02-26 -- Add support for Custom Methods with `#[route]` macro. [#2969] +- Add support for custom methods with the `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 813739520..1eb1f02c9 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2022-xx-xx +## 4.3.1 - 2023-02-26 + - Add support for custom methods with the `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index c0bb430ad..d8d9969eb 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.3.0" +version = "4.3.1" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-web/README.md b/actix-web/README.md index a92837c3b..3c6524d36 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -5,7 +5,7 @@

-[![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=4.3.0)](https://docs.rs/actix-web/4.3.0) ![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.0/status.svg)](https://deps.rs/crate/actix-web/4.3.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) +[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

From 4e056293681c05542eef245b09984cad9deda8f0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 03:47:25 +0000 Subject: [PATCH 028/314] specify safe tokio version range --- actix-http-test/Cargo.toml | 2 +- actix-http/Cargo.toml | 4 ++-- actix-multipart/Cargo.toml | 4 ++-- actix-test/Cargo.toml | 2 +- actix-web-actors/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 23fffdc17..cd5e87162 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -47,7 +47,7 @@ serde_json = "1.0" slab = "0.4" serde_urlencoded = "0.7" tls-openssl = { version = "0.10.9", package = "openssl", optional = true } -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } [dev-dependencies] actix-web = { version = "4", default-features = false, features = ["cookies"] } diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 19302d002..71b5a600b 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -77,7 +77,7 @@ mime = "0.3" percent-encoding = "2.1" pin-project-lite = "0.2" smallvec = "1.6.1" -tokio = { version = "1.18.5", features = [] } +tokio = { version = "1.24.2", features = [] } tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } @@ -119,7 +119,7 @@ serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.9" } tls-rustls = { package = "rustls", version = "0.20.0" } -tokio = { version = "1.18.5", features = ["net", "rt", "macros"] } +tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 2a14be007..b63ab1f86 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -44,7 +44,7 @@ serde_json = "1" serde_plain = "1" # TODO(MSRV 1.60): replace with dep: prefix tempfile-dep = { package = "tempfile", version = "3.4", optional = true } -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } [dev-dependencies] actix-http = "3" @@ -53,5 +53,5 @@ actix-rt = "2.2" actix-test = "0.1" awc = "3" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } tokio-stream = "0.1" diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 213d6bc36..956005d8a 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -45,4 +45,4 @@ serde_json = "1" serde_urlencoded = "0.7" tls-openssl = { package = "openssl", version = "0.10.9", optional = true } tls-rustls = { package = "rustls", version = "0.20.0", optional = true } -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 4eb9ddc62..e89baed96 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -23,7 +23,7 @@ bytes = "1" bytestring = "1" futures-core = { version = "0.3.17", default-features = false } pin-project-lite = "0.2" -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } tokio-util = { version = "0.7", features = ["codec"] } [dev-dependencies] diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index d8d9969eb..afc7feab1 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -115,7 +115,7 @@ serde = { version = "1.0", features = ["derive"] } static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.9" } tls-rustls = { package = "rustls", version = "0.20.0" } -tokio = { version = "1.18.5", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.12" [[test]] diff --git a/awc/Cargo.toml b/awc/Cargo.toml index c3dab92b0..0c3027c99 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -80,7 +80,7 @@ rand = "0.8" serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" -tokio = { version = "1.18.5", features = ["sync"] } +tokio = { version = "1.24.2", features = ["sync"] } cookie = { version = "0.16", features = ["percent-encode"], optional = true } @@ -106,7 +106,7 @@ futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" rcgen = "0.9" rustls-pemfile = "1" -tokio = { version = "1.18.5", features = ["rt-multi-thread", "macros"] } +tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.12" [[example]] From fdfb3d45dbf85e7b4ecd1b2dacfec11bf584a7dd Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 03:50:36 +0000 Subject: [PATCH 029/314] remove direct dep on ahash for client pool --- actix-http/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 1 - awc/src/client/pool.rs | 7 +++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 71b5a600b..108b2314a 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -61,7 +61,7 @@ actix-codec = "0.5" actix-utils = "3" actix-rt = { version = "2.2", default-features = false } -ahash = "0.7" +ahash = "0.8" bitflags = "1.2" bytes = "1" bytestring = "1" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index afc7feab1..6eb1f862b 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -72,7 +72,7 @@ actix-http = { version = "3.3", features = ["http2", "ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } -ahash = "0.7" +ahash = "0.8" bytes = "1" bytestring = "1" cfg-if = "1" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 0c3027c99..8a75e28f7 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -62,7 +62,6 @@ actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3", features = ["connect", "uri"] } actix-utils = "3" -ahash = "0.7" base64 = "0.21" bytes = "1" cfg-if = "1" diff --git a/awc/src/client/pool.rs b/awc/src/client/pool.rs index 47c1fdd67..632608c45 100644 --- a/awc/src/client/pool.rs +++ b/awc/src/client/pool.rs @@ -2,7 +2,7 @@ use std::{ cell::RefCell, - collections::VecDeque, + collections::{HashMap, VecDeque}, future::Future, io, ops::Deref, @@ -17,7 +17,6 @@ use actix_codec::{AsyncRead, AsyncWrite, ReadBuf}; use actix_http::Protocol; use actix_rt::time::{sleep, Sleep}; use actix_service::Service; -use ahash::AHashMap; use futures_core::future::LocalBoxFuture; use futures_util::FutureExt as _; use http::uri::Authority; @@ -62,7 +61,7 @@ where { fn new(config: ConnectorConfig) -> Self { let permits = Arc::new(Semaphore::new(config.limit)); - let available = RefCell::new(AHashMap::default()); + let available = RefCell::new(HashMap::default()); Self(Rc::new(ConnectionPoolInnerPriv { config, @@ -124,7 +123,7 @@ where Io: AsyncWrite + Unpin + 'static, { config: ConnectorConfig, - available: RefCell>>>, + available: RefCell>>>, permits: Arc, } From fbfff3e7515d7afc4fbe089275cb627e8c300b27 Mon Sep 17 00:00:00 2001 From: Kristian Gaylord Date: Sat, 25 Feb 2023 22:25:36 -0700 Subject: [PATCH 030/314] actix-test: allow dynamic port setting (#2960) Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 1 + actix-test/src/lib.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 23f4b4db1..5dec9cf1f 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased - 2022-xx-xx +- Add `TestServerConfig::port()` setter method. - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. ## 0.1.0 - 2022-07-24 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 1aff2dc83..18453b599 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -145,7 +145,7 @@ where // run server in separate orphaned thread thread::spawn(move || { rt::System::new().block_on(async move { - let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap(); + let tcp = net::TcpListener::bind(("127.0.0.1", cfg.port)).unwrap(); let local_addr = tcp.local_addr().unwrap(); let factory = factory.clone(); let srv_cfg = cfg.clone(); @@ -390,6 +390,7 @@ pub struct TestServerConfig { tp: HttpVer, stream: StreamType, client_request_timeout: Duration, + port: u16, } impl Default for TestServerConfig { @@ -405,6 +406,7 @@ impl TestServerConfig { tp: HttpVer::Both, stream: StreamType::Tcp, client_request_timeout: Duration::from_secs(5), + port: 0, } } @@ -439,6 +441,14 @@ impl TestServerConfig { self.client_request_timeout = dur; self } + + /// Sets test server port. + /// + /// By default, a random free port is determined by the OS. + pub fn port(mut self, port: u16) -> Self { + self.port = port; + self + } } /// A basic HTTP server controller that simplifies the process of writing integration tests for From e97329eb2ac7e12febe95fedf4ed5aa343cddaee Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 04:07:10 +0000 Subject: [PATCH 031/314] bump socket2 dep to 0.5 --- actix-http-test/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index cd5e87162..7c6190bd3 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -41,7 +41,7 @@ bytes = "1" futures-core = { version = "0.3.17", default-features = false } http = "0.2.5" log = "0.4" -socket2 = "0.4" +socket2 = "0.5" serde = "1.0" serde_json = "1.0" slab = "0.4" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 6eb1f862b..81235395b 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -93,7 +93,7 @@ serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" smallvec = "1.6.1" -socket2 = "0.4.0" +socket2 = "0.5" time = { version = "0.3", default-features = false, features = ["formatting"] } url = "2.1" From 8d5d6a2598887ef74e162f32dd34138b8cd0a75c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 13:28:15 +0000 Subject: [PATCH 032/314] tweak err handlers docs --- actix-web/src/middleware/err_handlers.rs | 76 ++++++++++++++++-------- 1 file changed, 50 insertions(+), 26 deletions(-) diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index 00fb5cf59..557fa3849 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -50,18 +50,24 @@ type DefaultHandler = Option>>; /// will pass by unchanged by this middleware. /// /// # Examples -/// ## Handler Response -/// Header +/// +/// Adding a header: +/// /// ``` -/// use actix_web::http::{header, StatusCode}; -/// use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; -/// use actix_web::{dev, web, App, HttpResponse, Result}; +/// use actix_web::{ +/// dev::ServiceResponse, +/// http::{header, StatusCode}, +/// middleware::{ErrorHandlerResponse, ErrorHandlers}, +/// web, App, HttpResponse, Result, +/// }; /// /// fn add_error_header(mut res: dev::ServiceResponse) -> Result> { /// res.response_mut().headers_mut().insert( /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Error"), /// ); +/// +/// // body is unchanged, map to "left" slot /// Ok(ErrorHandlerResponse::Response(res.map_into_left_body())) /// } /// @@ -70,37 +76,52 @@ type DefaultHandler = Option>>; /// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError))); /// ``` /// -/// Body Content +/// Modifying response body: +/// /// ``` -/// use actix_web::http::{header, StatusCode}; -/// use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; -/// use actix_web::{dev, web, App, HttpResponse, Result}; -/// fn add_error_body(res: dev::ServiceResponse) -> Result> { -/// // Get the error message and status code -/// let error_message = "An error occurred"; -/// // Destructures ServiceResponse into request and response components -/// let (req, res) = res.into_parts(); -/// // Create a new response with the modified body -/// let res = res.set_body(error_message).map_into_boxed_body(); -/// // Create a new ServiceResponse with the modified response -/// let res = dev::ServiceResponse::new(req, res).map_into_right_body(); -/// Ok(ErrorHandlerResponse::Response(res)) -///} +/// use actix_web::{ +/// dev::ServiceResponse, +/// http::{header, StatusCode}, +/// middleware::{ErrorHandlerResponse, ErrorHandlers}, +/// web, App, HttpResponse, Result, +/// }; +/// +/// fn add_error_body(res: ServiceResponse) -> Result> { +/// // split service response into request and response components +/// let (req, res) = res.into_parts(); +/// +/// // set body of response to modified body +/// let res = res.set_body("An error occurred."); +/// +/// // modified bodies need to be boxed and placed in the "right" slot +/// let res = ServiceResponse::new(req, res) +/// .map_into_boxed_body() +/// .map_into_right_body(); +/// +/// Ok(ErrorHandlerResponse::Response(res)) +/// } /// /// let app = App::new() /// .wrap(ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, add_error_body)) /// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError))); /// ``` -/// ## Registering default handler +/// +/// Registering default handler: +/// /// ``` -/// # use actix_web::http::{header, StatusCode}; -/// # use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; -/// # use actix_web::{dev, web, App, HttpResponse, Result}; +/// # use actix_web::{ +/// # dev::ServiceResponse, +/// # http::{header, StatusCode}, +/// # middleware::{ErrorHandlerResponse, ErrorHandlers}, +/// # web, App, HttpResponse, Result, +/// # }; /// fn add_error_header(mut res: dev::ServiceResponse) -> Result> { /// res.response_mut().headers_mut().insert( /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Error"), /// ); +/// +/// // body is unchanged, map to "left" slot /// Ok(ErrorHandlerResponse::Response(res.map_into_left_body())) /// } /// @@ -109,6 +130,8 @@ type DefaultHandler = Option>>; /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Bad Request Error"), /// ); +/// +/// // body is unchanged, map to "left" slot /// Ok(ErrorHandlerResponse::Response(res.map_into_left_body())) /// } /// @@ -122,9 +145,10 @@ type DefaultHandler = Option>>; /// ) /// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError))); /// ``` -/// Alternatively, you can set default handlers for only client or only server errors: /// -/// ```rust +/// You can set default handlers for all client (4xx) or all server (5xx) errors: +/// +/// ``` /// # use actix_web::http::{header, StatusCode}; /// # use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; /// # use actix_web::{dev, web, App, HttpResponse, Result}; From ad27150c5fea237789ce110a71fe724678dcfb22 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 14:14:04 +0000 Subject: [PATCH 033/314] fix doc tests --- actix-http-test/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- actix-web/src/middleware/err_handlers.rs | 19 +++++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 7c6190bd3..cd5e87162 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -41,7 +41,7 @@ bytes = "1" futures-core = { version = "0.3.17", default-features = false } http = "0.2.5" log = "0.4" -socket2 = "0.5" +socket2 = "0.4" serde = "1.0" serde_json = "1.0" slab = "0.4" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 81235395b..664379c79 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -93,7 +93,7 @@ serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" smallvec = "1.6.1" -socket2 = "0.5" +socket2 = "0.4" time = { version = "0.3", default-features = false, features = ["formatting"] } url = "2.1" diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index 557fa3849..5522cc021 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -61,7 +61,7 @@ type DefaultHandler = Option>>; /// web, App, HttpResponse, Result, /// }; /// -/// fn add_error_header(mut res: dev::ServiceResponse) -> Result> { +/// fn add_error_header(mut res: ServiceResponse) -> Result> { /// res.response_mut().headers_mut().insert( /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Error"), @@ -115,7 +115,7 @@ type DefaultHandler = Option>>; /// # middleware::{ErrorHandlerResponse, ErrorHandlers}, /// # web, App, HttpResponse, Result, /// # }; -/// fn add_error_header(mut res: dev::ServiceResponse) -> Result> { +/// fn add_error_header(mut res: ServiceResponse) -> Result> { /// res.response_mut().headers_mut().insert( /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Error"), @@ -125,7 +125,7 @@ type DefaultHandler = Option>>; /// Ok(ErrorHandlerResponse::Response(res.map_into_left_body())) /// } /// -/// fn handle_bad_request(mut res: dev::ServiceResponse) -> Result> { +/// fn handle_bad_request(mut res: ServiceResponse) -> Result> { /// res.response_mut().headers_mut().insert( /// header::CONTENT_TYPE, /// header::HeaderValue::from_static("Bad Request Error"), @@ -149,17 +149,20 @@ type DefaultHandler = Option>>; /// You can set default handlers for all client (4xx) or all server (5xx) errors: /// /// ``` -/// # use actix_web::http::{header, StatusCode}; -/// # use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers}; -/// # use actix_web::{dev, web, App, HttpResponse, Result}; -/// # fn add_error_header(mut res: dev::ServiceResponse) -> Result> { +/// # use actix_web::{ +/// # dev::ServiceResponse, +/// # http::{header, StatusCode}, +/// # middleware::{ErrorHandlerResponse, ErrorHandlers}, +/// # web, App, HttpResponse, Result, +/// # }; +/// # fn add_error_header(mut res: ServiceResponse) -> Result> { /// # res.response_mut().headers_mut().insert( /// # header::CONTENT_TYPE, /// # header::HeaderValue::from_static("Error"), /// # ); /// # Ok(ErrorHandlerResponse::Response(res.map_into_left_body())) /// # } -/// # fn handle_bad_request(mut res: dev::ServiceResponse) -> Result> { +/// # fn handle_bad_request(mut res: ServiceResponse) -> Result> { /// # res.response_mut().headers_mut().insert( /// # header::CONTENT_TYPE, /// # header::HeaderValue::from_static("Bad Request Error"), From 129b78f9c7a3c4178b521b5dfcc25fa53adc87ac Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 14:20:48 +0000 Subject: [PATCH 034/314] prepare actix-test release 0.1.1 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 5dec9cf1f..28b772b38 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2022-xx-xx +## 0.1.1 - 2023-02-26 + - Add `TestServerConfig::port()` setter method. - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 956005d8a..f2cbfe5cd 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.0" +version = "0.1.1" authors = [ "Nikolay Kim ", "Rob Ede ", From f27584046cbcbc8086574ba6bfebf6e35a6efc2c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 16:31:40 +0000 Subject: [PATCH 035/314] add todo for header names in next breaking release --- actix-http/src/header/common.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actix-http/src/header/common.rs b/actix-http/src/header/common.rs index 67b0a9069..6942dc26a 100644 --- a/actix-http/src/header/common.rs +++ b/actix-http/src/header/common.rs @@ -8,12 +8,14 @@ use http::header::HeaderName; /// request. /// /// See [RFC 9211](https://www.rfc-editor.org/rfc/rfc9211) for full semantics. +// TODO(breaking): replace with http's version pub const CACHE_STATUS: HeaderName = HeaderName::from_static("cache-status"); /// Response header field that allows origin servers to control the behavior of CDN caches /// interposed between them and clients separately from other caches that might handle the response. /// /// See [RFC 9213](https://www.rfc-editor.org/rfc/rfc9213) for full semantics. +// TODO(breaking): replace with http's version pub const CDN_CACHE_CONTROL: HeaderName = HeaderName::from_static("cdn-cache-control"); /// Response header that prevents a document from loading any cross-origin resources that don't From 740d0c0c9dc256c1aee0bad6f514f8cd9d6443d9 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 21:44:14 +0000 Subject: [PATCH 036/314] prepare actix-multipart-derive release 0.6.0 --- actix-multipart-derive/CHANGES.md | 5 +++++ actix-multipart-derive/Cargo.toml | 6 +++++- actix-multipart-derive/README.md | 16 +++++++++++++++- actix-multipart/Cargo.toml | 6 +----- 4 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 actix-multipart-derive/CHANGES.md diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md new file mode 100644 index 000000000..8dd7aa4d0 --- /dev/null +++ b/actix-multipart-derive/CHANGES.md @@ -0,0 +1,5 @@ +# Changes + +## 0.6.0 - 2023-02-26 + +- Add `MultipartForm` derive macro. diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index 4a30898b4..d2db040d4 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart-derive" -version = "0.5.0" +version = "0.6.0" authors = ["Jacob Halsey "] description = "Multipart form derive macro for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] @@ -9,6 +9,10 @@ repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" edition = "2018" +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] +all-features = true + [lib] proc-macro = true diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index 95f80bc79..44f08c7bd 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -1,3 +1,17 @@ # actix-multipart-derive -> The derive macro implementation for actix-multipart. +> The derive macro implementation for actix-multipart-derive. + +[![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) +[![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart-derive/0.5.0) +![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg) +
+[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.5.0) +[![Download](https://img.shields.io/crates/d/actix-multipart-derive.svg)](https://crates.io/crates/actix-multipart-derive) +[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + +## Documentation & Resources + +- [API Documentation](https://docs.rs/actix-multipart-derive) +- Minimum Supported Rust Version (MSRV): 1.59 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index b63ab1f86..90670f11b 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -21,12 +21,8 @@ default = ["tempfile", "derive"] derive = ["actix-multipart-derive"] tempfile = ["tempfile-dep", "tokio/fs"] -[lib] -name = "actix_multipart" -path = "src/lib.rs" - [dependencies] -actix-multipart-derive = { version = "=0.5.0", optional = true } +actix-multipart-derive = { version = "=0.6.0", optional = true } actix-utils = "3" actix-web = { version = "4", default-features = false } From c4db9a1ae2a70867c976fe496ec549a6528e0994 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 21:44:57 +0000 Subject: [PATCH 037/314] prepare actix-multipart release 0.6.0 --- actix-multipart-derive/Cargo.toml | 2 +- actix-multipart/CHANGES.md | 2 ++ actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index d2db040d4..e0b78fa26 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -24,7 +24,7 @@ quote = "1" syn = "1" [dev-dependencies] -actix-multipart = "0.5" +actix-multipart = "0.6" actix-web = "4" rustversion = "1" trybuild = "1" diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 3d93a4921..eb1ad6b02 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2022-xx-xx +## 0.6.0 - 2023-02-26 + - Added `MultipartForm` typed data extractor. [#2883] [#2883]: https://github.com/actix/actix-web/pull/2883 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 90670f11b..a36fbffc0 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.5.0" +version = "0.6.0" authors = [ "Nikolay Kim ", "Jacob Halsey ", diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 23c7aa4f5..c4101e1ce 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -3,11 +3,11 @@ > Multipart form support for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) -[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart/0.5.0) +[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.0)](https://docs.rs/actix-multipart/0.6.0) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart/0.5.0) +[![dependency status](https://deps.rs/crate/actix-multipart/0.6.0/status.svg)](https://deps.rs/crate/actix-multipart/0.6.0) [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From d77bcb0b7cee83f40c097de94ab07f40a3b6c98d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 21:45:36 +0000 Subject: [PATCH 038/314] update date in unreleased changelog sections --- actix-files/CHANGES.md | 2 +- actix-http-test/CHANGES.md | 2 +- actix-http/CHANGES.md | 2 +- actix-multipart/CHANGES.md | 2 +- actix-router/CHANGES.md | 2 +- actix-test/CHANGES.md | 2 +- actix-web-actors/CHANGES.md | 2 +- actix-web-codegen/CHANGES.md | 2 +- actix-web/CHANGES.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index b4b2fd8c1..d64380a8d 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 0.6.3 - 2023-01-21 diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index e56883c19..ec31b6196 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 3.1.0 - 2023-01-21 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 033cd994c..3a7af60af 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 3.3.0 - 2023-01-21 diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index eb1ad6b02..4bb120c61 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 0.6.0 - 2023-02-26 diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index b3a85d3fe..7ef9497dc 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 0.5.1 - 2022-09-19 diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 28b772b38..47fea4173 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 0.1.1 - 2023-02-26 diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 480470bee..ea19411b5 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 4.2.0 - 2023-01-21 diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 5bc510273..6e962a6ca 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 4.2.0 - 2023-02-26 diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 1eb1f02c9..093c77891 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased - 2022-xx-xx +## Unreleased - 2023-xx-xx ## 4.3.1 - 2023-02-26 From 67efa4a4dbc8f7812a562d19fbb4e9cd5442df55 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 26 Feb 2023 21:55:25 +0000 Subject: [PATCH 039/314] migrate to doc_auto_cfg --- actix-files/src/lib.rs | 3 +++ actix-http-test/src/lib.rs | 1 + actix-http/src/builder.rs | 1 - actix-http/src/error.rs | 2 -- actix-http/src/h1/service.rs | 2 -- actix-http/src/h2/service.rs | 2 -- actix-http/src/lib.rs | 5 +---- actix-http/src/service.rs | 6 ------ actix-multipart-derive/src/lib.rs | 2 +- actix-multipart/src/form/mod.rs | 2 -- actix-multipart/src/lib.rs | 4 +++- actix-router/src/lib.rs | 1 + actix-test/src/lib.rs | 3 +++ actix-web-actors/src/lib.rs | 3 +++ actix-web-codegen/src/lib.rs | 3 +++ actix-web/src/lib.rs | 4 +--- actix-web/src/request.rs | 2 -- actix-web/src/server.rs | 5 ----- awc/src/lib.rs | 1 + 19 files changed, 21 insertions(+), 31 deletions(-) diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 0fbe39a8e..bed8194c8 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -14,6 +14,9 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible, missing_docs, missing_debug_implementations)] #![allow(clippy::uninlined_format_args)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] use actix_service::boxed::{BoxService, BoxServiceFactory}; use actix_web::{ diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs index a66f7b486..55224dc46 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -5,6 +5,7 @@ #![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; diff --git a/actix-http/src/builder.rs b/actix-http/src/builder.rs index e2693acaf..916083a98 100644 --- a/actix-http/src/builder.rs +++ b/actix-http/src/builder.rs @@ -211,7 +211,6 @@ where /// Finish service configuration and create a service for the HTTP/2 protocol. #[cfg(feature = "http2")] - #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub fn h2(self, service: F) -> crate::h2::H2Service where F: IntoServiceFactory, diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 2d443369d..41522a254 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -294,7 +294,6 @@ impl std::error::Error for PayloadError { PayloadError::Overflow => None, PayloadError::UnknownLength => None, #[cfg(feature = "http2")] - #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] PayloadError::Http2Payload(err) => Some(err), PayloadError::Io(err) => Some(err), } @@ -352,7 +351,6 @@ pub enum DispatchError { /// HTTP/2 error. #[display(fmt = "{}", _0)] #[cfg(feature = "http2")] - #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] H2(h2::Error), /// The first request did not complete within the specified timeout. diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index e4d90424d..a791ea8c3 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -134,7 +134,6 @@ mod openssl { U::InitError: fmt::Debug, { /// Create OpenSSL based service. - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn openssl( self, acceptor: SslAcceptor, @@ -197,7 +196,6 @@ mod rustls { U::InitError: fmt::Debug, { /// Create Rustls based service. - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn rustls( self, config: ServerConfig, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 2a45fc1dc..e526918c7 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -117,7 +117,6 @@ mod openssl { B: MessageBody + 'static, { /// Create OpenSSL based service. - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn openssl( self, acceptor: SslAcceptor, @@ -165,7 +164,6 @@ mod rustls { B: MessageBody + 'static, { /// Create Rustls based service. - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn rustls( self, mut config: ServerConfig, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 05f80eba4..8bf834f73 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -26,7 +26,7 @@ )] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] pub use ::http::{uri, uri::Uri}; pub use ::http::{Method, StatusCode, Version}; @@ -41,7 +41,6 @@ pub mod error; mod extensions; pub mod h1; #[cfg(feature = "http2")] -#[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub mod h2; pub mod header; mod helpers; @@ -56,7 +55,6 @@ mod responses; mod service; pub mod test; #[cfg(feature = "ws")] -#[cfg_attr(docsrs, doc(cfg(feature = "ws")))] pub mod ws; pub use self::builder::HttpServiceBuilder; @@ -74,7 +72,6 @@ pub use self::requests::{Request, RequestHead, RequestHeadType}; pub use self::responses::{Response, ResponseBuilder, ResponseHead}; pub use self::service::HttpService; #[cfg(any(feature = "openssl", feature = "rustls"))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "openssl", feature = "rustls"))))] pub use self::service::TlsAcceptorConfig; /// A major HTTP protocol version. diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index 62128f3ec..22177b849 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -217,7 +217,6 @@ where /// Creates TCP stream service from HTTP service that automatically selects HTTP/1.x or HTTP/2 /// on plaintext connections. #[cfg(feature = "http2")] - #[cfg_attr(docsrs, doc(cfg(feature = "http2")))] pub fn tcp_auto_h2c( self, ) -> impl ServiceFactory< @@ -253,7 +252,6 @@ where /// Configuration options used when accepting TLS connection. #[cfg(any(feature = "openssl", feature = "rustls"))] -#[cfg_attr(docsrs, doc(cfg(any(feature = "openssl", feature = "rustls"))))] #[derive(Debug, Default)] pub struct TlsAcceptorConfig { pub(crate) handshake_timeout: Option, @@ -309,7 +307,6 @@ mod openssl { U::InitError: fmt::Debug, { /// Create OpenSSL based service. - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn openssl( self, acceptor: SslAcceptor, @@ -324,7 +321,6 @@ mod openssl { } /// Create OpenSSL based service with custom TLS acceptor configuration. - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn openssl_with_config( self, acceptor: SslAcceptor, @@ -404,7 +400,6 @@ mod rustls { U::InitError: fmt::Debug, { /// Create Rustls based service. - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn rustls( self, config: ServerConfig, @@ -419,7 +414,6 @@ mod rustls { } /// Create Rustls based service with custom TLS acceptor configuration. - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn rustls_with_config( self, mut config: ServerConfig, diff --git a/actix-multipart-derive/src/lib.rs b/actix-multipart-derive/src/lib.rs index 9b6ecbae6..2af023aec 100644 --- a/actix-multipart-derive/src/lib.rs +++ b/actix-multipart-derive/src/lib.rs @@ -6,7 +6,7 @@ #![warn(future_incompatible)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] use std::{collections::HashSet, convert::TryFrom as _}; diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index b0285d97e..711d4aeb6 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -16,12 +16,10 @@ use crate::{Field, Multipart, MultipartError}; pub mod bytes; pub mod json; -#[cfg_attr(docsrs, doc(cfg(feature = "tempfile")))] #[cfg(feature = "tempfile")] pub mod tempfile; pub mod text; -#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] #[cfg(feature = "derive")] pub use actix_multipart_derive::MultipartForm; diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index c8fba77d0..73e10c913 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -3,7 +3,9 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] #![allow(clippy::borrow_interior_mutable_const, clippy::uninlined_format_args)] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] // This allows us to use the actix_multipart_derive within this crate's tests #[cfg(test)] diff --git a/actix-router/src/lib.rs b/actix-router/src/lib.rs index 418dd432b..a02129495 100644 --- a/actix-router/src/lib.rs +++ b/actix-router/src/lib.rs @@ -5,6 +5,7 @@ #![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] mod de; mod path; diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 18453b599..2beb64dca 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -28,6 +28,9 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; diff --git a/actix-web-actors/src/lib.rs b/actix-web-actors/src/lib.rs index 7a34048da..cf2eb3645 100644 --- a/actix-web-actors/src/lib.rs +++ b/actix-web-actors/src/lib.rs @@ -58,6 +58,9 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] #![allow(clippy::uninlined_format_args)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] mod context; pub mod ws; diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 5d392be1d..8b68ea16b 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -75,6 +75,9 @@ #![recursion_limit = "512"] #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] +#![doc(html_logo_url = "https://actix.rs/img/logo.png")] +#![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] use proc_macro::TokenStream; use quote::quote; diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index 6a94976c5..57cdaea69 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -72,7 +72,7 @@ #![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] mod app; mod app_service; @@ -119,14 +119,12 @@ pub use crate::types::Either; pub use actix_http::{body, HttpMessage}; #[cfg(feature = "cookies")] -#[cfg_attr(docsrs, doc(cfg(feature = "cookies")))] #[doc(inline)] pub use cookie; macro_rules! codegen_reexport { ($name:ident) => { #[cfg(feature = "macros")] - #[cfg_attr(docsrs, doc(cfg(feature = "macros")))] pub use actix_web_codegen::$name; }; } diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index a99dcaa3e..16a947b65 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -311,7 +311,6 @@ impl HttpRequest { /// Load request cookies. #[cfg(feature = "cookies")] - #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))] pub fn cookies(&self) -> Result>>, CookieParseError> { use actix_http::header::COOKIE; @@ -335,7 +334,6 @@ impl HttpRequest { /// Return request cookie. #[cfg(feature = "cookies")] - #[cfg_attr(docsrs, doc(cfg(feature = "cookies")))] pub fn cookie(&self, name: &str) -> Option> { if let Ok(cookies) = self.cookies() { for cookie in cookies.iter() { diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 3a8897f11..c87fea7f3 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -217,7 +217,6 @@ where /// /// By default handshake timeout is set to 3000 milliseconds. #[cfg(any(feature = "openssl", feature = "rustls"))] - #[cfg_attr(docsrs, doc(cfg(any(feature = "openssl", feature = "rustls"))))] pub fn tls_handshake_timeout(self, dur: Duration) -> Self { self.config .lock() @@ -382,7 +381,6 @@ where /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls")] - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn bind_rustls( mut self, addrs: A, @@ -402,7 +400,6 @@ where /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "openssl")] - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn bind_openssl(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result where A: net::ToSocketAddrs, @@ -469,7 +466,6 @@ where /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls")] - #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))] pub fn listen_rustls( self, lst: net::TcpListener, @@ -535,7 +531,6 @@ where /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "openssl")] - #[cfg_attr(docsrs, doc(cfg(feature = "openssl")))] pub fn listen_openssl( self, lst: net::TcpListener, diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 42f029669..b06df6b7d 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -110,6 +110,7 @@ )] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] pub use actix_http::body; From d7c6774ad525821cdba2c6625399ba31d718ef06 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 2 Mar 2023 08:22:22 +0000 Subject: [PATCH 040/314] add resource method helpers (#2978) --- actix-web/CHANGES.md | 2 ++ actix-web/src/resource.rs | 50 +++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 093c77891..9a768a122 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. + ## 4.3.1 - 2023-02-26 - Add support for custom methods with the `#[route]` macro. [#2969] diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 997036751..5d2c9706a 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -21,7 +21,7 @@ use crate::{ BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest, ServiceResponse, }, - Error, FromRequest, HttpResponse, Responder, + web, Error, FromRequest, HttpResponse, Responder, }; /// A collection of [`Route`]s that respond to the same path pattern. @@ -38,11 +38,13 @@ use crate::{ /// /// let app = App::new().service( /// web::resource("/") -/// .route(web::get().to(|| HttpResponse::Ok()))); +/// .get(|| HttpResponse::Ok()) +/// .post(|| async { "Hello World!" }) +/// ); /// ``` /// -/// If no matching route is found, [a 405 response is returned with an appropriate Allow header][RFC -/// 9110 §15.5.6]. This default behavior can be overridden using +/// If no matching route is found, an empty 405 response is returned which includes an +/// [appropriate Allow header][RFC 9110 §15.5.6]. This default behavior can be overridden using /// [`default_service()`](Self::default_service). /// /// [RFC 9110 §15.5.6]: https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.6 @@ -58,6 +60,7 @@ pub struct Resource { } impl Resource { + /// Constructs new resource that matches a `path` pattern. pub fn new(path: T) -> Resource { let fref = Rc::new(RefCell::new(None)); @@ -368,6 +371,45 @@ where } } +macro_rules! route_shortcut { + ($method_fn:ident, $method_upper:literal) => { + #[doc = concat!(" Adds a ", $method_upper, " route.")] + /// + /// Use [`route`](Self::route) if you need to add additional guards. + /// + /// # Examples + /// + /// ``` + /// # use actix_web::web; + /// web::resource("/") + #[doc = concat!(" .", stringify!($method_fn), "(|| async { \"Hello World!\" })")] + /// # ; + /// ``` + pub fn $method_fn(self, handler: F) -> Self + where + F: Handler, + Args: FromRequest + 'static, + F::Output: Responder + 'static, + { + self.route(web::$method_fn().to(handler)) + } + }; +} + +/// Concise routes for well-known HTTP methods. +impl Resource +where + T: ServiceFactory, +{ + route_shortcut!(get, "GET"); + route_shortcut!(post, "POST"); + route_shortcut!(put, "PUT"); + route_shortcut!(patch, "PATCH"); + route_shortcut!(delete, "DELETE"); + route_shortcut!(head, "HEAD"); + route_shortcut!(trace, "TRACE"); +} + impl HttpServiceFactory for Resource where T: ServiceFactory< From 20c7c07dc00236b2d74aaed8c79a805aec54f89e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 2 Mar 2023 16:21:13 +0000 Subject: [PATCH 041/314] fix http version req --- actix-http-test/Cargo.toml | 2 +- actix-http/CHANGES.md | 4 ++++ actix-http/Cargo.toml | 2 +- actix-router/Cargo.toml | 4 ++-- actix-web/Cargo.toml | 1 - awc/Cargo.toml | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index cd5e87162..cb4754125 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -39,7 +39,7 @@ awc = { version = "3", default-features = false } bytes = "1" futures-core = { version = "0.3.17", default-features = false } -http = "0.2.5" +http = "0.2.7" log = "0.4" socket2 = "0.4" serde = "1.0" diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 3a7af60af..29cc22d35 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased - 2023-xx-xx +### Fixed + +- Use correct `http` version requirement to ensure support for const `HeaderName` definitions. + ## 3.3.0 - 2023-01-21 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 108b2314a..77fcd4243 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -68,7 +68,7 @@ bytestring = "1" derive_more = "0.99.5" encoding_rs = "0.8" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } -http = "0.2.5" +http = "0.2.7" httparse = "1.5.1" httpdate = "1.0.1" itoa = "1" diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index f3a5f15e4..f8efd5350 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -21,14 +21,14 @@ default = ["http"] [dependencies] bytestring = ">=0.1.5, <2" -http = { version = "0.2.5", optional = true } +http = { version = "0.2.7", optional = true } regex = "1.5" serde = "1" tracing = { version = "0.1.30", default-features = false, features = ["log"] } [dev-dependencies] criterion = { version = "0.4", features = ["html_reports"] } -http = "0.2.5" +http = "0.2.7" serde = { version = "1", features = ["derive"] } percent-encoding = "2.1" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 664379c79..c7314422d 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -81,7 +81,6 @@ derive_more = "0.99.8" encoding_rs = "0.8" futures-core = { version = "0.3.17", default-features = false } futures-util = { version = "0.3.17", default-features = false } -http = "0.2.8" itoa = "1" language-tags = "0.3" log = "0.4" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 8a75e28f7..8edc90fd1 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -69,7 +69,7 @@ derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.17", default-features = false, features = ["alloc", "sink"] } h2 = "0.3.9" -http = "0.2.5" +http = "0.2.7" itoa = "1" log =" 0.4" mime = "0.3" From e0939a01fcb82bf948b3e4fe4cc9889c10518394 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 2 Mar 2023 17:09:26 +0000 Subject: [PATCH 042/314] prepare actix-http release 3.3.1 --- actix-http/CHANGES.md | 2 ++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 29cc22d35..831a0bcd0 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +## 3.3.1 - 2023-03-02 + ### Fixed - Use correct `http` version requirement to ensure support for const `HeaderName` definitions. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 77fcd4243..d2218f6de 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.3.0" +version = "3.3.1" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index aa98f953f..f372096ff 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -3,11 +3,11 @@ > 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=3.3.0)](https://docs.rs/actix-http/3.3.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.3.1)](https://docs.rs/actix-http/3.3.1) ![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.3.0/status.svg)](https://deps.rs/crate/actix-http/3.3.0) +[![dependency status](https://deps.rs/crate/actix-http/3.3.1/status.svg)](https://deps.rs/crate/actix-http/3.3.1) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 4c4024c949f219d9108f00c8cda759e82c6f81b3 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 11 Mar 2023 22:14:58 +0000 Subject: [PATCH 043/314] fix minimal version specs for mime --- actix-files/Cargo.toml | 4 ++-- actix-http-test/Cargo.toml | 4 ++-- actix-http/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 4c29c95b2..6909c0ef2 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -32,11 +32,11 @@ derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } http-range = "0.1.4" log = "0.4" -mime = "0.3" +mime = "0.3.9" mime_guess = "2.0.1" percent-encoding = "2.1" pin-project-lite = "0.2.7" -v_htmlescape= "0.15" +v_htmlescape = "0.15.5" # experimental-io-uring [target.'cfg(target_os = "linux")'.dependencies] diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index cb4754125..12739fbd4 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -42,8 +42,8 @@ futures-core = { version = "0.3.17", default-features = false } http = "0.2.7" log = "0.4" socket2 = "0.4" -serde = "1.0" -serde_json = "1.0" +serde = "1" +serde_json = "1" slab = "0.4" serde_urlencoded = "0.7" tls-openssl = { version = "0.10.9", package = "openssl", optional = true } diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index d2218f6de..07e412a2c 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -73,7 +73,7 @@ httparse = "1.5.1" httpdate = "1.0.1" itoa = "1" language-tags = "0.3" -mime = "0.3" +mime = "0.3.4" percent-encoding = "2.1" pin-project-lite = "0.2" smallvec = "1.6.1" From 3fc01c48878ee487b872551d9ac5898fc2031086 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 11 Mar 2023 22:17:52 +0000 Subject: [PATCH 044/314] refactor server binding --- actix-web/src/server.rs | 67 +++++++++++++++++++---------------- actix-web/src/types/either.rs | 6 ++-- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index c87fea7f3..1fa279a65 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -338,7 +338,7 @@ where /// # ; Ok(()) } /// ``` pub fn bind(mut self, addrs: A) -> io::Result { - let sockets = self.bind2(addrs)?; + let sockets = bind_addrs(addrs, self.backlog)?; for lst in sockets { self = self.listen(lst)?; @@ -347,33 +347,6 @@ where Ok(self) } - fn bind2(&self, addrs: A) -> io::Result> { - let mut err = None; - let mut success = false; - let mut sockets = Vec::new(); - - for addr in addrs.to_socket_addrs()? { - match create_tcp_listener(addr, self.backlog) { - Ok(lst) => { - success = true; - sockets.push(lst); - } - Err(e) => err = Some(e), - } - } - - if success { - Ok(sockets) - } else if let Some(e) = err.take() { - Err(e) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - "Can not bind to address.", - )) - } - } - /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using Rustls. /// @@ -386,7 +359,7 @@ where addrs: A, config: RustlsServerConfig, ) -> io::Result { - let sockets = self.bind2(addrs)?; + let sockets = bind_addrs(addrs, self.backlog)?; for lst in sockets { self = self.listen_rustls_inner(lst, config.clone())?; } @@ -404,7 +377,7 @@ where where A: net::ToSocketAddrs, { - let sockets = self.bind2(addrs)?; + let sockets = bind_addrs(addrs, self.backlog)?; let acceptor = openssl_acceptor(builder)?; for lst in sockets { @@ -719,6 +692,38 @@ where } } +/// Bind TCP listeners to socket addresses resolved from `addrs` with options. +fn bind_addrs( + addrs: impl net::ToSocketAddrs, + backlog: u32, +) -> io::Result> { + let mut err = None; + let mut success = false; + let mut sockets = Vec::new(); + + for addr in addrs.to_socket_addrs()? { + match create_tcp_listener(addr, backlog) { + Ok(lst) => { + success = true; + sockets.push(lst); + } + Err(e) => err = Some(e), + } + } + + if success { + Ok(sockets) + } else if let Some(err) = err.take() { + Err(err) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "Can not bind to address.", + )) + } +} + +/// Creates a TCP listener from socket address and options. fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result { use socket2::{Domain, Protocol, Socket, Type}; let domain = Domain::for_address(addr); @@ -731,7 +736,7 @@ fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result io::Result { builder.set_alpn_select_callback(|_, protocols| { diff --git a/actix-web/src/types/either.rs b/actix-web/src/types/either.rs index 119dd0d62..df93fb5ec 100644 --- a/actix-web/src/types/either.rs +++ b/actix-web/src/types/either.rs @@ -304,7 +304,7 @@ mod tests { #[actix_rt::test] async fn test_either_extract_first_try() { let (req, mut pl) = TestRequest::default() - .set_form(&TestForm { + .set_form(TestForm { hello: "world".to_owned(), }) .to_http_parts(); @@ -320,7 +320,7 @@ mod tests { #[actix_rt::test] async fn test_either_extract_fallback() { let (req, mut pl) = TestRequest::default() - .set_json(&TestForm { + .set_json(TestForm { hello: "world".to_owned(), }) .to_http_parts(); @@ -351,7 +351,7 @@ mod tests { #[actix_rt::test] async fn test_either_extract_recursive_fallback_inner() { let (req, mut pl) = TestRequest::default() - .set_json(&TestForm { + .set_json(TestForm { hello: "world".to_owned(), }) .to_http_parts(); From 0ba147ef71072e7ce780da85a71307e8de138e38 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 11 Mar 2023 23:19:03 +0000 Subject: [PATCH 045/314] update actions/checkout to v3 --- .github/workflows/bench.yml | 2 +- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 8 ++++---- .github/workflows/clippy-fmt.yml | 6 +++--- .github/workflows/coverage.yml | 2 +- .github/workflows/upload-doc.yml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 008c33f89..3d16a7eb7 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install Rust uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 7ac6388d4..30d13bf88 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -29,7 +29,7 @@ jobs: CARGO_UNSTABLE_SPARSE_REGISTRY: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # install OpenSSL on Windows # TODO: GitHub actions docs state that OpenSSL is @@ -93,7 +93,7 @@ jobs: CARGO_INCREMENTAL: 0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable @@ -120,7 +120,7 @@ jobs: CARGO_INCREMENTAL: 0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 421becc63..48380265a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read # to fetch code (actions/checkout) jobs: build_and_test: @@ -31,7 +31,7 @@ jobs: VCPKGRS_DYNAMIC: 1 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # install OpenSSL on Windows # TODO: GitHub actions docs state that OpenSSL is @@ -102,7 +102,7 @@ jobs: name: io-uring tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable @@ -123,7 +123,7 @@ jobs: name: doc tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index e94c4d1af..877ca74e4 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -8,7 +8,7 @@ jobs: fmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly with: { components: rustfmt } - run: cargo fmt --all -- --check @@ -16,7 +16,7 @@ jobs: clippy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable with: { components: clippy } @@ -35,7 +35,7 @@ jobs: lint-docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable with: { components: rust-docs } diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 137a413d0..bb6d7fb97 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -12,7 +12,7 @@ jobs: name: coverage runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install stable uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 9aadafafc..2464ebcd6 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@nightly From 4131786127bb1633a2731108195055b52d7a8cf6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 11 Mar 2023 23:20:02 +0000 Subject: [PATCH 046/314] remove old benchmarks --- actix-http/Cargo.toml | 16 -- actix-http/benches/quality-value.rs | 97 ----------- actix-http/benches/status-line.rs | 214 ------------------------- actix-http/benches/uninit-headers.rs | 135 ---------------- actix-http/benches/write-camel-case.rs | 93 ----------- 5 files changed, 555 deletions(-) delete mode 100644 actix-http/benches/quality-value.rs delete mode 100644 actix-http/benches/status-line.rs delete mode 100644 actix-http/benches/uninit-headers.rs delete mode 100644 actix-http/benches/write-camel-case.rs diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 07e412a2c..ce653f440 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -124,19 +124,3 @@ tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" required-features = ["ws", "rustls"] - -[[bench]] -name = "write-camel-case" -harness = false - -[[bench]] -name = "status-line" -harness = false - -[[bench]] -name = "uninit-headers" -harness = false - -[[bench]] -name = "quality-value" -harness = false diff --git a/actix-http/benches/quality-value.rs b/actix-http/benches/quality-value.rs deleted file mode 100644 index 0ed274ded..000000000 --- a/actix-http/benches/quality-value.rs +++ /dev/null @@ -1,97 +0,0 @@ -#![allow(clippy::uninlined_format_args)] - -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; - -const CODES: &[u16] = &[0, 1000, 201, 800, 550]; - -fn bench_quality_display_impls(c: &mut Criterion) { - let mut group = c.benchmark_group("quality value display impls"); - - for i in CODES.iter() { - group.bench_with_input(BenchmarkId::new("New (fast?)", i), i, |b, &i| { - b.iter(|| _new::Quality(i).to_string()) - }); - - group.bench_with_input(BenchmarkId::new("Naive", i), i, |b, &i| { - b.iter(|| _naive::Quality(i).to_string()) - }); - } - - group.finish(); -} - -criterion_group!(benches, bench_quality_display_impls); -criterion_main!(benches); - -mod _new { - use std::fmt; - - pub struct Quality(pub(crate) u16); - - impl fmt::Display for Quality { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - 0 => f.write_str("0"), - 1000 => f.write_str("1"), - - // some number in the range 1–999 - x => { - f.write_str("0.")?; - - // this implementation avoids string allocation otherwise required - // for `.trim_end_matches('0')` - - if x < 10 { - f.write_str("00")?; - // 0 is handled so it's not possible to have a trailing 0, we can just return - itoa_fmt(f, x) - } else if x < 100 { - f.write_str("0")?; - if x % 10 == 0 { - // trailing 0, divide by 10 and write - itoa_fmt(f, x / 10) - } else { - itoa_fmt(f, x) - } - } else { - // x is in range 101–999 - - if x % 100 == 0 { - // two trailing 0s, divide by 100 and write - itoa_fmt(f, x / 100) - } else if x % 10 == 0 { - // one trailing 0, divide by 10 and write - itoa_fmt(f, x / 10) - } else { - itoa_fmt(f, x) - } - } - } - } - } - } - - pub fn itoa_fmt(mut wr: W, value: V) -> fmt::Result { - let mut buf = itoa::Buffer::new(); - wr.write_str(buf.format(value)) - } -} - -mod _naive { - use std::fmt; - - pub struct Quality(pub(crate) u16); - - impl fmt::Display for Quality { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - 0 => f.write_str("0"), - 1000 => f.write_str("1"), - - x => { - write!(f, "{}", format!("{:03}", x).trim_end_matches('0')) - } - } - } - } -} diff --git a/actix-http/benches/status-line.rs b/actix-http/benches/status-line.rs deleted file mode 100644 index 9fe099478..000000000 --- a/actix-http/benches/status-line.rs +++ /dev/null @@ -1,214 +0,0 @@ -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; - -use bytes::BytesMut; -use http::Version; - -const CODES: &[u16] = &[201, 303, 404, 515]; - -fn bench_write_status_line_11(c: &mut Criterion) { - let mut group = c.benchmark_group("write_status_line v1.1"); - - let version = Version::HTTP_11; - - for i in CODES.iter() { - group.bench_with_input(BenchmarkId::new("Original (unsafe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _original::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("New (safe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _new::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("Naive", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _naive::write_status_line(version, i, &mut b); - }) - }); - } - - group.finish(); -} - -fn bench_write_status_line_10(c: &mut Criterion) { - let mut group = c.benchmark_group("write_status_line v1.0"); - - let version = Version::HTTP_10; - - for i in CODES.iter() { - group.bench_with_input(BenchmarkId::new("Original (unsafe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _original::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("New (safe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _new::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("Naive", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _naive::write_status_line(version, i, &mut b); - }) - }); - } - - group.finish(); -} - -fn bench_write_status_line_09(c: &mut Criterion) { - let mut group = c.benchmark_group("write_status_line v0.9"); - - let version = Version::HTTP_09; - - for i in CODES.iter() { - group.bench_with_input(BenchmarkId::new("Original (unsafe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _original::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("New (safe)", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _new::write_status_line(version, i, &mut b); - }) - }); - - group.bench_with_input(BenchmarkId::new("Naive", i), i, |b, &i| { - b.iter(|| { - let mut b = BytesMut::with_capacity(35); - _naive::write_status_line(version, i, &mut b); - }) - }); - } - - group.finish(); -} - -criterion_group!( - benches, - bench_write_status_line_11, - bench_write_status_line_10, - bench_write_status_line_09 -); -criterion_main!(benches); - -mod _naive { - use bytes::{BufMut, BytesMut}; - use http::Version; - - pub(crate) fn write_status_line(version: Version, n: u16, bytes: &mut BytesMut) { - match version { - Version::HTTP_11 => bytes.put_slice(b"HTTP/1.1 "), - Version::HTTP_10 => bytes.put_slice(b"HTTP/1.0 "), - Version::HTTP_09 => bytes.put_slice(b"HTTP/0.9 "), - _ => { - // other HTTP version handlers do not use this method - } - } - - bytes.put_slice(n.to_string().as_bytes()); - } -} - -mod _new { - use bytes::{BufMut, BytesMut}; - use http::Version; - - const DIGITS_START: u8 = b'0'; - - pub(crate) fn write_status_line(version: Version, n: u16, bytes: &mut BytesMut) { - match version { - Version::HTTP_11 => bytes.put_slice(b"HTTP/1.1 "), - Version::HTTP_10 => bytes.put_slice(b"HTTP/1.0 "), - Version::HTTP_09 => bytes.put_slice(b"HTTP/0.9 "), - _ => { - // other HTTP version handlers do not use this method - } - } - - let d100 = (n / 100) as u8; - let d10 = ((n / 10) % 10) as u8; - let d1 = (n % 10) as u8; - - bytes.put_u8(DIGITS_START + d100); - bytes.put_u8(DIGITS_START + d10); - bytes.put_u8(DIGITS_START + d1); - - bytes.put_u8(b' '); - } -} - -mod _original { - use std::ptr; - - use bytes::{BufMut, BytesMut}; - use http::Version; - - const DEC_DIGITS_LUT: &[u8] = b"0001020304050607080910111213141516171819\ - 2021222324252627282930313233343536373839\ - 4041424344454647484950515253545556575859\ - 6061626364656667686970717273747576777879\ - 8081828384858687888990919293949596979899"; - - pub(crate) const STATUS_LINE_BUF_SIZE: usize = 13; - - pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesMut) { - let mut buf: [u8; STATUS_LINE_BUF_SIZE] = *b"HTTP/1.1 "; - - match version { - Version::HTTP_2 => buf[5] = b'2', - Version::HTTP_10 => buf[7] = b'0', - Version::HTTP_09 => { - buf[5] = b'0'; - buf[7] = b'9'; - } - _ => {} - } - - let mut curr: isize = 12; - let buf_ptr = buf.as_mut_ptr(); - let lut_ptr = DEC_DIGITS_LUT.as_ptr(); - let four = n > 999; - - // decode 2 more chars, if > 2 chars - let d1 = (n % 100) << 1; - n /= 100; - curr -= 2; - unsafe { - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(curr), 2); - } - - // decode last 1 or 2 chars - if n < 10 { - curr -= 1; - unsafe { - *buf_ptr.offset(curr) = (n as u8) + b'0'; - } - } else { - let d1 = n << 1; - curr -= 2; - unsafe { - ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(curr), 2); - } - } - - bytes.put_slice(&buf); - if four { - bytes.put_u8(b' '); - } - } -} diff --git a/actix-http/benches/uninit-headers.rs b/actix-http/benches/uninit-headers.rs deleted file mode 100644 index 688c64d6e..000000000 --- a/actix-http/benches/uninit-headers.rs +++ /dev/null @@ -1,135 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -use bytes::BytesMut; - -// A Miri run detects UB, seen on this playground: -// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f5d9aa166aa48df8dca05fce2b6c3915 - -fn bench_header_parsing(c: &mut Criterion) { - c.bench_function("Original (Unsound) [short]", |b| { - b.iter(|| { - let mut buf = BytesMut::from(REQ_SHORT); - _original::parse_headers(&mut buf); - }) - }); - - c.bench_function("New (safe) [short]", |b| { - b.iter(|| { - let mut buf = BytesMut::from(REQ_SHORT); - _new::parse_headers(&mut buf); - }) - }); - - c.bench_function("Original (Unsound) [realistic]", |b| { - b.iter(|| { - let mut buf = BytesMut::from(REQ); - _original::parse_headers(&mut buf); - }) - }); - - c.bench_function("New (safe) [realistic]", |b| { - b.iter(|| { - let mut buf = BytesMut::from(REQ); - _new::parse_headers(&mut buf); - }) - }); -} - -criterion_group!(benches, bench_header_parsing); -criterion_main!(benches); - -const MAX_HEADERS: usize = 96; - -const EMPTY_HEADER_ARRAY: [httparse::Header<'static>; MAX_HEADERS] = - [httparse::EMPTY_HEADER; MAX_HEADERS]; - -#[derive(Clone, Copy)] -struct HeaderIndex { - name: (usize, usize), - value: (usize, usize), -} - -const EMPTY_HEADER_INDEX: HeaderIndex = HeaderIndex { - name: (0, 0), - value: (0, 0), -}; - -const EMPTY_HEADER_INDEX_ARRAY: [HeaderIndex; MAX_HEADERS] = [EMPTY_HEADER_INDEX; MAX_HEADERS]; - -impl HeaderIndex { - fn record(bytes: &[u8], headers: &[httparse::Header<'_>], indices: &mut [HeaderIndex]) { - let bytes_ptr = bytes.as_ptr() as usize; - for (header, indices) in headers.iter().zip(indices.iter_mut()) { - let name_start = header.name.as_ptr() as usize - bytes_ptr; - let name_end = name_start + header.name.len(); - indices.name = (name_start, name_end); - let value_start = header.value.as_ptr() as usize - bytes_ptr; - let value_end = value_start + header.value.len(); - indices.value = (value_start, value_end); - } - } -} - -// test cases taken from: -// https://github.com/seanmonstar/httparse/blob/master/benches/parse.rs - -const REQ_SHORT: &[u8] = b"\ -GET / HTTP/1.0\r\n\ -Host: example.com\r\n\ -Cookie: session=60; user_id=1\r\n\r\n"; - -const REQ: &[u8] = b"\ -GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n\ -Host: www.kittyhell.com\r\n\ -User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9\r\n\ -Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\ -Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n\ -Accept-Encoding: gzip,deflate\r\n\ -Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n\ -Keep-Alive: 115\r\n\ -Connection: keep-alive\r\n\ -Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; __utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; __utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral|padding=under256\r\n\r\n"; - -mod _new { - use super::*; - - pub fn parse_headers(src: &mut BytesMut) -> usize { - let mut headers: [HeaderIndex; MAX_HEADERS] = EMPTY_HEADER_INDEX_ARRAY; - let mut parsed: [httparse::Header<'_>; MAX_HEADERS] = EMPTY_HEADER_ARRAY; - - let mut req = httparse::Request::new(&mut parsed); - match req.parse(src).unwrap() { - httparse::Status::Complete(_len) => { - HeaderIndex::record(src, req.headers, &mut headers); - req.headers.len() - } - _ => unreachable!(), - } - } -} - -mod _original { - use super::*; - - use std::mem::MaybeUninit; - - pub fn parse_headers(src: &mut BytesMut) -> usize { - #![allow(invalid_value, clippy::uninit_assumed_init)] - - let mut headers: [HeaderIndex; MAX_HEADERS] = - unsafe { MaybeUninit::uninit().assume_init() }; - - #[allow(invalid_value)] - let mut parsed: [httparse::Header<'_>; MAX_HEADERS] = - unsafe { MaybeUninit::uninit().assume_init() }; - - let mut req = httparse::Request::new(&mut parsed); - match req.parse(src).unwrap() { - httparse::Status::Complete(_len) => { - HeaderIndex::record(src, req.headers, &mut headers); - req.headers.len() - } - _ => unreachable!(), - } - } -} diff --git a/actix-http/benches/write-camel-case.rs b/actix-http/benches/write-camel-case.rs deleted file mode 100644 index ccf09b37e..000000000 --- a/actix-http/benches/write-camel-case.rs +++ /dev/null @@ -1,93 +0,0 @@ -use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; - -fn bench_write_camel_case(c: &mut Criterion) { - let mut group = c.benchmark_group("write_camel_case"); - - let names = ["connection", "Transfer-Encoding", "transfer-encoding"]; - - for &i in &names { - let bts = i.as_bytes(); - - group.bench_with_input(BenchmarkId::new("Original", i), bts, |b, bts| { - b.iter(|| { - let mut buf = black_box([0; 24]); - _original::write_camel_case(black_box(bts), &mut buf) - }); - }); - - group.bench_with_input(BenchmarkId::new("New", i), bts, |b, bts| { - b.iter(|| { - let mut buf = black_box([0; 24]); - let len = black_box(bts.len()); - _new::write_camel_case(black_box(bts), buf.as_mut_ptr(), len) - }); - }); - } - - group.finish(); -} - -criterion_group!(benches, bench_write_camel_case); -criterion_main!(benches); - -mod _new { - pub fn write_camel_case(value: &[u8], buf: *mut u8, len: usize) { - // first copy entire (potentially wrong) slice to output - let buffer = unsafe { - std::ptr::copy_nonoverlapping(value.as_ptr(), buf, len); - std::slice::from_raw_parts_mut(buf, len) - }; - - let mut iter = value.iter(); - - // first character should be uppercase - if let Some(c @ b'a'..=b'z') = iter.next() { - buffer[0] = c & 0b1101_1111; - } - - // track 1 ahead of the current position since that's the location being assigned to - let mut index = 2; - - // remaining characters after hyphens should also be uppercase - while let Some(&c) = iter.next() { - if c == b'-' { - // advance iter by one and uppercase if needed - if let Some(c @ b'a'..=b'z') = iter.next() { - buffer[index] = c & 0b1101_1111; - } - } - - index += 1; - } - } -} - -mod _original { - pub fn write_camel_case(value: &[u8], buffer: &mut [u8]) { - let mut index = 0; - let key = value; - let mut key_iter = key.iter(); - - if let Some(c) = key_iter.next() { - if *c >= b'a' && *c <= b'z' { - buffer[index] = *c ^ b' '; - index += 1; - } - } else { - return; - } - - while let Some(c) = key_iter.next() { - buffer[index] = *c; - index += 1; - if *c == b'-' { - if let Some(c) = key_iter.next() { - if *c >= b'a' && *c <= b'z' { - buffer[index] = *c ^ b' '; - index += 1; - } - } - } - } - } -} From 19c9d858f25e8262e14546f430d713addb397e96 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 12 Mar 2023 04:29:22 +0000 Subject: [PATCH 047/314] support 16 extractors --- actix-web/CHANGES.md | 8 ++++++++ actix-web/src/extract.rs | 4 ++++ actix-web/src/handler.rs | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 9a768a122..757e31eeb 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,10 +2,18 @@ ## Unreleased - 2023-xx-xx +### Added + - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. +### Changed + +- Handler functions can now receive up to 16 extractor parameters. + ## 4.3.1 - 2023-02-26 +### Added + - Add support for custom methods with the `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 diff --git a/actix-web/src/extract.rs b/actix-web/src/extract.rs index d4f5cc91f..84904a9eb 100644 --- a/actix-web/src/extract.rs +++ b/actix-web/src/extract.rs @@ -416,6 +416,10 @@ mod tuple_from_req { tuple_from_req! { TupleFromRequest10; A, B, C, D, E, F, G, H, I, J } tuple_from_req! { TupleFromRequest11; A, B, C, D, E, F, G, H, I, J, K } tuple_from_req! { TupleFromRequest12; A, B, C, D, E, F, G, H, I, J, K, L } + tuple_from_req! { TupleFromRequest13; A, B, C, D, E, F, G, H, I, J, K, L, M } + tuple_from_req! { TupleFromRequest14; A, B, C, D, E, F, G, H, I, J, K, L, M, N } + tuple_from_req! { TupleFromRequest15; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O } + tuple_from_req! { TupleFromRequest16; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P } } #[cfg(test)] diff --git a/actix-web/src/handler.rs b/actix-web/src/handler.rs index 522a48b82..0c5e58e28 100644 --- a/actix-web/src/handler.rs +++ b/actix-web/src/handler.rs @@ -151,6 +151,10 @@ factory_tuple! { A B C D E F G H I } factory_tuple! { A B C D E F G H I J } factory_tuple! { A B C D E F G H I J K } factory_tuple! { A B C D E F G H I J K L } +factory_tuple! { A B C D E F G H I J K L M } +factory_tuple! { A B C D E F G H I J K L M N } +factory_tuple! { A B C D E F G H I J K L M N O } +factory_tuple! { A B C D E F G H I J K L M N O P } #[cfg(test)] mod tests { @@ -167,6 +171,7 @@ mod tests { async fn handler_max( _01: (), _02: (), _03: (), _04: (), _05: (), _06: (), _07: (), _08: (), _09: (), _10: (), _11: (), _12: (), + _13: (), _14: (), _15: (), _16: (), ) {} assert_impl_handler(handler_min); From dfaca18584cc36c08506cf8433ac2d118e450856 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 12 Mar 2023 15:32:07 +0000 Subject: [PATCH 048/314] add compression_responses benchmark (#3001) --- actix-http/Cargo.toml | 5 ++ .../benches/response-body-compression.rs | 90 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 actix-http/benches/response-body-compression.rs diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index ce653f440..235e4e980 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -124,3 +124,8 @@ tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" required-features = ["ws", "rustls"] + +[[bench]] +name = "response-body-compression" +harness = false +required-features = ["compress-brotli", "compress-gzip", "compress-zstd"] diff --git a/actix-http/benches/response-body-compression.rs b/actix-http/benches/response-body-compression.rs new file mode 100644 index 000000000..d128bf75b --- /dev/null +++ b/actix-http/benches/response-body-compression.rs @@ -0,0 +1,90 @@ +#![allow(clippy::uninlined_format_args)] + +use std::convert::Infallible; + +use actix_http::{encoding::Encoder, ContentEncoding, Request, Response, StatusCode}; +use actix_service::{fn_service, Service as _}; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + +static BODY: &[u8] = include_bytes!("../Cargo.toml"); + +fn compression_responses(c: &mut Criterion) { + let mut group = c.benchmark_group("compression responses"); + + group.bench_function("identity", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Identity, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("gzip", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Gzip, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("br", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Brotli, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.bench_function("zstd", |b| { + let rt = actix_rt::Runtime::new().unwrap(); + + let identity_svc = fn_service(|_: Request| async move { + let mut res = Response::with_body(StatusCode::OK, ()); + let body = black_box(Encoder::response( + ContentEncoding::Zstd, + res.head_mut(), + BODY, + )); + Ok::<_, Infallible>(black_box(res.set_body(black_box(body)))) + }); + + b.iter(|| { + rt.block_on(identity_svc.call(Request::new())).unwrap(); + }); + }); + + group.finish(); +} + +criterion_group!(benches, compression_responses); +criterion_main!(benches); From 9e7a6fe57bfffc36d199c3e729f3470d10a381aa Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 13:31:48 +0000 Subject: [PATCH 049/314] add `body::to_bytes_limited` (#3000 * add body::to_body_limit * rename to_bytes_limited --- actix-http/CHANGES.md | 5 ++ actix-http/src/body/mod.rs | 2 +- actix-http/src/body/utils.rs | 141 ++++++++++++++++++++++++++++++++--- 3 files changed, 135 insertions(+), 13 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 831a0bcd0..aaf84d765 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,11 @@ ## Unreleased - 2023-xx-xx +### Added + +- Add `body::to_body_limit()` function. +- Add `body::BodyLimitExceeded` error type. + ## 3.3.1 - 2023-03-02 ### Fixed diff --git a/actix-http/src/body/mod.rs b/actix-http/src/body/mod.rs index 0fb090eb5..d1708b9d5 100644 --- a/actix-http/src/body/mod.rs +++ b/actix-http/src/body/mod.rs @@ -22,4 +22,4 @@ pub(crate) use self::message_body::MessageBodyMapErr; pub use self::none::None; pub use self::size::BodySize; pub use self::sized_stream::SizedStream; -pub use self::utils::to_bytes; +pub use self::utils::{to_bytes, to_bytes_limited, BodyLimitExceeded}; diff --git a/actix-http/src/body/utils.rs b/actix-http/src/body/utils.rs index 0a6fb0c15..c741eefd2 100644 --- a/actix-http/src/body/utils.rs +++ b/actix-http/src/body/utils.rs @@ -7,71 +7,188 @@ use futures_core::ready; use super::{BodySize, MessageBody}; -/// Collects the body produced by a `MessageBody` implementation into `Bytes`. +/// Collects all the bytes produced by `body`. /// /// Any errors produced by the body stream are returned immediately. /// +/// Consider using [`to_bytes_limited`] instead to protect against memory exhaustion. +/// /// # Examples +/// /// ``` /// use actix_http::body::{self, to_bytes}; /// use bytes::Bytes; /// -/// # async fn test_to_bytes() { +/// # actix_rt::System::new().block_on(async { /// let body = body::None::new(); /// let bytes = to_bytes(body).await.unwrap(); /// assert!(bytes.is_empty()); /// /// let body = Bytes::from_static(b"123"); /// let bytes = to_bytes(body).await.unwrap(); -/// assert_eq!(bytes, b"123"[..]); -/// # } +/// assert_eq!(bytes, "123"); +/// # }); /// ``` pub async fn to_bytes(body: B) -> Result { + to_bytes_limited(body, usize::MAX) + .await + .expect("body should never overflow usize::MAX") +} + +/// Error type returned from [`to_bytes_limited`] when body produced exceeds limit. +#[derive(Debug)] +#[non_exhaustive] +pub struct BodyLimitExceeded; + +/// Collects the bytes produced by `body`, up to `limit` bytes. +/// +/// If a chunk read from `poll_next` causes the total number of bytes read to exceed `limit`, an +/// `Err(BodyLimitExceeded)` is returned. +/// +/// Any errors produced by the body stream are returned immediately as `Ok(Err(B::Error))`. +/// +/// # Examples +/// +/// ``` +/// use actix_http::body::{self, to_bytes_limited}; +/// use bytes::Bytes; +/// +/// # actix_rt::System::new().block_on(async { +/// let body = body::None::new(); +/// let bytes = to_bytes_limited(body, 10).await.unwrap().unwrap(); +/// assert!(bytes.is_empty()); +/// +/// let body = Bytes::from_static(b"123"); +/// let bytes = to_bytes_limited(body, 10).await.unwrap().unwrap(); +/// assert_eq!(bytes, "123"); +/// +/// let body = Bytes::from_static(b"123"); +/// assert!(to_bytes_limited(body, 2).await.is_err()); +/// # }); +/// ``` +pub async fn to_bytes_limited( + body: B, + limit: usize, +) -> Result, BodyLimitExceeded> { let cap = match body.size() { - BodySize::None | BodySize::Sized(0) => return Ok(Bytes::new()), + BodySize::None | BodySize::Sized(0) => return Ok(Ok(Bytes::new())), + BodySize::Sized(size) if size as usize > limit => return Err(BodyLimitExceeded), BodySize::Sized(size) => size as usize, // good enough first guess for chunk size BodySize::Stream => 32_768, }; + let mut exceeded_limit = false; let mut buf = BytesMut::with_capacity(cap); pin!(body); - poll_fn(|cx| loop { + match poll_fn(|cx| loop { let body = body.as_mut(); match ready!(body.poll_next(cx)) { - Some(Ok(bytes)) => buf.extend_from_slice(&bytes), + Some(Ok(bytes)) => { + // if limit is exceeded... + if buf.len() + bytes.len() > limit { + // ...set flag to true and break out of poll_fn + exceeded_limit = true; + return Poll::Ready(Ok(())); + } + + buf.extend_from_slice(&bytes) + } None => return Poll::Ready(Ok(())), Some(Err(err)) => return Poll::Ready(Err(err)), } }) - .await?; + .await + { + // propagate error returned from body poll + Err(err) => Ok(Err(err)), - Ok(buf.freeze()) + // limit was exceeded while reading body + Ok(()) if exceeded_limit => Err(BodyLimitExceeded), + + // otherwise return body buffer + Ok(()) => Ok(Ok(buf.freeze())), + } } #[cfg(test)] -mod test { +mod tests { + use std::io; + use futures_util::{stream, StreamExt as _}; use super::*; - use crate::{body::BodyStream, Error}; + use crate::{ + body::{BodyStream, SizedStream}, + Error, + }; #[actix_rt::test] - async fn test_to_bytes() { + async fn to_bytes_complete() { let bytes = to_bytes(()).await.unwrap(); assert!(bytes.is_empty()); let body = Bytes::from_static(b"123"); let bytes = to_bytes(body).await.unwrap(); assert_eq!(bytes, b"123"[..]); + } + #[actix_rt::test] + async fn to_bytes_streams() { let stream = stream::iter(vec![Bytes::from_static(b"123"), Bytes::from_static(b"abc")]) .map(Ok::<_, Error>); let body = BodyStream::new(stream); let bytes = to_bytes(body).await.unwrap(); assert_eq!(bytes, b"123abc"[..]); } + + #[actix_rt::test] + async fn to_bytes_limited_complete() { + let bytes = to_bytes_limited((), 0).await.unwrap().unwrap(); + assert!(bytes.is_empty()); + + let bytes = to_bytes_limited((), 1).await.unwrap().unwrap(); + assert!(bytes.is_empty()); + + assert!(to_bytes_limited(Bytes::from_static(b"12"), 0) + .await + .is_err()); + assert!(to_bytes_limited(Bytes::from_static(b"12"), 1) + .await + .is_err()); + assert!(to_bytes_limited(Bytes::from_static(b"12"), 2).await.is_ok()); + assert!(to_bytes_limited(Bytes::from_static(b"12"), 3).await.is_ok()); + } + + #[actix_rt::test] + async fn to_bytes_limited_streams() { + // hinting a larger body fails + let body = SizedStream::new(8, stream::empty().map(Ok::<_, Error>)); + assert!(to_bytes_limited(body, 3).await.is_err()); + + // hinting a smaller body is okay + let body = SizedStream::new(3, stream::empty().map(Ok::<_, Error>)); + assert!(to_bytes_limited(body, 3).await.unwrap().unwrap().is_empty()); + + // hinting a smaller body then returning a larger one fails + let stream = stream::iter(vec![Bytes::from_static(b"1234")]).map(Ok::<_, Error>); + let body = SizedStream::new(3, stream); + assert!(to_bytes_limited(body, 3).await.is_err()); + + let stream = stream::iter(vec![Bytes::from_static(b"123"), Bytes::from_static(b"abc")]) + .map(Ok::<_, Error>); + let body = BodyStream::new(stream); + assert!(to_bytes_limited(body, 3).await.is_err()); + } + + #[actix_rt::test] + async fn to_body_limit_error() { + let err_stream = stream::once(async { Err(io::Error::new(io::ErrorKind::Other, "")) }); + let body = SizedStream::new(8, err_stream); + // not too big, but propagates error from body stream + assert!(to_bytes_limited(body, 10).await.unwrap().is_err()); + } } From 44c5cdaa107e4c5bc220428f44166441144c2238 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 13:40:07 +0000 Subject: [PATCH 050/314] bound initial allocation in to_bytes_limited --- actix-http/src/body/utils.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-http/src/body/utils.rs b/actix-http/src/body/utils.rs index c741eefd2..7af5a50ad 100644 --- a/actix-http/src/body/utils.rs +++ b/actix-http/src/body/utils.rs @@ -32,7 +32,7 @@ use super::{BodySize, MessageBody}; pub async fn to_bytes(body: B) -> Result { to_bytes_limited(body, usize::MAX) .await - .expect("body should never overflow usize::MAX") + .expect("body should never yield more than usize::MAX bytes") } /// Error type returned from [`to_bytes_limited`] when body produced exceeds limit. @@ -70,12 +70,14 @@ pub async fn to_bytes_limited( body: B, limit: usize, ) -> Result, BodyLimitExceeded> { + /// Sensible default (32kB) for initial, bounded allocation when collecting body bytes. + const INITIAL_ALLOC_BYTES: usize = 32 * 1024; + let cap = match body.size() { BodySize::None | BodySize::Sized(0) => return Ok(Ok(Bytes::new())), BodySize::Sized(size) if size as usize > limit => return Err(BodyLimitExceeded), - BodySize::Sized(size) => size as usize, - // good enough first guess for chunk size - BodySize::Stream => 32_768, + BodySize::Sized(size) => (size as usize).min(INITIAL_ALLOC_BYTES), + BodySize::Stream => INITIAL_ALLOC_BYTES, }; let mut exceeded_limit = false; From 0e7380659f844d216b206faaae6abd51f9d1aeea Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 13:40:09 +0000 Subject: [PATCH 051/314] implement Error for BodyLimitExceeded --- actix-http/src/body/utils.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-http/src/body/utils.rs b/actix-http/src/body/utils.rs index 7af5a50ad..d1449179f 100644 --- a/actix-http/src/body/utils.rs +++ b/actix-http/src/body/utils.rs @@ -3,6 +3,7 @@ use std::task::Poll; use actix_rt::pin; use actix_utils::future::poll_fn; use bytes::{Bytes, BytesMut}; +use derive_more::{Display, Error}; use futures_core::ready; use super::{BodySize, MessageBody}; @@ -36,7 +37,8 @@ pub async fn to_bytes(body: B) -> Result { } /// Error type returned from [`to_bytes_limited`] when body produced exceeds limit. -#[derive(Debug)] +#[derive(Debug, Display, Error)] +#[display(fmt = "limit exceeded while collecting body bytes")] #[non_exhaustive] pub struct BodyLimitExceeded; From bfdc29ebb8d93f5cc276ed32e81bed37bceb4fa6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 14:22:50 +0000 Subject: [PATCH 052/314] normalize actix-files error messages --- actix-files/src/error.rs | 32 +++++++++++----------- actix-files/src/range.rs | 58 +++++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/actix-files/src/error.rs b/actix-files/src/error.rs index 2f3a36cd1..68cea8d89 100644 --- a/actix-files/src/error.rs +++ b/actix-files/src/error.rs @@ -4,46 +4,44 @@ use derive_more::Display; /// Errors which can occur when serving static files. #[derive(Debug, PartialEq, Eq, Display)] pub enum FilesError { - /// Path is not a directory + /// Path is not a directory. #[allow(dead_code)] - #[display(fmt = "Path is not a directory. Unable to serve static files")] + #[display(fmt = "path is not a directory. Unable to serve static files")] IsNotDirectory, - /// Cannot render directory - #[display(fmt = "Unable to render directory without index file")] + /// Cannot render directory. + #[display(fmt = "unable to render directory without index file")] IsDirectory, } -/// Return `NotFound` for `FilesError` impl ResponseError for FilesError { + /// Returns `404 Not Found`. fn status_code(&self) -> StatusCode { StatusCode::NOT_FOUND } } -#[allow(clippy::enum_variant_names)] #[derive(Debug, PartialEq, Eq, Display)] #[non_exhaustive] pub enum UriSegmentError { - /// The segment started with the wrapped invalid character. - #[display(fmt = "The segment started with the wrapped invalid character")] + /// Segment started with the wrapped invalid character. + #[display(fmt = "segment started with invalid character: ('{_0}')")] BadStart(char), - /// The segment contained the wrapped invalid character. - #[display(fmt = "The segment contained the wrapped invalid character")] + /// Segment contained the wrapped invalid character. + #[display(fmt = "segment contained invalid character ('{_0}')")] BadChar(char), - /// The segment ended with the wrapped invalid character. - #[display(fmt = "The segment ended with the wrapped invalid character")] + /// Segment ended with the wrapped invalid character. + #[display(fmt = "segment ended with invalid character: ('{_0}')")] BadEnd(char), - - /// The path is not a valid UTF-8 string after doing percent decoding. - #[display(fmt = "The path is not a valid UTF-8 string after percent-decoding")] - NotValidUtf8, + // /// Path is not a valid UTF-8 string after percent-decoding. + // #[display(fmt = "path is not a valid UTF-8 string after percent-decoding")] + // NotValidUtf8, } -/// Return `BadRequest` for `UriSegmentError` impl ResponseError for UriSegmentError { + /// Returns `400 Bad Request`. fn status_code(&self) -> StatusCode { StatusCode::BAD_REQUEST } diff --git a/actix-files/src/range.rs b/actix-files/src/range.rs index 8d9fe9445..65c680ede 100644 --- a/actix-files/src/range.rs +++ b/actix-files/src/range.rs @@ -1,4 +1,36 @@ -use derive_more::{Display, Error}; +use std::fmt; + +use derive_more::Error; + +/// Copy of `http_range::HttpRangeParseError`. +#[derive(Debug, Clone)] +enum HttpRangeParseError { + InvalidRange, + NoOverlap, +} + +impl From for HttpRangeParseError { + fn from(err: http_range::HttpRangeParseError) -> Self { + match err { + http_range::HttpRangeParseError::InvalidRange => Self::InvalidRange, + http_range::HttpRangeParseError::NoOverlap => Self::NoOverlap, + } + } +} + +#[derive(Debug, Clone, Error)] +#[non_exhaustive] +pub struct ParseRangeErr(#[error(not(source))] HttpRangeParseError); + +impl fmt::Display for ParseRangeErr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("invalid Range header: ")?; + f.write_str(match self.0 { + HttpRangeParseError::InvalidRange => "invalid syntax", + HttpRangeParseError::NoOverlap => "range starts after end of content", + }) + } +} /// HTTP Range header representation. #[derive(Debug, Clone, Copy)] @@ -10,26 +42,22 @@ pub struct HttpRange { pub length: u64, } -#[derive(Debug, Clone, Display, Error)] -#[display(fmt = "Parse HTTP Range failed")] -pub struct ParseRangeErr(#[error(not(source))] ()); - impl HttpRange { /// Parses Range HTTP header string as per RFC 2616. /// /// `header` is HTTP Range header (e.g. `bytes=bytes=0-9`). /// `size` is full size of response (file). pub fn parse(header: &str, size: u64) -> Result, ParseRangeErr> { - match http_range::HttpRange::parse(header, size) { - Ok(ranges) => Ok(ranges - .iter() - .map(|range| HttpRange { - start: range.start, - length: range.length, - }) - .collect()), - Err(_) => Err(ParseRangeErr(())), - } + let ranges = http_range::HttpRange::parse(header, size) + .map_err(|err| ParseRangeErr(err.into()))?; + + Ok(ranges + .iter() + .map(|range| HttpRange { + start: range.start, + length: range.length, + }) + .collect()) } } From 442fa279dad32c34556624fdcbad077cd415bd09 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 14:30:21 +0000 Subject: [PATCH 053/314] uncomment error variant --- actix-files/src/error.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/actix-files/src/error.rs b/actix-files/src/error.rs index 68cea8d89..d614651fc 100644 --- a/actix-files/src/error.rs +++ b/actix-files/src/error.rs @@ -35,9 +35,10 @@ pub enum UriSegmentError { /// Segment ended with the wrapped invalid character. #[display(fmt = "segment ended with invalid character: ('{_0}')")] BadEnd(char), - // /// Path is not a valid UTF-8 string after percent-decoding. - // #[display(fmt = "path is not a valid UTF-8 string after percent-decoding")] - // NotValidUtf8, + + /// Path is not a valid UTF-8 string after percent-decoding. + #[display(fmt = "path is not a valid UTF-8 string after percent-decoding")] + NotValidUtf8, } impl ResponseError for UriSegmentError { From 5e29726c4fa725b1bf3a0317c57e3f0d1b3e327c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 13 Mar 2023 17:17:02 +0000 Subject: [PATCH 054/314] standardize error messages in actix-http --- actix-http/src/error.rs | 66 +++++++++++++-------------- actix-http/src/ws/mod.rs | 32 ++++++------- actix-http/tests/test_ws.rs | 6 +-- actix-web/src/error/response_error.rs | 2 +- 4 files changed, 52 insertions(+), 54 deletions(-) diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 41522a254..fa0228a50 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -161,44 +161,44 @@ impl From for Error { #[non_exhaustive] pub enum ParseError { /// An invalid `Method`, such as `GE.T`. - #[display(fmt = "Invalid Method specified")] + #[display(fmt = "invalid method specified")] Method, /// An invalid `Uri`, such as `exam ple.domain`. - #[display(fmt = "Uri error: {}", _0)] + #[display(fmt = "URI error: {}", _0)] Uri(InvalidUri), /// An invalid `HttpVersion`, such as `HTP/1.1` - #[display(fmt = "Invalid HTTP version specified")] + #[display(fmt = "invalid HTTP version specified")] Version, /// An invalid `Header`. - #[display(fmt = "Invalid Header provided")] + #[display(fmt = "invalid Header provided")] Header, /// A message head is too large to be reasonable. - #[display(fmt = "Message head is too large")] + #[display(fmt = "message head is too large")] TooLarge, /// A message reached EOF, but is not complete. - #[display(fmt = "Message is incomplete")] + #[display(fmt = "message is incomplete")] Incomplete, /// An invalid `Status`, such as `1337 ELITE`. - #[display(fmt = "Invalid Status provided")] + #[display(fmt = "invalid status provided")] Status, /// A timeout occurred waiting for an IO event. #[allow(dead_code)] - #[display(fmt = "Timeout")] + #[display(fmt = "timeout")] Timeout, - /// An `io::Error` that occurred while trying to read or write to a network stream. - #[display(fmt = "IO error: {}", _0)] + /// An I/O error that occurred while trying to read or write to a network stream. + #[display(fmt = "I/O error: {}", _0)] Io(io::Error), /// Parsing a field as string failed. - #[display(fmt = "UTF8 error: {}", _0)] + #[display(fmt = "UTF-8 error: {}", _0)] Utf8(Utf8Error), } @@ -257,22 +257,19 @@ impl From for Response { #[non_exhaustive] pub enum PayloadError { /// A payload reached EOF, but is not complete. - #[display( - fmt = "A payload reached EOF, but is not complete. Inner error: {:?}", - _0 - )] + #[display(fmt = "payload reached EOF before completing: {:?}", _0)] Incomplete(Option), /// Content encoding stream corruption. - #[display(fmt = "Can not decode content-encoding.")] + #[display(fmt = "can not decode content-encoding")] EncodingCorrupted, /// Payload reached size limit. - #[display(fmt = "Payload reached size limit.")] + #[display(fmt = "payload reached size limit")] Overflow, /// Payload length is unknown. - #[display(fmt = "Payload length is unknown.")] + #[display(fmt = "payload length is unknown")] UnknownLength, /// HTTP/2 payload error. @@ -330,22 +327,23 @@ impl From for Error { #[non_exhaustive] pub enum DispatchError { /// Service error. - #[display(fmt = "Service Error")] + #[display(fmt = "service error")] Service(Response), /// Body streaming error. - #[display(fmt = "Body error: {}", _0)] + #[display(fmt = "body error: {}", _0)] Body(Box), /// Upgrade service error. + #[display(fmt = "upgrade error")] Upgrade, /// An `io::Error` that occurred while trying to read or write to a network stream. - #[display(fmt = "IO error: {}", _0)] + #[display(fmt = "I/O error: {}", _0)] Io(io::Error), /// Request parse error. - #[display(fmt = "Request parse error: {}", _0)] + #[display(fmt = "request parse error: {}", _0)] Parse(ParseError), /// HTTP/2 error. @@ -354,19 +352,19 @@ pub enum DispatchError { H2(h2::Error), /// The first request did not complete within the specified timeout. - #[display(fmt = "The first request did not complete within the specified timeout")] + #[display(fmt = "request did not complete within the specified timeout")] SlowRequestTimeout, - /// Disconnect timeout. Makes sense for ssl streams. - #[display(fmt = "Connection shutdown timeout")] + /// Disconnect timeout. Makes sense for TLS streams. + #[display(fmt = "connection shutdown timeout")] DisconnectTimeout, /// Handler dropped payload before reading EOF. - #[display(fmt = "Handler dropped payload before reading EOF")] + #[display(fmt = "handler dropped payload before reading EOF")] HandlerDroppedPayload, /// Internal error. - #[display(fmt = "Internal error")] + #[display(fmt = "internal error")] InternalError, } @@ -391,12 +389,12 @@ impl StdError for DispatchError { #[cfg_attr(test, derive(PartialEq, Eq))] #[non_exhaustive] pub enum ContentTypeError { - /// Can not parse content type - #[display(fmt = "Can not parse content type")] + /// Can not parse content type. + #[display(fmt = "could not parse content type")] ParseError, - /// Unknown content encoding - #[display(fmt = "Unknown content encoding")] + /// Unknown content encoding. + #[display(fmt = "unknown content encoding")] UnknownEncoding, } @@ -424,7 +422,7 @@ mod tests { let err: Error = ParseError::Io(orig).into(); assert_eq!( format!("{}", err), - "error parsing HTTP message: IO error: other" + "error parsing HTTP message: I/O error: other" ); } @@ -451,7 +449,7 @@ mod tests { let err = PayloadError::Incomplete(None); assert_eq!( err.to_string(), - "A payload reached EOF, but is not complete. Inner error: None" + "payload reached EOF before completing: None" ); } @@ -471,7 +469,7 @@ mod tests { match ParseError::from($from) { e @ $error => { let desc = format!("{}", e); - assert_eq!(desc, format!("IO error: {}", $from)); + assert_eq!(desc, format!("I/O error: {}", $from)); } _ => unreachable!("{:?}", $from), } diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs index 75d4ca628..2a0b0a99c 100644 --- a/actix-http/src/ws/mod.rs +++ b/actix-http/src/ws/mod.rs @@ -26,39 +26,39 @@ pub use self::proto::{hash_key, CloseCode, CloseReason, OpCode}; #[derive(Debug, Display, Error, From)] pub enum ProtocolError { /// Received an unmasked frame from client. - #[display(fmt = "Received an unmasked frame from client.")] + #[display(fmt = "received an unmasked frame from client")] UnmaskedFrame, /// Received a masked frame from server. - #[display(fmt = "Received a masked frame from server.")] + #[display(fmt = "received a masked frame from server")] MaskedFrame, /// Encountered invalid opcode. - #[display(fmt = "Invalid opcode: {}.", _0)] + #[display(fmt = "invalid opcode ({})", _0)] InvalidOpcode(#[error(not(source))] u8), /// Invalid control frame length - #[display(fmt = "Invalid control frame length: {}.", _0)] + #[display(fmt = "invalid control frame length ({})", _0)] InvalidLength(#[error(not(source))] usize), /// Bad opcode. - #[display(fmt = "Bad opcode.")] + #[display(fmt = "bad opcode")] BadOpCode, /// A payload reached size limit. - #[display(fmt = "A payload reached size limit.")] + #[display(fmt = "payload reached size limit")] Overflow, - /// Continuation is not started. - #[display(fmt = "Continuation is not started.")] + /// Continuation has not started. + #[display(fmt = "continuation has not started")] ContinuationNotStarted, /// Received new continuation but it is already started. - #[display(fmt = "Received new continuation but it is already started.")] + #[display(fmt = "received new continuation but it has already started")] ContinuationStarted, /// Unknown continuation fragment. - #[display(fmt = "Unknown continuation fragment: {}.", _0)] + #[display(fmt = "unknown continuation fragment: {}", _0)] ContinuationFragment(#[error(not(source))] OpCode), /// I/O error. @@ -70,27 +70,27 @@ pub enum ProtocolError { #[derive(Debug, Clone, Copy, PartialEq, Eq, Display, Error)] pub enum HandshakeError { /// Only get method is allowed. - #[display(fmt = "Method not allowed.")] + #[display(fmt = "method not allowed")] GetMethodRequired, /// Upgrade header if not set to WebSocket. - #[display(fmt = "WebSocket upgrade is expected.")] + #[display(fmt = "WebSocket upgrade is expected")] NoWebsocketUpgrade, /// Connection header is not set to upgrade. - #[display(fmt = "Connection upgrade is expected.")] + #[display(fmt = "connection upgrade is expected")] NoConnectionUpgrade, /// WebSocket version header is not set. - #[display(fmt = "WebSocket version header is required.")] + #[display(fmt = "WebSocket version header is required")] NoVersionHeader, /// Unsupported WebSocket version. - #[display(fmt = "Unsupported WebSocket version.")] + #[display(fmt = "unsupported WebSocket version")] UnsupportedVersion, /// WebSocket key is not set or wrong. - #[display(fmt = "Unknown websocket key.")] + #[display(fmt = "unknown WebSocket key")] BadWebsocketKey, } diff --git a/actix-http/tests/test_ws.rs b/actix-http/tests/test_ws.rs index a9c1acd33..a2866613b 100644 --- a/actix-http/tests/test_ws.rs +++ b/actix-http/tests/test_ws.rs @@ -39,13 +39,13 @@ impl WsService { #[derive(Debug, Display, Error, From)] enum WsServiceError { - #[display(fmt = "http error")] + #[display(fmt = "HTTP error")] Http(actix_http::Error), - #[display(fmt = "ws handshake error")] + #[display(fmt = "WS handshake error")] Ws(actix_http::ws::HandshakeError), - #[display(fmt = "io error")] + #[display(fmt = "I/O error")] Io(std::io::Error), #[display(fmt = "dispatcher error")] diff --git a/actix-web/src/error/response_error.rs b/actix-web/src/error/response_error.rs index 7d2c06154..f5d8cf467 100644 --- a/actix-web/src/error/response_error.rs +++ b/actix-web/src/error/response_error.rs @@ -152,7 +152,7 @@ mod tests { let resp_err: &dyn ResponseError = &err; let err = resp_err.downcast_ref::().unwrap(); - assert_eq!(err.to_string(), "Payload reached size limit."); + assert_eq!(err.to_string(), "payload reached size limit"); let not_err = resp_err.downcast_ref::(); assert!(not_err.is_none()); From 0f3068f4884dfa439fcc3d87b21ff7c3c67208b6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 15 Mar 2023 05:39:02 +0000 Subject: [PATCH 055/314] ci(windows): use choco to install openssl (#3003 ci: remove openssl install on windows --- .github/workflows/ci.yml | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48380265a..88353fd30 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: target: - { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu } - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - - { name: Windows, os: windows-2022, triple: x86_64-pc-windows-msvc } + - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - 1.59.0 # MSRV - stable @@ -28,20 +28,16 @@ jobs: env: CI: 1 CARGO_INCREMENTAL: 0 - VCPKGRS_DYNAMIC: 1 steps: - uses: actions/checkout@v3 - # install OpenSSL on Windows - # TODO: GitHub actions docs state that OpenSSL is - # already installed on these Windows machines somewhere - - name: Set vcpkg root - if: matrix.target.triple == 'x86_64-pc-windows-msvc' - run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install OpenSSL - if: matrix.target.triple == 'x86_64-pc-windows-msvc' - run: vcpkg install openssl:x64-windows + if: matrix.target.os == 'windows-latest' + run: choco install openssl + - name: Set OpenSSL dir in env + if: matrix.target.os == 'windows-latest' + run: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 From e68f87f84f3109b31de2f2361d4c06af691d8bfb Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 15 Mar 2023 13:32:55 +0000 Subject: [PATCH 056/314] add API diff to CI (#3002) --- .github/workflows/bench.yml | 6 +++- .github/workflows/ci-post-merge.yml | 8 +++-- .github/workflows/ci.yml | 12 ++++--- .github/workflows/clippy-fmt.yml | 51 +++++++++++++++++++++++------ .github/workflows/coverage.yml | 7 ++++ .github/workflows/upload-doc.yml | 10 ++++-- 6 files changed, 74 insertions(+), 20 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 3d16a7eb7..a1a31fb8d 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -6,7 +6,11 @@ on: - master permissions: - contents: read # to fetch code (actions/checkout) + contents: read # to fetch code (actions/checkout) + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: check_benchmark: diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 30d13bf88..6ca17ef63 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -5,7 +5,11 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read # to fetch code (actions/checkout) + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: build_and_test_nightly: @@ -81,7 +85,7 @@ jobs: - name: Clear the cargo caches run: | - cargo install cargo-cache --version 0.8.2 --no-default-features --features ci-autoclean + cargo install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean cargo-cache ci_feature_powerset_check: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88353fd30..f8867ce22 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,10 @@ on: permissions: contents: read # to fetch code (actions/checkout) +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build_and_test: strategy: @@ -91,7 +95,7 @@ jobs: - name: Clear the cargo caches run: | - cargo install cargo-cache --version 0.8.2 --no-default-features --features ci-autoclean + cargo install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean cargo-cache io-uring: @@ -110,10 +114,8 @@ jobs: - name: tests (io-uring) timeout-minutes: 60 run: > - sudo bash -c "ulimit -Sl 512 - && ulimit -Hl 512 - && PATH=$PATH:/usr/share/rust/.cargo/bin - && RUSTUP_TOOLCHAIN=stable cargo test --lib --tests -p=actix-files --all-features" + sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=stable cargo test --lib --tests -p=actix-files --all-features" + rustdoc: name: doc tests diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 877ca74e4..90e3b3a98 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -4,28 +4,42 @@ on: pull_request: types: [opened, synchronize, reopened] +permissions: + contents: read # to fetch code (actions/checkout) + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - with: { components: rustfmt } + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: nightly + components: rustfmt + - run: cargo fmt --all -- --check clippy: + permissions: + checks: write # to add clippy checks to PR diffs + runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: { components: clippy } - name: Generate Cargo.lock run: cargo generate-lockfile - name: Cache Dependencies uses: Swatinem/rust-cache@v1.2.0 - + - name: Check with Clippy uses: actions-rs/clippy-check@v1 with: @@ -37,13 +51,30 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - uses: actions-rust-lang/setup-rust-toolchain@v1 with: { components: rust-docs } - name: Check for broken intra-doc links - uses: actions-rs/cargo@v1 - env: - RUSTDOCFLAGS: "-D warnings" + env: { RUSTDOCFLAGS: "-D warnings" } + run: cargo doc --no-deps --all-features --workspace + + public-api-diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 with: - command: doc - args: --no-deps --all-features --workspace + ref: ${{ github.base_ref }} + + - uses: actions/checkout@v3 + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: { toolchain: nightly } + + - uses: taiki-e/cache-cargo-install-action@v1 + with: { tool: cargo-public-api } + + - name: generate API diff + run: | + for f in $(find -mindepth 2 -maxdepth 2 -name Cargo.toml); do + cargo public-api --manifest-path "$f" diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} + done diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bb6d7fb97..11538c3d6 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -6,6 +6,13 @@ on: push: branches: [master] +permissions: + contents: read # to fetch code (actions/checkout) + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: # job currently (1st Feb 2022) segfaults coverage: diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 2464ebcd6..743e14412 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -4,11 +4,17 @@ on: push: branches: [master] -permissions: {} +permissions: + contents: read # to fetch code (actions/checkout) + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: build: permissions: - contents: write # to push changes in repo (jamesives/github-pages-deploy-action) + contents: write # to push changes in repo (jamesives/github-pages-deploy-action) runs-on: ubuntu-latest From 8dee8a14265f02d3486cd0a58d5f3a8ddbc5679e Mon Sep 17 00:00:00 2001 From: Elijah <83283675+tltsutltsu@users.noreply.github.com> Date: Sat, 1 Apr 2023 00:09:13 +0600 Subject: [PATCH 057/314] docs(actix-http-test): update test server example (#3007) --- actix-http-test/src/lib.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs index 55224dc46..8dcbe759d 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -34,7 +34,9 @@ use tokio::sync::mpsc; /// ```no_run /// use actix_http::HttpService; /// use actix_http_test::test_server; -/// use actix_web::{web, App, HttpResponse, Error}; +/// use actix_service::map_config; +/// use actix_service::ServiceFactoryExt; +/// use actix_web::{dev::AppConfig, web, App, Error, HttpResponse}; /// /// async fn my_handler() -> Result { /// Ok(HttpResponse::Ok().into()) @@ -42,14 +44,19 @@ use tokio::sync::mpsc; /// /// #[actix_web::test] /// async fn test_example() { -/// let mut srv = TestServer::start(|| -/// HttpService::new( -/// App::new().service(web::resource("/").to(my_handler)) -/// ) -/// ); +/// let srv = test_server(|| { +/// let app = App::new().service(web::resource("/").to(my_handler)); +/// +/// HttpService::build() +/// .h1(map_config(app, |_| AppConfig::default())) +/// .tcp() +/// .map_err(|_| ()) +/// }) +/// .await; /// /// let req = srv.get("/"); /// let response = req.send().await.unwrap(); +/// /// assert!(response.status().is_success()); /// } /// ``` From 97399e8c8ce584d005577604c10bd391e5da7268 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 2 Apr 2023 03:27:14 +0100 Subject: [PATCH 058/314] simplify CI --- .github/workflows/ci-post-merge.yml | 2 +- .github/workflows/ci.yml | 36 ++++++++--------------------- .github/workflows/clippy-fmt.yml | 13 ++++------- .github/workflows/coverage.yml | 14 ++--------- 4 files changed, 17 insertions(+), 48 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 6ca17ef63..d47083575 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -48,7 +48,7 @@ jobs: - name: Install ${{ matrix.version }} uses: actions-rs/toolchain@v1 with: - toolchain: ${{ matrix.version }}-${{ matrix.target.triple }} + toolchain: ${{ matrix.version }} profile: minimal override: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8867ce22..4c9149722 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,9 +29,7 @@ jobs: name: ${{ matrix.target.name }} / ${{ matrix.version }} runs-on: ${{ matrix.target.os }} - env: - CI: 1 - CARGO_INCREMENTAL: 0 + env: {} steps: - uses: actions/checkout@v3 @@ -43,12 +41,10 @@ jobs: if: matrix.target.os == 'windows-latest' run: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append - - name: Install ${{ matrix.version }} - uses: actions-rs/toolchain@v1 + - name: Install Rust (${{ matrix.version }}) + uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: ${{ matrix.version }}-${{ matrix.target.triple }} - profile: minimal - override: true + toolchain: ${{ matrix.version }} - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack @@ -60,12 +56,6 @@ jobs: cargo add const-str@0.3 --dev -p=actix-web cargo add const-str@0.3 --dev -p=awc - - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } - - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.2.0 - - name: workaround MSRV issues if: matrix.version != 'stable' run: | @@ -104,12 +94,9 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable - - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.3.0 + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: { toolchain: nightly } - name: tests (io-uring) timeout-minutes: 60 @@ -123,12 +110,9 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly - - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.3.0 + - name: Install Rust (nightly) + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: { toolchain: nightly } - name: doc tests run: cargo ci-doctest diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 90e3b3a98..a7da9b1c5 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -35,16 +35,11 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: { components: clippy } - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.2.0 - - - name: Check with Clippy - uses: actions-rs/clippy-check@v1 + - uses: giraffate/clippy-action@v1 with: - args: --workspace --tests --examples --all-features - token: ${{ secrets.GITHUB_TOKEN }} + reporter: 'github-pr-check' + github_token: ${{ secrets.GITHUB_TOKEN }} + clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo lint-docs: runs-on: ubuntu-latest diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 11538c3d6..d537031c3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -21,18 +21,8 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable-x86_64-unknown-linux-gnu - profile: minimal - override: true - - - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } - - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.2.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: { toolchain: nightly } - name: Generate coverage file run: | From e81dc768dcbb0c2f4147439a4249a8d97352302d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 6 Apr 2023 03:11:28 +0100 Subject: [PATCH 059/314] expose h2c methods on HttpServer (#2999 * expose h2c methods on HttpServer * update h2c docs --- actix-web/CHANGES.md | 1 + actix-web/examples/on-connect.rs | 9 ++-- actix-web/src/server.rs | 80 +++++++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 757e31eeb..d5989982a 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `HttpServer::{bind,listen}_auto_h2c()` method. - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. ### Changed diff --git a/actix-web/examples/on-connect.rs b/actix-web/examples/on-connect.rs index 57017fcd6..0d56a8f25 100644 --- a/actix-web/examples/on-connect.rs +++ b/actix-web/examples/on-connect.rs @@ -4,8 +4,6 @@ //! For an example of extracting a client TLS certificate, see: //! -#![allow(clippy::uninlined_format_args)] - use std::{any::Any, io, net::SocketAddr}; use actix_web::{ @@ -24,8 +22,7 @@ struct ConnectionInfo { async fn route_whoami(req: HttpRequest) -> impl Responder { match req.conn_data::() { Some(info) => HttpResponse::Ok().body(format!( - "Here is some info about your connection:\n\n{:#?}", - info + "Here is some info about your connection:\n\n{info:#?}", )), None => { HttpResponse::InternalServerError().body("Missing expected request extension data") @@ -54,8 +51,8 @@ async fn main() -> io::Result<()> { HttpServer::new(|| App::new().default_service(web::to(route_whoami))) .on_connect(get_conn_info) - .bind(bind)? - .workers(1) + .bind_auto_h2c(bind)? + .workers(2) .run() .await } diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 1fa279a65..c11d0ef53 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -41,10 +41,19 @@ struct Config { /// /// Create new HTTP server with application factory. /// -/// # HTTP/2 -/// Currently, HTTP/2 is only supported when using TLS (HTTPS). See `bind_rustls` or `bind_openssl`. +/// # Automatic HTTP Version Selection +/// +/// There are two ways to select the HTTP version of an incoming connection: +/// +/// - One is to rely on the ALPN information that is provided when using a TLS (HTTPS); both +/// versions are supported automatically when using either of the `.bind_rustls()` or +/// `.bind_openssl()` methods. +/// - The other is to read the first few bytes of the TCP stream. This is the only viable approach +/// for supporting H2C, which allows the HTTP/2 protocol to work over plaintext connections. Use +/// the `.bind_auto_h2c()` method to enable this behavior. /// /// # Examples +/// /// ```no_run /// use actix_web::{web, App, HttpResponse, HttpServer}; /// @@ -347,6 +356,18 @@ where Ok(self) } + /// Resolves socket address(es) and binds server to created listener(s) for plaintext HTTP/1.x + /// or HTTP/2 connections. + pub fn bind_auto_h2c(mut self, addrs: A) -> io::Result { + let sockets = bind_addrs(addrs, self.backlog)?; + + for lst in sockets { + self = self.listen_auto_h2c(lst)?; + } + + Ok(self) + } + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using Rustls. /// @@ -406,13 +427,13 @@ where self.builder = self.builder .listen(format!("actix-web-service-{}", addr), lst, move || { - let c = cfg.lock().unwrap(); - let host = c.host.clone().unwrap_or_else(|| format!("{}", addr)); + let cfg = cfg.lock().unwrap(); + let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr)); let mut svc = HttpService::build() - .keep_alive(c.keep_alive) - .client_request_timeout(c.client_request_timeout) - .client_disconnect_timeout(c.client_disconnect_timeout) + .keep_alive(cfg.keep_alive) + .client_request_timeout(cfg.client_request_timeout) + .client_disconnect_timeout(cfg.client_disconnect_timeout) .local_addr(addr); if let Some(handler) = on_connect_fn.clone() { @@ -430,6 +451,51 @@ where })) .tcp() })?; + + Ok(self) + } + + /// Binds to existing listener for accepting incoming plaintext HTTP/1.x or HTTP/2 connections. + pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result { + let cfg = self.config.clone(); + let factory = self.factory.clone(); + let addr = lst.local_addr().unwrap(); + + self.sockets.push(Socket { + addr, + scheme: "http", + }); + + let on_connect_fn = self.on_connect_fn.clone(); + + self.builder = + self.builder + .listen(format!("actix-web-service-{}", addr), lst, move || { + let cfg = cfg.lock().unwrap(); + let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr)); + + let mut svc = HttpService::build() + .keep_alive(cfg.keep_alive) + .client_request_timeout(cfg.client_request_timeout) + .client_disconnect_timeout(cfg.client_disconnect_timeout) + .local_addr(addr); + + if let Some(handler) = on_connect_fn.clone() { + svc = svc.on_connect_ext(move |io: &_, ext: _| { + (handler)(io as &dyn Any, ext) + }) + }; + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + svc.finish(map_config(fac, move |_| { + AppConfig::new(false, host.clone(), addr) + })) + .tcp_auto_h2c() + })?; + Ok(self) } From 5d4f5918752a873113863a17e91c16867b6f9bde Mon Sep 17 00:00:00 2001 From: Surya Date: Sat, 22 Apr 2023 13:53:35 +0100 Subject: [PATCH 060/314] fix RUSTSEC-2023-0034 by updating h2 (#3022) --- 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 235e4e980..7c5f07f2d 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -82,7 +82,7 @@ tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } # http2 -h2 = { version = "0.3.9", optional = true } +h2 = { version = "0.3.17", optional = true } # websockets local-channel = { version = "0.1", optional = true } From de1efa673f13c6263e04acbc6c61b948dfa35b07 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 24 Apr 2023 04:46:57 +0900 Subject: [PATCH 061/314] Refine GHA workflows (#3023) --- .github/workflows/bench.yml | 14 +++++--------- .github/workflows/ci-post-merge.yml | 24 ++++++++++-------------- .github/workflows/ci.yml | 6 ++---- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a1a31fb8d..f8bf2abda 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -20,14 +20,10 @@ jobs: - uses: actions/checkout@v3 - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - profile: minimal - override: true + run: | + rustup set profile minimal + rustup install nightly + rustup override set nightly - name: Check benchmark - uses: actions-rs/cargo@v1 - with: - command: bench - args: --bench=server -- --sample-size=15 + run: cargo bench --bench=server -- --sample-size=15 diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d47083575..8dd941e04 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -46,28 +46,24 @@ jobs: run: vcpkg install openssl:x64-windows - name: Install ${{ matrix.version }} - uses: actions-rs/toolchain@v1 - with: - toolchain: ${{ matrix.version }} - profile: minimal - override: true + run: | + rustup set profile minimal + rustup install ${{ matrix.version }} + rustup override set ${{ matrix.version }} - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - name: Generate Cargo.lock - uses: actions-rs/cargo@v1 - with: { command: generate-lockfile } + run: cargo generate-lockfile - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.2.0 + uses: Swatinem/rust-cache@v2.2.1 - name: check minimal - uses: actions-rs/cargo@v1 - with: { command: ci-check-min } + run: cargo ci-check-min - name: check default - uses: actions-rs/cargo@v1 - with: { command: ci-check-default } + run: cargo ci-check-default - name: tests timeout-minutes: 60 @@ -107,7 +103,7 @@ jobs: - name: Generate Cargo.lock run: cargo generate-lockfile - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.2.0 + uses: Swatinem/rust-cache@v2.2.1 - name: check feature combinations run: cargo ci-check-all-feature-powerset @@ -134,7 +130,7 @@ jobs: - name: Generate Cargo.lock run: cargo generate-lockfile - name: Cache Dependencies - uses: Swatinem/rust-cache@v1.3.0 + uses: Swatinem/rust-cache@v2.2.1 - name: Test with cargo-nextest run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c9149722..2d0b71616 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,12 +62,10 @@ jobs: cargo update -p=zstd-sys --precise=2.0.1+zstd.1.5.2 - name: check minimal - uses: actions-rs/cargo@v1 - with: { command: ci-check-min } + run: cargo ci-check-min - name: check default - uses: actions-rs/cargo@v1 - with: { command: ci-check-default } + run: cargo ci-check-default - name: tests timeout-minutes: 60 From 8b2b755cdecdd21277ebcf8611f8bf028b05cbb1 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 6 May 2023 11:37:11 +0100 Subject: [PATCH 062/314] fix guard mod docs --- .github/workflows/ci.yml | 1 - actix-web/CHANGES.md | 5 +++-- actix-web/MIGRATION-4.0.md | 1 - actix-web/src/guard/mod.rs | 7 +++++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d0b71616..e0511339d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,6 @@ jobs: run: > sudo bash -c "ulimit -Sl 512 && ulimit -Hl 512 && PATH=$PATH:/usr/share/rust/.cargo/bin && RUSTUP_TOOLCHAIN=stable cargo test --lib --tests -p=actix-files --all-features" - rustdoc: name: doc tests runs-on: ubuntu-latest diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index d5989982a..9688370b7 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -917,9 +917,9 @@ ### Changed -- Updated actix-web-codegen dependency for access to new `#[route(...)]` multi-method macro. +- Updated `actix-web-codegen` dependency for access to new `#[route(...)]` multi-method macro. - Print non-configured `Data` type when attempting extraction. [#1743] -- Re-export bytes::Buf{Mut} in web module. [#1750] +- Re-export `bytes::Buf{Mut}` in web module. [#1750] - Upgrade `pin-project` to `1.0`. [#1723]: https://github.com/actix/actix-web/pull/1723 @@ -927,6 +927,7 @@ [#1748]: https://github.com/actix/actix-web/pull/1748 [#1750]: https://github.com/actix/actix-web/pull/1750 [#1754]: https://github.com/actix/actix-web/pull/1754 +[#1757]: https://github.com/actix/actix-web/pull/1757 [#1749]: https://github.com/actix/actix-web/pull/1749 ## 3.1.0 - 2020-09-29 diff --git a/actix-web/MIGRATION-4.0.md b/actix-web/MIGRATION-4.0.md index 7b1cfc03b..0f0bd3a53 100644 --- a/actix-web/MIGRATION-4.0.md +++ b/actix-web/MIGRATION-4.0.md @@ -31,7 +31,6 @@ Headings marked with :warning: are **breaking behavioral changes**. They will pr - [Returning `HttpResponse` synchronously](#returning-httpresponse-synchronously) - [`#[actix_web::main]` and `#[tokio::main]`](#actix_webmain-and-tokiomain) - [`web::block`](#webblock) -- ## MSRV diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index 164032bdc..a9173a9d1 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -18,6 +18,7 @@ //! There are shortcuts for routes with method guards in the [`web`](crate::web) module: //! [`web::get()`](crate::web::get), [`web::post()`](crate::web::post), etc. The routes created by //! the following calls are equivalent: +//! //! - `web::get()` (recommended form) //! - `web::route().guard(guard::Get())` //! @@ -28,9 +29,11 @@ //! would result in inaccessible routes. See the [`Host`] guard for an example of virtual hosting. //! //! # Examples +//! //! In the following code, the `/guarded` resource has one defined route whose handler will only be -//! called if the request method is `POST` and there is a request header with name and value equal -//! to `x-guarded` and `secret`, respectively. +//! called if the request method is GET or POST and there is a `x-guarded` request header with value +//! equal to `secret`. +//! //! ``` //! use actix_web::{web, http::Method, guard, HttpResponse}; //! From 6fdda45ca371a4905d434d61584a4bc4bc944131 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 6 May 2023 11:38:51 +0100 Subject: [PATCH 063/314] update bitflags to v2 --- actix-files/Cargo.toml | 2 +- actix-files/src/named.rs | 1 + actix-http/Cargo.toml | 2 +- actix-http/src/h1/client.rs | 1 + actix-http/src/h1/codec.rs | 1 + actix-http/src/h1/dispatcher.rs | 1 + actix-http/src/message.rs | 1 + actix-http/src/ws/codec.rs | 1 + 8 files changed, 8 insertions(+), 2 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 6909c0ef2..41f3b1135 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -26,7 +26,7 @@ actix-service = "2" actix-utils = "3" actix-web = { version = "4", default-features = false } -bitflags = "1" +bitflags = "2" bytes = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 23d3093dc..c10bc00ed 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -29,6 +29,7 @@ use mime_guess::from_path; use crate::{encoding::equiv_utf8_text, range::HttpRange}; bitflags! { + #[derive(Debug, Clone, Copy)] pub(crate) struct Flags: u8 { const ETAG = 0b0000_0001; const LAST_MD = 0b0000_0010; diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 7c5f07f2d..222a04c8f 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -62,7 +62,7 @@ actix-utils = "3" actix-rt = { version = "2.2", default-features = false } ahash = "0.8" -bitflags = "1.2" +bitflags = "2" bytes = "1" bytestring = "1" derive_more = "0.99.5" diff --git a/actix-http/src/h1/client.rs b/actix-http/src/h1/client.rs index 6a0d531d0..f3947dd12 100644 --- a/actix-http/src/h1/client.rs +++ b/actix-http/src/h1/client.rs @@ -16,6 +16,7 @@ use crate::{ }; bitflags! { + #[derive(Debug, Clone, Copy)] struct Flags: u8 { const HEAD = 0b0000_0001; const KEEP_ALIVE_ENABLED = 0b0000_1000; diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index e11f175c9..e1b629146 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -14,6 +14,7 @@ use crate::{ }; bitflags! { + #[derive(Debug, Clone, Copy)] struct Flags: u8 { const HEAD = 0b0000_0001; const KEEP_ALIVE_ENABLED = 0b0000_0010; diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 60660b85b..c2f8ea453 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -40,6 +40,7 @@ const HW_BUFFER_SIZE: usize = 1024 * 8; const MAX_PIPELINED_MESSAGES: usize = 16; bitflags! { + #[derive(Debug, Clone, Copy)] pub struct Flags: u8 { /// Set when stream is read for first time. const STARTED = 0b0000_0001; diff --git a/actix-http/src/message.rs b/actix-http/src/message.rs index 7469d74ee..47b128fd0 100644 --- a/actix-http/src/message.rs +++ b/actix-http/src/message.rs @@ -16,6 +16,7 @@ pub enum ConnectionType { } bitflags! { + #[derive(Debug, Clone, Copy)] pub(crate) struct Flags: u8 { const CLOSE = 0b0000_0001; const KEEP_ALIVE = 0b0000_0010; diff --git a/actix-http/src/ws/codec.rs b/actix-http/src/ws/codec.rs index 6a149f9a4..681649a7e 100644 --- a/actix-http/src/ws/codec.rs +++ b/actix-http/src/ws/codec.rs @@ -74,6 +74,7 @@ pub struct Codec { } bitflags! { + #[derive(Debug, Clone, Copy)] struct Flags: u8 { const SERVER = 0b0000_0001; const CONTINUATION = 0b0000_0010; From 17218dc6c88848938cebc560deafbf1c2184fa56 Mon Sep 17 00:00:00 2001 From: moh-eulith <101080211+moh-eulith@users.noreply.github.com> Date: Sun, 7 May 2023 11:13:10 -0400 Subject: [PATCH 064/314] minor optimization: reserve buffer once length is known (ws) (#2950) --- actix-http/src/ws/frame.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs index c7e0427ea..dddb03d18 100644 --- a/actix-http/src/ws/frame.rs +++ b/actix-http/src/ws/frame.rs @@ -1,3 +1,4 @@ +use std::cmp::min; use std::convert::TryFrom; use bytes::{Buf, BufMut, BytesMut}; @@ -96,6 +97,10 @@ impl Parser { // not enough data if src.len() < idx + length { + let min_length = min(length, max_size); + if src.capacity() < idx + min_length { + src.reserve(idx + min_length - src.capacity()); + } return Ok(None); } From 58c19b817fc248b4185f3e3d2151deac83c06d02 Mon Sep 17 00:00:00 2001 From: Imamuzzaki Abu Salam Date: Fri, 9 Jun 2023 20:29:10 +0700 Subject: [PATCH 065/314] docs(actix-web/README.md): update benchmark link (#3046) Round 20 doesn't have actix score, but round 21 has. So I changed it to the round 21 link for everyone to see this is one of the best frameworks for Web/API. --- actix-web/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/README.md b/actix-web/README.md index 3c6524d36..32932cc0e 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -85,7 +85,7 @@ You may consider checking out [this directory](https://github.com/actix/examples ## Benchmarks -One of the fastest web frameworks available according to the [TechEmpower Framework Benchmark](https://www.techempower.com/benchmarks/#section=data-r20&test=composite). +One of the fastest web frameworks available according to the [TechEmpower Framework Benchmark](https://www.techempower.com/benchmarks/#section=data-r21&test=composite). ## License From 1072d0dacf3a5a7a8e2d5fd7fe5bb47658198bf8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 9 Jun 2023 15:15:09 +0100 Subject: [PATCH 066/314] address lints --- actix-http/src/body/message_body.rs | 1 + actix-web/benches/responder.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-http/src/body/message_body.rs b/actix-http/src/body/message_body.rs index e274cf8aa..c3f55ce7d 100644 --- a/actix-http/src/body/message_body.rs +++ b/actix-http/src/body/message_body.rs @@ -555,6 +555,7 @@ mod tests { }; } + #[allow(unused_allocation)] // triggered by `Box::new(()).size()` #[actix_rt::test] async fn boxing_equivalence() { assert_eq!(().size(), BodySize::Sized(0)); diff --git a/actix-web/benches/responder.rs b/actix-web/benches/responder.rs index 20aae3351..ac4d18324 100644 --- a/actix-web/benches/responder.rs +++ b/actix-web/benches/responder.rs @@ -87,7 +87,7 @@ fn future_responder(c: &mut Criterion) { let start = Instant::now(); - let _res = rt.block_on(async { futs.await }); + let _res = rt.block_on(futs); start.elapsed() }) From 241da6e0815d359cc29233a242624cbd28f46c92 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 2 Jul 2023 01:09:15 +0100 Subject: [PATCH 067/314] update MSRV to 1.65 (#3059) --- .github/workflows/ci.yml | 16 +++------- .github/workflows/clippy-fmt.yml | 3 +- actix-files/CHANGES.md | 2 ++ actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 +-- actix-files/src/path_buf.rs | 2 -- actix-http-test/CHANGES.md | 2 ++ actix-http-test/Cargo.toml | 6 ++-- actix-http-test/README.md | 4 +-- actix-http/CHANGES.md | 4 +++ actix-http/Cargo.toml | 12 +++---- actix-http/README.md | 4 +-- actix-http/src/body/boxed.rs | 1 - actix-http/src/h1/decoder.rs | 2 +- actix-http/src/h1/service.rs | 1 - actix-http/src/header/into_pair.rs | 2 -- actix-http/src/header/into_value.rs | 2 -- .../src/header/shared/content_encoding.rs | 2 +- actix-http/src/header/shared/quality.rs | 5 +-- actix-http/src/header/shared/quality_item.rs | 2 +- actix-http/src/requests/request.rs | 1 - actix-http/src/service.rs | 6 ++-- actix-http/src/ws/frame.rs | 1 - actix-http/tests/test_rustls.rs | 2 +- actix-multipart-derive/CHANGES.md | 4 +++ actix-multipart-derive/Cargo.toml | 2 +- actix-multipart-derive/README.md | 4 +-- actix-multipart-derive/src/lib.rs | 2 +- actix-multipart-derive/tests/trybuild.rs | 2 +- actix-multipart/CHANGES.md | 2 ++ actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 +-- actix-multipart/src/server.rs | 4 +-- actix-router/CHANGES.md | 2 ++ actix-router/Cargo.toml | 4 +-- actix-router/src/resource.rs | 2 -- actix-router/src/url.rs | 1 - actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 6 ++-- actix-web-actors/CHANGES.md | 2 ++ actix-web-actors/Cargo.toml | 7 ++-- actix-web-actors/README.md | 4 +-- actix-web-actors/src/ws.rs | 1 - actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 +-- actix-web-codegen/src/route.rs | 2 +- actix-web-codegen/tests/trybuild.rs | 2 +- .../trybuild/route-custom-lowercase.stderr | 12 ++++++- .../route-duplicate-method-fail.stderr | 32 ++++++++++++------- .../trybuild/route-missing-method-fail.stderr | 32 ++++++++++++------- .../trybuild/routes-missing-args-fail.stderr | 32 ++++++++++++------- .../routes-missing-method-fail.stderr | 32 ++++++++++++------- actix-web/CHANGES.md | 1 + actix-web/Cargo.toml | 16 +++++----- actix-web/README.md | 4 +-- actix-web/src/guard/mod.rs | 1 - actix-web/src/middleware/default_headers.rs | 1 - actix-web/src/middleware/err_handlers.rs | 4 +-- actix-web/src/middleware/logger.rs | 1 - actix-web/src/middleware/normalize.rs | 9 ++---- actix-web/src/request_data.rs | 1 - actix-web/src/response/builder.rs | 1 - actix-web/src/rmap.rs | 4 +-- actix-web/src/test/test_utils.rs | 1 - awc/CHANGES.md | 2 ++ awc/Cargo.toml | 12 +++---- awc/README.md | 2 +- awc/src/builder.rs | 2 +- awc/src/client/mod.rs | 2 +- awc/src/middleware/redirect.rs | 1 - awc/src/request.rs | 2 +- awc/src/ws.rs | 2 +- clippy.toml | 2 +- 74 files changed, 202 insertions(+), 166 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0511339d..10e80b751 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - 1.59.0 # MSRV + - 1.65.0 # MSRV - stable name: ${{ matrix.target.name }} / ${{ matrix.version }} @@ -49,17 +49,9 @@ jobs: - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - - name: workaround MSRV issues - if: matrix.version != 'stable' - run: | - cargo install cargo-edit --version=0.8.0 - cargo add const-str@0.3 --dev -p=actix-web - cargo add const-str@0.3 --dev -p=awc - - - name: workaround MSRV issues - if: matrix.version != 'stable' - run: | - cargo update -p=zstd-sys --precise=2.0.1+zstd.1.5.2 + # - name: workaround MSRV issues + # if: matrix.version != 'stable' + # run: | - name: check minimal run: cargo ci-check-min diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index a7da9b1c5..109165ce0 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -63,7 +63,8 @@ jobs: - uses: actions/checkout@v3 - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { toolchain: nightly } + # temp: unpin once https://github.com/rust-lang/rust/issues/113152 is fixed + with: { toolchain: nightly-2023-06-28 } - uses: taiki-e/cache-cargo-install-action@v1 with: { tool: cargo-public-api } diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index d64380a8d..4e45ce517 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 0.6.3 - 2023-01-21 - XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903] diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 41f3b1135..80c609d1d 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -11,7 +11,7 @@ homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web" categories = ["asynchronous", "web-programming::http-server"] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [lib] name = "actix_files" diff --git a/actix-files/README.md b/actix-files/README.md index 8869ca436..f01fc8566 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -4,7 +4,7 @@ [![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.6.3)](https://docs.rs/actix-files/0.6.3) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
[![dependency status](https://deps.rs/crate/actix-files/0.6.3/status.svg)](https://deps.rs/crate/actix-files/0.6.3) @@ -15,4 +15,4 @@ - [API Documentation](https://docs.rs/actix-files) - [Example Project](https://github.com/actix/examples/tree/master/basics/static-files) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 diff --git a/actix-files/src/path_buf.rs b/actix-files/src/path_buf.rs index 650f55247..c1983279b 100644 --- a/actix-files/src/path_buf.rs +++ b/actix-files/src/path_buf.rs @@ -97,8 +97,6 @@ impl FromRequest for PathBufWrap { #[cfg(test)] mod tests { - use std::iter::FromIterator; - use super::*; #[test] diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index ec31b6196..3b8c83b3c 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 3.1.0 - 2023-01-21 - Minimum supported Rust version (MSRV) is now 1.59. diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 12739fbd4..87422551d 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -13,7 +13,7 @@ categories = [ "web-programming::websocket", ] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [package.metadata.docs.rs] features = [] @@ -41,12 +41,12 @@ bytes = "1" futures-core = { version = "0.3.17", default-features = false } http = "0.2.7" log = "0.4" -socket2 = "0.4" +socket2 = "0.5" serde = "1" serde_json = "1" slab = "0.4" serde_urlencoded = "0.7" -tls-openssl = { version = "0.10.9", package = "openssl", optional = true } +tls-openssl = { version = "0.10.55", package = "openssl", optional = true } tokio = { version = "1.24.2", features = ["sync"] } [dev-dependencies] diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 94f0e88a5..935be407f 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -4,7 +4,7 @@ [![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=3.1.0)](https://docs.rs/actix-http-test/3.1.0) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
[![Dependency Status](https://deps.rs/crate/actix-http-test/3.1.0/status.svg)](https://deps.rs/crate/actix-http-test/3.1.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http-test) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index aaf84d765..a105c02c1 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -7,6 +7,10 @@ - Add `body::to_body_limit()` function. - Add `body::BodyLimitExceeded` error type. +### Changed + +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 3.3.1 - 2023-03-02 ### Fixed diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 222a04c8f..6909b785f 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -16,7 +16,7 @@ categories = [ "web-programming::websocket", ] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [package.metadata.docs.rs] # features that docs.rs will build with @@ -105,20 +105,20 @@ actix-tls = { version = "3", features = ["openssl"] } actix-web = "4" async-stream = "0.3" -criterion = { version = "0.4", features = ["html_reports"] } -env_logger = "0.9" +criterion = { version = "0.5", features = ["html_reports"] } +env_logger = "0.10" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" -rcgen = "0.9" +rcgen = "0.11" regex = "1.3" rustversion = "1" rustls-pemfile = "1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" static_assertions = "1" -tls-openssl = { package = "openssl", version = "0.10.9" } -tls-rustls = { package = "rustls", version = "0.20.0" } +tls-openssl = { package = "openssl", version = "0.10.55" } +tls-rustls = { package = "rustls", version = "0.20" } tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] diff --git a/actix-http/README.md b/actix-http/README.md index f372096ff..0c5fcb6b6 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -4,7 +4,7 @@ [![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=3.3.1)](https://docs.rs/actix-http/3.3.1) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
[![dependency status](https://deps.rs/crate/actix-http/3.3.1/status.svg)](https://deps.rs/crate/actix-http/3.3.1) @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 ## Example diff --git a/actix-http/src/body/boxed.rs b/actix-http/src/body/boxed.rs index 5fcc42f56..2bbb75369 100644 --- a/actix-http/src/body/boxed.rs +++ b/actix-http/src/body/boxed.rs @@ -104,7 +104,6 @@ impl MessageBody for BoxBody { #[cfg(test)] mod tests { - use static_assertions::{assert_impl_all, assert_not_impl_any}; use super::*; diff --git a/actix-http/src/h1/decoder.rs b/actix-http/src/h1/decoder.rs index 0b06bfe24..829f40e10 100644 --- a/actix-http/src/h1/decoder.rs +++ b/actix-http/src/h1/decoder.rs @@ -1,4 +1,4 @@ -use std::{convert::TryFrom, io, marker::PhantomData, mem::MaybeUninit, task::Poll}; +use std::{io, marker::PhantomData, mem::MaybeUninit, task::Poll}; use actix_codec::Decoder; use bytes::{Bytes, BytesMut}; diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index a791ea8c3..9eebe2126 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -160,7 +160,6 @@ mod openssl { #[cfg(feature = "rustls")] mod rustls { - use std::io; use actix_service::ServiceFactoryExt as _; diff --git a/actix-http/src/header/into_pair.rs b/actix-http/src/header/into_pair.rs index 91c3e6640..0a71f857a 100644 --- a/actix-http/src/header/into_pair.rs +++ b/actix-http/src/header/into_pair.rs @@ -1,7 +1,5 @@ //! [`TryIntoHeaderPair`] trait and implementations. -use std::convert::TryFrom as _; - use super::{ Header, HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue, TryIntoHeaderValue, }; diff --git a/actix-http/src/header/into_value.rs b/actix-http/src/header/into_value.rs index 6d369ee65..253900633 100644 --- a/actix-http/src/header/into_value.rs +++ b/actix-http/src/header/into_value.rs @@ -1,7 +1,5 @@ //! [`TryIntoHeaderValue`] trait and implementations. -use std::convert::TryFrom as _; - use bytes::Bytes; use http::{header::InvalidHeaderValue, Error as HttpError, HeaderValue}; use mime::Mime; diff --git a/actix-http/src/header/shared/content_encoding.rs b/actix-http/src/header/shared/content_encoding.rs index bd25de704..c3b4bc4c2 100644 --- a/actix-http/src/header/shared/content_encoding.rs +++ b/actix-http/src/header/shared/content_encoding.rs @@ -1,4 +1,4 @@ -use std::{convert::TryFrom, str::FromStr}; +use std::str::FromStr; use derive_more::{Display, Error}; use http::header::InvalidHeaderValue; diff --git a/actix-http/src/header/shared/quality.rs b/actix-http/src/header/shared/quality.rs index c80dd0a8e..c2276cf1b 100644 --- a/actix-http/src/header/shared/quality.rs +++ b/actix-http/src/header/shared/quality.rs @@ -1,7 +1,4 @@ -use std::{ - convert::{TryFrom, TryInto}, - fmt, -}; +use std::fmt; use derive_more::{Display, Error}; diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs index 0b35b5401..ee1fdb928 100644 --- a/actix-http/src/header/shared/quality_item.rs +++ b/actix-http/src/header/shared/quality_item.rs @@ -1,4 +1,4 @@ -use std::{cmp, convert::TryFrom as _, fmt, str}; +use std::{cmp, fmt, str}; use crate::error::ParseError; diff --git a/actix-http/src/requests/request.rs b/actix-http/src/requests/request.rs index ac358e8df..f4d605b39 100644 --- a/actix-http/src/requests/request.rs +++ b/actix-http/src/requests/request.rs @@ -234,7 +234,6 @@ impl

fmt::Debug for Request

{ #[cfg(test)] mod tests { use super::*; - use std::convert::TryFrom; #[test] fn test_basics() { diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index 22177b849..108b09c4e 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -30,9 +30,9 @@ use crate::{ /// /// # Automatic HTTP Version Selection /// There are two ways to select the HTTP version of an incoming connection: -/// - One is to rely on the ALPN information that is provided when using a TLS (HTTPS); both -/// versions are supported automatically when using either of the `.rustls()` or `.openssl()` -/// finalizing methods. +/// - One is to rely on the ALPN information that is provided when using TLS (HTTPS); both versions +/// are supported automatically when using either of the `.rustls()` or `.openssl()` finalizing +/// methods. /// - The other is to read the first few bytes of the TCP stream. This is the only viable approach /// for supporting H2C, which allows the HTTP/2 protocol to work over plaintext connections. Use /// the `.tcp_auto_h2c()` finalizing method to enable this behavior. diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs index dddb03d18..ce6f1b256 100644 --- a/actix-http/src/ws/frame.rs +++ b/actix-http/src/ws/frame.rs @@ -1,5 +1,4 @@ use std::cmp::min; -use std::convert::TryFrom; use bytes::{Buf, BufMut, BytesMut}; use tracing::debug; diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index 0b8197a69..bf3a9243b 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -4,7 +4,7 @@ extern crate tls_rustls as rustls; use std::{ - convert::{Infallible, TryFrom}, + convert::Infallible, io::{self, BufReader, Write}, net::{SocketAddr, TcpStream as StdTcpStream}, sync::Arc, diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index 8dd7aa4d0..caf75aeb3 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## Unreleased + +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 0.6.0 - 2023-02-26 - Add `MultipartForm` derive macro. diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index e0b78fa26..aca6de84a 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -7,7 +7,7 @@ keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index 44f08c7bd..b077d355c 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) [![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart-derive/0.5.0) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg)
[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.5.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart-derive) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 diff --git a/actix-multipart-derive/src/lib.rs b/actix-multipart-derive/src/lib.rs index 2af023aec..9552ad2d9 100644 --- a/actix-multipart-derive/src/lib.rs +++ b/actix-multipart-derive/src/lib.rs @@ -8,7 +8,7 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -use std::{collections::HashSet, convert::TryFrom as _}; +use std::collections::HashSet; use darling::{FromDeriveInput, FromField, FromMeta}; use parse_size::parse_size; diff --git a/actix-multipart-derive/tests/trybuild.rs b/actix-multipart-derive/tests/trybuild.rs index 7b9f14ed7..829c1d771 100644 --- a/actix-multipart-derive/tests/trybuild.rs +++ b/actix-multipart-derive/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.59)] // MSRV +#[rustversion::stable(1.65)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 4bb120c61..410c8af17 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 0.6.0 - 2023-02-26 - Added `MultipartForm` typed data extractor. [#2883] diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index a36fbffc0..384c0e151 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] diff --git a/actix-multipart/README.md b/actix-multipart/README.md index c4101e1ce..3e2a7a127 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) [![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.0)](https://docs.rs/actix-multipart/0.6.0) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
[![dependency status](https://deps.rs/crate/actix-multipart/0.6.0/status.svg)](https://deps.rs/crate/actix-multipart/0.6.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index 6726bc9d3..5dc4d6f69 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -2,9 +2,7 @@ use std::{ cell::{Cell, RefCell, RefMut}, - cmp, - convert::TryFrom, - fmt, + cmp, fmt, marker::PhantomData, pin::Pin, rc::Rc, diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 7ef9497dc..1f5552193 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 0.5.1 - 2022-09-19 - Correct typo in error string for `i32` deserialization. [#2876] diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index f8efd5350..adf43a086 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -10,7 +10,7 @@ description = "Resource path matching and router" keywords = ["actix", "router", "routing"] repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [lib] name = "actix_router" @@ -27,7 +27,7 @@ serde = "1" tracing = { version = "0.1.30", default-features = false, features = ["log"] } [dev-dependencies] -criterion = { version = "0.4", features = ["html_reports"] } +criterion = { version = "0.5", features = ["html_reports"] } http = "0.2.7" serde = { version = "1", features = ["derive"] } percent-encoding = "2.1" diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index f198115ad..c868a3e6f 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -1389,8 +1389,6 @@ mod tests { #[cfg(feature = "http")] #[test] fn parse_urlencoded_param() { - use std::convert::TryFrom; - let re = ResourceDef::new("/user/{id}/test"); let mut path = Path::new("/user/2345/test"); diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index 8ac033861..8ae9ea9d8 100644 --- a/actix-router/src/url.rs +++ b/actix-router/src/url.rs @@ -65,7 +65,6 @@ impl ResourcePath for Url { #[cfg(test)] mod tests { use http::Uri; - use std::convert::TryFrom; use super::*; use crate::{Path, ResourceDef}; diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 47fea4173..e3a66c663 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 0.1.1 - 2023-02-26 - Add `TestServerConfig::port()` setter method. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index f2cbfe5cd..9cf5aa76c 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -16,7 +16,7 @@ categories = [ "web-programming::websocket", ] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [features] default = [] @@ -43,6 +43,6 @@ log = "0.4" serde = { version = "1", features = ["derive"] } serde_json = "1" serde_urlencoded = "0.7" -tls-openssl = { package = "openssl", version = "0.10.9", optional = true } -tls-rustls = { package = "rustls", version = "0.20.0", optional = true } +tls-openssl = { package = "openssl", version = "0.10.55", optional = true } +tls-rustls = { package = "rustls", version = "0.20", optional = true } tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index ea19411b5..4799c7b67 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 4.2.0 - 2023-01-21 - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index e89baed96..c6f14554a 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -7,7 +7,7 @@ keywords = ["actix", "http", "web", "framework", "async"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [lib] name = "actix_web_actors" @@ -32,7 +32,6 @@ actix-test = "0.1" awc = { version = "3", default-features = false } actix-web = { version = "4", features = ["macros"] } +env_logger = "0.10" +futures-util = { version = "0.3.17", default-features = false, features = ["std"] } mime = "0.3" - -env_logger = "0.9" -futures-util = { version = "0.3.17", default-features = false } diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index dce91f503..fe6122115 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) [![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.2.0)](https://docs.rs/actix-web-actors/4.2.0) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
[![dependency status](https://deps.rs/crate/actix-web-actors/4.2.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.2.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-actors) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index e1110eddb..731f33f86 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -58,7 +58,6 @@ use std::{ collections::VecDeque, - convert::TryFrom, future::Future, io, mem, pin::Pin, diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 6e962a6ca..b9e4b0aad 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 4.2.0 - 2023-02-26 - Add support for custom methods with the `#[route]` macro. [#2969] diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 51cb0dfef..4f2fdc566 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -9,7 +9,7 @@ authors = [ "Rob Ede ", ] license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [lib] proc-macro = true diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 8dd3e986e..531f44a5d 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) [![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.0)](https://docs.rs/actix-web-codegen/4.2.0) -![Version](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.0) @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-codegen) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 ## Compile Testing diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 0772dbd94..0b8bb0f38 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, convert::TryFrom}; +use std::collections::HashSet; use actix_router::ResourceDef; use proc_macro::TokenStream; diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 8839dca3d..9f0aa02f4 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.59)] // MSRV +#[rustversion::stable(1.65)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr index 243c4dd68..88198a55d 100644 --- a/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr +++ b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr @@ -8,10 +8,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future --> tests/trybuild/route-custom-lowercase.rs:14:55 | 14 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for fn item `fn() -> impl std::future::Future {index}` | | | required by a bound introduced by this call | + = help: the following other types implement trait `HttpServiceFactory`: + (A, B) + (A, B, C) + (A, B, C, D) + (A, B, C, D, E) + (A, B, C, D, E, F) + (A, B, C, D, E, F, G) + (A, B, C, D, E, F, G, H) + (A, B, C, D, E, F, G, H, I) + and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | diff --git a/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr b/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr index 7eac84f3e..bda736348 100644 --- a/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr @@ -5,15 +5,25 @@ error: HTTP method defined more than once: `GET` | ^^^^^ error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied - --> tests/trybuild/route-duplicate-method-fail.rs:12:55 - | -12 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` - | | - | required by a bound introduced by this call - | + --> tests/trybuild/route-duplicate-method-fail.rs:12:55 + | +12 | let srv = actix_test::start(|| App::new().service(index)); + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for fn item `fn() -> impl std::future::Future {index}` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `HttpServiceFactory`: + (A, B) + (A, B, C) + (A, B, C, D) + (A, B, C, D, E) + (A, B, C, D, E, F) + (A, B, C, D, E, F, G) + (A, B, C, D, E, F, G, H) + (A, B, C, D, E, F, G, H, I) + and $N others note: required by a bound in `App::::service` - --> $WORKSPACE/actix-web/src/app.rs - | - | F: HttpServiceFactory + 'static, - | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` + --> $WORKSPACE/actix-web/src/app.rs + | + | F: HttpServiceFactory + 'static, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr b/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr index bc8497c10..9f2f788fb 100644 --- a/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr @@ -7,15 +7,25 @@ error: The #[route(..)] macro requires at least one `method` attribute = note: this error originates in the attribute macro `route` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied - --> tests/trybuild/route-missing-method-fail.rs:12:55 - | -12 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` - | | - | required by a bound introduced by this call - | + --> tests/trybuild/route-missing-method-fail.rs:12:55 + | +12 | let srv = actix_test::start(|| App::new().service(index)); + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for fn item `fn() -> impl std::future::Future {index}` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `HttpServiceFactory`: + (A, B) + (A, B, C) + (A, B, C, D) + (A, B, C, D, E) + (A, B, C, D, E, F) + (A, B, C, D, E, F, G) + (A, B, C, D, E, F, G, H) + (A, B, C, D, E, F, G, H, I) + and $N others note: required by a bound in `App::::service` - --> $WORKSPACE/actix-web/src/app.rs - | - | F: HttpServiceFactory + 'static, - | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` + --> $WORKSPACE/actix-web/src/app.rs + | + | F: HttpServiceFactory + 'static, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr index 785d6f326..e845241a4 100644 --- a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr +++ b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr @@ -13,15 +13,25 @@ error: Invalid input for macro | ^^^^^^ error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied - --> tests/trybuild/routes-missing-args-fail.rs:13:55 - | -13 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` - | | - | required by a bound introduced by this call - | + --> tests/trybuild/routes-missing-args-fail.rs:13:55 + | +13 | let srv = actix_test::start(|| App::new().service(index)); + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for fn item `fn() -> impl std::future::Future {index}` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `HttpServiceFactory`: + (A, B) + (A, B, C) + (A, B, C, D) + (A, B, C, D, E) + (A, B, C, D, E, F) + (A, B, C, D, E, F, G) + (A, B, C, D, E, F, G, H) + (A, B, C, D, E, F, G, H, I) + and $N others note: required by a bound in `App::::service` - --> $WORKSPACE/actix-web/src/app.rs - | - | F: HttpServiceFactory + 'static, - | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` + --> $WORKSPACE/actix-web/src/app.rs + | + | F: HttpServiceFactory + 'static, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr b/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr index 38a6d2f9b..228dced9c 100644 --- a/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr @@ -7,15 +7,25 @@ error: The #[routes] macro requires at least one `#[(..)]` attribute. = note: this error originates in the attribute macro `routes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied - --> tests/trybuild/routes-missing-method-fail.rs:12:55 - | -12 | let srv = actix_test::start(|| App::new().service(index)); - | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for `fn() -> impl std::future::Future {index}` - | | - | required by a bound introduced by this call - | + --> tests/trybuild/routes-missing-method-fail.rs:12:55 + | +12 | let srv = actix_test::start(|| App::new().service(index)); + | ------- ^^^^^ the trait `HttpServiceFactory` is not implemented for fn item `fn() -> impl std::future::Future {index}` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `HttpServiceFactory`: + (A, B) + (A, B, C) + (A, B, C, D) + (A, B, C, D, E) + (A, B, C, D, E, F) + (A, B, C, D, E, F, G) + (A, B, C, D, E, F, G, H) + (A, B, C, D, E, F, G, H, I) + and $N others note: required by a bound in `App::::service` - --> $WORKSPACE/actix-web/src/app.rs - | - | F: HttpServiceFactory + 'static, - | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` + --> $WORKSPACE/actix-web/src/app.rs + | + | F: HttpServiceFactory + 'static, + | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 9688370b7..417bb5a4c 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -10,6 +10,7 @@ ### Changed - Handler functions can now receive up to 16 extractor parameters. +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 4.3.1 - 2023-02-26 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index c7314422d..0091175be 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -16,7 +16,7 @@ categories = [ homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [package.metadata.docs.rs] # features that docs.rs will build with @@ -92,7 +92,7 @@ serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" smallvec = "1.6.1" -socket2 = "0.4" +socket2 = "0.5" time = { version = "0.3", default-features = false, features = ["formatting"] } url = "2.1" @@ -102,18 +102,18 @@ actix-test = { version = "0.1", features = ["openssl", "rustls"] } awc = { version = "3", features = ["openssl"] } brotli = "3.3.3" -const-str = "0.3" -criterion = { version = "0.4", features = ["html_reports"] } -env_logger = "0.9" +const-str = "0.5" +criterion = { version = "0.5", features = ["html_reports"] } +env_logger = "0.10" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } rand = "0.8" -rcgen = "0.9" +rcgen = "0.11" rustls-pemfile = "1" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" -tls-openssl = { package = "openssl", version = "0.10.9" } -tls-rustls = { package = "rustls", version = "0.20.0" } +tls-openssl = { package = "openssl", version = "0.10.55" } +tls-rustls = { package = "rustls", version = "0.20" } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.12" diff --git a/actix-web/README.md b/actix-web/README.md index 32932cc0e..cc2d9abe0 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -5,7 +5,7 @@

-[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.59+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) +[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

@@ -24,7 +24,7 @@ - SSL support using OpenSSL or Rustls - Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/)) - Integrates with the [`awc` HTTP client](https://docs.rs/awc/) -- Runs on stable Rust 1.59+ +- Runs on stable Rust 1.65+ ## Documentation diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index a9173a9d1..3aca11df2 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -51,7 +51,6 @@ use std::{ cell::{Ref, RefMut}, - convert::TryFrom, rc::Rc, }; diff --git a/actix-web/src/middleware/default_headers.rs b/actix-web/src/middleware/default_headers.rs index 003abd40d..b5a5a6998 100644 --- a/actix-web/src/middleware/default_headers.rs +++ b/actix-web/src/middleware/default_headers.rs @@ -1,7 +1,6 @@ //! For middleware documentation, see [`DefaultHeaders`]. use std::{ - convert::TryFrom, future::Future, marker::PhantomData, pin::Pin, diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index 5522cc021..051a0c6b3 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -270,8 +270,8 @@ impl ErrorHandlers { handlers .get(status) .map(|h| h.as_ref()) - .or_else(|| status.is_client_error().then(|| default_client).flatten()) - .or_else(|| status.is_server_error().then(|| default_server).flatten()) + .or_else(|| status.is_client_error().then_some(default_client).flatten()) + .or_else(|| status.is_server_error().then_some(default_server).flatten()) } } diff --git a/actix-web/src/middleware/logger.rs b/actix-web/src/middleware/logger.rs index 5fec5a013..0207798ae 100644 --- a/actix-web/src/middleware/logger.rs +++ b/actix-web/src/middleware/logger.rs @@ -3,7 +3,6 @@ use std::{ borrow::Cow, collections::HashSet, - convert::TryFrom, env, fmt::{self, Display as _}, future::Future, diff --git a/actix-web/src/middleware/normalize.rs b/actix-web/src/middleware/normalize.rs index 3ab908481..afcc0faac 100644 --- a/actix-web/src/middleware/normalize.rs +++ b/actix-web/src/middleware/normalize.rs @@ -15,11 +15,12 @@ use crate::{ /// /// The default is `TrailingSlash::Trim`. #[non_exhaustive] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum TrailingSlash { /// Trim trailing slashes from the end of the path. /// /// Using this will require all routes to omit trailing slashes for them to be accessible. + #[default] Trim, /// Only merge any present multiple trailing slashes. @@ -33,12 +34,6 @@ pub enum TrailingSlash { Always, } -impl Default for TrailingSlash { - fn default() -> Self { - TrailingSlash::Trim - } -} - /// Middleware for normalizing a request's path so that routes can be matched more flexibly. /// /// # Normalization Steps diff --git a/actix-web/src/request_data.rs b/actix-web/src/request_data.rs index 719e6551f..bffbf74da 100644 --- a/actix-web/src/request_data.rs +++ b/actix-web/src/request_data.rs @@ -27,7 +27,6 @@ use crate::{ /// # Examples /// ```no_run /// # use actix_web::{web, HttpResponse, HttpRequest, Responder, HttpMessage as _}; -/// /// #[derive(Debug, Clone, PartialEq)] /// struct FlagFromMiddleware(String); /// diff --git a/actix-web/src/response/builder.rs b/actix-web/src/response/builder.rs index 120d4c358..a7f3f36c3 100644 --- a/actix-web/src/response/builder.rs +++ b/actix-web/src/response/builder.rs @@ -1,6 +1,5 @@ use std::{ cell::{Ref, RefMut}, - convert::TryInto, future::Future, pin::Pin, task::{Context, Poll}, diff --git a/actix-web/src/rmap.rs b/actix-web/src/rmap.rs index 6e10717c3..8a2ec3297 100644 --- a/actix-web/src/rmap.rs +++ b/actix-web/src/rmap.rs @@ -136,7 +136,7 @@ impl ResourceMap { .root_rmap_fn(String::with_capacity(AVG_PATH_LEN), |mut acc, node| { node.pattern .resource_path_from_iter(&mut acc, &mut elements) - .then(|| acc) + .then_some(acc) }) .ok_or(UrlGenerationError::NotEnoughElements)?; @@ -149,7 +149,7 @@ impl ResourceMap { // external resource; third slash would be the root slash in the path let third_slash_index = path .char_indices() - .filter_map(|(i, c)| (c == '/').then(|| i)) + .filter_map(|(i, c)| (c == '/').then_some(i)) .nth(2) .unwrap_or(path.len()); diff --git a/actix-web/src/test/test_utils.rs b/actix-web/src/test/test_utils.rs index b985c3b36..bba23a0fe 100644 --- a/actix-web/src/test/test_utils.rs +++ b/actix-web/src/test/test_utils.rs @@ -359,7 +359,6 @@ where #[cfg(test)] mod tests { - use serde::{Deserialize, Serialize}; use super::*; diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 03cbf61d4..f5bddd04d 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. + ## 3.1.1 - 2023-02-26 ### Changed diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 8edc90fd1..9a23e4baf 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -13,7 +13,7 @@ categories = [ homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2018" +edition = "2021" [lib] name = "awc" @@ -83,8 +83,8 @@ tokio = { version = "1.24.2", features = ["sync"] } cookie = { version = "0.16", features = ["percent-encode"], optional = true } -tls-openssl = { package = "openssl", version = "0.10.9", optional = true } -tls-rustls = { package = "rustls", version = "0.20.0", optional = true, features = ["dangerous_configuration"] } +tls-openssl = { package = "openssl", version = "0.10.55", optional = true } +tls-rustls = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } trust-dns-resolver = { version = "0.22", optional = true } @@ -98,12 +98,12 @@ actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } brotli = "3.3.3" -const-str = "0.3" -env_logger = "0.9" +const-str = "0.5" +env_logger = "0.10" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" -rcgen = "0.9" +rcgen = "0.11" rustls-pemfile = "1" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.12" diff --git a/awc/README.md b/awc/README.md index a9d411067..1a480df12 100644 --- a/awc/README.md +++ b/awc/README.md @@ -12,7 +12,7 @@ - [API Documentation](https://docs.rs/awc) - [Example Project](https://github.com/actix/examples/tree/master/https-tls/awc-https) -- Minimum Supported Rust Version (MSRV): 1.59 +- Minimum Supported Rust Version (MSRV): 1.65 ## Example diff --git a/awc/src/builder.rs b/awc/src/builder.rs index 79838a3f6..b15e2de0b 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -1,4 +1,4 @@ -use std::{convert::TryFrom, fmt, net::IpAddr, rc::Rc, time::Duration}; +use std::{fmt, net::IpAddr, rc::Rc, time::Duration}; use base64::prelude::*; diff --git a/awc/src/client/mod.rs b/awc/src/client/mod.rs index e898d2d04..b1df1fd3d 100644 --- a/awc/src/client/mod.rs +++ b/awc/src/client/mod.rs @@ -1,6 +1,6 @@ //! HTTP client. -use std::{convert::TryFrom, rc::Rc, time::Duration}; +use std::{rc::Rc, time::Duration}; use actix_http::{error::HttpError, header::HeaderMap, Method, RequestHead, Uri}; use actix_rt::net::TcpStream; diff --git a/awc/src/middleware/redirect.rs b/awc/src/middleware/redirect.rs index 67ef5d76f..d1216fa57 100644 --- a/awc/src/middleware/redirect.rs +++ b/awc/src/middleware/redirect.rs @@ -1,5 +1,4 @@ use std::{ - convert::TryFrom, future::Future, net::SocketAddr, pin::Pin, diff --git a/awc/src/request.rs b/awc/src/request.rs index d3a4eda8c..5e04aa8de 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -1,4 +1,4 @@ -use std::{convert::TryFrom, fmt, net, rc::Rc, time::Duration}; +use std::{fmt, net, rc::Rc, time::Duration}; use base64::prelude::*; use bytes::Bytes; diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 406368e62..67fcd2429 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -26,7 +26,7 @@ //! } //! ``` -use std::{convert::TryFrom, fmt, net::SocketAddr, str}; +use std::{fmt, net::SocketAddr, str}; use base64::prelude::*; diff --git a/clippy.toml b/clippy.toml index abe19b3a0..04371125d 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.59" +msrv = "1.65" From 4eeb01415c05e6136ae0f17ac7f45160c907ad68 Mon Sep 17 00:00:00 2001 From: Raminder Singh Date: Sun, 2 Jul 2023 06:06:06 +0530 Subject: [PATCH 068/314] Fix failing test on Windows (#3037) --- actix-files/src/files.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs index be2a450d2..4a259d233 100644 --- a/actix-files/src/files.rs +++ b/actix-files/src/files.rs @@ -422,10 +422,14 @@ mod tests { assert_eq!(res.status(), StatusCode::OK); let body = test::read_body(res).await; + let body_str = std::str::from_utf8(&body).unwrap(); + let actual_path = Path::new(&body_str); + let expected_path = Path::new("actix-files/tests"); assert!( - body.ends_with(b"actix-files/tests/"), - "body {:?} does not end with `actix-files/tests/`", - body + actual_path.ends_with(expected_path), + "body {:?} does not end with {:?}", + actual_path, + expected_path ); } } From 0e8ed50e3a7ac93d94e6c1c6603d0048e1f33fb8 Mon Sep 17 00:00:00 2001 From: Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> Date: Sun, 2 Jul 2023 06:26:12 +0530 Subject: [PATCH 069/314] align awc's h2 version (#3051) Co-authored-by: Rob Ede --- awc/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 9a23e4baf..daec84ab9 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -68,7 +68,7 @@ cfg-if = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.17", default-features = false, features = ["alloc", "sink"] } -h2 = "0.3.9" +h2 = "0.3.17" http = "0.2.7" itoa = "1" log =" 0.4" From ce3af777a05e6be2673290417b25f714e6e25830 Mon Sep 17 00:00:00 2001 From: mitsubosh <8204936+MITSUBOSHI@users.noreply.github.com> Date: Thu, 6 Jul 2023 01:29:10 +0900 Subject: [PATCH 070/314] Fix typo (#3062) --- actix-http/src/http_message.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/src/http_message.rs b/actix-http/src/http_message.rs index 198254e02..20becc310 100644 --- a/actix-http/src/http_message.rs +++ b/actix-http/src/http_message.rs @@ -146,7 +146,7 @@ mod tests { .finish(); assert_eq!(req.content_type(), "text/plain"); let req = TestRequest::default() - .insert_header(("content-type", "application/json; charset=utf=8")) + .insert_header(("content-type", "application/json; charset=utf-8")) .finish(); assert_eq!(req.content_type(), "application/json"); let req = TestRequest::default().finish(); From c34a18f64a0d452ea36fcc20d92f106d564be5a0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 17 Jul 2023 01:47:26 +0100 Subject: [PATCH 071/314] changelog file is optional in bump script --- scripts/bump | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/scripts/bump b/scripts/bump index 40d43d429..b09d9d196 100755 --- a/scripts/bump +++ b/scripts/bump @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # developed on macOS and probably doesn't work on Linux yet due to minor # differences in flags on sed @@ -21,12 +21,9 @@ README_FILE=$DIR/README.md # determine changelog file name if [ -f "$DIR/CHANGES.md" ]; then - CHANGELOG_FILE=$DIR/CHANGES.md + CHANGELOG_FILE="$DIR/CHANGES.md" elif [ -f "$DIR/CHANGELOG.md" ]; then - CHANGELOG_FILE=$DIR/CHANGELOG.md -else - echo "No changelog file found" - exit 1 + CHANGELOG_FILE="$DIR/CHANGELOG.md" fi # get current version @@ -37,15 +34,17 @@ CHANGE_CHUNK_FILE="$(mktemp)" echo saving changelog to $CHANGE_CHUNK_FILE echo -# get changelog chunk and save to temp file -cat "$CHANGELOG_FILE" | - # skip up to unreleased heading - sed '1,/Unreleased/ d' | - # take up to previous version heading - sed "/$CURRENT_VERSION/ q" | - # drop last line - sed '$d' \ - >"$CHANGE_CHUNK_FILE" +if [ -n "${CHANGELOG_FILE-}" ]; then + # get changelog chunk and save to temp file + cat "$CHANGELOG_FILE" | + # skip up to unreleased heading + sed '1,/Unreleased/ d' | + # take up to previous version heading + sed "/$CURRENT_VERSION/ q" | + # drop last line + sed '$d' \ + >"$CHANGE_CHUNK_FILE" +fi # if word count of changelog chunk is 0 then insert filler changelog chunk if [ "$(wc -w "$CHANGE_CHUNK_FILE" | awk '{ print $1 }')" = "0" ]; then @@ -68,8 +67,7 @@ if [ "${NEW_VERSION:0:1}" = "v" ]; then NEW_VERSION="${NEW_VERSION:1}" fi -DATE="$(date -u +"%Y-%m-%d")" -echo "updating from $CURRENT_VERSION => $NEW_VERSION ($DATE)" +echo "updating from $CURRENT_VERSION => $NEW_VERSION" # update package.version field sed -i.bak -E "s/^version ?= ?\"[^\"]+\"$/version = \"$NEW_VERSION\"/" "$CARGO_MANIFEST" @@ -77,19 +75,21 @@ sed -i.bak -E "s/^version ?= ?\"[^\"]+\"$/version = \"$NEW_VERSION\"/" "$CARGO_M # update readme [ -f "$README_FILE" ] && sed -i.bak -E "s#$CURRENT_VERSION([/)])#$NEW_VERSION\1#g" "$README_FILE" -# update changelog file -( - sed '/Unreleased/ q' "$CHANGELOG_FILE" # up to unreleased heading - echo # blank line - echo "## $NEW_VERSION - $DATE" # new version heading - cat "$CHANGE_CHUNK_FILE" # previously unreleased changes - sed "/$CURRENT_VERSION/ q" "$CHANGELOG_FILE" | tail -n 1 # the previous version heading - sed "1,/$CURRENT_VERSION/ d" "$CHANGELOG_FILE" # everything after previous version heading -) >"$CHANGELOG_FILE.bak" -mv "$CHANGELOG_FILE.bak" "$CHANGELOG_FILE" +if [ -n "${CHANGELOG_FILE-}" ]; then + # update changelog file + ( + sed '/Unreleased/ q' "$CHANGELOG_FILE" # up to unreleased heading + echo # blank line + echo "## $NEW_VERSION" # new version heading + cat "$CHANGE_CHUNK_FILE" # previously unreleased changes + sed "/$CURRENT_VERSION/ q" "$CHANGELOG_FILE" | tail -n 1 # the previous version heading + sed "1,/$CURRENT_VERSION/ d" "$CHANGELOG_FILE" # everything after previous version heading + ) >"$CHANGELOG_FILE.bak" + mv "$CHANGELOG_FILE.bak" "$CHANGELOG_FILE" -# format CHANGELOG file according to prettier -npx -y prettier --write "$CHANGELOG_FILE" || true + # format CHANGELOG file according to prettier + npx -y prettier --write "$CHANGELOG_FILE" || true +fi # done; remove backup files rm -f $CARGO_MANIFEST.bak From e4e839f4d1cb53b201d9c9cc4c188cfa5701e527 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 17 Jul 2023 01:51:10 +0100 Subject: [PATCH 072/314] only enable actix-http's http2 feature when TLS features are enabled closes #3071 --- actix-web/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 0091175be..79ad005c2 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -47,10 +47,10 @@ cookies = ["cookie"] secure-cookies = ["cookies", "cookie/secure"] # TLS via OpenSSL -openssl = ["actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] +openssl = ["actix-http/http2", "actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] # TLS via Rustls -rustls = ["actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] +rustls = ["actix-http/http2", "actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. @@ -68,7 +68,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3", default-features = false, optional = true } -actix-http = { version = "3.3", features = ["http2", "ws"] } +actix-http = { version = "3.3", features = ["ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } From 60c76c5e10a016953bd2552b8e069e9cc902f2d2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 17 Jul 2023 02:19:26 +0100 Subject: [PATCH 073/314] revert http2 feature flag change --- rustfmt.toml => .rustfmt.toml | 0 actix-web/Cargo.toml | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename rustfmt.toml => .rustfmt.toml (100%) diff --git a/rustfmt.toml b/.rustfmt.toml similarity index 100% rename from rustfmt.toml rename to .rustfmt.toml diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 79ad005c2..0091175be 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -47,10 +47,10 @@ cookies = ["cookie"] secure-cookies = ["cookies", "cookie/secure"] # TLS via OpenSSL -openssl = ["actix-http/http2", "actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] +openssl = ["actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] # TLS via Rustls -rustls = ["actix-http/http2", "actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] +rustls = ["actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. @@ -68,7 +68,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3", default-features = false, optional = true } -actix-http = { version = "3.3", features = ["ws"] } +actix-http = { version = "3.3", features = ["http2", "ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } From 79a38e0628b2bf0d3261594eee82d7e6180a27bc Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 17 Jul 2023 02:38:12 +0100 Subject: [PATCH 074/314] apply standard formatting --- .rustfmt.toml | 5 +- actix-files/src/chunked.rs | 5 +- actix-files/src/directory.rs | 7 +- actix-files/src/files.rs | 11 +-- actix-files/src/lib.rs | 35 +++++----- actix-files/src/named.rs | 12 ++-- actix-files/src/range.rs | 4 +- actix-files/src/service.rs | 21 ++---- actix-files/tests/encoding.rs | 3 +- actix-files/tests/guard.rs | 4 +- actix-files/tests/traversal.rs | 3 +- actix-http/examples/hello-world.rs | 5 +- actix-http/src/body/boxed.rs | 8 +-- actix-http/src/body/mod.rs | 18 ++--- actix-http/src/config.rs | 6 +- actix-http/src/encoding/decoder.rs | 10 ++- actix-http/src/encoding/encoder.rs | 6 +- actix-http/src/encoding/mod.rs | 3 +- actix-http/src/error.rs | 3 +- actix-http/src/h1/codec.rs | 4 +- actix-http/src/h1/decoder.rs | 14 ++-- actix-http/src/h1/dispatcher.rs | 51 ++++---------- actix-http/src/h1/dispatcher_tests.rs | 21 +++--- actix-http/src/h1/mod.rs | 18 ++--- actix-http/src/h1/service.rs | 16 ++--- actix-http/src/h2/mod.rs | 8 +-- actix-http/src/h2/service.rs | 3 +- actix-http/src/header/map.rs | 4 +- actix-http/src/header/mod.rs | 50 ++++++------- actix-http/src/header/shared/mod.rs | 17 +++-- actix-http/src/header/shared/quality_item.rs | 3 +- actix-http/src/http_message.rs | 4 +- actix-http/src/lib.rs | 31 ++++---- actix-http/src/requests/mod.rs | 6 +- actix-http/src/requests/request.rs | 3 +- actix-http/src/responses/mod.rs | 4 +- actix-http/src/service.rs | 28 ++------ actix-http/src/ws/dispatcher.rs | 9 +-- actix-http/src/ws/frame.rs | 3 +- actix-http/src/ws/mod.rs | 17 +++-- actix-http/tests/test_openssl.rs | 3 +- actix-http/tests/test_rustls.rs | 8 +-- actix-http/tests/test_server.rs | 11 ++- actix-multipart/src/form/bytes.rs | 6 +- actix-multipart/src/form/json.rs | 3 +- actix-multipart/src/form/mod.rs | 16 ++--- actix-multipart/src/form/tempfile.rs | 33 ++++----- actix-multipart/src/lib.rs | 6 +- actix-multipart/src/server.rs | 18 ++--- actix-router/benches/quoter.rs | 4 +- actix-router/src/de.rs | 28 ++++---- actix-router/src/lib.rs | 17 ++--- actix-router/src/path.rs | 6 +- actix-router/src/resource.rs | 4 +- actix-router/src/router.rs | 12 ++-- actix-router/src/url.rs | 4 +- actix-test/src/lib.rs | 67 ++++++------------ actix-web-actors/src/context.rs | 22 +++--- actix-web-actors/src/ws.rs | 27 ++++--- actix-web-codegen/src/lib.rs | 62 ++++++++-------- actix-web-codegen/src/route.rs | 39 ++++++----- actix-web/benches/responder.rs | 3 +- actix-web/benches/service.rs | 15 ++-- actix-web/examples/on-connect.rs | 7 +- actix-web/src/app.rs | 8 +-- actix-web/src/app_service.rs | 12 ++-- actix-web/src/config.rs | 16 ++--- actix-web/src/data.rs | 27 +++---- actix-web/src/dev.rs | 21 +++--- actix-web/src/error/macros.rs | 9 ++- actix-web/src/error/mod.rs | 14 ++-- actix-web/src/extract.rs | 6 +- actix-web/src/guard/mod.rs | 6 +- actix-web/src/http/header/accept_encoding.rs | 9 +-- .../src/http/header/content_disposition.rs | 27 +++---- actix-web/src/http/header/content_range.rs | 3 +- actix-web/src/http/header/content_type.rs | 3 +- actix-web/src/http/header/date.rs | 3 +- actix-web/src/http/header/entity.rs | 4 +- actix-web/src/http/header/if_range.rs | 4 +- actix-web/src/http/header/macros.rs | 4 +- actix-web/src/http/header/mod.rs | 56 +++++++-------- actix-web/src/lib.rs | 35 +++++----- actix-web/src/middleware/compat.rs | 9 ++- actix-web/src/middleware/err_handlers.rs | 30 +++----- actix-web/src/middleware/logger.rs | 12 +--- actix-web/src/middleware/mod.rs | 17 ++--- actix-web/src/redirect.rs | 3 +- actix-web/src/request.rs | 13 ++-- actix-web/src/resource.rs | 46 +++++------- actix-web/src/response/builder.rs | 11 +-- actix-web/src/response/customize_responder.rs | 7 +- actix-web/src/response/http_codes.rs | 3 +- actix-web/src/response/mod.rs | 9 ++- actix-web/src/response/responder.rs | 3 +- actix-web/src/response/response.rs | 1 - actix-web/src/route.rs | 51 +++++++------- actix-web/src/rt.rs | 3 +- actix-web/src/scope.rs | 70 +++++++++---------- actix-web/src/server.rs | 24 +++---- actix-web/src/service.rs | 65 +++++++++-------- actix-web/src/test/mod.rs | 18 ++--- actix-web/src/test/test_request.rs | 14 ++-- actix-web/src/test/test_utils.rs | 69 +++++++++--------- actix-web/src/types/either.rs | 34 ++++----- actix-web/src/types/form.rs | 8 +-- actix-web/src/types/header.rs | 6 +- actix-web/src/types/json.rs | 18 ++--- actix-web/src/types/mod.rs | 18 ++--- actix-web/src/types/path.rs | 6 +- actix-web/src/types/payload.rs | 11 +-- actix-web/src/web.rs | 14 ++-- actix-web/tests/test_server.rs | 34 ++++----- actix-web/tests/utils.rs | 12 ++-- awc/src/any_body.rs | 3 +- awc/src/builder.rs | 21 ++---- awc/src/client/connection.rs | 13 +--- awc/src/client/connector.rs | 25 ++----- awc/src/client/error.rs | 4 +- awc/src/client/h1proto.rs | 3 +- awc/src/client/h2proto.rs | 25 +++---- awc/src/client/mod.rs | 8 ++- awc/src/client/pool.rs | 16 +++-- awc/src/connect.rs | 16 ++--- awc/src/error.rs | 1 - awc/src/frozen.rs | 7 +- awc/src/lib.rs | 19 +++-- awc/src/middleware/mod.rs | 4 +- awc/src/middleware/redirect.rs | 8 +-- awc/src/request.rs | 19 ++--- awc/src/responses/mod.rs | 3 +- awc/src/responses/response.rs | 7 +- awc/src/sender.rs | 13 ++-- awc/src/ws.rs | 11 ++- awc/tests/test_client.rs | 36 ++++------ awc/tests/test_connector.rs | 3 +- awc/tests/test_ssl_client.rs | 9 +-- awc/tests/utils.rs | 12 ++-- 138 files changed, 916 insertions(+), 1180 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index 973e002c0..71b9be3ae 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,2 +1,3 @@ -max_width = 96 -reorder_imports = true +group_imports = "StdExternalCrate" +imports_granularity = "Crate" +use_field_init_shorthand = true diff --git a/actix-files/src/chunked.rs b/actix-files/src/chunked.rs index 241b4dccb..c6c019038 100644 --- a/actix-files/src/chunked.rs +++ b/actix-files/src/chunked.rs @@ -7,11 +7,10 @@ use std::{ }; use actix_web::{error::Error, web::Bytes}; -use futures_core::{ready, Stream}; -use pin_project_lite::pin_project; - #[cfg(feature = "experimental-io-uring")] use bytes::BytesMut; +use futures_core::{ready, Stream}; +use pin_project_lite::pin_project; use super::named::File; diff --git a/actix-files/src/directory.rs b/actix-files/src/directory.rs index 3af53a31a..6ade424b9 100644 --- a/actix-files/src/directory.rs +++ b/actix-files/src/directory.rs @@ -1,4 +1,9 @@ -use std::{fmt::Write, fs::DirEntry, io, path::Path, path::PathBuf}; +use std::{ + fmt::Write, + fs::DirEntry, + io, + path::{Path, PathBuf}, +}; use actix_web::{dev::ServiceResponse, HttpRequest, HttpResponse}; use percent_encoding::{utf8_percent_encode, CONTROLS}; diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs index 4a259d233..e34b5f26a 100644 --- a/actix-files/src/files.rs +++ b/actix-files/src/files.rs @@ -8,8 +8,7 @@ use std::{ use actix_service::{boxed, IntoServiceFactory, ServiceFactory, ServiceFactoryExt}; use actix_web::{ dev::{ - AppService, HttpServiceFactory, RequestHead, ResourceDef, ServiceRequest, - ServiceResponse, + AppService, HttpServiceFactory, RequestHead, ResourceDef, ServiceRequest, ServiceResponse, }, error::Error, guard::Guard, @@ -301,12 +300,8 @@ impl Files { pub fn default_handler(mut self, f: F) -> Self where F: IntoServiceFactory, - U: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - > + 'static, + U: ServiceFactory + + 'static, { // create and configure default resource self.default = Rc::new(RefCell::new(Some(Rc::new(boxed::factory( diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index bed8194c8..1d8609889 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -18,6 +18,8 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +use std::path::Path; + use actix_service::boxed::{BoxService, BoxServiceFactory}; use actix_web::{ dev::{RequestHead, ServiceRequest, ServiceResponse}, @@ -25,7 +27,6 @@ use actix_web::{ http::header::DispositionType, }; use mime_guess::from_ext; -use std::path::Path; mod chunked; mod directory; @@ -37,16 +38,15 @@ mod path_buf; mod range; mod service; -pub use self::chunked::ChunkedReadFile; -pub use self::directory::Directory; -pub use self::files::Files; -pub use self::named::NamedFile; -pub use self::range::HttpRange; -pub use self::service::FilesService; - -use self::directory::{directory_listing, DirectoryRenderer}; -use self::error::FilesError; -use self::path_buf::PathBufWrap; +pub use self::{ + chunked::ChunkedReadFile, directory::Directory, files::Files, named::NamedFile, + range::HttpRange, service::FilesService, +}; +use self::{ + directory::{directory_listing, DirectoryRenderer}, + error::FilesError, + path_buf::PathBufWrap, +}; type HttpService = BoxService; type HttpNewService = BoxServiceFactory<(), ServiceRequest, ServiceResponse, Error, ()>; @@ -554,10 +554,9 @@ mod tests { #[actix_rt::test] async fn test_static_files_with_spaces() { - let srv = test::init_service( - App::new().service(Files::new("/", ".").index_file("Cargo.toml")), - ) - .await; + let srv = + test::init_service(App::new().service(Files::new("/", ".").index_file("Cargo.toml"))) + .await; let request = TestRequest::get() .uri("/tests/test%20space.binary") .to_request(); @@ -667,8 +666,7 @@ mod tests { #[actix_rt::test] async fn test_static_files() { let srv = - test::init_service(App::new().service(Files::new("/", ".").show_files_listing())) - .await; + test::init_service(App::new().service(Files::new("/", ".").show_files_listing())).await; let req = TestRequest::with_uri("/missing").to_request(); let resp = test::call_service(&srv, req).await; @@ -681,8 +679,7 @@ mod tests { assert_eq!(resp.status(), StatusCode::NOT_FOUND); let srv = - test::init_service(App::new().service(Files::new("/", ".").show_files_listing())) - .await; + test::init_service(App::new().service(Files::new("/", ".").show_files_listing())).await; let req = TestRequest::with_uri("/tests").to_request(); let resp = test::call_service(&srv, req).await; assert_eq!( diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index c10bc00ed..d7795ba73 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -8,13 +8,13 @@ use std::{ use actix_web::{ body::{self, BoxBody, SizedStream}, dev::{ - self, AppService, HttpServiceFactory, ResourceDef, Service, ServiceFactory, - ServiceRequest, ServiceResponse, + self, AppService, HttpServiceFactory, ResourceDef, Service, ServiceFactory, ServiceRequest, + ServiceResponse, }, http::{ header::{ - self, Charset, ContentDisposition, ContentEncoding, DispositionParam, - DispositionType, ExtendedValue, HeaderValue, + self, Charset, ContentDisposition, ContentEncoding, DispositionParam, DispositionType, + ExtendedValue, HeaderValue, }, StatusCode, }, @@ -85,6 +85,7 @@ pub struct NamedFile { #[cfg(not(feature = "experimental-io-uring"))] pub(crate) use std::fs::File; + #[cfg(feature = "experimental-io-uring")] pub(crate) use tokio_uring::fs::File; @@ -139,8 +140,7 @@ impl NamedFile { _ => DispositionType::Attachment, }; - let mut parameters = - vec![DispositionParam::Filename(String::from(filename.as_ref()))]; + let mut parameters = vec![DispositionParam::Filename(String::from(filename.as_ref()))]; if !filename.is_ascii() { parameters.push(DispositionParam::FilenameExt(ExtendedValue { diff --git a/actix-files/src/range.rs b/actix-files/src/range.rs index 65c680ede..528911ae0 100644 --- a/actix-files/src/range.rs +++ b/actix-files/src/range.rs @@ -48,8 +48,8 @@ impl HttpRange { /// `header` is HTTP Range header (e.g. `bytes=bytes=0-9`). /// `size` is full size of response (file). pub fn parse(header: &str, size: u64) -> Result, ParseRangeErr> { - let ranges = http_range::HttpRange::parse(header, size) - .map_err(|err| ParseRangeErr(err.into()))?; + let ranges = + http_range::HttpRange::parse(header, size).map_err(|err| ParseRangeErr(err.into()))?; Ok(ranges .iter() diff --git a/actix-files/src/service.rs b/actix-files/src/service.rs index d94fd5850..3d3b36c40 100644 --- a/actix-files/src/service.rs +++ b/actix-files/src/service.rs @@ -62,11 +62,7 @@ impl FilesService { } } - fn serve_named_file( - &self, - req: ServiceRequest, - mut named_file: NamedFile, - ) -> ServiceResponse { + fn serve_named_file(&self, req: ServiceRequest, mut named_file: NamedFile) -> ServiceResponse { if let Some(ref mime_override) = self.mime_override { let new_disposition = mime_override(&named_file.content_type.type_()); named_file.content_disposition.disposition = new_disposition; @@ -120,13 +116,11 @@ impl Service for FilesService { )); } - let path_on_disk = match PathBufWrap::parse_path( - req.match_info().unprocessed(), - this.hidden_files, - ) { - Ok(item) => item, - Err(err) => return Ok(req.error_response(err)), - }; + let path_on_disk = + match PathBufWrap::parse_path(req.match_info().unprocessed(), this.hidden_files) { + Ok(item) => item, + Err(err) => return Ok(req.error_response(err)), + }; if let Some(filter) = &this.path_filter { if !filter(path_on_disk.as_ref(), req.head()) { @@ -177,8 +171,7 @@ impl Service for FilesService { match NamedFile::open_async(&path).await { Ok(mut named_file) => { if let Some(ref mime_override) = this.mime_override { - let new_disposition = - mime_override(&named_file.content_type.type_()); + let new_disposition = mime_override(&named_file.content_type.type_()); named_file.content_disposition.disposition = new_disposition; } named_file.flags = this.file_flags; diff --git a/actix-files/tests/encoding.rs b/actix-files/tests/encoding.rs index 7aec25ff9..3c8bdb59b 100644 --- a/actix-files/tests/encoding.rs +++ b/actix-files/tests/encoding.rs @@ -24,8 +24,7 @@ async fn test_utf8_file_contents() { // disable UTF-8 attribute let srv = - test::init_service(App::new().service(Files::new("/", "./tests").prefer_utf8(false))) - .await; + test::init_service(App::new().service(Files::new("/", "./tests").prefer_utf8(false))).await; let req = TestRequest::with_uri("/utf8.txt").to_request(); let res = test::call_service(&srv, req).await; diff --git a/actix-files/tests/guard.rs b/actix-files/tests/guard.rs index d053f3fdc..5a97f75d6 100644 --- a/actix-files/tests/guard.rs +++ b/actix-files/tests/guard.rs @@ -12,9 +12,7 @@ async fn test_guard_filter() { let srv = test::init_service( App::new() .service(Files::new("/", "./tests/fixtures/guards/first").guard(Host("first.com"))) - .service( - Files::new("/", "./tests/fixtures/guards/second").guard(Host("second.com")), - ), + .service(Files::new("/", "./tests/fixtures/guards/second").guard(Host("second.com"))), ) .await; diff --git a/actix-files/tests/traversal.rs b/actix-files/tests/traversal.rs index c890b3fe4..4eecb8dde 100644 --- a/actix-files/tests/traversal.rs +++ b/actix-files/tests/traversal.rs @@ -9,8 +9,7 @@ use actix_web::{ async fn test_directory_traversal_prevention() { let srv = test::init_service(App::new().service(Files::new("/", "./tests"))).await; - let req = - TestRequest::with_uri("/../../../../../../../../../../../etc/passwd").to_request(); + let req = TestRequest::with_uri("/../../../../../../../../../../../etc/passwd").to_request(); let res = test::call_service(&srv, req).await; assert_eq!(res.status(), StatusCode::NOT_FOUND); diff --git a/actix-http/examples/hello-world.rs b/actix-http/examples/hello-world.rs index c749cdd00..cf10beddf 100644 --- a/actix-http/examples/hello-world.rs +++ b/actix-http/examples/hello-world.rs @@ -23,10 +23,7 @@ async fn main() -> io::Result<()> { res.insert_header(("x-head", HeaderValue::from_static("dummy value!"))); let forty_two = req.conn_data::().unwrap().to_string(); - res.insert_header(( - "x-forty-two", - HeaderValue::from_str(&forty_two).unwrap(), - )); + res.insert_header(("x-forty-two", HeaderValue::from_str(&forty_two).unwrap())); Ok::<_, Infallible>(res.body("Hello world!")) }) diff --git a/actix-http/src/body/boxed.rs b/actix-http/src/body/boxed.rs index 2bbb75369..0151ff3a5 100644 --- a/actix-http/src/body/boxed.rs +++ b/actix-http/src/body/boxed.rs @@ -77,12 +77,8 @@ impl MessageBody for BoxBody { cx: &mut Context<'_>, ) -> Poll>> { match &mut self.0 { - BoxBodyInner::None(body) => { - Pin::new(body).poll_next(cx).map_err(|err| match err {}) - } - BoxBodyInner::Bytes(body) => { - Pin::new(body).poll_next(cx).map_err(|err| match err {}) - } + BoxBodyInner::None(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}), + BoxBodyInner::Bytes(body) => Pin::new(body).poll_next(cx).map_err(|err| match err {}), BoxBodyInner::Stream(body) => Pin::new(body).poll_next(cx), } } diff --git a/actix-http/src/body/mod.rs b/actix-http/src/body/mod.rs index d1708b9d5..1a12f3336 100644 --- a/actix-http/src/body/mod.rs +++ b/actix-http/src/body/mod.rs @@ -14,12 +14,14 @@ mod size; mod sized_stream; mod utils; -pub use self::body_stream::BodyStream; -pub use self::boxed::BoxBody; -pub use self::either::EitherBody; -pub use self::message_body::MessageBody; pub(crate) use self::message_body::MessageBodyMapErr; -pub use self::none::None; -pub use self::size::BodySize; -pub use self::sized_stream::SizedStream; -pub use self::utils::{to_bytes, to_bytes_limited, BodyLimitExceeded}; +pub use self::{ + body_stream::BodyStream, + boxed::BoxBody, + either::EitherBody, + message_body::MessageBody, + none::None, + size::BodySize, + sized_stream::SizedStream, + utils::{to_bytes, to_bytes_limited, BodyLimitExceeded}, +}; diff --git a/actix-http/src/config.rs b/actix-http/src/config.rs index c0d297a20..b3b215da4 100644 --- a/actix-http/src/config.rs +++ b/actix-http/src/config.rs @@ -132,15 +132,15 @@ impl ServiceConfig { #[cfg(test)] mod tests { - use super::*; - use crate::{date::DATE_VALUE_LENGTH, notify_on_drop}; - use actix_rt::{ task::yield_now, time::{sleep, sleep_until}, }; use memchr::memmem; + use super::*; + use crate::{date::DATE_VALUE_LENGTH, notify_on_drop}; + #[actix_rt::test] async fn test_date_service_update() { let settings = diff --git a/actix-http/src/encoding/decoder.rs b/actix-http/src/encoding/decoder.rs index 06b672fd8..e9aba25e7 100644 --- a/actix-http/src/encoding/decoder.rs +++ b/actix-http/src/encoding/decoder.rs @@ -9,11 +9,9 @@ use std::{ use actix_rt::task::{spawn_blocking, JoinHandle}; use bytes::Bytes; -use futures_core::{ready, Stream}; - #[cfg(feature = "compress-gzip")] use flate2::write::{GzDecoder, ZlibDecoder}; - +use futures_core::{ready, Stream}; #[cfg(feature = "compress-zstd")] use zstd::stream::write::Decoder as ZstdDecoder; @@ -49,9 +47,9 @@ where ))), #[cfg(feature = "compress-gzip")] - ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new( - ZlibDecoder::new(Writer::new()), - ))), + ContentEncoding::Deflate => Some(ContentDecoder::Deflate(Box::new(ZlibDecoder::new( + Writer::new(), + )))), #[cfg(feature = "compress-gzip")] ContentEncoding::Gzip => Some(ContentDecoder::Gzip(Box::new(GzDecoder::new( diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index bbe53e8e8..527bfebaa 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -11,12 +11,10 @@ use std::{ use actix_rt::task::{spawn_blocking, JoinHandle}; use bytes::Bytes; use derive_more::Display; -use futures_core::ready; -use pin_project_lite::pin_project; - #[cfg(feature = "compress-gzip")] use flate2::write::{GzEncoder, ZlibEncoder}; - +use futures_core::ready; +use pin_project_lite::pin_project; use tracing::trace; #[cfg(feature = "compress-zstd")] use zstd::stream::write::Encoder as ZstdEncoder; diff --git a/actix-http/src/encoding/mod.rs b/actix-http/src/encoding/mod.rs index d51dd66c0..7823f3979 100644 --- a/actix-http/src/encoding/mod.rs +++ b/actix-http/src/encoding/mod.rs @@ -7,8 +7,7 @@ use bytes::{Bytes, BytesMut}; mod decoder; mod encoder; -pub use self::decoder::Decoder; -pub use self::encoder::Encoder; +pub use self::{decoder::Decoder, encoder::Encoder}; /// Special-purpose writer for streaming (de-)compression. /// diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index fa0228a50..fbd2eb7ae 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -3,12 +3,11 @@ use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; use derive_more::{Display, Error, From}; +pub use http::Error as HttpError; use http::{uri::InvalidUri, StatusCode}; use crate::{body::BoxBody, Response}; -pub use http::Error as HttpError; - pub struct Error { inner: Box, } diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index e1b629146..8dae2e43e 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -9,9 +9,7 @@ use super::{ decoder::{self, PayloadDecoder, PayloadItem, PayloadType}, encoder, Message, MessageType, }; -use crate::{ - body::BodySize, error::ParseError, ConnectionType, Request, Response, ServiceConfig, -}; +use crate::{body::BodySize, error::ParseError, ConnectionType, Request, Response, ServiceConfig}; bitflags! { #[derive(Debug, Clone, Copy)] diff --git a/actix-http/src/h1/decoder.rs b/actix-http/src/h1/decoder.rs index 829f40e10..9e9b253d6 100644 --- a/actix-http/src/h1/decoder.rs +++ b/actix-http/src/h1/decoder.rs @@ -94,9 +94,7 @@ pub(crate) trait MessageType: Sized { // SAFETY: httparse already checks header value is only visible ASCII bytes // from_maybe_shared_unchecked contains debug assertions so they are omitted here let value = unsafe { - HeaderValue::from_maybe_shared_unchecked( - slice.slice(idx.value.0..idx.value.1), - ) + HeaderValue::from_maybe_shared_unchecked(slice.slice(idx.value.0..idx.value.1)) }; match name { @@ -275,8 +273,7 @@ impl MessageType for Request { let mut msg = Request::new(); // convert headers - let mut length = - msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?; + let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?; // disallow HTTP/1.0 POST requests that do not contain a Content-Length headers // see https://datatracker.ietf.org/doc/html/rfc1945#section-7.2.2 @@ -356,8 +353,8 @@ impl MessageType for ResponseHead { Version::HTTP_10 }; - let status = StatusCode::from_u16(res.code.unwrap()) - .map_err(|_| ParseError::Status)?; + let status = + StatusCode::from_u16(res.code.unwrap()).map_err(|_| ParseError::Status)?; HeaderIndex::record(src, res.headers, &mut headers); (len, version, status, res.headers.len()) @@ -378,8 +375,7 @@ impl MessageType for ResponseHead { msg.version = ver; // convert headers - let mut length = - msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?; + let mut length = msg.set_headers(&src.split_to(len).freeze(), &headers[..h_len], ver)?; // Remove CL value if 0 now that all headers and HTTP/1.0 special cases are processed. // Protects against some request smuggling attacks. diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index c2f8ea453..270707807 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -19,14 +19,6 @@ use tokio::io::{AsyncRead, AsyncWrite}; use tokio_util::codec::{Decoder as _, Encoder as _}; use tracing::{error, trace}; -use crate::{ - body::{BodySize, BoxBody, MessageBody}, - config::ServiceConfig, - error::{DispatchError, ParseError, PayloadError}, - service::HttpFlow, - Error, Extensions, OnConnectData, Request, Response, StatusCode, -}; - use super::{ codec::Codec, decoder::MAX_BUFFER_SIZE, @@ -34,6 +26,13 @@ use super::{ timer::TimerState, Message, MessageType, }; +use crate::{ + body::{BodySize, BoxBody, MessageBody}, + config::ServiceConfig, + error::{DispatchError, ParseError, PayloadError}, + service::HttpFlow, + Error, Extensions, OnConnectData, Request, Response, StatusCode, +}; const LW_BUFFER_SIZE: usize = 1024; const HW_BUFFER_SIZE: usize = 1024 * 8; @@ -213,9 +212,7 @@ where fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::None => write!(f, "State::None"), - Self::ExpectCall { .. } => { - f.debug_struct("State::ExpectCall").finish_non_exhaustive() - } + Self::ExpectCall { .. } => f.debug_struct("State::ExpectCall").finish_non_exhaustive(), Self::ServiceCall { .. } => { f.debug_struct("State::ServiceCall").finish_non_exhaustive() } @@ -276,9 +273,7 @@ where head_timer: TimerState::new(config.client_request_deadline().is_some()), ka_timer: TimerState::new(config.keep_alive().enabled()), - shutdown_timer: TimerState::new( - config.client_disconnect_deadline().is_some(), - ), + shutdown_timer: TimerState::new(config.client_disconnect_deadline().is_some()), io: Some(io), read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE), @@ -456,9 +451,7 @@ where } // return with upgrade request and poll it exclusively - Some(DispatcherMessage::Upgrade(req)) => { - return Ok(PollResponse::Upgrade(req)) - } + Some(DispatcherMessage::Upgrade(req)) => return Ok(PollResponse::Upgrade(req)), // all messages are dealt with None => { @@ -675,9 +668,7 @@ where } _ => { - unreachable!( - "State must be set to ServiceCall or ExceptCall in handle_request" - ) + unreachable!("State must be set to ServiceCall or ExceptCall in handle_request") } } } @@ -686,10 +677,7 @@ where /// Process one incoming request. /// /// Returns true if any meaningful work was done. - fn poll_request( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Result { + fn poll_request(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result { let pipeline_queue_full = self.messages.len() >= MAX_PIPELINED_MESSAGES; let can_not_read = !self.can_read(cx); @@ -859,10 +847,7 @@ where Ok(()) } - fn poll_ka_timer( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Result<(), DispatchError> { + fn poll_ka_timer(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> { let this = self.as_mut().project(); if let TimerState::Active { timer } = this.ka_timer { debug_assert!( @@ -927,10 +912,7 @@ where } /// Poll head, keep-alive, and disconnect timer. - fn poll_timers( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Result<(), DispatchError> { + fn poll_timers(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result<(), DispatchError> { self.as_mut().poll_head_timer(cx)?; self.as_mut().poll_ka_timer(cx)?; self.as_mut().poll_shutdown_timer(cx)?; @@ -944,10 +926,7 @@ where /// - `std::io::ErrorKind::ConnectionReset` after partial read; /// - all data read done. #[inline(always)] // TODO: bench this inline - fn read_available( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Result { + fn read_available(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Result { let this = self.project(); if this.flags.contains(Flags::READ_DISCONNECT) { diff --git a/actix-http/src/h1/dispatcher_tests.rs b/actix-http/src/h1/dispatcher_tests.rs index db46cdefc..50259e6ce 100644 --- a/actix-http/src/h1/dispatcher_tests.rs +++ b/actix-http/src/h1/dispatcher_tests.rs @@ -1,14 +1,11 @@ use std::{future::Future, str, task::Poll, time::Duration}; -use actix_rt::{pin, time::sleep}; -use actix_service::fn_service; -use actix_utils::future::{ready, Ready}; -use bytes::Bytes; -use futures_util::future::lazy; - use actix_codec::Framed; -use actix_service::Service; -use bytes::{Buf, BytesMut}; +use actix_rt::{pin, time::sleep}; +use actix_service::{fn_service, Service}; +use actix_utils::future::{ready, Ready}; +use bytes::{Buf, Bytes, BytesMut}; +use futures_util::future::lazy; use super::dispatcher::{Dispatcher, DispatcherState, DispatcherStateProj, Flags}; use crate::{ @@ -43,8 +40,8 @@ fn status_service( fn_service(move |_req: Request| ready(Ok::<_, Error>(Response::new(status)))) } -fn echo_path_service( -) -> impl Service, Error = Error> { +fn echo_path_service() -> impl Service, Error = Error> +{ fn_service(|req: Request| { let path = req.path().as_bytes(); ready(Ok::<_, Error>( @@ -53,8 +50,8 @@ fn echo_path_service( }) } -fn drop_payload_service( -) -> impl Service, Error = Error> { +fn drop_payload_service() -> impl Service, Error = Error> +{ fn_service(|mut req: Request| async move { let _ = req.take_payload(); Ok::<_, Error>(Response::with_body(StatusCode::OK, "payload dropped")) diff --git a/actix-http/src/h1/mod.rs b/actix-http/src/h1/mod.rs index 858cf542a..9e44608d8 100644 --- a/actix-http/src/h1/mod.rs +++ b/actix-http/src/h1/mod.rs @@ -17,14 +17,16 @@ mod timer; mod upgrade; mod utils; -pub use self::client::{ClientCodec, ClientPayloadCodec}; -pub use self::codec::Codec; -pub use self::dispatcher::Dispatcher; -pub use self::expect::ExpectHandler; -pub use self::payload::Payload; -pub use self::service::{H1Service, H1ServiceHandler}; -pub use self::upgrade::UpgradeHandler; -pub use self::utils::SendResponse; +pub use self::{ + client::{ClientCodec, ClientPayloadCodec}, + codec::Codec, + dispatcher::Dispatcher, + expect::ExpectHandler, + payload::Payload, + service::{H1Service, H1ServiceHandler}, + upgrade::UpgradeHandler, + utils::SendResponse, +}; #[derive(Debug)] /// Codec message diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 9eebe2126..fbda7138e 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -15,6 +15,7 @@ use actix_utils::future::ready; use futures_core::future::LocalBoxFuture; use tracing::error; +use super::{codec::Codec, dispatcher::Dispatcher, ExpectHandler, UpgradeHandler}; use crate::{ body::{BoxBody, MessageBody}, config::ServiceConfig, @@ -23,8 +24,6 @@ use crate::{ ConnectCallback, OnConnectData, Request, Response, }; -use super::{codec::Codec, dispatcher::Dispatcher, ExpectHandler, UpgradeHandler}; - /// `ServiceFactory` implementation for HTTP1 transport pub struct H1Service { srv: S, @@ -82,13 +81,8 @@ where /// Create simple tcp stream service pub fn tcp( self, - ) -> impl ServiceFactory< - TcpStream, - Config = (), - Response = (), - Error = DispatchError, - InitError = (), - > { + ) -> impl ServiceFactory + { fn_service(|io: TcpStream| { let peer_addr = io.peer_addr().ok(); ready(Ok((io, peer_addr))) @@ -99,8 +93,6 @@ where #[cfg(feature = "openssl")] mod openssl { - use super::*; - use actix_tls::accept::{ openssl::{ reexports::{Error as SslError, SslAcceptor}, @@ -109,6 +101,8 @@ mod openssl { TlsError, }; + use super::*; + impl H1Service, S, B, X, U> where S: ServiceFactory, diff --git a/actix-http/src/h2/mod.rs b/actix-http/src/h2/mod.rs index 39198e0fe..e47099cac 100644 --- a/actix-http/src/h2/mod.rs +++ b/actix-http/src/h2/mod.rs @@ -23,8 +23,7 @@ use crate::{ mod dispatcher; mod service; -pub use self::dispatcher::Dispatcher; -pub use self::service::H2Service; +pub use self::{dispatcher::Dispatcher, service::H2Service}; /// HTTP/2 peer stream. pub struct Payload { @@ -58,10 +57,7 @@ impl Stream for Payload { } } -pub(crate) fn handshake_with_timeout( - io: T, - config: &ServiceConfig, -) -> HandshakeWithTimeout +pub(crate) fn handshake_with_timeout(io: T, config: &ServiceConfig) -> HandshakeWithTimeout where T: AsyncRead + AsyncWrite + Unpin, { diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index e526918c7..3f742135a 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -16,6 +16,7 @@ use actix_utils::future::ready; use futures_core::{future::LocalBoxFuture, ready}; use tracing::{error, trace}; +use super::{dispatcher::Dispatcher, handshake_with_timeout, HandshakeWithTimeout}; use crate::{ body::{BoxBody, MessageBody}, config::ServiceConfig, @@ -24,8 +25,6 @@ use crate::{ ConnectCallback, OnConnectData, Request, Response, }; -use super::{dispatcher::Dispatcher, handshake_with_timeout, HandshakeWithTimeout}; - /// `ServiceFactory` implementation for HTTP/2 transport pub struct H2Service { srv: S, diff --git a/actix-http/src/header/map.rs b/actix-http/src/header/map.rs index d7b4e6dde..e8118be93 100644 --- a/actix-http/src/header/map.rs +++ b/actix-http/src/header/map.rs @@ -1120,9 +1120,7 @@ mod tests { assert!(vals.next().is_none()); } - fn owned_pair<'a>( - (name, val): (&'a HeaderName, &'a HeaderValue), - ) -> (HeaderName, HeaderValue) { + fn owned_pair<'a>((name, val): (&'a HeaderName, &'a HeaderValue)) -> (HeaderName, HeaderValue) { (name.clone(), val.clone()) } } diff --git a/actix-http/src/header/mod.rs b/actix-http/src/header/mod.rs index a63174a92..79f91afef 100644 --- a/actix-http/src/header/mod.rs +++ b/actix-http/src/header/mod.rs @@ -3,33 +3,30 @@ // declaring new header consts will yield this error #![allow(clippy::declare_interior_mutable_const)] -use percent_encoding::{AsciiSet, CONTROLS}; - // re-export from http except header map related items pub use ::http::header::{ HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue, ToStrError, }; - // re-export const header names, list is explicit so that any updates to `common` module do not // conflict with this set pub use ::http::header::{ ACCEPT, ACCEPT_CHARSET, ACCEPT_ENCODING, ACCEPT_LANGUAGE, ACCEPT_RANGES, - ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, - ACCESS_CONTROL_ALLOW_METHODS, ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS, - ACCESS_CONTROL_MAX_AGE, ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, AGE, - ALLOW, ALT_SVC, AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION, - CONTENT_ENCODING, CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_RANGE, - CONTENT_SECURITY_POLICY, CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, COOKIE, DATE, - DNT, ETAG, EXPECT, EXPIRES, FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE, - IF_NONE_MATCH, IF_RANGE, IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, LOCATION, MAX_FORWARDS, - ORIGIN, PRAGMA, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, PUBLIC_KEY_PINS, - PUBLIC_KEY_PINS_REPORT_ONLY, RANGE, REFERER, REFERRER_POLICY, REFRESH, RETRY_AFTER, - SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_EXTENSIONS, SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL, - SEC_WEBSOCKET_VERSION, SERVER, SET_COOKIE, STRICT_TRANSPORT_SECURITY, TE, TRAILER, - TRANSFER_ENCODING, UPGRADE, UPGRADE_INSECURE_REQUESTS, USER_AGENT, VARY, VIA, WARNING, - WWW_AUTHENTICATE, X_CONTENT_TYPE_OPTIONS, X_DNS_PREFETCH_CONTROL, X_FRAME_OPTIONS, - X_XSS_PROTECTION, + ACCESS_CONTROL_ALLOW_CREDENTIALS, ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_METHODS, + ACCESS_CONTROL_ALLOW_ORIGIN, ACCESS_CONTROL_EXPOSE_HEADERS, ACCESS_CONTROL_MAX_AGE, + ACCESS_CONTROL_REQUEST_HEADERS, ACCESS_CONTROL_REQUEST_METHOD, AGE, ALLOW, ALT_SVC, + AUTHORIZATION, CACHE_CONTROL, CONNECTION, CONTENT_DISPOSITION, CONTENT_ENCODING, + CONTENT_LANGUAGE, CONTENT_LENGTH, CONTENT_LOCATION, CONTENT_RANGE, CONTENT_SECURITY_POLICY, + CONTENT_SECURITY_POLICY_REPORT_ONLY, CONTENT_TYPE, COOKIE, DATE, DNT, ETAG, EXPECT, EXPIRES, + FORWARDED, FROM, HOST, IF_MATCH, IF_MODIFIED_SINCE, IF_NONE_MATCH, IF_RANGE, + IF_UNMODIFIED_SINCE, LAST_MODIFIED, LINK, LOCATION, MAX_FORWARDS, ORIGIN, PRAGMA, + PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, PUBLIC_KEY_PINS, PUBLIC_KEY_PINS_REPORT_ONLY, RANGE, + REFERER, REFERRER_POLICY, REFRESH, RETRY_AFTER, SEC_WEBSOCKET_ACCEPT, SEC_WEBSOCKET_EXTENSIONS, + SEC_WEBSOCKET_KEY, SEC_WEBSOCKET_PROTOCOL, SEC_WEBSOCKET_VERSION, SERVER, SET_COOKIE, + STRICT_TRANSPORT_SECURITY, TE, TRAILER, TRANSFER_ENCODING, UPGRADE, UPGRADE_INSECURE_REQUESTS, + USER_AGENT, VARY, VIA, WARNING, WWW_AUTHENTICATE, X_CONTENT_TYPE_OPTIONS, + X_DNS_PREFETCH_CONTROL, X_FRAME_OPTIONS, X_XSS_PROTECTION, }; +use percent_encoding::{AsciiSet, CONTROLS}; use crate::{error::ParseError, HttpMessage}; @@ -43,23 +40,22 @@ mod utils; pub use self::{ as_name::AsHeaderName, + // re-export list is explicit so that any updates to `http` do not conflict with this set + common::{ + CACHE_STATUS, CDN_CACHE_CONTROL, CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY, + CROSS_ORIGIN_RESOURCE_POLICY, PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST, + X_FORWARDED_PROTO, + }, into_pair::TryIntoHeaderPair, into_value::TryIntoHeaderValue, map::HeaderMap, shared::{ - parse_extended_value, q, Charset, ContentEncoding, ExtendedValue, HttpDate, - LanguageTag, Quality, QualityItem, + parse_extended_value, q, Charset, ContentEncoding, ExtendedValue, HttpDate, LanguageTag, + Quality, QualityItem, }, utils::{fmt_comma_delimited, from_comma_delimited, from_one_raw_str, http_percent_encode}, }; -// re-export list is explicit so that any updates to `http` do not conflict with this set -pub use self::common::{ - CACHE_STATUS, CDN_CACHE_CONTROL, CROSS_ORIGIN_EMBEDDER_POLICY, CROSS_ORIGIN_OPENER_POLICY, - CROSS_ORIGIN_RESOURCE_POLICY, PERMISSIONS_POLICY, X_FORWARDED_FOR, X_FORWARDED_HOST, - X_FORWARDED_PROTO, -}; - /// An interface for types that already represent a valid header. pub trait Header: TryIntoHeaderValue { /// Returns the name of the header field. diff --git a/actix-http/src/header/shared/mod.rs b/actix-http/src/header/shared/mod.rs index 257e54d7a..889c73c45 100644 --- a/actix-http/src/header/shared/mod.rs +++ b/actix-http/src/header/shared/mod.rs @@ -1,5 +1,7 @@ //! Originally taken from `hyper::header::shared`. +pub use language_tags::LanguageTag; + mod charset; mod content_encoding; mod extended; @@ -7,10 +9,11 @@ mod http_date; mod quality; mod quality_item; -pub use self::charset::Charset; -pub use self::content_encoding::ContentEncoding; -pub use self::extended::{parse_extended_value, ExtendedValue}; -pub use self::http_date::HttpDate; -pub use self::quality::{q, Quality}; -pub use self::quality_item::QualityItem; -pub use language_tags::LanguageTag; +pub use self::{ + charset::Charset, + content_encoding::ContentEncoding, + extended::{parse_extended_value, ExtendedValue}, + http_date::HttpDate, + quality::{q, Quality}, + quality_item::QualityItem, +}; diff --git a/actix-http/src/header/shared/quality_item.rs b/actix-http/src/header/shared/quality_item.rs index ee1fdb928..a41369c20 100644 --- a/actix-http/src/header/shared/quality_item.rs +++ b/actix-http/src/header/shared/quality_item.rs @@ -1,8 +1,7 @@ use std::{cmp, fmt, str}; -use crate::error::ParseError; - use super::Quality; +use crate::error::ParseError; /// Represents an item with a quality value as defined /// in [RFC 7231 §5.3.1](https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.1). diff --git a/actix-http/src/http_message.rs b/actix-http/src/http_message.rs index 20becc310..3ba9ef752 100644 --- a/actix-http/src/http_message.rs +++ b/actix-http/src/http_message.rs @@ -61,9 +61,7 @@ pub trait HttpMessage: Sized { 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::for_label_no_replacement(charset.as_str().as_bytes()) - { + if let Some(enc) = Encoding::for_label_no_replacement(charset.as_str().as_bytes()) { Ok(enc) } else { Err(ContentTypeError::UnknownEncoding) diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 8bf834f73..8b755f2f4 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -28,8 +28,7 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub use ::http::{uri, uri::Uri}; -pub use ::http::{Method, StatusCode, Version}; +pub use ::http::{uri, uri::Uri, Method, StatusCode, Version}; pub mod body; mod builder; @@ -57,22 +56,24 @@ pub mod test; #[cfg(feature = "ws")] pub mod ws; -pub use self::builder::HttpServiceBuilder; -pub use self::config::ServiceConfig; -pub use self::error::Error; -pub use self::extensions::Extensions; -pub use self::header::ContentEncoding; -pub use self::http_message::HttpMessage; -pub use self::keep_alive::KeepAlive; -pub use self::message::ConnectionType; -pub use self::message::Message; #[allow(deprecated)] -pub use self::payload::{BoxedPayloadStream, Payload, PayloadStream}; -pub use self::requests::{Request, RequestHead, RequestHeadType}; -pub use self::responses::{Response, ResponseBuilder, ResponseHead}; -pub use self::service::HttpService; +pub use self::payload::PayloadStream; #[cfg(any(feature = "openssl", feature = "rustls"))] pub use self::service::TlsAcceptorConfig; +pub use self::{ + builder::HttpServiceBuilder, + config::ServiceConfig, + error::Error, + extensions::Extensions, + header::ContentEncoding, + http_message::HttpMessage, + keep_alive::KeepAlive, + message::{ConnectionType, Message}, + payload::{BoxedPayloadStream, Payload}, + requests::{Request, RequestHead, RequestHeadType}, + responses::{Response, ResponseBuilder, ResponseHead}, + service::HttpService, +}; /// A major HTTP protocol version. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] diff --git a/actix-http/src/requests/mod.rs b/actix-http/src/requests/mod.rs index fc35da65a..4a27818a5 100644 --- a/actix-http/src/requests/mod.rs +++ b/actix-http/src/requests/mod.rs @@ -3,5 +3,7 @@ mod head; mod request; -pub use self::head::{RequestHead, RequestHeadType}; -pub use self::request::Request; +pub use self::{ + head::{RequestHead, RequestHeadType}, + request::Request, +}; diff --git a/actix-http/src/requests/request.rs b/actix-http/src/requests/request.rs index f4d605b39..1750fb2f7 100644 --- a/actix-http/src/requests/request.rs +++ b/actix-http/src/requests/request.rs @@ -10,8 +10,7 @@ use std::{ use http::{header, Method, Uri, Version}; use crate::{ - header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload, - RequestHead, + header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload, RequestHead, }; /// An HTTP request. diff --git a/actix-http/src/responses/mod.rs b/actix-http/src/responses/mod.rs index 899232b9f..d99628232 100644 --- a/actix-http/src/responses/mod.rs +++ b/actix-http/src/responses/mod.rs @@ -5,7 +5,5 @@ mod head; #[allow(clippy::module_inception)] mod response; -pub use self::builder::ResponseBuilder; pub(crate) use self::head::BoxedResponseHead; -pub use self::head::ResponseHead; -pub use self::response::Response; +pub use self::{builder::ResponseBuilder, head::ResponseHead, response::Response}; diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index 108b09c4e..e118d8361 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -200,13 +200,8 @@ where /// The resulting service only supports HTTP/1.x. pub fn tcp( self, - ) -> impl ServiceFactory< - TcpStream, - Config = (), - Response = (), - Error = DispatchError, - InitError = (), - > { + ) -> impl ServiceFactory + { fn_service(|io: TcpStream| async { let peer_addr = io.peer_addr().ok(); Ok((io, Protocol::Http1, peer_addr)) @@ -219,13 +214,8 @@ where #[cfg(feature = "http2")] pub fn tcp_auto_h2c( self, - ) -> impl ServiceFactory< - TcpStream, - Config = (), - Response = (), - Error = DispatchError, - InitError = (), - > { + ) -> impl ServiceFactory + { fn_service(move |io: TcpStream| async move { // subset of HTTP/2 preface defined by RFC 9113 §3.4 // this subset was chosen to maximize likelihood that peeking only once will allow us to @@ -563,10 +553,7 @@ where } } - pub(super) fn _poll_ready( - &self, - cx: &mut Context<'_>, - ) -> Poll>> { + pub(super) fn _poll_ready(&self, cx: &mut Context<'_>) -> Poll>> { ready!(self.flow.expect.poll_ready(cx).map_err(Into::into))?; ready!(self.flow.service.poll_ready(cx).map_err(Into::into))?; @@ -625,10 +612,7 @@ where }) } - fn call( - &self, - (io, proto, peer_addr): (T, Protocol, Option), - ) -> Self::Future { + fn call(&self, (io, proto, peer_addr): (T, Protocol, Option)) -> Self::Future { let conn_data = OnConnectData::from_io(&io, self.on_connect_ext.as_deref()); match proto { diff --git a/actix-http/src/ws/dispatcher.rs b/actix-http/src/ws/dispatcher.rs index 396f1e86c..1354d5ae1 100644 --- a/actix-http/src/ws/dispatcher.rs +++ b/actix-http/src/ws/dispatcher.rs @@ -70,15 +70,14 @@ mod inner { task::{Context, Poll}, }; + use actix_codec::Framed; use actix_service::{IntoService, Service}; use futures_core::stream::Stream; use local_channel::mpsc; use pin_project_lite::pin_project; - use tracing::debug; - - use actix_codec::Framed; use tokio::io::{AsyncRead, AsyncWrite}; use tokio_util::codec::{Decoder, Encoder}; + use tracing::debug; use crate::{body::BoxBody, Response}; @@ -413,9 +412,7 @@ mod inner { } State::Error(_) => { // flush write buffer - if !this.framed.is_write_buf_empty() - && this.framed.flush(cx).is_pending() - { + if !this.framed.is_write_buf_empty() && this.framed.flush(cx).is_pending() { return Poll::Pending; } Poll::Ready(Err(this.state.take_error())) diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs index ce6f1b256..c9fb0cde9 100644 --- a/actix-http/src/ws/frame.rs +++ b/actix-http/src/ws/frame.rs @@ -221,9 +221,10 @@ impl Parser { #[cfg(test)] mod tests { - use super::*; use bytes::Bytes; + use super::*; + struct F { finished: bool, opcode: OpCode, diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs index 2a0b0a99c..87f9b38f3 100644 --- a/actix-http/src/ws/mod.rs +++ b/actix-http/src/ws/mod.rs @@ -8,8 +8,7 @@ use std::io; use derive_more::{Display, Error, From}; use http::{header, Method, StatusCode}; -use crate::body::BoxBody; -use crate::{header::HeaderValue, RequestHead, Response, ResponseBuilder}; +use crate::{body::BoxBody, header::HeaderValue, RequestHead, Response, ResponseBuilder}; mod codec; mod dispatcher; @@ -17,10 +16,12 @@ mod frame; mod mask; mod proto; -pub use self::codec::{Codec, Frame, Item, Message}; -pub use self::dispatcher::Dispatcher; -pub use self::frame::Parser; -pub use self::proto::{hash_key, CloseCode, CloseReason, OpCode}; +pub use self::{ + codec::{Codec, Frame, Item, Message}, + dispatcher::Dispatcher, + frame::Parser, + proto::{hash_key, CloseCode, CloseReason, OpCode}, +}; /// WebSocket protocol errors. #[derive(Debug, Display, Error, From)] @@ -219,10 +220,8 @@ pub fn handshake_response(req: &RequestHead) -> ResponseBuilder { #[cfg(test)] mod tests { - use crate::{header, Method}; - use super::*; - use crate::test::TestRequest; + use crate::{header, test::TestRequest, Method}; #[test] fn test_handshake() { diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs index 7464bee4e..b4d8ed1a5 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -321,8 +321,7 @@ async fn h2_body_length() { let mut srv = test_server(move || { HttpService::build() .h2(|_| async { - let body = - once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) }); + let body = once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) }); Ok::<_, Infallible>( Response::ok().set_body(SizedStream::new(STR.len() as u64, body)), diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index bf3a9243b..3d9a39cbd 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -90,11 +90,9 @@ pub fn get_negotiated_alpn_protocol( config.alpn_protocols.push(client_alpn_protocol.to_vec()); - let mut sess = rustls::ClientConnection::new( - Arc::new(config), - ServerName::try_from("localhost").unwrap(), - ) - .unwrap(); + let mut sess = + rustls::ClientConnection::new(Arc::new(config), ServerName::try_from("localhost").unwrap()) + .unwrap(); let mut sock = StdTcpStream::connect(addr).unwrap(); let mut stream = rustls::Stream::new(&mut sess, &mut sock); diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index 2efb336ae..cfb4d17b8 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -166,8 +166,7 @@ async fn chunked_payload() { for chunk_size in chunk_sizes.iter() { let mut bytes = Vec::new(); - let random_bytes: Vec = - (0..*chunk_size).map(|_| rand::random::()).collect(); + let random_bytes: Vec = (0..*chunk_size).map(|_| rand::random::()).collect(); bytes.extend(format!("{:X}\r\n", chunk_size).as_bytes()); bytes.extend(&random_bytes[..]); @@ -352,8 +351,7 @@ async fn http10_keepalive() { .await; let mut stream = net::TcpStream::connect(srv.addr()).unwrap(); - let _ = - stream.write_all(b"GET /test/tests/test HTTP/1.0\r\nconnection: keep-alive\r\n\r\n"); + let _ = stream.write_all(b"GET /test/tests/test HTTP/1.0\r\nconnection: keep-alive\r\n\r\n"); let mut data = vec![0; 1024]; let _ = stream.read(&mut data); assert_eq!(&data[..17], b"HTTP/1.0 200 OK\r\n"); @@ -795,8 +793,9 @@ async fn not_modified_spec_h1() { .map_into_boxed_body(), // with no content-length - "/body" => Response::with_body(StatusCode::NOT_MODIFIED, "1234") - .map_into_boxed_body(), + "/body" => { + Response::with_body(StatusCode::NOT_MODIFIED, "1234").map_into_boxed_body() + } // with manual content-length header and specific None body "/cl-none" => { diff --git a/actix-multipart/src/form/bytes.rs b/actix-multipart/src/form/bytes.rs index 7d64fffce..3c5e2eb10 100644 --- a/actix-multipart/src/form/bytes.rs +++ b/actix-multipart/src/form/bytes.rs @@ -27,11 +27,7 @@ pub struct Bytes { impl<'t> FieldReader<'t> for Bytes { type Future = LocalBoxFuture<'t, Result>; - fn read_field( - _: &'t HttpRequest, - mut field: Field, - limits: &'t mut Limits, - ) -> Self::Future { + fn read_field(_: &'t HttpRequest, mut field: Field, limits: &'t mut Limits) -> Self::Future { Box::pin(async move { let mut buf = BytesMut::with_capacity(131_072); diff --git a/actix-multipart/src/form/json.rs b/actix-multipart/src/form/json.rs index 9951eaaaf..fb90a82b9 100644 --- a/actix-multipart/src/form/json.rs +++ b/actix-multipart/src/form/json.rs @@ -7,13 +7,12 @@ use derive_more::{Deref, DerefMut, Display, Error}; use futures_core::future::LocalBoxFuture; use serde::de::DeserializeOwned; +use super::FieldErrorHandler; use crate::{ form::{bytes::Bytes, FieldReader, Limits}, Field, MultipartError, }; -use super::FieldErrorHandler; - /// Deserialize from JSON. #[derive(Debug, Deref, DerefMut)] pub struct Json(pub T); diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index 711d4aeb6..67adfd4b2 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -429,8 +429,7 @@ mod tests { #[actix_rt::test] async fn test_options() { - let srv = - actix_test::start(|| App::new().route("/", web::post().to(test_options_route))); + let srv = actix_test::start(|| App::new().route("/", web::post().to(test_options_route))); let mut form = multipart::Form::default(); form.add_text("field1", "value"); @@ -481,9 +480,7 @@ mod tests { field3: Text, } - async fn test_field_renaming_route( - form: MultipartForm, - ) -> impl Responder { + async fn test_field_renaming_route(form: MultipartForm) -> impl Responder { assert_eq!(&*form.field1, "renamed"); assert_eq!(&*form.field2, "field1"); assert_eq!(&*form.field3, "field3"); @@ -492,9 +489,8 @@ mod tests { #[actix_rt::test] async fn test_field_renaming() { - let srv = actix_test::start(|| { - App::new().route("/", web::post().to(test_field_renaming_route)) - }); + let srv = + actix_test::start(|| App::new().route("/", web::post().to(test_field_renaming_route))); let mut form = multipart::Form::default(); form.add_text("renamed", "renamed"); @@ -623,9 +619,7 @@ mod tests { HttpResponse::Ok().finish() } - async fn test_upload_limits_file( - form: MultipartForm, - ) -> impl Responder { + async fn test_upload_limits_file(form: MultipartForm) -> impl Responder { assert!(form.field.size > 0); HttpResponse::Ok().finish() } diff --git a/actix-multipart/src/form/tempfile.rs b/actix-multipart/src/form/tempfile.rs index 3c637e717..2f611ba04 100644 --- a/actix-multipart/src/form/tempfile.rs +++ b/actix-multipart/src/form/tempfile.rs @@ -39,23 +39,20 @@ pub struct TempFile { impl<'t> FieldReader<'t> for TempFile { type Future = LocalBoxFuture<'t, Result>; - fn read_field( - req: &'t HttpRequest, - mut field: Field, - limits: &'t mut Limits, - ) -> Self::Future { + fn read_field(req: &'t HttpRequest, mut field: Field, limits: &'t mut Limits) -> Self::Future { Box::pin(async move { let config = TempFileConfig::from_req(req); let field_name = field.name().to_owned(); let mut size = 0; - let file = config.create_tempfile().map_err(|err| { - config.map_error(req, &field_name, TempFileError::FileIo(err)) - })?; + let file = config + .create_tempfile() + .map_err(|err| config.map_error(req, &field_name, TempFileError::FileIo(err)))?; - let mut file_async = tokio::fs::File::from_std(file.reopen().map_err(|err| { - config.map_error(req, &field_name, TempFileError::FileIo(err)) - })?); + let mut file_async = + tokio::fs::File::from_std(file.reopen().map_err(|err| { + config.map_error(req, &field_name, TempFileError::FileIo(err)) + })?); while let Some(chunk) = field.try_next().await? { limits.try_consume_limits(chunk.len(), false)?; @@ -65,9 +62,10 @@ impl<'t> FieldReader<'t> for TempFile { })?; } - file_async.flush().await.map_err(|err| { - config.map_error(req, &field_name, TempFileError::FileIo(err)) - })?; + file_async + .flush() + .await + .map_err(|err| config.map_error(req, &field_name, TempFileError::FileIo(err)))?; Ok(TempFile { file, @@ -131,12 +129,7 @@ impl TempFileConfig { .unwrap_or(&DEFAULT_CONFIG) } - fn map_error( - &self, - req: &HttpRequest, - field_name: &str, - err: TempFileError, - ) -> MultipartError { + fn map_error(&self, req: &HttpRequest, field_name: &str, err: TempFileError) -> MultipartError { let source = if let Some(ref err_handler) = self.err_handler { (err_handler)(err, req) } else { diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index 73e10c913..615a8e6de 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -17,5 +17,7 @@ mod server; pub mod form; -pub use self::error::MultipartError; -pub use self::server::{Field, Multipart}; +pub use self::{ + error::MultipartError, + server::{Field, Multipart}, +}; diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index 5dc4d6f69..b20429040 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -161,8 +161,8 @@ impl InnerMultipart { for h in hdrs { let name = HeaderName::try_from(h.name).map_err(|_| ParseError::Header)?; - let value = HeaderValue::try_from(h.value) - .map_err(|_| ParseError::Header)?; + let value = + HeaderValue::try_from(h.value).map_err(|_| ParseError::Header)?; headers.append(name, value); } @@ -222,8 +222,7 @@ impl InnerMultipart { if chunk.len() < boundary.len() { continue; } - if &chunk[..2] == b"--" && &chunk[2..chunk.len() - 2] == boundary.as_bytes() - { + if &chunk[..2] == b"--" && &chunk[2..chunk.len() - 2] == boundary.as_bytes() { break; } else { if chunk.len() < boundary.len() + 2 { @@ -268,9 +267,7 @@ impl InnerMultipart { match field.borrow_mut().poll(safety) { Poll::Pending => return Poll::Pending, Poll::Ready(Some(Ok(_))) => continue, - Poll::Ready(Some(Err(err))) => { - return Poll::Ready(Some(Err(err))) - } + Poll::Ready(Some(Err(err))) => return Poll::Ready(Some(Err(err))), Poll::Ready(None) => true, } } @@ -289,8 +286,7 @@ impl InnerMultipart { match self.state { // read until first boundary InnerState::FirstBoundary => { - match InnerMultipart::skip_until_boundary(&mut payload, &self.boundary)? - { + match InnerMultipart::skip_until_boundary(&mut payload, &self.boundary)? { Some(eof) => { if eof { self.state = InnerState::Eof; @@ -667,9 +663,7 @@ impl InnerField { Ok(None) => Poll::Pending, Ok(Some(line)) => { if line.as_ref() != b"\r\n" { - log::warn!( - "multipart field did not read all the data or it is malformed" - ); + log::warn!("multipart field did not read all the data or it is malformed"); } Poll::Ready(None) } diff --git a/actix-router/benches/quoter.rs b/actix-router/benches/quoter.rs index 9ca06da39..2065fd563 100644 --- a/actix-router/benches/quoter.rs +++ b/actix-router/benches/quoter.rs @@ -1,9 +1,9 @@ #![allow(clippy::uninlined_format_args)] -use criterion::{black_box, criterion_group, criterion_main, Criterion}; - use std::borrow::Cow; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; + fn compare_quoters(c: &mut Criterion) { let mut group = c.benchmark_group("Compare Quoters"); diff --git a/actix-router/src/de.rs b/actix-router/src/de.rs index 458e08930..e8c7c658e 100644 --- a/actix-router/src/de.rs +++ b/actix-router/src/de.rs @@ -1,10 +1,14 @@ use std::borrow::Cow; -use serde::de::{self, Deserializer, Error as DeError, Visitor}; -use serde::forward_to_deserialize_any; +use serde::{ + de::{self, Deserializer, Error as DeError, Visitor}, + forward_to_deserialize_any, +}; -use crate::path::{Path, PathIter}; -use crate::{Quoter, ResourcePath}; +use crate::{ + path::{Path, PathIter}, + Quoter, ResourcePath, +}; thread_local! { static FULL_QUOTER: Quoter = Quoter::new(b"", b""); @@ -486,11 +490,7 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { Err(de::value::Error::custom("not supported")) } - fn struct_variant( - self, - _: &'static [&'static str], - _: V, - ) -> Result + fn struct_variant(self, _: &'static [&'static str], _: V) -> Result where V: Visitor<'de>, { @@ -503,9 +503,7 @@ mod tests { use serde::{de, Deserialize}; use super::*; - use crate::path::Path; - use crate::router::Router; - use crate::ResourceDef; + use crate::{path::Path, router::Router, ResourceDef}; #[derive(Deserialize)] struct MyStruct { @@ -572,13 +570,11 @@ mod tests { assert_eq!(s.key, "name"); assert_eq!(s.value, 32); - let s: (String, u8) = - de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); + let s: (String, u8) = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); assert_eq!(s.0, "name"); assert_eq!(s.1, 32); - let res: Vec = - de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); + let res: Vec = de::Deserialize::deserialize(PathDeserializer::new(&path)).unwrap(); assert_eq!(res[0], "name".to_owned()); assert_eq!(res[1], "32".to_owned()); } diff --git a/actix-router/src/lib.rs b/actix-router/src/lib.rs index a02129495..53c0ad82a 100644 --- a/actix-router/src/lib.rs +++ b/actix-router/src/lib.rs @@ -18,13 +18,14 @@ mod router; #[cfg(feature = "http")] mod url; -pub use self::de::PathDeserializer; -pub use self::path::Path; -pub use self::pattern::{IntoPatterns, Patterns}; -pub use self::quoter::Quoter; -pub use self::resource::ResourceDef; -pub use self::resource_path::{Resource, ResourcePath}; -pub use self::router::{ResourceId, Router, RouterBuilder}; - #[cfg(feature = "http")] pub use self::url::Url; +pub use self::{ + de::PathDeserializer, + path::Path, + pattern::{IntoPatterns, Patterns}, + quoter::Quoter, + resource::ResourceDef, + resource_path::{Resource, ResourcePath}, + router::{ResourceId, Router, RouterBuilder}, +}; diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index 34dabcfbe..dc4150ddc 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -1,5 +1,7 @@ -use std::borrow::Cow; -use std::ops::{DerefMut, Index}; +use std::{ + borrow::Cow, + ops::{DerefMut, Index}, +}; use serde::de; diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index c868a3e6f..860993a37 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -1741,9 +1741,7 @@ mod tests { ResourceDef::new("/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}"); // panics - ResourceDef::new( - "/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}/{q}", - ); + ResourceDef::new("/{a}/{b}/{c}/{d}/{e}/{f}/{g}/{h}/{i}/{j}/{k}/{l}/{m}/{n}/{o}/{p}/{q}"); } #[test] diff --git a/actix-router/src/router.rs b/actix-router/src/router.rs index 064c5e904..d31d10ce8 100644 --- a/actix-router/src/router.rs +++ b/actix-router/src/router.rs @@ -117,11 +117,7 @@ where U: Default, { /// Registers resource for specified path. - pub fn path( - &mut self, - path: impl IntoPatterns, - val: T, - ) -> (&mut ResourceDef, &mut T, &mut U) { + pub fn path(&mut self, path: impl IntoPatterns, val: T) -> (&mut ResourceDef, &mut T, &mut U) { self.push(ResourceDef::new(path), val, U::default()) } @@ -142,8 +138,10 @@ where #[cfg(test)] mod tests { - use crate::path::Path; - use crate::router::{ResourceId, Router}; + use crate::{ + path::Path, + router::{ResourceId, Router}, + }; #[allow(clippy::cognitive_complexity)] #[test] diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index 8ae9ea9d8..2920e271d 100644 --- a/actix-router/src/url.rs +++ b/actix-router/src/url.rs @@ -1,6 +1,4 @@ -use crate::ResourcePath; - -use crate::Quoter; +use crate::{Quoter, ResourcePath}; thread_local! { static DEFAULT_QUOTER: Quoter = Quoter::new(b"", b"%/+"); diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 2beb64dca..7781edab4 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -45,8 +45,8 @@ use actix_http::{header::HeaderMap, ws, HttpService, Method, Request, Response}; pub use actix_http_test::unused_addr; use actix_service::{map_config, IntoServiceFactory, ServiceFactory, ServiceFactoryExt as _}; pub use actix_web::test::{ - call_and_read_body, call_and_read_body_json, call_service, init_service, ok_service, - read_body, read_body_json, status_service, TestRequest, + call_and_read_body, call_and_read_body_json, call_service, init_service, ok_service, read_body, + read_body_json, status_service, TestRequest, }; use actix_web::{ body::MessageBody, @@ -159,11 +159,8 @@ where let srv = match srv_cfg.stream { StreamType::Tcp => match srv_cfg.tp { HttpVer::Http1 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -175,11 +172,8 @@ where .tcp() }), HttpVer::Http2 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -191,11 +185,8 @@ where .tcp() }), HttpVer::Both => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -210,11 +201,8 @@ where #[cfg(feature = "openssl")] StreamType::Openssl(acceptor) => match cfg.tp { HttpVer::Http1 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -226,11 +214,8 @@ where .openssl(acceptor.clone()) }), HttpVer::Http2 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -242,11 +227,8 @@ where .openssl(acceptor.clone()) }), HttpVer::Both => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -261,11 +243,8 @@ where #[cfg(feature = "rustls")] StreamType::Rustls(config) => match cfg.tp { HttpVer::Http1 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -277,11 +256,8 @@ where .rustls(config.clone()) }), HttpVer::Http2 => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() @@ -293,11 +269,8 @@ where .rustls(config.clone()) }), HttpVer::Both => builder.listen("test", tcp, move || { - let app_cfg = AppConfig::__priv_test_new( - false, - local_addr.to_string(), - local_addr, - ); + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); let fac = factory() .into_factory() diff --git a/actix-web-actors/src/context.rs b/actix-web-actors/src/context.rs index f7b11c780..be8fd387c 100644 --- a/actix-web-actors/src/context.rs +++ b/actix-web-actors/src/context.rs @@ -1,11 +1,13 @@ -use std::collections::VecDeque; -use std::future::Future; -use std::pin::Pin; -use std::task::{Context, Poll}; +use std::{ + collections::VecDeque, + future::Future, + pin::Pin, + task::{Context, Poll}, +}; -use actix::dev::{AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, ToEnvelope}; -use actix::fut::ActorFuture; use actix::{ + dev::{AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, ToEnvelope}, + fut::ActorFuture, Actor, ActorContext, ActorState, Addr, AsyncContext, Handler, Message, SpawnHandle, }; use actix_web::error::Error; @@ -247,9 +249,11 @@ mod tests { use std::time::Duration; use actix::Actor; - use actix_web::http::StatusCode; - use actix_web::test::{call_service, init_service, read_body, TestRequest}; - use actix_web::{web, App, HttpResponse}; + use actix_web::{ + http::StatusCode, + test::{call_service, init_service, read_body, TestRequest}, + web, App, HttpResponse, + }; use bytes::Bytes; use super::*; diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 731f33f86..6ce3e69a1 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -66,17 +66,14 @@ use std::{ use actix::{ dev::{ - AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, StreamHandler, - ToEnvelope, + AsyncContextParts, ContextFut, ContextParts, Envelope, Mailbox, StreamHandler, ToEnvelope, }, fut::ActorFuture, Actor, ActorContext, ActorState, Addr, AsyncContext, Handler, Message as ActixMessage, SpawnHandle, }; use actix_http::ws::{hash_key, Codec}; -pub use actix_http::ws::{ - CloseCode, CloseReason, Frame, HandshakeError, Message, ProtocolError, -}; +pub use actix_http::ws::{CloseCode, CloseReason, Frame, HandshakeError, Message, ProtocolError}; use actix_web::{ error::{Error, PayloadError}, http::{ @@ -426,16 +423,16 @@ pub fn handshake_with_protocols( }; // check requested protocols - let protocol = - req.headers() - .get(&header::SEC_WEBSOCKET_PROTOCOL) - .and_then(|req_protocols| { - let req_protocols = req_protocols.to_str().ok()?; - req_protocols - .split(',') - .map(|req_p| req_p.trim()) - .find(|req_p| protocols.iter().any(|p| p == req_p)) - }); + let protocol = req + .headers() + .get(&header::SEC_WEBSOCKET_PROTOCOL) + .and_then(|req_protocols| { + let req_protocols = req_protocols.to_str().ok()?; + req_protocols + .split(',') + .map(|req_p| req_p.trim()) + .find(|req_p| protocols.iter().any(|p| p == req_p)) + }); let mut response = HttpResponse::build(StatusCode::SWITCHING_PROTOCOLS) .upgrade("websocket") diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 8b68ea16b..6d6f4f79d 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -153,37 +153,37 @@ pub fn routes(_: TokenStream, input: TokenStream) -> TokenStream { macro_rules! method_macro { ($variant:ident, $method:ident) => { -#[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")] -/// -/// # Syntax -/// ```plain -#[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)] -/// ``` -/// -/// # Attributes -/// - `"path"`: Raw literal string with path for which to register handler. -/// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the function -/// name of handler is used. -/// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`. -/// - `wrap = "Middleware"`: Registers a resource middleware. -/// -/// # Notes -/// Function name can be specified as any expression that is going to be accessible to the -/// generate code, e.g `my_guard` or `my_module::my_guard`. -/// -/// # Examples -/// ``` -/// # use actix_web::HttpResponse; -#[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")] -#[doc = concat!("#[", stringify!($method), r#"("/")]"#)] -/// async fn example() -> HttpResponse { -/// HttpResponse::Ok().finish() -/// } -/// ``` -#[proc_macro_attribute] -pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream { - route::with_method(Some(route::MethodType::$variant), args, input) -} + #[doc = concat!("Creates route handler with `actix_web::guard::", stringify!($variant), "`.")] + /// + /// # Syntax + /// ```plain + #[doc = concat!("#[", stringify!($method), r#"("path"[, attributes])]"#)] + /// ``` + /// + /// # Attributes + /// - `"path"`: Raw literal string with path for which to register handler. + /// - `name = "resource_name"`: Specifies resource name for the handler. If not set, the + /// function name of handler is used. + /// - `guard = "function_name"`: Registers function as guard using `actix_web::guard::fn_guard`. + /// - `wrap = "Middleware"`: Registers a resource middleware. + /// + /// # Notes + /// Function name can be specified as any expression that is going to be accessible to the + /// generate code, e.g `my_guard` or `my_module::my_guard`. + /// + /// # Examples + /// ``` + /// # use actix_web::HttpResponse; + #[doc = concat!("# use actix_web_codegen::", stringify!($method), ";")] + #[doc = concat!("#[", stringify!($method), r#"("/")]"#)] + /// async fn example() -> HttpResponse { + /// HttpResponse::Ok().finish() + /// } + /// ``` + #[proc_macro_attribute] + pub fn $method(args: TokenStream, input: TokenStream) -> TokenStream { + route::with_method(Some(route::MethodType::$variant), args, input) + } }; } diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 0b8bb0f38..e87d37941 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -488,31 +488,32 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream { ast.attrs = others.into_iter().map(Result::unwrap_err).collect(); - let methods = - match methods - .into_iter() - .map(Result::unwrap) - .map(|(method, attr)| { - attr.parse_meta().and_then(|args| { - if let Meta::List(args) = args { - Args::new(args.nested.into_iter().collect(), Some(method)) - } else { - Err(syn::Error::new_spanned(attr, "Invalid input for macro")) - } - }) + let methods = match methods + .into_iter() + .map(Result::unwrap) + .map(|(method, attr)| { + attr.parse_meta().and_then(|args| { + if let Meta::List(args) = args { + Args::new(args.nested.into_iter().collect(), Some(method)) + } else { + Err(syn::Error::new_spanned(attr, "Invalid input for macro")) + } }) - .collect::, _>>() - { - Ok(methods) if methods.is_empty() => return input_and_compile_error( + }) + .collect::, _>>() + { + Ok(methods) if methods.is_empty() => { + return input_and_compile_error( input, syn::Error::new( Span::call_site(), "The #[routes] macro requires at least one `#[(..)]` attribute.", ), - ), - Ok(methods) => methods, - Err(err) => return input_and_compile_error(input, err), - }; + ) + } + Ok(methods) => methods, + Err(err) => return input_and_compile_error(input, err), + }; match Route::multiple(methods, ast) { Ok(route) => route.into_token_stream().into(), diff --git a/actix-web/benches/responder.rs b/actix-web/benches/responder.rs index ac4d18324..c675eadff 100644 --- a/actix-web/benches/responder.rs +++ b/actix-web/benches/responder.rs @@ -99,8 +99,7 @@ fn responder(c: &mut Criterion) { let req = TestRequest::default().to_http_request(); c.bench_function("responder", move |b| { b.iter_custom(|_| { - let responders = - (0..100_000).map(|_| StringResponder(String::from("Hello World!!"))); + let responders = (0..100_000).map(|_| StringResponder(String::from("Hello World!!"))); let start = Instant::now(); let _res = rt.block_on(async { diff --git a/actix-web/benches/service.rs b/actix-web/benches/service.rs index 87e51f170..9b29df8e5 100644 --- a/actix-web/benches/service.rs +++ b/actix-web/benches/service.rs @@ -1,11 +1,12 @@ -use actix_service::Service; -use actix_web::dev::{ServiceRequest, ServiceResponse}; -use actix_web::{web, App, Error, HttpResponse}; -use criterion::{criterion_main, Criterion}; -use std::cell::RefCell; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; -use actix_web::test::{init_service, ok_service, TestRequest}; +use actix_service::Service; +use actix_web::{ + dev::{ServiceRequest, ServiceResponse}, + test::{init_service, ok_service, TestRequest}, + web, App, Error, HttpResponse, +}; +use criterion::{criterion_main, Criterion}; /// Criterion Benchmark for async Service /// Should be used from within criterion group: diff --git a/actix-web/examples/on-connect.rs b/actix-web/examples/on-connect.rs index 0d56a8f25..dc9273b46 100644 --- a/actix-web/examples/on-connect.rs +++ b/actix-web/examples/on-connect.rs @@ -7,8 +7,7 @@ use std::{any::Any, io, net::SocketAddr}; use actix_web::{ - dev::Extensions, rt::net::TcpStream, web, App, HttpRequest, HttpResponse, HttpServer, - Responder, + dev::Extensions, rt::net::TcpStream, web, App, HttpRequest, HttpResponse, HttpServer, Responder, }; #[allow(dead_code)] @@ -24,9 +23,7 @@ async fn route_whoami(req: HttpRequest) -> impl Responder { Some(info) => HttpResponse::Ok().body(format!( "Here is some info about your connection:\n\n{info:#?}", )), - None => { - HttpResponse::InternalServerError().body("Missing expected request extension data") - } + None => HttpResponse::InternalServerError().body("Missing expected request extension data"), } } diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index 353b82b19..a4b576b0e 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -264,12 +264,8 @@ where pub fn default_service(mut self, svc: F) -> Self where F: IntoServiceFactory, - U: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - > + 'static, + U: ServiceFactory + + 'static, U::InitError: fmt::Debug, { let svc = svc diff --git a/actix-web/src/app_service.rs b/actix-web/src/app_service.rs index 0fc856203..513e7a8a1 100644 --- a/actix-web/src/app_service.rs +++ b/actix-web/src/app_service.rs @@ -348,13 +348,17 @@ impl ServiceFactory for AppEntry { #[cfg(test)] mod tests { - use std::sync::atomic::{AtomicBool, Ordering}; - use std::sync::Arc; + use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }; use actix_service::Service; - use crate::test::{init_service, TestRequest}; - use crate::{web, App, HttpResponse}; + use crate::{ + test::{init_service, TestRequest}, + web, App, HttpResponse, + }; struct DropData(Arc); diff --git a/actix-web/src/config.rs b/actix-web/src/config.rs index 11eaf8720..fba0c2717 100644 --- a/actix-web/src/config.rs +++ b/actix-web/src/config.rs @@ -232,12 +232,8 @@ impl ServiceConfig { pub fn default_service(&mut self, f: F) -> &mut Self where F: IntoServiceFactory, - U: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - > + 'static, + U: ServiceFactory + + 'static, U::InitError: std::fmt::Debug, { let svc = f @@ -308,9 +304,11 @@ mod tests { use bytes::Bytes; use super::*; - use crate::http::{Method, StatusCode}; - use crate::test::{assert_body_eq, call_service, init_service, read_body, TestRequest}; - use crate::{web, App, HttpRequest, HttpResponse}; + use crate::{ + http::{Method, StatusCode}, + test::{assert_body_eq, call_service, init_service, read_body, TestRequest}, + web, App, HttpRequest, HttpResponse, + }; // allow deprecated `ServiceConfig::data` #[allow(deprecated)] diff --git a/actix-web/src/data.rs b/actix-web/src/data.rs index 89104a1ac..423dd598c 100644 --- a/actix-web/src/data.rs +++ b/actix-web/src/data.rs @@ -186,12 +186,14 @@ mod tests { #[allow(deprecated)] #[actix_rt::test] async fn test_data_extractor() { - let srv = init_service(App::new().data("TEST".to_string()).service( - web::resource("/").to(|data: web::Data| { - assert_eq!(data.to_lowercase(), "test"); - HttpResponse::Ok() - }), - )) + let srv = init_service( + App::new() + .data("TEST".to_string()) + .service(web::resource("/").to(|data: web::Data| { + assert_eq!(data.to_lowercase(), "test"); + HttpResponse::Ok() + })), + ) .await; let req = TestRequest::default().to_request(); @@ -286,16 +288,17 @@ mod tests { #[allow(deprecated)] #[actix_rt::test] async fn test_override_data() { - let srv = - init_service(App::new().data(1usize).service( - web::resource("/").data(10usize).route(web::get().to( + let srv = init_service( + App::new() + .data(1usize) + .service(web::resource("/").data(10usize).route(web::get().to( |data: web::Data| { assert_eq!(**data, 10); HttpResponse::Ok() }, - )), - )) - .await; + ))), + ) + .await; let req = TestRequest::default().to_request(); let resp = srv.call(req).await.unwrap(); diff --git a/actix-web/src/dev.rs b/actix-web/src/dev.rs index 5c7adfdaf..2a0791a1c 100644 --- a/actix-web/src/dev.rs +++ b/actix-web/src/dev.rs @@ -7,26 +7,25 @@ //! - [`ConnectionInfo`]: Connection information //! - [`PeerAddr`]: Connection information +#[cfg(feature = "__compress")] +pub use actix_http::encoding::Decoder as Decompress; pub use actix_http::{Extensions, Payload, RequestHead, Response, ResponseHead}; +use actix_router::Patterns; pub use actix_router::{Path, ResourceDef, ResourcePath, Url}; pub use actix_server::{Server, ServerHandle}; pub use actix_service::{ always_ready, fn_factory, fn_service, forward_ready, Service, ServiceFactory, Transform, }; -#[cfg(feature = "__compress")] -pub use actix_http::encoding::Decoder as Decompress; - -pub use crate::config::{AppConfig, AppService}; #[doc(hidden)] pub use crate::handler::Handler; -pub use crate::info::{ConnectionInfo, PeerAddr}; -pub use crate::rmap::ResourceMap; -pub use crate::service::{HttpServiceFactory, ServiceRequest, ServiceResponse, WebService}; - -pub use crate::types::{JsonBody, Readlines, UrlEncoded}; - -use actix_router::Patterns; +pub use crate::{ + config::{AppConfig, AppService}, + info::{ConnectionInfo, PeerAddr}, + rmap::ResourceMap, + service::{HttpServiceFactory, ServiceRequest, ServiceResponse, WebService}, + types::{JsonBody, Readlines, UrlEncoded}, +}; pub(crate) fn ensure_leading_slash(mut patterns: Patterns) -> Patterns { match &mut patterns { diff --git a/actix-web/src/error/macros.rs b/actix-web/src/error/macros.rs index 78b1ed9f6..8634557c9 100644 --- a/actix-web/src/error/macros.rs +++ b/actix-web/src/error/macros.rs @@ -42,8 +42,7 @@ macro_rules! downcast_dyn { /// Downcasts generic body to a specific type. #[allow(dead_code)] pub fn downcast_ref(&self) -> Option<&T> { - if self.__private_get_type_id__(PrivateHelper(())).0 - == std::any::TypeId::of::() + if self.__private_get_type_id__(PrivateHelper(())).0 == std::any::TypeId::of::() { // SAFETY: external crates cannot override the default // implementation of `__private_get_type_id__`, since @@ -59,8 +58,7 @@ macro_rules! downcast_dyn { /// Downcasts a generic body to a mutable specific type. #[allow(dead_code)] pub fn downcast_mut(&mut self) -> Option<&mut T> { - if self.__private_get_type_id__(PrivateHelper(())).0 - == std::any::TypeId::of::() + if self.__private_get_type_id__(PrivateHelper(())).0 == std::any::TypeId::of::() { // SAFETY: external crates cannot override the default // implementation of `__private_get_type_id__`, since @@ -76,7 +74,8 @@ macro_rules! downcast_dyn { }; } -pub(crate) use {downcast_dyn, downcast_get_type_id}; +pub(crate) use downcast_dyn; +pub(crate) use downcast_get_type_id; #[cfg(test)] mod tests { diff --git a/actix-web/src/error/mod.rs b/actix-web/src/error/mod.rs index 604c539f3..91a6bcc3f 100644 --- a/actix-web/src/error/mod.rs +++ b/actix-web/src/error/mod.rs @@ -5,14 +5,10 @@ // expanded manually. // // See -pub use actix_http::error::{ - ContentTypeError, DispatchError, HttpError, ParseError, PayloadError, -}; - +pub use actix_http::error::{ContentTypeError, DispatchError, HttpError, ParseError, PayloadError}; use derive_more::{Display, Error, From}; use serde_json::error::Error as JsonError; -use serde_urlencoded::de::Error as FormDeError; -use serde_urlencoded::ser::Error as FormError; +use serde_urlencoded::{de::Error as FormDeError, ser::Error as FormError}; use url::ParseError as UrlParseError; use crate::http::StatusCode; @@ -23,10 +19,8 @@ mod internal; mod macros; mod response_error; -pub use self::error::Error; -pub use self::internal::*; -pub use self::response_error::ResponseError; -pub(crate) use macros::{downcast_dyn, downcast_get_type_id}; +pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id}; +pub use self::{error::Error, internal::*, response_error::ResponseError}; /// A convenience [`Result`](std::result::Result) for Actix Web operations. /// diff --git a/actix-web/src/extract.rs b/actix-web/src/extract.rs index 84904a9eb..a2afd3827 100644 --- a/actix-web/src/extract.rs +++ b/actix-web/src/extract.rs @@ -429,8 +429,10 @@ mod tests { use serde::Deserialize; use super::*; - use crate::test::TestRequest; - use crate::types::{Form, FormConfig}; + use crate::{ + test::TestRequest, + types::{Form, FormConfig}, + }; #[derive(Deserialize, Debug, PartialEq)] struct Info { diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index 3aca11df2..35294a3c4 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -61,8 +61,10 @@ use crate::{http::header::Header, service::ServiceRequest, HttpMessage as _}; mod acceptable; mod host; -pub use self::acceptable::Acceptable; -pub use self::host::{Host, HostGuard}; +pub use self::{ + acceptable::Acceptable, + host::{Host, HostGuard}, +}; /// Provides access to request parts that are useful during routing. #[derive(Debug)] diff --git a/actix-web/src/http/header/accept_encoding.rs b/actix-web/src/http/header/accept_encoding.rs index 8c35179b6..715126a03 100644 --- a/actix-web/src/http/header/accept_encoding.rs +++ b/actix-web/src/http/header/accept_encoding.rs @@ -94,10 +94,7 @@ impl AcceptEncoding { /// includes the server's supported encodings in the body plus a [`Vary`] header. /// /// [`Vary`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary - pub fn negotiate<'a>( - &self, - supported: impl Iterator, - ) -> Option { + pub fn negotiate<'a>(&self, supported: impl Iterator) -> Option { // 1. If no Accept-Encoding field is in the request, any content-coding is considered // acceptable by the user agent. @@ -375,9 +372,7 @@ mod tests { Some(Encoding::deflate()) ); assert_eq!( - test.negotiate( - [Encoding::gzip(), Encoding::deflate(), Encoding::identity()].iter() - ), + test.negotiate([Encoding::gzip(), Encoding::deflate(), Encoding::identity()].iter()), Some(Encoding::gzip()) ); assert_eq!( diff --git a/actix-web/src/http/header/content_disposition.rs b/actix-web/src/http/header/content_disposition.rs index f743302a2..0606f5aef 100644 --- a/actix-web/src/http/header/content_disposition.rs +++ b/actix-web/src/http/header/content_disposition.rs @@ -592,9 +592,8 @@ mod tests { fn test_from_raw_basic() { assert!(ContentDisposition::from_raw(&HeaderValue::from_static("")).is_err()); - let a = HeaderValue::from_static( - "form-data; dummy=3; name=upload; filename=\"sample.png\"", - ); + let a = + HeaderValue::from_static("form-data; dummy=3; name=upload; filename=\"sample.png\""); let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap(); let b = ContentDisposition { disposition: DispositionType::FormData, @@ -648,8 +647,8 @@ mod tests { charset: Charset::Ext(String::from("UTF-8")), language_tag: None, value: vec![ - 0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', - b'a', b't', b'e', b's', + 0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', b'a', + b't', b'e', b's', ], })], }; @@ -665,8 +664,8 @@ mod tests { charset: Charset::Ext(String::from("UTF-8")), language_tag: None, value: vec![ - 0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', - b'a', b't', b'e', b's', + 0xc2, 0xa3, 0x20, b'a', b'n', b'd', 0x20, 0xe2, 0x82, 0xac, 0x20, b'r', b'a', + b't', b'e', b's', ], })], }; @@ -742,8 +741,8 @@ mod tests { }; assert_eq!(a, b); - let a = ContentDisposition::from_raw(&HeaderValue::from_static("unknown-disp-param")) - .unwrap(); + let a = + ContentDisposition::from_raw(&HeaderValue::from_static("unknown-disp-param")).unwrap(); let b = ContentDisposition { disposition: DispositionType::Ext(String::from("unknown-disp-param")), parameters: vec![], @@ -782,8 +781,7 @@ mod tests { Mainstream browsers like Firefox (gecko) and Chrome use UTF-8 directly as above. (And now, only UTF-8 is handled by this implementation.) */ - let a = - HeaderValue::from_str("form-data; name=upload; filename=\"文件.webp\"").unwrap(); + let a = HeaderValue::from_str("form-data; name=upload; filename=\"文件.webp\"").unwrap(); let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap(); let b = ContentDisposition { disposition: DispositionType::FormData, @@ -803,9 +801,7 @@ mod tests { disposition: DispositionType::FormData, parameters: vec![ DispositionParam::Name(String::from("upload")), - DispositionParam::Filename(String::from( - "余固知謇謇之為患兮,忍而不能舍也.pptx", - )), + DispositionParam::Filename(String::from("余固知謇謇之為患兮,忍而不能舍也.pptx")), ], }; assert_eq!(a, b); @@ -870,8 +866,7 @@ mod tests { }; assert_eq!(a, b); - let a = - HeaderValue::from_static("form-data; name=photo; filename=\"%74%65%73%74.png\""); + let a = HeaderValue::from_static("form-data; name=photo; filename=\"%74%65%73%74.png\""); let a: ContentDisposition = ContentDisposition::from_raw(&a).unwrap(); let b = ContentDisposition { disposition: DispositionType::FormData, diff --git a/actix-web/src/http/header/content_range.rs b/actix-web/src/http/header/content_range.rs index bcbe77e66..8befffd95 100644 --- a/actix-web/src/http/header/content_range.rs +++ b/actix-web/src/http/header/content_range.rs @@ -127,8 +127,7 @@ impl FromStr for ContentRangeSpec { fn from_str(s: &str) -> Result { let res = match split_in_two(s, ' ') { Some(("bytes", resp)) => { - let (range, instance_length) = - split_in_two(resp, '/').ok_or(ParseError::Header)?; + let (range, instance_length) = split_in_two(resp, '/').ok_or(ParseError::Header)?; let instance_length = if instance_length == "*" { None diff --git a/actix-web/src/http/header/content_type.rs b/actix-web/src/http/header/content_type.rs index 1fc75d0e2..41c0c1fc9 100644 --- a/actix-web/src/http/header/content_type.rs +++ b/actix-web/src/http/header/content_type.rs @@ -1,6 +1,7 @@ -use super::CONTENT_TYPE; use mime::Mime; +use super::CONTENT_TYPE; + crate::http::header::common_header! { /// `Content-Type` header, defined /// in [RFC 7231 §3.1.1.5](https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.5) diff --git a/actix-web/src/http/header/date.rs b/actix-web/src/http/header/date.rs index f62740211..a8ac65660 100644 --- a/actix-web/src/http/header/date.rs +++ b/actix-web/src/http/header/date.rs @@ -1,6 +1,7 @@ -use super::{HttpDate, DATE}; use std::time::SystemTime; +use super::{HttpDate, DATE}; + crate::http::header::common_header! { /// `Date` header, defined /// in [RFC 7231 §7.1.1.2](https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.2) diff --git a/actix-web/src/http/header/entity.rs b/actix-web/src/http/header/entity.rs index 0eaa12b5d..a5ef3c5b7 100644 --- a/actix-web/src/http/header/entity.rs +++ b/actix-web/src/http/header/entity.rs @@ -152,9 +152,7 @@ impl FromStr for EntityTag { return Err(crate::error::ParseError::Header); } // The etag is weak if its first char is not a DQUOTE. - if slice.len() >= 2 - && slice.starts_with('"') - && check_slice_validity(&slice[1..length - 1]) + if slice.len() >= 2 && slice.starts_with('"') && check_slice_validity(&slice[1..length - 1]) { // No need to check if the last char is a DQUOTE, // we already did that above. diff --git a/actix-web/src/http/header/if_range.rs b/actix-web/src/http/header/if_range.rs index eb3632a4d..d7375c4c5 100644 --- a/actix-web/src/http/header/if_range.rs +++ b/actix-web/src/http/header/if_range.rs @@ -4,9 +4,7 @@ use super::{ from_one_raw_str, EntityTag, Header, HeaderName, HeaderValue, HttpDate, InvalidHeaderValue, TryIntoHeaderValue, Writer, }; -use crate::error::ParseError; -use crate::http::header; -use crate::HttpMessage; +use crate::{error::ParseError, http::header, HttpMessage}; /// `If-Range` header, defined /// in [RFC 7233 §3.2](https://datatracker.ietf.org/doc/html/rfc7233#section-3.2) diff --git a/actix-web/src/http/header/macros.rs b/actix-web/src/http/header/macros.rs index b40eca03b..d9755e15e 100644 --- a/actix-web/src/http/header/macros.rs +++ b/actix-web/src/http/header/macros.rs @@ -314,7 +314,7 @@ macro_rules! common_header { }; } -pub(crate) use {common_header, common_header_test_module}; - +pub(crate) use common_header; #[cfg(test)] pub(crate) use common_header_test; +pub(crate) use common_header_test_module; diff --git a/actix-web/src/http/header/mod.rs b/actix-web/src/http/header/mod.rs index 9807d5f5e..65c5c88a0 100644 --- a/actix-web/src/http/header/mod.rs +++ b/actix-web/src/http/header/mod.rs @@ -6,8 +6,6 @@ use std::fmt; -use bytes::{Bytes, BytesMut}; - // re-export from actix-http // - header name / value types // - relevant traits for converting to header name / value @@ -16,6 +14,7 @@ use bytes::{Bytes, BytesMut}; // - the few typed headers from actix-http // - header parsing utils pub use actix_http::header::*; +use bytes::{Bytes, BytesMut}; mod accept; mod accept_charset; @@ -43,32 +42,33 @@ mod preference; mod range; #[cfg(test)] -pub(crate) use macros::common_header_test; -pub(crate) use macros::{common_header, common_header_test_module}; - -pub use self::accept::Accept; -pub use self::accept_charset::AcceptCharset; -pub use self::accept_encoding::AcceptEncoding; -pub use self::accept_language::AcceptLanguage; -pub use self::allow::Allow; -pub use self::cache_control::{CacheControl, CacheDirective}; -pub use self::content_disposition::{ContentDisposition, DispositionParam, DispositionType}; -pub use self::content_language::ContentLanguage; -pub use self::content_range::{ContentRange, ContentRangeSpec}; -pub use self::content_type::ContentType; -pub use self::date::Date; -pub use self::encoding::Encoding; -pub use self::entity::EntityTag; -pub use self::etag::ETag; -pub use self::expires::Expires; -pub use self::if_match::IfMatch; -pub use self::if_modified_since::IfModifiedSince; -pub use self::if_none_match::IfNoneMatch; -pub use self::if_range::IfRange; -pub use self::if_unmodified_since::IfUnmodifiedSince; -pub use self::last_modified::LastModified; -pub use self::preference::Preference; -pub use self::range::{ByteRangeSpec, Range}; +pub(crate) use self::macros::common_header_test; +pub(crate) use self::macros::{common_header, common_header_test_module}; +pub use self::{ + accept::Accept, + accept_charset::AcceptCharset, + accept_encoding::AcceptEncoding, + accept_language::AcceptLanguage, + allow::Allow, + cache_control::{CacheControl, CacheDirective}, + content_disposition::{ContentDisposition, DispositionParam, DispositionType}, + content_language::ContentLanguage, + content_range::{ContentRange, ContentRangeSpec}, + content_type::ContentType, + date::Date, + encoding::Encoding, + entity::EntityTag, + etag::ETag, + expires::Expires, + if_match::IfMatch, + if_modified_since::IfModifiedSince, + if_none_match::IfNoneMatch, + if_range::IfRange, + if_unmodified_since::IfUnmodifiedSince, + last_modified::LastModified, + preference::Preference, + range::{ByteRangeSpec, Range}, +}; /// Format writer ([`fmt::Write`]) for a [`BytesMut`]. #[derive(Debug, Default)] diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index 57cdaea69..e982a43b1 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -74,6 +74,11 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +pub use actix_http::{body, HttpMessage}; +#[cfg(feature = "cookies")] +#[doc(inline)] +pub use cookie; + mod app; mod app_service; mod config; @@ -102,25 +107,21 @@ pub mod test; pub(crate) mod types; pub mod web; -pub use crate::app::App; #[doc(inline)] pub use crate::error::Result; -pub use crate::error::{Error, ResponseError}; -pub use crate::extract::FromRequest; -pub use crate::handler::Handler; -pub use crate::request::HttpRequest; -pub use crate::resource::Resource; -pub use crate::response::{CustomizeResponder, HttpResponse, HttpResponseBuilder, Responder}; -pub use crate::route::Route; -pub use crate::scope::Scope; -pub use crate::server::HttpServer; -pub use crate::types::Either; - -pub use actix_http::{body, HttpMessage}; - -#[cfg(feature = "cookies")] -#[doc(inline)] -pub use cookie; +pub use crate::{ + app::App, + error::{Error, ResponseError}, + extract::FromRequest, + handler::Handler, + request::HttpRequest, + resource::Resource, + response::{CustomizeResponder, HttpResponse, HttpResponseBuilder, Responder}, + route::Route, + scope::Scope, + server::HttpServer, + types::Either, +}; macro_rules! codegen_reexport { ($name:ident) => { diff --git a/actix-web/src/middleware/compat.rs b/actix-web/src/middleware/compat.rs index ee8b8a498..7df510a5c 100644 --- a/actix-web/src/middleware/compat.rs +++ b/actix-web/src/middleware/compat.rs @@ -146,10 +146,9 @@ mod tests { // easier to code when cookies feature is disabled #![allow(unused_imports)] - use super::*; - use actix_service::IntoService; + use super::*; use crate::{ dev::ServiceRequest, http::StatusCode, @@ -207,9 +206,9 @@ mod tests { #[actix_rt::test] async fn test_condition_scope_middleware() { let srv = |req: ServiceRequest| { - Box::pin(async move { - Ok(req.into_response(HttpResponse::InternalServerError().finish())) - }) + Box::pin( + async move { Ok(req.into_response(HttpResponse::InternalServerError().finish())) }, + ) }; let logger = Logger::default(); diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index 051a0c6b3..e640bba08 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -540,21 +540,17 @@ mod tests { let mw_server = make_mw(StatusCode::INTERNAL_SERVER_ERROR).await; let mw_client = make_mw(StatusCode::BAD_REQUEST).await; - let resp = - test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); - let resp = - test::call_service(&mw_server, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_server, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); } #[actix_rt::test] async fn default_handlers_separate_client_server() { #[allow(clippy::unnecessary_wraps)] - fn error_handler_client( - mut res: ServiceResponse, - ) -> Result> { + fn error_handler_client(mut res: ServiceResponse) -> Result> { res.response_mut() .headers_mut() .insert(CONTENT_TYPE, HeaderValue::from_static("0001")); @@ -562,9 +558,7 @@ mod tests { } #[allow(clippy::unnecessary_wraps)] - fn error_handler_server( - mut res: ServiceResponse, - ) -> Result> { + fn error_handler_server(mut res: ServiceResponse) -> Result> { res.response_mut() .headers_mut() .insert(CONTENT_TYPE, HeaderValue::from_static("0002")); @@ -582,21 +576,17 @@ mod tests { let mw_server = make_mw(StatusCode::INTERNAL_SERVER_ERROR).await; let mw_client = make_mw(StatusCode::BAD_REQUEST).await; - let resp = - test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); - let resp = - test::call_service(&mw_server, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_server, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0002"); } #[actix_rt::test] async fn default_handlers_specialization() { #[allow(clippy::unnecessary_wraps)] - fn error_handler_client( - mut res: ServiceResponse, - ) -> Result> { + fn error_handler_client(mut res: ServiceResponse) -> Result> { res.response_mut() .headers_mut() .insert(CONTENT_TYPE, HeaderValue::from_static("0001")); @@ -624,12 +614,10 @@ mod tests { let mw_client = make_mw(StatusCode::BAD_REQUEST).await; let mw_specific = make_mw(StatusCode::UNPROCESSABLE_ENTITY).await; - let resp = - test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_client, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); - let resp = - test::call_service(&mw_specific, TestRequest::default().to_srv_request()).await; + let resp = test::call_service(&mw_specific, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0003"); } } diff --git a/actix-web/src/middleware/logger.rs b/actix-web/src/middleware/logger.rs index 0207798ae..06d26617a 100644 --- a/actix-web/src/middleware/logger.rs +++ b/actix-web/src/middleware/logger.rs @@ -489,12 +489,8 @@ impl Format { unreachable!("regex and code mismatch") } } - "i" => { - FormatText::RequestHeader(HeaderName::try_from(key.as_str()).unwrap()) - } - "o" => { - FormatText::ResponseHeader(HeaderName::try_from(key.as_str()).unwrap()) - } + "i" => FormatText::RequestHeader(HeaderName::try_from(key.as_str()).unwrap()), + "o" => FormatText::ResponseHeader(HeaderName::try_from(key.as_str()).unwrap()), "e" => FormatText::EnvironHeader(key.as_str().to_owned()), "xi" => FormatText::CustomRequest(key.as_str().to_owned(), None), "xo" => FormatText::CustomResponse(key.as_str().to_owned(), None), @@ -710,9 +706,7 @@ impl FormatText { } /// Converter to get a String from something that writes to a Formatter. -pub(crate) struct FormatDisplay<'a>( - &'a dyn Fn(&mut fmt::Formatter<'_>) -> Result<(), fmt::Error>, -); +pub(crate) struct FormatDisplay<'a>(&'a dyn Fn(&mut fmt::Formatter<'_>) -> Result<(), fmt::Error>); impl<'a> fmt::Display for FormatDisplay<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index 0a61ad6cb..eb3550b52 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -9,14 +9,16 @@ mod logger; mod noop; mod normalize; -pub use self::compat::Compat; -pub use self::condition::Condition; -pub use self::default_headers::DefaultHeaders; -pub use self::err_handlers::{ErrorHandlerResponse, ErrorHandlers}; -pub use self::logger::Logger; #[cfg(test)] pub(crate) use self::noop::Noop; -pub use self::normalize::{NormalizePath, TrailingSlash}; +pub use self::{ + compat::Compat, + condition::Condition, + default_headers::DefaultHeaders, + err_handlers::{ErrorHandlerResponse, ErrorHandlers}, + logger::Logger, + normalize::{NormalizePath, TrailingSlash}, +}; #[cfg(feature = "__compress")] mod compress; @@ -26,9 +28,8 @@ pub use self::compress::Compress; #[cfg(test)] mod tests { - use crate::{http::StatusCode, App}; - use super::*; + use crate::{http::StatusCode, App}; #[test] fn common_combinations() { diff --git a/actix-web/src/redirect.rs b/actix-web/src/redirect.rs index 5611cc368..f9e9f2d7a 100644 --- a/actix-web/src/redirect.rs +++ b/actix-web/src/redirect.rs @@ -181,9 +181,8 @@ impl Responder for Redirect { #[cfg(test)] mod tests { - use crate::{dev::Service, http::StatusCode, test, App}; - use super::*; + use crate::{dev::Service, http::StatusCode, test, App}; #[actix_rt::test] async fn absolute_redirects() { diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index 16a947b65..543c9dfbe 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -653,13 +653,13 @@ mod tests { #[actix_rt::test] async fn test_drop_http_request_pool() { - let srv = init_service(App::new().service(web::resource("/").to( - |req: HttpRequest| { + let srv = init_service( + App::new().service(web::resource("/").to(|req: HttpRequest| { HttpResponse::Ok() .insert_header(("pool_cap", req.app_state().pool().cap)) .finish() - }, - ))) + })), + ) .await; let req = TestRequest::default().to_request(); @@ -807,10 +807,7 @@ mod tests { web::scope("/user/{id}") .service(web::resource("/profile").route(web::get().to( move |req: HttpRequest| { - assert_eq!( - req.match_pattern(), - Some("/user/{id}/profile".to_owned()) - ); + assert_eq!(req.match_pattern(), Some("/user/{id}/profile".to_owned())); HttpResponse::Ok().finish() }, diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 5d2c9706a..95185b80a 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -353,12 +353,8 @@ where pub fn default_service(mut self, f: F) -> Self where F: IntoServiceFactory, - U: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - > + 'static, + U: ServiceFactory + + 'static, U::InitError: fmt::Debug, { // create and configure default resource @@ -625,10 +621,8 @@ mod tests { let fut = srv.call(req); async { fut.await.map(|mut res| { - res.headers_mut().insert( - header::CONTENT_TYPE, - HeaderValue::from_static("0001"), - ); + res.headers_mut() + .insert(header::CONTENT_TYPE, HeaderValue::from_static("0001")); res }) } @@ -660,12 +654,9 @@ mod tests { #[actix_rt::test] async fn test_pattern() { - let srv = init_service( - App::new().service( - web::resource(["/test", "/test2"]) - .to(|| async { Ok::<_, Error>(HttpResponse::Ok()) }), - ), - ) + let srv = init_service(App::new().service( + web::resource(["/test", "/test2"]).to(|| async { Ok::<_, Error>(HttpResponse::Ok()) }), + )) .await; let req = TestRequest::with_uri("/test").to_request(); let resp = call_service(&srv, req).await; @@ -804,17 +795,18 @@ mod tests { #[allow(deprecated)] #[actix_rt::test] async fn test_data_default_service() { - let srv = init_service( - App::new().data(1usize).service( - web::resource("/test") - .data(10usize) - .default_service(web::to(|data: web::Data| { - assert_eq!(**data, 10); - HttpResponse::Ok() - })), - ), - ) - .await; + let srv = + init_service( + App::new().data(1usize).service( + web::resource("/test") + .data(10usize) + .default_service(web::to(|data: web::Data| { + assert_eq!(**data, 10); + HttpResponse::Ok() + })), + ), + ) + .await; let req = TestRequest::get().uri("/test").to_request(); let resp = call_service(&srv, req).await; diff --git a/actix-web/src/response/builder.rs b/actix-web/src/response/builder.rs index a7f3f36c3..2c06941cd 100644 --- a/actix-web/src/response/builder.rs +++ b/actix-web/src/response/builder.rs @@ -14,8 +14,10 @@ use crate::{ body::{BodyStream, BoxBody, MessageBody}, dev::Extensions, error::{Error, JsonPayloadError}, - http::header::{self, HeaderName, TryIntoHeaderPair, TryIntoHeaderValue}, - http::{ConnectionType, StatusCode}, + http::{ + header::{self, HeaderName, TryIntoHeaderPair, TryIntoHeaderValue}, + ConnectionType, StatusCode, + }, BoxError, HttpRequest, HttpResponse, Responder, }; @@ -472,9 +474,8 @@ mod tests { #[actix_rt::test] async fn test_serde_json_in_body() { - let resp = HttpResponse::Ok().body( - serde_json::to_vec(&serde_json::json!({ "test-key": "test-value" })).unwrap(), - ); + let resp = HttpResponse::Ok() + .body(serde_json::to_vec(&serde_json::json!({ "test-key": "test-value" })).unwrap()); assert_eq!( body::to_bytes(resp.into_body()).await.unwrap().as_ref(), diff --git a/actix-web/src/response/customize_responder.rs b/actix-web/src/response/customize_responder.rs index f6f4b9236..aad0039e0 100644 --- a/actix-web/src/response/customize_responder.rs +++ b/actix-web/src/response/customize_responder.rs @@ -1,5 +1,7 @@ use actix_http::{ - body::EitherBody, error::HttpError, header::HeaderMap, header::TryIntoHeaderPair, + body::EitherBody, + error::HttpError, + header::{HeaderMap, TryIntoHeaderPair}, StatusCode, }; @@ -168,9 +170,8 @@ where #[cfg(test)] mod tests { - use bytes::Bytes; - use actix_http::body::to_bytes; + use bytes::Bytes; use super::*; use crate::{ diff --git a/actix-web/src/response/http_codes.rs b/actix-web/src/response/http_codes.rs index 986735346..2ac83046a 100644 --- a/actix-web/src/response/http_codes.rs +++ b/actix-web/src/response/http_codes.rs @@ -87,8 +87,7 @@ impl HttpResponse { #[cfg(test)] mod tests { - use crate::http::StatusCode; - use crate::HttpResponse; + use crate::{http::StatusCode, HttpResponse}; #[test] fn test_build() { diff --git a/actix-web/src/response/mod.rs b/actix-web/src/response/mod.rs index 977147104..11fd28301 100644 --- a/actix-web/src/response/mod.rs +++ b/actix-web/src/response/mod.rs @@ -5,10 +5,9 @@ mod responder; #[allow(clippy::module_inception)] mod response; -pub use self::builder::HttpResponseBuilder; -pub use self::customize_responder::CustomizeResponder; -pub use self::responder::Responder; -pub use self::response::HttpResponse; - #[cfg(feature = "cookies")] pub use self::response::CookieIter; +pub use self::{ + builder::HttpResponseBuilder, customize_responder::CustomizeResponder, responder::Responder, + response::HttpResponse, +}; diff --git a/actix-web/src/response/responder.rs b/actix-web/src/response/responder.rs index 965163a1f..7d0b0e585 100644 --- a/actix-web/src/response/responder.rs +++ b/actix-web/src/response/responder.rs @@ -186,11 +186,10 @@ impl_into_string_responder!(Cow<'_, str>); #[cfg(test)] pub(crate) mod tests { + use actix_http::body::to_bytes; use actix_service::Service; use bytes::{Bytes, BytesMut}; - use actix_http::body::to_bytes; - use super::*; use crate::{ error, diff --git a/actix-web/src/response/response.rs b/actix-web/src/response/response.rs index ead8badba..fbd87e10c 100644 --- a/actix-web/src/response/response.rs +++ b/actix-web/src/response/response.rs @@ -8,7 +8,6 @@ use actix_http::{ header::HeaderMap, Extensions, Response, ResponseHead, StatusCode, }; - #[cfg(feature = "cookies")] use { actix_http::{ diff --git a/actix-web/src/route.rs b/actix-web/src/route.rs index b37128f2c..674d0082a 100644 --- a/actix-web/src/route.rs +++ b/actix-web/src/route.rs @@ -290,31 +290,32 @@ mod tests { #[actix_rt::test] async fn test_route() { - let srv = init_service( - App::new() - .service( - web::resource("/test") - .route(web::get().to(HttpResponse::Ok)) - .route(web::put().to(|| async { - Err::(error::ErrorBadRequest("err")) - })) - .route(web::post().to(|| async { - sleep(Duration::from_millis(100)).await; - Ok::<_, Infallible>(HttpResponse::Created()) - })) - .route(web::delete().to(|| async { - sleep(Duration::from_millis(100)).await; - Err::(error::ErrorBadRequest("err")) - })), - ) - .service(web::resource("/json").route(web::get().to(|| async { - sleep(Duration::from_millis(25)).await; - web::Json(MyObject { - name: "test".to_string(), - }) - }))), - ) - .await; + let srv = + init_service( + App::new() + .service( + web::resource("/test") + .route(web::get().to(HttpResponse::Ok)) + .route(web::put().to(|| async { + Err::(error::ErrorBadRequest("err")) + })) + .route(web::post().to(|| async { + sleep(Duration::from_millis(100)).await; + Ok::<_, Infallible>(HttpResponse::Created()) + })) + .route(web::delete().to(|| async { + sleep(Duration::from_millis(100)).await; + Err::(error::ErrorBadRequest("err")) + })), + ) + .service(web::resource("/json").route(web::get().to(|| async { + sleep(Duration::from_millis(25)).await; + web::Json(MyObject { + name: "test".to_string(), + }) + }))), + ) + .await; let req = TestRequest::with_uri("/test") .method(Method::GET) diff --git a/actix-web/src/rt.rs b/actix-web/src/rt.rs index 7973da73c..629ffe3a0 100644 --- a/actix-web/src/rt.rs +++ b/actix-web/src/rt.rs @@ -66,8 +66,7 @@ // - Re-export but hide the runtime macros because they won't work directly but are required for // `#[actix_web::main]` and `#[actix_web::test]` to work. -pub use actix_rt::{net, pin, signal, spawn, task, time, Runtime, System, SystemRunner}; - #[cfg(feature = "macros")] #[doc(hidden)] pub use actix_macros::{main, test}; +pub use actix_rt::{net, pin, signal, spawn, task, time, Runtime, System, SystemRunner}; diff --git a/actix-web/src/scope.rs b/actix-web/src/scope.rs index 9af05674b..e7c4e047a 100644 --- a/actix-web/src/scope.rs +++ b/actix-web/src/scope.rs @@ -3,8 +3,8 @@ use std::{cell::RefCell, fmt, future::Future, mem, rc::Rc}; use actix_http::{body::MessageBody, Extensions}; use actix_router::{ResourceDef, Router}; use actix_service::{ - apply, apply_fn_factory, boxed, IntoServiceFactory, Service, ServiceFactory, - ServiceFactoryExt, Transform, + apply, apply_fn_factory, boxed, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt, + Transform, }; use futures_core::future::LocalBoxFuture; use futures_util::future::join_all; @@ -273,12 +273,8 @@ where pub fn default_service(mut self, f: F) -> Self where F: IntoServiceFactory, - U: ServiceFactory< - ServiceRequest, - Config = (), - Response = ServiceResponse, - Error = Error, - > + 'static, + U: ServiceFactory + + 'static, U::InitError: fmt::Debug, { // create and configure default resource @@ -604,11 +600,11 @@ mod tests { #[actix_rt::test] async fn test_scope() { - let srv = - init_service(App::new().service( - web::scope("/app").service(web::resource("/path1").to(HttpResponse::Ok)), - )) - .await; + let srv = init_service( + App::new() + .service(web::scope("/app").service(web::resource("/path1").to(HttpResponse::Ok))), + ) + .await; let req = TestRequest::with_uri("/app/path1").to_request(); let resp = srv.call(req).await.unwrap(); @@ -638,8 +634,7 @@ mod tests { #[actix_rt::test] async fn test_scope_root2() { let srv = init_service( - App::new() - .service(web::scope("/app/").service(web::resource("").to(HttpResponse::Ok))), + App::new().service(web::scope("/app/").service(web::resource("").to(HttpResponse::Ok))), ) .await; @@ -784,10 +779,11 @@ mod tests { #[actix_rt::test] async fn test_nested_scope_no_slash() { - let srv = init_service(App::new().service(web::scope("/app").service( - web::scope("t1").service(web::resource("/path1").to(HttpResponse::Created)), - ))) - .await; + let srv = + init_service(App::new().service(web::scope("/app").service( + web::scope("t1").service(web::resource("/path1").to(HttpResponse::Created)), + ))) + .await; let req = TestRequest::with_uri("/app/t1/path1").to_request(); let resp = srv.call(req).await.unwrap(); @@ -845,12 +841,9 @@ mod tests { #[actix_rt::test] async fn test_nested_scope_with_variable_segment() { let srv = init_service(App::new().service(web::scope("/app").service( - web::scope("/{project_id}").service(web::resource("/path1").to( - |r: HttpRequest| { - HttpResponse::Created() - .body(format!("project: {}", &r.match_info()["project_id"])) - }, - )), + web::scope("/{project_id}").service(web::resource("/path1").to(|r: HttpRequest| { + HttpResponse::Created().body(format!("project: {}", &r.match_info()["project_id"])) + })), ))) .await; @@ -1065,15 +1058,16 @@ mod tests { #[allow(deprecated)] #[actix_rt::test] async fn test_override_data_default_service() { - let srv = init_service(App::new().data(1usize).service( - web::scope("app").data(10usize).default_service(web::to( - |data: web::Data| { - assert_eq!(**data, 10); - HttpResponse::Ok() - }, - )), - )) - .await; + let srv = + init_service(App::new().data(1usize).service( + web::scope("app").data(10usize).default_service(web::to( + |data: web::Data| { + assert_eq!(**data, 10); + HttpResponse::Ok() + }, + )), + )) + .await; let req = TestRequest::with_uri("/app/t").to_request(); let resp = call_service(&srv, req).await; @@ -1150,11 +1144,11 @@ mod tests { #[actix_rt::test] async fn test_url_for_nested() { let 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| { + 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())) - }), - )), + }, + ))), ))) .await; diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index c11d0ef53..b96a84939 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -7,20 +7,18 @@ use std::{ time::Duration, }; +#[cfg(any(feature = "openssl", feature = "rustls"))] +use actix_http::TlsAcceptorConfig; use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response}; use actix_server::{Server, ServerBuilder}; use actix_service::{ map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _, }; - #[cfg(feature = "openssl")] use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder}; #[cfg(feature = "rustls")] use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig; -#[cfg(any(feature = "openssl", feature = "rustls"))] -use actix_http::TlsAcceptorConfig; - use crate::{config::AppConfig, Error}; struct Socket { @@ -437,9 +435,8 @@ where .local_addr(addr); if let Some(handler) = on_connect_fn.clone() { - svc = svc.on_connect_ext(move |io: &_, ext: _| { - (handler)(io as &dyn Any, ext) - }) + svc = + svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)) }; let fac = factory() @@ -481,9 +478,8 @@ where .local_addr(addr); if let Some(handler) = on_connect_fn.clone() { - svc = svc.on_connect_ext(move |io: &_, ext: _| { - (handler)(io as &dyn Any, ext) - }) + svc = + svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)) }; let fac = factory() @@ -715,8 +711,7 @@ where .client_disconnect_timeout(c.client_disconnect_timeout); if let Some(handler) = on_connect_fn.clone() { - svc = svc - .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)); + svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)); } let fac = factory() @@ -759,10 +754,7 @@ where } /// Bind TCP listeners to socket addresses resolved from `addrs` with options. -fn bind_addrs( - addrs: impl net::ToSocketAddrs, - backlog: u32, -) -> io::Result> { +fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result> { let mut err = None; let mut success = false; let mut sockets = Vec::new(); diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index f7692ce16..0e17c9949 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -696,30 +696,36 @@ service_tuple! { A B C D E F G H I J K L } #[cfg(test)] mod tests { - use super::*; - use crate::test::{self, init_service, TestRequest}; - use crate::{guard, http, web, App, HttpResponse}; use actix_service::Service; use actix_utils::future::ok; + use super::*; + use crate::{ + guard, http, + test::{self, init_service, TestRequest}, + web, App, HttpResponse, + }; + #[actix_rt::test] async fn test_service() { - let srv = init_service( - App::new().service(web::service("/test").name("test").finish( - |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())), - )), - ) - .await; + let srv = + init_service( + App::new().service(web::service("/test").name("test").finish( + |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())), + )), + ) + .await; let req = TestRequest::with_uri("/test").to_request(); let resp = srv.call(req).await.unwrap(); assert_eq!(resp.status(), http::StatusCode::OK); - let srv = init_service( - App::new().service(web::service("/test").guard(guard::Get()).finish( - |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())), - )), - ) - .await; + let srv = + init_service( + App::new().service(web::service("/test").guard(guard::Get()).finish( + |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())), + )), + ) + .await; let req = TestRequest::with_uri("/test") .method(http::Method::PUT) .to_request(); @@ -731,18 +737,19 @@ mod tests { #[allow(deprecated)] #[actix_rt::test] async fn test_service_data() { - let srv = - init_service( - App::new() - .data(42u32) - .service(web::service("/test").name("test").finish( - |req: ServiceRequest| { + let srv = init_service( + App::new() + .data(42u32) + .service( + web::service("/test") + .name("test") + .finish(|req: ServiceRequest| { assert_eq!(req.app_data::>().unwrap().as_ref(), &42); ok(req.into_response(HttpResponse::Ok().finish())) - }, - )), - ) - .await; + }), + ), + ) + .await; let req = TestRequest::with_uri("/test").to_request(); let resp = srv.call(req).await.unwrap(); assert_eq!(resp.status(), http::StatusCode::OK); @@ -773,9 +780,7 @@ mod tests { async fn test_services_macro() { let scoped = services![ web::service("/scoped_test1").name("scoped_test1").finish( - |req: ServiceRequest| async { - Ok(req.into_response(HttpResponse::Ok().finish())) - } + |req: ServiceRequest| async { Ok(req.into_response(HttpResponse::Ok().finish())) } ), web::resource("/scoped_test2").to(|| async { "test2" }), ]; @@ -861,9 +866,7 @@ mod tests { svc.call(req) }) .route("/", web::get().to(|| async { "" })) - .service( - web::resource("/resource1/{name}/index.html").route(web::get().to(index)), - ), + .service(web::resource("/resource1/{name}/index.html").route(web::get().to(index))), ) .await; diff --git a/actix-web/src/test/mod.rs b/actix-web/src/test/mod.rs index 5d9367b82..5e647956b 100644 --- a/actix-web/src/test/mod.rs +++ b/actix-web/src/test/mod.rs @@ -29,18 +29,20 @@ mod test_request; mod test_services; mod test_utils; -pub use self::test_request::TestRequest; #[allow(deprecated)] pub use self::test_services::{default_service, ok_service, simple_service, status_service}; -#[allow(deprecated)] -pub use self::test_utils::{ - call_and_read_body, call_and_read_body_json, call_service, init_service, read_body, - read_body_json, read_response, read_response_json, try_call_and_read_body_json, - try_call_service, try_read_body, try_read_body_json, -}; - #[cfg(test)] pub(crate) use self::test_utils::try_init_service; +#[allow(deprecated)] +pub use self::test_utils::{read_response, read_response_json}; +pub use self::{ + test_request::TestRequest, + test_utils::{ + call_and_read_body, call_and_read_body_json, call_service, init_service, read_body, + read_body_json, try_call_and_read_body_json, try_call_service, try_read_body, + try_read_body_json, + }, +}; /// Reduces boilerplate code when testing expected response payloads. /// diff --git a/actix-web/src/test/test_request.rs b/actix-web/src/test/test_request.rs index e81561d17..5491af0ac 100644 --- a/actix-web/src/test/test_request.rs +++ b/actix-web/src/test/test_request.rs @@ -3,13 +3,17 @@ use std::{borrow::Cow, net::SocketAddr, rc::Rc}; use actix_http::{test::TestRequest as HttpTestRequest, Request}; use serde::Serialize; +#[cfg(feature = "cookies")] +use crate::cookie::{Cookie, CookieJar}; use crate::{ app_service::AppInitServiceState, config::AppConfig, data::Data, dev::{Extensions, Path, Payload, ResourceDef, Service, Url}, - http::header::ContentType, - http::{header::TryIntoHeaderPair, Method, Uri, Version}, + http::{ + header::{ContentType, TryIntoHeaderPair}, + Method, Uri, Version, + }, rmap::ResourceMap, service::{ServiceRequest, ServiceResponse}, test, @@ -17,9 +21,6 @@ use crate::{ HttpRequest, HttpResponse, }; -#[cfg(feature = "cookies")] -use crate::cookie::{Cookie, CookieJar}; - /// Test `Request` builder. /// /// For unit testing, actix provides a request builder type and a simple handler runner. TestRequest implements a builder-like pattern. @@ -197,8 +198,7 @@ impl TestRequest { /// /// The `Content-Type` header is set to `application/json`. pub fn set_json(mut self, data: impl Serialize) -> Self { - let bytes = - serde_json::to_string(&data).expect("Failed to serialize test data to json"); + let bytes = serde_json::to_string(&data).expect("Failed to serialize test data to json"); self.req.set_payload(bytes); self.req.insert_header(ContentType::json()); self diff --git a/actix-web/src/test/test_utils.rs b/actix-web/src/test/test_utils.rs index bba23a0fe..4540d8a6b 100644 --- a/actix-web/src/test/test_utils.rs +++ b/actix-web/src/test/test_utils.rs @@ -201,9 +201,7 @@ where } /// Fallible version of [`read_body`] that allows testing MessageBody reading errors. -pub async fn try_read_body( - res: ServiceResponse, -) -> Result::Error> +pub async fn try_read_body(res: ServiceResponse) -> Result::Error> where B: MessageBody, { @@ -363,8 +361,7 @@ mod tests { use super::*; use crate::{ - dev::ServiceRequest, http::header, test::TestRequest, web, App, HttpMessage, - HttpResponse, + dev::ServiceRequest, http::header, test::TestRequest, web, App, HttpMessage, HttpResponse, }; #[actix_rt::test] @@ -408,10 +405,11 @@ mod tests { #[actix_rt::test] async fn test_response_json() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ))) + .await; let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes(); @@ -427,10 +425,11 @@ mod tests { #[actix_rt::test] async fn test_try_response_json_error() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ))) + .await; let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes(); @@ -447,10 +446,11 @@ mod tests { #[actix_rt::test] async fn test_body_json() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ))) + .await; let payload = r#"{"id":"12345","name":"User name"}"#.as_bytes(); @@ -467,10 +467,11 @@ mod tests { #[actix_rt::test] async fn test_try_body_json_error() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ))) + .await; // Use a number for id to cause a deserialization error. let payload = r#"{"id":12345,"name":"User name"}"#.as_bytes(); @@ -488,10 +489,11 @@ mod tests { #[actix_rt::test] async fn test_request_response_form() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Form| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Form| HttpResponse::Ok().json(person)), + ))) + .await; let payload = Person { id: "12345".to_string(), @@ -531,10 +533,11 @@ mod tests { #[actix_rt::test] async fn test_request_response_json() { - let app = init_service(App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - ))) - .await; + let app = + init_service(App::new().service(web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ))) + .await; let payload = Person { id: "12345".to_string(), @@ -565,9 +568,11 @@ mod tests { InitError = (), >, > { - App::new().service(web::resource("/people").route( - web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), - )) + App::new().service( + web::resource("/people").route( + web::post().to(|person: web::Json| HttpResponse::Ok().json(person)), + ), + ) } async fn test_service( diff --git a/actix-web/src/types/either.rs b/actix-web/src/types/either.rs index df93fb5ec..db244fd9a 100644 --- a/actix-web/src/types/either.rs +++ b/actix-web/src/types/either.rs @@ -238,8 +238,7 @@ where match res { Ok(bytes) => { let fallback = bytes.clone(); - let left = - L::from_request(this.req, &mut payload_from_bytes(bytes)); + let left = L::from_request(this.req, &mut payload_from_bytes(bytes)); EitherExtractState::Left { left, fallback } } Err(err) => break Err(EitherExtractError::Bytes(err)), @@ -266,10 +265,7 @@ where match res { Ok(data) => break Ok(Either::Right(data)), Err(err) => { - break Err(EitherExtractError::Extract( - left_err.take().unwrap(), - err, - )); + break Err(EitherExtractError::Extract(left_err.take().unwrap(), err)); } } } @@ -339,12 +335,11 @@ mod tests { .set_payload(Bytes::from_static(b"!@$%^&*()")) .to_http_parts(); - let payload = Either::, Json>, Bytes>::from_request( - &req, &mut pl, - ) - .await - .unwrap() - .unwrap_right(); + let payload = + Either::, Json>, Bytes>::from_request(&req, &mut pl) + .await + .unwrap() + .unwrap_right(); assert_eq!(&payload.as_ref(), &b"!@$%^&*()"); } @@ -356,14 +351,13 @@ mod tests { }) .to_http_parts(); - let form = Either::, Json>, Bytes>::from_request( - &req, &mut pl, - ) - .await - .unwrap() - .unwrap_left() - .unwrap_right() - .into_inner(); + 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/actix-web/src/types/form.rs b/actix-web/src/types/form.rs index d73f8ba74..7096b1e9c 100644 --- a/actix-web/src/types/form.rs +++ b/actix-web/src/types/form.rs @@ -20,9 +20,8 @@ use serde::{de::DeserializeOwned, Serialize}; #[cfg(feature = "__compress")] use crate::dev::Decompress; use crate::{ - body::EitherBody, error::UrlencodedError, extract::FromRequest, - http::header::CONTENT_LENGTH, web, Error, HttpMessage, HttpRequest, HttpResponse, - Responder, + body::EitherBody, error::UrlencodedError, extract::FromRequest, http::header::CONTENT_LENGTH, + web, Error, HttpMessage, HttpRequest, HttpResponse, Responder, }; /// URL encoded payload extractor and responder. @@ -417,13 +416,12 @@ mod tests { use serde::{Deserialize, Serialize}; use super::*; - use crate::test::TestRequest; use crate::{ http::{ header::{HeaderValue, CONTENT_LENGTH, CONTENT_TYPE}, StatusCode, }, - test::assert_body_eq, + test::{assert_body_eq, TestRequest}, }; #[derive(Deserialize, Serialize, Debug, PartialEq)] diff --git a/actix-web/src/types/header.rs b/actix-web/src/types/header.rs index 6ea77faf6..8b1740e6c 100644 --- a/actix-web/src/types/header.rs +++ b/actix-web/src/types/header.rs @@ -75,8 +75,10 @@ where #[cfg(test)] mod tests { use super::*; - use crate::http::{header, Method}; - use crate::test::TestRequest; + use crate::{ + http::{header, Method}, + test::TestRequest, + }; #[actix_rt::test] async fn test_header_extract() { diff --git a/actix-web/src/types/json.rs b/actix-web/src/types/json.rs index 4eab55175..2523e55f2 100644 --- a/actix-web/src/types/json.rs +++ b/actix-web/src/types/json.rs @@ -10,12 +10,11 @@ use std::{ task::{Context, Poll}, }; +use actix_http::Payload; use bytes::BytesMut; use futures_core::{ready, Stream as _}; use serde::{de::DeserializeOwned, Serialize}; -use actix_http::Payload; - #[cfg(feature = "__compress")] use crate::dev::Decompress; use crate::{ @@ -158,8 +157,7 @@ impl FromRequest for Json { } } -type JsonErrorHandler = - Option Error + Send + Sync>>; +type JsonErrorHandler = Option Error + Send + Sync>>; pub struct JsonExtractFut { req: Option, @@ -423,9 +421,7 @@ impl Future for JsonBody { let chunk = chunk?; let buf_len = buf.len() + chunk.len(); if buf_len > *limit { - return Poll::Ready(Err(JsonPayloadError::Overflow { - limit: *limit, - })); + return Poll::Ready(Err(JsonPayloadError::Overflow { limit: *limit })); } else { buf.extend_from_slice(&chunk); } @@ -508,8 +504,7 @@ mod tests { let msg = MyObject { name: "invalid request".to_string(), }; - let resp = - HttpResponse::BadRequest().body(serde_json::to_string(&msg).unwrap()); + let resp = HttpResponse::BadRequest().body(serde_json::to_string(&msg).unwrap()); InternalError::from_response(err, resp).into() })) .to_http_parts(); @@ -747,7 +742,8 @@ mod tests { assert!(s.is_err()); let err_str = s.err().unwrap().to_string(); - assert!(err_str - .contains("JSON payload (16 bytes) is larger than allowed (limit: 10 bytes).")); + assert!( + err_str.contains("JSON payload (16 bytes) is larger than allowed (limit: 10 bytes).") + ); } } diff --git a/actix-web/src/types/mod.rs b/actix-web/src/types/mod.rs index bab7c3bc0..792edd650 100644 --- a/actix-web/src/types/mod.rs +++ b/actix-web/src/types/mod.rs @@ -9,11 +9,13 @@ mod payload; mod query; mod readlines; -pub use self::either::Either; -pub use self::form::{Form, FormConfig, UrlEncoded}; -pub use self::header::Header; -pub use self::json::{Json, JsonBody, JsonConfig}; -pub use self::path::{Path, PathConfig}; -pub use self::payload::{Payload, PayloadConfig}; -pub use self::query::{Query, QueryConfig}; -pub use self::readlines::Readlines; +pub use self::{ + either::Either, + form::{Form, FormConfig, UrlEncoded}, + header::Header, + json::{Json, JsonBody, JsonConfig}, + path::{Path, PathConfig}, + payload::{Payload, PayloadConfig}, + query::{Query, QueryConfig}, + readlines::Readlines, +}; diff --git a/actix-web/src/types/path.rs b/actix-web/src/types/path.rs index a90c912f6..cc87bb80f 100644 --- a/actix-web/src/types/path.rs +++ b/actix-web/src/types/path.rs @@ -156,8 +156,7 @@ mod tests { use serde::Deserialize; use super::*; - use crate::test::TestRequest; - use crate::{error, http, HttpResponse}; + use crate::{error, http, test::TestRequest, HttpResponse}; #[derive(Deserialize, Debug, Display)] #[display(fmt = "MyStruct({}, {})", key, value)] @@ -276,8 +275,7 @@ mod tests { async fn test_custom_err_handler() { let (req, mut pl) = TestRequest::with_uri("/name/user1/") .app_data(PathConfig::default().error_handler(|err, _| { - error::InternalError::from_response(err, HttpResponse::Conflict().finish()) - .into() + error::InternalError::from_response(err, HttpResponse::Conflict().finish()).into() })) .to_http_parts(); diff --git a/actix-web/src/types/payload.rs b/actix-web/src/types/payload.rs index 4045cedb4..1d9c6aba5 100644 --- a/actix-web/src/types/payload.rs +++ b/actix-web/src/types/payload.rs @@ -16,8 +16,7 @@ use futures_core::{ready, stream::Stream}; use mime::Mime; use crate::{ - dev, error::ErrorBadRequest, http::header, web, Error, FromRequest, HttpMessage, - HttpRequest, + dev, error::ErrorBadRequest, http::header, web, Error, FromRequest, HttpMessage, HttpRequest, }; /// Extract a request's raw payload stream. @@ -377,9 +376,11 @@ mod tests { use bytes::Bytes; use super::*; - use crate::http::{header, StatusCode}; - use crate::test::{call_service, init_service, TestRequest}; - use crate::{web, App, Responder}; + use crate::{ + http::{header, StatusCode}, + test::{call_service, init_service, TestRequest}, + web, App, Responder, + }; #[actix_rt::test] async fn test_payload_config() { diff --git a/actix-web/src/web.rs b/actix-web/src/web.rs index 0533f7f8f..204313752 100644 --- a/actix-web/src/web.rs +++ b/actix-web/src/web.rs @@ -21,17 +21,14 @@ use std::{borrow::Cow, future::Future}; use actix_router::IntoPatterns; pub use bytes::{Buf, BufMut, Bytes, BytesMut}; +pub use crate::{ + config::ServiceConfig, data::Data, redirect::Redirect, request_data::ReqData, types::*, +}; use crate::{ error::BlockingError, http::Method, service::WebService, FromRequest, Handler, Resource, Responder, Route, Scope, }; -pub use crate::config::ServiceConfig; -pub use crate::data::Data; -pub use crate::redirect::Redirect; -pub use crate::request_data::ReqData; -pub use crate::types::*; - /// Creates a new resource for a specific path. /// /// Resources may have dynamic path segments. For example, a resource with the path `/a/{name}/c` @@ -200,10 +197,7 @@ pub fn service(path: T) -> WebService { /// // the client will resolve this redirect to /api/to-path /// .service(web::redirect("/api/from-path", "to-path")); /// ``` -pub fn redirect( - from: impl Into>, - to: impl Into>, -) -> Redirect { +pub fn redirect(from: impl Into>, to: impl Into>) -> Redirect { Redirect::new(from, to) } diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 270223d69..8ce889396 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -19,14 +19,13 @@ use actix_web::{ }; use bytes::Bytes; use futures_core::ready; -use rand::{distributions::Alphanumeric, Rng as _}; - #[cfg(feature = "openssl")] use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslMethod}, x509::X509, }; +use rand::{distributions::Alphanumeric, Rng as _}; mod utils; @@ -94,9 +93,8 @@ impl futures_core::stream::Stream for TestBody { #[actix_rt::test] async fn test_body() { let srv = actix_test::start(|| { - App::new().service( - web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) })), - ) + App::new() + .service(web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) }))) }); let mut res = srv.get("/").send().await.unwrap(); @@ -226,8 +224,7 @@ async fn test_body_chunked_implicit() { App::new() .wrap(Compress::default()) .service(web::resource("/").route(web::get().to(|| async { - HttpResponse::Ok() - .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) + HttpResponse::Ok().streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) }))) }); @@ -256,8 +253,7 @@ async fn test_body_br_streaming() { App::new() .wrap(Compress::default()) .service(web::resource("/").route(web::to(|| async { - HttpResponse::Ok() - .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) + HttpResponse::Ok().streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) }))) }); @@ -392,8 +388,7 @@ async fn test_body_zstd_streaming() { App::new() .wrap(Compress::default()) .service(web::resource("/").route(web::to(move || async { - HttpResponse::Ok() - .streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) + HttpResponse::Ok().streaming(TestBody::new(Bytes::from_static(STR.as_ref()), 24)) }))) }); @@ -686,15 +681,14 @@ async fn test_brotli_encoding_large_openssl() { use actix_web::http::header; let data = STR.repeat(10); - let srv = - actix_test::start_with(actix_test::config().openssl(openssl_config()), move || { - App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { - // echo decompressed request body back in response - HttpResponse::Ok() - .insert_header(header::ContentEncoding::Identity) - .body(bytes) - }))) - }); + let srv = actix_test::start_with(actix_test::config().openssl(openssl_config()), move || { + App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { + // echo decompressed request body back in response + HttpResponse::Ok() + .insert_header(header::ContentEncoding::Identity) + .body(bytes) + }))) + }); let mut res = srv .post("/") diff --git a/actix-web/tests/utils.rs b/actix-web/tests/utils.rs index 2532640c6..b9c708884 100644 --- a/actix-web/tests/utils.rs +++ b/actix-web/tests/utils.rs @@ -4,9 +4,10 @@ use std::io::{Read as _, Write as _}; pub mod gzip { - use super::*; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = GzEncoder::new(Vec::new(), Compression::fast()); encoder.write_all(bytes.as_ref()).unwrap(); @@ -22,9 +23,10 @@ pub mod gzip { } pub mod deflate { - use super::*; use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = ZlibEncoder::new(Vec::new(), Compression::fast()); encoder.write_all(bytes.as_ref()).unwrap(); @@ -40,9 +42,10 @@ pub mod deflate { } pub mod brotli { - use super::*; use ::brotli::{reader::Decompressor as BrotliDecoder, CompressorWriter as BrotliEncoder}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = BrotliEncoder::new( Vec::new(), @@ -64,9 +67,10 @@ pub mod brotli { } pub mod zstd { - use super::*; use ::zstd::stream::{read::Decoder, write::Encoder}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = Encoder::new(Vec::new(), 3).unwrap(); encoder.write_all(bytes.as_ref()).unwrap(); diff --git a/awc/src/any_body.rs b/awc/src/any_body.rs index d9c259d8f..08f5cc25e 100644 --- a/awc/src/any_body.rs +++ b/awc/src/any_body.rs @@ -4,11 +4,10 @@ use std::{ task::{Context, Poll}, }; +use actix_http::body::{BodySize, BoxBody, MessageBody}; use bytes::Bytes; use pin_project_lite::pin_project; -use actix_http::body::{BodySize, BoxBody, MessageBody}; - pin_project! { /// Represents various types of HTTP message body. #[derive(Clone)] diff --git a/awc/src/builder.rs b/awc/src/builder.rs index b15e2de0b..a54960382 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -1,7 +1,5 @@ use std::{fmt, net::IpAddr, rc::Rc, time::Duration}; -use base64::prelude::*; - use actix_http::{ error::HttpError, header::{self, HeaderMap, HeaderName, TryIntoHeaderPair}, @@ -9,6 +7,7 @@ use actix_http::{ }; use actix_rt::net::{ActixStream, TcpStream}; use actix_service::{boxed, Service}; +use base64::prelude::*; use crate::{ client::{ @@ -72,11 +71,8 @@ where /// Use custom connector service. pub fn connector(self, connector: Connector) -> ClientBuilder where - S1: Service< - ConnectInfo, - Response = TcpConnection, - Error = TcpConnectError, - > + Clone + S1: Service, Response = TcpConnection, Error = TcpConnectError> + + Clone + 'static, Io1: ActixStream + fmt::Debug + 'static, { @@ -227,10 +223,7 @@ where /// Registers middleware, in the form of a middleware component (type), that runs during inbound /// and/or outbound processing in the request life-cycle (request -> response), /// modifying request/response as necessary, across all requests managed by the `Client`. - pub fn wrap( - self, - mw: M1, - ) -> ClientBuilder> + pub fn wrap(self, mw: M1) -> ClientBuilder> where M: Transform, M1: Transform, @@ -253,8 +246,7 @@ where pub fn finish(self) -> Client where M: Transform>, ConnectRequest> + 'static, - M::Transform: - Service, + M::Transform: Service, { let max_redirects = self.max_redirects; @@ -269,8 +261,7 @@ where fn _finish(self) -> Client where M: Transform>, ConnectRequest> + 'static, - M::Transform: - Service, + M::Transform: Service, { let mut connector = self.connector; diff --git a/awc/src/client/connection.rs b/awc/src/client/connection.rs index 9de4ece4f..64075eae8 100644 --- a/awc/src/client/connection.rs +++ b/awc/src/client/connection.rs @@ -7,19 +7,15 @@ use std::{ }; use actix_codec::{AsyncRead, AsyncWrite, Framed, ReadBuf}; +use actix_http::{body::MessageBody, h1::ClientCodec, Payload, RequestHeadType, ResponseHead}; use actix_rt::task::JoinHandle; use bytes::Bytes; use futures_core::future::LocalBoxFuture; use h2::client::SendRequest; -use actix_http::{body::MessageBody, h1::ClientCodec, Payload, RequestHeadType, ResponseHead}; - +use super::{error::SendRequestError, h1proto, h2proto, pool::Acquired}; use crate::BoxError; -use super::error::SendRequestError; -use super::pool::Acquired; -use super::{h1proto, h2proto}; - /// Trait alias for types impl [tokio::io::AsyncRead] and [tokio::io::AsyncWrite]. pub trait ConnectionIo: AsyncRead + AsyncWrite + Unpin + 'static {} @@ -83,10 +79,7 @@ impl AsyncWrite for H1Connection { self.io_pin_mut().poll_flush(cx) } - fn poll_shutdown( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { + fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { self.io_pin_mut().poll_shutdown(cx) } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 51d6e180b..1ecaf9947 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -133,11 +133,8 @@ impl Connector { pub fn connector(self, connector: S1) -> Connector where Io1: ActixStream + fmt::Debug + 'static, - S1: Service< - ConnectInfo, - Response = TcpConnection, - Error = TcpConnectError, - > + Clone, + S1: Service, Response = TcpConnection, Error = TcpConnectError> + + Clone, { Connector { connector, @@ -189,10 +186,7 @@ where #[doc(hidden)] #[cfg(feature = "openssl")] #[deprecated(since = "3.0.0", note = "Renamed to `Connector::openssl`.")] - pub fn ssl( - mut self, - connector: actix_tls::connect::openssl::reexports::SslConnector, - ) -> Self { + pub fn ssl(mut self, connector: actix_tls::connect::openssl::reexports::SslConnector) -> Self { self.tls = OurTlsConnector::Openssl(connector); self } @@ -312,9 +306,7 @@ where let tls = match self.tls { #[cfg(feature = "openssl")] - OurTlsConnector::OpensslBuilder(builder) => { - OurTlsConnector::Openssl(builder.build()) - } + OurTlsConnector::OpensslBuilder(builder) => OurTlsConnector::Openssl(builder.build()), tls => tls, }; @@ -467,9 +459,7 @@ pub struct TcpConnectorService { impl Service for TcpConnectorService where - S: Service, Error = ConnectError> - + Clone - + 'static, + S: Service, Error = ConnectError> + Clone + 'static, { type Response = (Io, Protocol); type Error = ConnectError; @@ -520,9 +510,8 @@ struct TlsConnectorService { impl Service for TlsConnectorService where - Tcp: Service, Error = ConnectError> - + Clone - + 'static, + Tcp: + Service, Error = ConnectError> + Clone + 'static, Tls: Service, Error = std::io::Error> + Clone + 'static, Tls::Response: IntoConnectionIo, IO: ConnectionIo, diff --git a/awc/src/client/error.rs b/awc/src/client/error.rs index 9f290c5c0..d351e1067 100644 --- a/awc/src/client/error.rs +++ b/awc/src/client/error.rs @@ -1,11 +1,9 @@ use std::{fmt, io}; -use derive_more::{Display, From}; - use actix_http::error::{HttpError, ParseError}; - #[cfg(feature = "openssl")] use actix_tls::accept::openssl::reexports::Error as OpensslError; +use derive_more::{Display, From}; use crate::BoxError; diff --git a/awc/src/client/h1proto.rs b/awc/src/client/h1proto.rs index 8738c2f7f..c756179a4 100644 --- a/awc/src/client/h1proto.rs +++ b/awc/src/client/h1proto.rs @@ -18,12 +18,11 @@ use futures_core::{ready, Stream}; use futures_util::SinkExt as _; use pin_project_lite::pin_project; -use crate::BoxError; - use super::{ connection::{ConnectionIo, H1Connection}, error::{ConnectError, SendRequestError}, }; +use crate::BoxError; pub(crate) async fn send_request( io: H1Connection, diff --git a/awc/src/client/h2proto.rs b/awc/src/client/h2proto.rs index 709896ddd..d18db1410 100644 --- a/awc/src/client/h2proto.rs +++ b/awc/src/client/h2proto.rs @@ -1,28 +1,29 @@ use std::future::Future; -use actix_utils::future::poll_fn; -use bytes::Bytes; -use h2::{ - client::{Builder, Connection, SendRequest}, - SendStream, -}; -use http::header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING}; -use http::{request::Request, Method, Version}; -use log::trace; - use actix_http::{ body::{BodySize, MessageBody}, header::HeaderMap, Payload, RequestHeadType, ResponseHead, }; - -use crate::BoxError; +use actix_utils::future::poll_fn; +use bytes::Bytes; +use h2::{ + client::{Builder, Connection, SendRequest}, + SendStream, +}; +use http::{ + header::{HeaderValue, CONNECTION, CONTENT_LENGTH, TRANSFER_ENCODING}, + request::Request, + Method, Version, +}; +use log::trace; use super::{ config::ConnectorConfig, connection::{ConnectionIo, H2Connection}, error::SendRequestError, }; +use crate::BoxError; pub(crate) async fn send_request( mut io: H2Connection, diff --git a/awc/src/client/mod.rs b/awc/src/client/mod.rs index b1df1fd3d..c9fa37253 100644 --- a/awc/src/client/mod.rs +++ b/awc/src/client/mod.rs @@ -19,9 +19,11 @@ mod h1proto; mod h2proto; mod pool; -pub use self::connection::{Connection, ConnectionIo}; -pub use self::connector::{Connector, ConnectorService}; -pub use self::error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError}; +pub use self::{ + connection::{Connection, ConnectionIo}, + connector::{Connector, ConnectorService}, + error::{ConnectError, FreezeRequestError, InvalidUrl, SendRequestError}, +}; #[derive(Clone)] pub struct Connect { diff --git a/awc/src/client/pool.rs b/awc/src/client/pool.rs index 632608c45..2cf1f3ace 100644 --- a/awc/src/client/pool.rs +++ b/awc/src/client/pool.rs @@ -23,11 +23,13 @@ use http::uri::Authority; use pin_project_lite::pin_project; use tokio::sync::{OwnedSemaphorePermit, Semaphore}; -use super::config::ConnectorConfig; -use super::connection::{ConnectionInnerType, ConnectionIo, ConnectionType, H2ConnectionInner}; -use super::error::ConnectError; -use super::h2proto::handshake; -use super::Connect; +use super::{ + config::ConnectorConfig, + connection::{ConnectionInnerType, ConnectionIo, ConnectionType, H2ConnectionInner}, + error::ConnectError, + h2proto::handshake, + Connect, +}; #[derive(Hash, Eq, PartialEq, Clone, Debug)] pub struct Key { @@ -201,7 +203,9 @@ where // check if the connection is still usable if let ConnectionInnerType::H1(ref mut io) = c.conn { let check = ConnectionCheckFuture { io }; - match check.now_or_never().expect("ConnectionCheckFuture must never yield with Poll::Pending.") { + match check.now_or_never().expect( + "ConnectionCheckFuture must never yield with Poll::Pending.", + ) { ConnectionState::Tainted => { inner.close(c.conn); continue; diff --git a/awc/src/connect.rs b/awc/src/connect.rs index be1ea0fee..14ed9e958 100644 --- a/awc/src/connect.rs +++ b/awc/src/connect.rs @@ -13,9 +13,7 @@ use futures_core::{future::LocalBoxFuture, ready}; use crate::{ any_body::AnyBody, - client::{ - Connect as ClientConnect, ConnectError, Connection, ConnectionIo, SendRequestError, - }, + client::{Connect as ClientConnect, ConnectError, Connection, ConnectionIo, SendRequestError}, ClientResponse, }; @@ -62,9 +60,9 @@ impl ConnectResponse { pub fn into_client_response(self) -> ClientResponse { match self { ConnectResponse::Client(res) => res, - _ => panic!( - "ClientResponse only reachable with ConnectResponse::ClientResponse variant" - ), + _ => { + panic!("ClientResponse only reachable with ConnectResponse::ClientResponse variant") + } } } @@ -75,9 +73,9 @@ impl ConnectResponse { pub fn into_tunnel_response(self) -> (ResponseHead, Framed) { match self { ConnectResponse::Tunnel(head, framed) => (head, framed), - _ => panic!( - "TunnelResponse only reachable with ConnectResponse::TunnelResponse variant" - ), + _ => { + panic!("TunnelResponse only reachable with ConnectResponse::TunnelResponse variant") + } } } } diff --git a/awc/src/error.rs b/awc/src/error.rs index aa9dc4d99..0104e5fe8 100644 --- a/awc/src/error.rs +++ b/awc/src/error.rs @@ -7,7 +7,6 @@ pub use actix_http::{ ws::{HandshakeError as WsHandshakeError, ProtocolError as WsProtocolError}, StatusCode, }; - use derive_more::{Display, From}; use serde_json::error::Error as JsonError; diff --git a/awc/src/frozen.rs b/awc/src/frozen.rs index 4023bd1c8..8f3244997 100644 --- a/awc/src/frozen.rs +++ b/awc/src/frozen.rs @@ -1,15 +1,14 @@ use std::{net, rc::Rc, time::Duration}; -use bytes::Bytes; -use futures_core::Stream; -use serde::Serialize; - use actix_http::{ body::MessageBody, error::HttpError, header::{HeaderMap, TryIntoHeaderPair}, Method, RequestHead, Uri, }; +use bytes::Bytes; +use futures_core::Stream; +use serde::Serialize; use crate::{ client::ClientConfig, diff --git a/awc/src/lib.rs b/awc/src/lib.rs index b06df6b7d..ce2dfb34f 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -113,7 +113,6 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] pub use actix_http::body; - #[cfg(feature = "cookies")] pub use cookie; @@ -134,18 +133,18 @@ pub mod http { //! Various HTTP related types. // TODO: figure out how best to expose http::Error vs actix_http::Error - pub use actix_http::{ - header, uri, ConnectionType, Error, Method, StatusCode, Uri, Version, - }; + pub use actix_http::{header, uri, ConnectionType, Error, Method, StatusCode, Uri, Version}; } -pub use self::builder::ClientBuilder; -pub use self::client::{Client, Connect, Connector}; -pub use self::connect::{BoxConnectorService, BoxedSocket, ConnectRequest, ConnectResponse}; -pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder}; -pub use self::request::ClientRequest; #[allow(deprecated)] pub use self::responses::{ClientResponse, JsonBody, MessageBody, ResponseBody}; -pub use self::sender::SendClientRequest; +pub use self::{ + builder::ClientBuilder, + client::{Client, Connect, Connector}, + connect::{BoxConnectorService, BoxedSocket, ConnectRequest, ConnectResponse}, + frozen::{FrozenClientRequest, FrozenSendBuilder}, + request::ClientRequest, + sender::SendClientRequest, +}; pub(crate) type BoxError = Box; diff --git a/awc/src/middleware/mod.rs b/awc/src/middleware/mod.rs index 330e3b7fe..8c63e9c75 100644 --- a/awc/src/middleware/mod.rs +++ b/awc/src/middleware/mod.rs @@ -1,11 +1,11 @@ mod redirect; -pub use self::redirect::Redirect; - use std::marker::PhantomData; use actix_service::Service; +pub use self::redirect::Redirect; + /// Trait for transform a type to another one. /// Both the input and output type should impl [actix_service::Service] trait. pub trait Transform { diff --git a/awc/src/middleware/redirect.rs b/awc/src/middleware/redirect.rs index d1216fa57..c38d6ad92 100644 --- a/awc/src/middleware/redirect.rs +++ b/awc/src/middleware/redirect.rs @@ -449,8 +449,7 @@ mod tests { } async fn test(req: HttpRequest, body: Bytes) -> HttpResponse { - if (req.method() == Method::GET || req.method() == Method::HEAD) - && body.is_empty() + if (req.method() == Method::GET || req.method() == Method::HEAD) && body.is_empty() { HttpResponse::Ok().finish() } else { @@ -550,10 +549,7 @@ mod tests { let port = *req.app_data::().unwrap(); if req.headers().get(header::AUTHORIZATION).is_some() { HttpResponse::Found() - .append_header(( - "location", - format!("http://localhost:{}/", port).as_str(), - )) + .append_header(("location", format!("http://localhost:{}/", port).as_str())) .finish() } else { HttpResponse::InternalServerError().finish() diff --git a/awc/src/request.rs b/awc/src/request.rs index 5e04aa8de..4e34e5771 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -1,17 +1,18 @@ use std::{fmt, net, rc::Rc, time::Duration}; -use base64::prelude::*; -use bytes::Bytes; -use futures_core::Stream; -use serde::Serialize; - use actix_http::{ body::MessageBody, error::HttpError, header::{self, HeaderMap, HeaderValue, TryIntoHeaderPair}, ConnectionType, Method, RequestHead, Uri, Version, }; +use base64::prelude::*; +use bytes::Bytes; +use futures_core::Stream; +use serde::Serialize; +#[cfg(feature = "cookies")] +use crate::cookie::{Cookie, CookieJar}; use crate::{ client::ClientConfig, error::{FreezeRequestError, InvalidUrl}, @@ -20,9 +21,6 @@ use crate::{ BoxError, }; -#[cfg(feature = "cookies")] -use crate::cookie::{Cookie, CookieJar}; - /// An HTTP Client request builder /// /// This type can be used to construct an instance of `ClientRequest` through a @@ -291,10 +289,7 @@ impl ClientRequest { } /// Sets the query part of the request - pub fn query( - mut self, - query: &T, - ) -> Result { + pub fn query(mut self, query: &T) -> Result { let mut parts = self.head.uri.clone().into_parts(); if let Some(path_and_query) = parts.path_and_query { diff --git a/awc/src/responses/mod.rs b/awc/src/responses/mod.rs index 588ce014c..95a078093 100644 --- a/awc/src/responses/mod.rs +++ b/awc/src/responses/mod.rs @@ -8,10 +8,9 @@ mod read_body; mod response; mod response_body; -pub use self::json_body::JsonBody; -pub use self::response::ClientResponse; #[allow(deprecated)] pub use self::response_body::{MessageBody, ResponseBody}; +pub use self::{json_body::JsonBody, response::ClientResponse}; /// Default body size limit: 2 MiB const DEFAULT_BODY_LIMIT: usize = 2 * 1024 * 1024; diff --git a/awc/src/responses/response.rs b/awc/src/responses/response.rs index c7c0a6362..0eafcff0a 100644 --- a/awc/src/responses/response.rs +++ b/awc/src/responses/response.rs @@ -7,8 +7,8 @@ use std::{ }; use actix_http::{ - error::PayloadError, header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, - Payload, ResponseHead, StatusCode, Version, + error::PayloadError, header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Payload, + ResponseHead, StatusCode, Version, }; use actix_rt::time::{sleep, Sleep}; use bytes::Bytes; @@ -16,11 +16,10 @@ use futures_core::Stream; use pin_project_lite::pin_project; use serde::de::DeserializeOwned; +use super::{JsonBody, ResponseBody, ResponseTimeout}; #[cfg(feature = "cookies")] use crate::cookie::{Cookie, ParseError as CookieParseError}; -use super::{JsonBody, ResponseBody, ResponseTimeout}; - pin_project! { /// Client Response pub struct ClientResponse { diff --git a/awc/src/sender.rs b/awc/src/sender.rs index cd30e571d..c2191d11b 100644 --- a/awc/src/sender.rs +++ b/awc/src/sender.rs @@ -13,15 +13,14 @@ use actix_http::{ header::{self, HeaderMap, HeaderName, TryIntoHeaderValue}, RequestHead, RequestHeadType, }; +#[cfg(feature = "__compress")] +use actix_http::{encoding::Decoder, header::ContentEncoding, Payload}; use actix_rt::time::{sleep, Sleep}; use bytes::Bytes; use derive_more::From; use futures_core::Stream; use serde::Serialize; -#[cfg(feature = "__compress")] -use actix_http::{encoding::Decoder, header::ContentEncoding, Payload}; - use crate::{ any_body::AnyBody, client::ClientConfig, @@ -106,8 +105,9 @@ impl Future for SendClientRequest { } let res = futures_core::ready!(send.as_mut().poll(cx)).map(|res| { - res.into_client_response()._timeout(delay.take()).map_body( - |head, payload| { + res.into_client_response() + ._timeout(delay.take()) + .map_body(|head, payload| { if *response_decompress { Payload::Stream { payload: Decoder::from_headers(payload, &head.headers), @@ -117,8 +117,7 @@ impl Future for SendClientRequest { payload: Decoder::new(payload, ContentEncoding::Identity), } } - }, - ) + }) }); Poll::Ready(res) diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 67fcd2429..836ff2024 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -28,15 +28,15 @@ use std::{fmt, net::SocketAddr, str}; -use base64::prelude::*; - use actix_codec::Framed; +pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message}; use actix_http::{ws, Payload, RequestHead}; use actix_rt::time::timeout; use actix_service::Service as _; +use base64::prelude::*; -pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message}; - +#[cfg(feature = "cookies")] +use crate::cookie::{Cookie, CookieJar}; use crate::{ client::ClientConfig, connect::{BoxedSocket, ConnectRequest}, @@ -48,9 +48,6 @@ use crate::{ ClientResponse, }; -#[cfg(feature = "cookies")] -use crate::cookie::{Cookie, CookieJar}; - /// WebSocket connection. pub struct WebsocketsRequest { pub(crate) head: RequestHead, diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index 9c3543ff0..6d1459ac0 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -12,19 +12,18 @@ use std::{ time::Duration, }; +use actix_http::{HttpService, StatusCode}; +use actix_http_test::test_server; +use actix_service::{fn_service, map_config, ServiceFactoryExt as _}; use actix_utils::future::ok; +use actix_web::{dev::AppConfig, http::header, web, App, Error, HttpRequest, HttpResponse}; +use awc::error::{JsonPayloadError, PayloadError, SendRequestError}; use base64::prelude::*; use bytes::Bytes; use cookie::Cookie; use futures_util::stream; use rand::Rng; -use actix_http::{HttpService, StatusCode}; -use actix_http_test::test_server; -use actix_service::{fn_service, map_config, ServiceFactoryExt as _}; -use actix_web::{dev::AppConfig, http::header, web, App, Error, HttpRequest, HttpResponse}; -use awc::error::{JsonPayloadError, PayloadError, SendRequestError}; - mod utils; const S: &str = "Hello World "; @@ -33,9 +32,8 @@ const STR: &str = const_str::repeat!(S, 100); #[actix_rt::test] async fn simple() { let srv = actix_test::start(|| { - App::new().service( - web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) })), - ) + App::new() + .service(web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) }))) }); let request = srv.get("/").insert_header(("x-test", "111")).send(); @@ -61,9 +59,8 @@ async fn simple() { #[actix_rt::test] async fn json() { let srv = actix_test::start(|| { - App::new().service( - web::resource("/").route(web::to(|_: web::Json| HttpResponse::Ok())), - ) + App::new() + .service(web::resource("/").route(web::to(|_: web::Json| HttpResponse::Ok()))) }); let request = srv @@ -340,8 +337,7 @@ async fn connection_wait_queue() { .and_then( HttpService::new(map_config( App::new().service( - web::resource("/") - .route(web::to(|| async { HttpResponse::Ok().body(STR) })), + web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) })), ), |_| AppConfig::default(), )) @@ -449,9 +445,7 @@ async fn no_decompress() { let srv = actix_test::start(|| { App::new() .wrap(actix_web::middleware::Compress::default()) - .service( - web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) })), - ) + .service(web::resource("/").route(web::to(|| async { HttpResponse::Ok().body(STR) }))) }); let mut res = awc::Client::new() @@ -833,12 +827,12 @@ async fn local_address() { let ip = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); let srv = actix_test::start(move || { - App::new().service(web::resource("/").route(web::to( - move |req: HttpRequest| async move { + App::new().service( + web::resource("/").route(web::to(move |req: HttpRequest| async move { assert_eq!(req.peer_addr().unwrap().ip(), ip); Ok::<_, Error>(HttpResponse::Ok()) - }, - ))) + })), + ) }); let client = awc::Client::builder().local_address(ip).finish(); diff --git a/awc/tests/test_connector.rs b/awc/tests/test_connector.rs index 0f0b81414..b3eb97367 100644 --- a/awc/tests/test_connector.rs +++ b/awc/tests/test_connector.rs @@ -5,8 +5,7 @@ extern crate tls_openssl as openssl; use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{map_config, ServiceFactoryExt}; -use actix_web::http::Version; -use actix_web::{dev::AppConfig, web, App, HttpResponse}; +use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslConnector, SslMethod, SslVerifyMode}, diff --git a/awc/tests/test_ssl_client.rs b/awc/tests/test_ssl_client.rs index 40c9ab8f0..5273c3fff 100644 --- a/awc/tests/test_ssl_client.rs +++ b/awc/tests/test_ssl_client.rs @@ -2,15 +2,16 @@ extern crate tls_openssl as openssl; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, +}; use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{fn_service, map_config, ServiceFactoryExt}; use actix_utils::future::ok; -use actix_web::http::Version; -use actix_web::{dev::AppConfig, web, App, HttpResponse}; +use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use openssl::{ pkey::PKey, ssl::{SslAcceptor, SslConnector, SslMethod, SslVerifyMode}, diff --git a/awc/tests/utils.rs b/awc/tests/utils.rs index 2532640c6..b9c708884 100644 --- a/awc/tests/utils.rs +++ b/awc/tests/utils.rs @@ -4,9 +4,10 @@ use std::io::{Read as _, Write as _}; pub mod gzip { - use super::*; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = GzEncoder::new(Vec::new(), Compression::fast()); encoder.write_all(bytes.as_ref()).unwrap(); @@ -22,9 +23,10 @@ pub mod gzip { } pub mod deflate { - use super::*; use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = ZlibEncoder::new(Vec::new(), Compression::fast()); encoder.write_all(bytes.as_ref()).unwrap(); @@ -40,9 +42,10 @@ pub mod deflate { } pub mod brotli { - use super::*; use ::brotli::{reader::Decompressor as BrotliDecoder, CompressorWriter as BrotliEncoder}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = BrotliEncoder::new( Vec::new(), @@ -64,9 +67,10 @@ pub mod brotli { } pub mod zstd { - use super::*; use ::zstd::stream::{read::Decoder, write::Encoder}; + use super::*; + pub fn encode(bytes: impl AsRef<[u8]>) -> Vec { let mut encoder = Encoder::new(Vec::new(), 3).unwrap(); encoder.write_all(bytes.as_ref()).unwrap(); From bf03207ca9b85232a2b3b2f7cc8311238ec5a2d6 Mon Sep 17 00:00:00 2001 From: James Rowe Date: Mon, 17 Jul 2023 16:59:10 -0400 Subject: [PATCH 075/314] Add http2 optional feature (#3072) Co-authored-by: Rob Ede --- actix-multipart/Cargo.toml | 2 +- actix-web/CHANGES.md | 2 +- actix-web/Cargo.toml | 10 ++++++---- actix-web/src/rmap.rs | 2 +- actix-web/src/server.rs | 2 ++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 384c0e151..f186bf8d9 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -40,7 +40,7 @@ serde_json = "1" serde_plain = "1" # TODO(MSRV 1.60): replace with dep: prefix tempfile-dep = { package = "tempfile", version = "3.4", optional = true } -tokio = { version = "1.24.2", features = ["sync"] } +tokio = { version = "1.24.2", features = ["io-util", "sync"] } [dev-dependencies] actix-http = "3" diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 417bb5a4c..6c83d129b 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,7 +4,7 @@ ### Added -- Add `HttpServer::{bind,listen}_auto_h2c()` method. +- Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature. - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. ### Changed diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 0091175be..4322fb871 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -28,7 +28,7 @@ name = "actix_web" path = "src/lib.rs" [features] -default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies"] +default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "http2"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -46,11 +46,13 @@ cookies = ["cookie"] # Secure & signed cookies secure-cookies = ["cookies", "cookie/secure"] +http2 = ["actix-http/http2"] + # TLS via OpenSSL -openssl = ["actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] +openssl = ["http2", "actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] # TLS via Rustls -rustls = ["actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] +rustls = ["http2", "actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. @@ -68,7 +70,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3", default-features = false, optional = true } -actix-http = { version = "3.3", features = ["http2", "ws"] } +actix-http = { version = "3.3", features = ["ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } diff --git a/actix-web/src/rmap.rs b/actix-web/src/rmap.rs index 8a2ec3297..462f3b313 100644 --- a/actix-web/src/rmap.rs +++ b/actix-web/src/rmap.rs @@ -81,7 +81,7 @@ impl ResourceMap { "`pattern` and `nested` mismatch" ); // parents absorb references to the named resources of children - self.named.extend(new_node.named.clone().into_iter()); + self.named.extend(new_node.named.clone()); self.nodes.as_mut().unwrap().push(new_node); } else { let new_node = Rc::new(ResourceMap { diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index b96a84939..a540da7c8 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -356,6 +356,7 @@ where /// Resolves socket address(es) and binds server to created listener(s) for plaintext HTTP/1.x /// or HTTP/2 connections. + #[cfg(feature = "http2")] pub fn bind_auto_h2c(mut self, addrs: A) -> io::Result { let sockets = bind_addrs(addrs, self.backlog)?; @@ -453,6 +454,7 @@ where } /// Binds to existing listener for accepting incoming plaintext HTTP/1.x or HTTP/2 connections. + #[cfg(feature = "http2")] pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result { let cfg = self.config.clone(); let factory = self.factory.clone(); From a4c9361791a9204e395ab99cb737cf821b7e2d16 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 18 Jul 2023 02:18:19 +0100 Subject: [PATCH 076/314] ci: fix windows openssl --- .github/workflows/ci-post-merge.yml | 59 ++++++++--------------------- .github/workflows/ci.yml | 8 ++-- actix-multipart/Cargo.toml | 7 ++-- 3 files changed, 22 insertions(+), 52 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 8dd941e04..d293fea95 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -26,39 +26,26 @@ jobs: name: ${{ matrix.target.name }} / ${{ matrix.version }} runs-on: ${{ matrix.target.os }} - env: - CI: 1 - CARGO_INCREMENTAL: 0 - VCPKGRS_DYNAMIC: 1 - CARGO_UNSTABLE_SPARSE_REGISTRY: true - steps: - uses: actions/checkout@v3 - # install OpenSSL on Windows - # TODO: GitHub actions docs state that OpenSSL is - # already installed on these Windows machines somewhere - - name: Set vcpkg root - if: matrix.target.triple == 'x86_64-pc-windows-msvc' - run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install OpenSSL - if: matrix.target.triple == 'x86_64-pc-windows-msvc' - run: vcpkg install openssl:x64-windows - - - name: Install ${{ matrix.version }} + if: matrix.target.os == 'windows-latest' + run: choco install openssl -y --forcex64 --no-progress + - name: Set OpenSSL dir in env + if: matrix.target.os == 'windows-latest' run: | - rustup set profile minimal - rustup install ${{ matrix.version }} - rustup override set ${{ matrix.version }} + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append + + - name: Install Rust (${{ matrix.version }}) + uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: ${{ matrix.version }} - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v2.2.1 - - name: check minimal run: cargo ci-check-min @@ -88,23 +75,15 @@ jobs: name: Verify Feature Combinations runs-on: ubuntu-latest - env: - CI: 1 - CARGO_INCREMENTAL: 0 - steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v2.2.1 - - name: check feature combinations run: cargo ci-check-all-feature-powerset @@ -115,22 +94,14 @@ jobs: name: nextest runs-on: ubuntu-latest - env: - CI: 1 - CARGO_INCREMENTAL: 0 - steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@stable + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1 - name: Install nextest uses: taiki-e/install-action@nextest - - name: Generate Cargo.lock - run: cargo generate-lockfile - - name: Cache Dependencies - uses: Swatinem/rust-cache@v2.2.1 - - name: Test with cargo-nextest run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10e80b751..f85548505 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,17 +29,17 @@ jobs: name: ${{ matrix.target.name }} / ${{ matrix.version }} runs-on: ${{ matrix.target.os }} - env: {} - steps: - uses: actions/checkout@v3 - name: Install OpenSSL if: matrix.target.os == 'windows-latest' - run: choco install openssl + run: choco install openssl -y --forcex64 --no-progress - name: Set OpenSSL dir in env if: matrix.target.os == 'windows-latest' - run: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append + run: | + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version }}) uses: actions-rust-lang/setup-rust-toolchain@v1 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index f186bf8d9..63cd99707 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -19,7 +19,7 @@ all-features = true [features] default = ["tempfile", "derive"] derive = ["actix-multipart-derive"] -tempfile = ["tempfile-dep", "tokio/fs"] +tempfile = ["dep:tempfile", "tokio/fs"] [dependencies] actix-multipart-derive = { version = "=0.6.0", optional = true } @@ -38,9 +38,8 @@ mime = "0.3" serde = "1" serde_json = "1" serde_plain = "1" -# TODO(MSRV 1.60): replace with dep: prefix -tempfile-dep = { package = "tempfile", version = "3.4", optional = true } -tokio = { version = "1.24.2", features = ["io-util", "sync"] } +tempfile-dep = { version = "3.4", optional = true } +tokio = { version = "1.24.2", features = ["sync", "io-util"] } [dev-dependencies] actix-http = "3" From 3b9b38c44e5d0c8775b371154116f04a4ef60ce0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 18 Jul 2023 02:22:09 +0100 Subject: [PATCH 077/314] fix tempfile dep spec --- actix-multipart/Cargo.toml | 2 +- actix-multipart/src/form/tempfile.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 63cd99707..9220e793c 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -38,7 +38,7 @@ mime = "0.3" serde = "1" serde_json = "1" serde_plain = "1" -tempfile-dep = { version = "3.4", optional = true } +tempfile = { version = "3.4", optional = true } tokio = { version = "1.24.2", features = ["sync", "io-util"] } [dev-dependencies] diff --git a/actix-multipart/src/form/tempfile.rs b/actix-multipart/src/form/tempfile.rs index 2f611ba04..9371a026b 100644 --- a/actix-multipart/src/form/tempfile.rs +++ b/actix-multipart/src/form/tempfile.rs @@ -11,7 +11,7 @@ use derive_more::{Display, Error}; use futures_core::future::LocalBoxFuture; use futures_util::TryStreamExt as _; use mime::Mime; -use tempfile_dep::NamedTempFile; +use tempfile::NamedTempFile; use tokio::io::AsyncWriteExt; use super::FieldErrorHandler; From b061f004219b1e970c3801e8ea7df2c007bf2ac3 Mon Sep 17 00:00:00 2001 From: nerix Date: Wed, 19 Jul 2023 12:24:14 +0200 Subject: [PATCH 078/314] Provide documentation in the `middleware` module (#3070) Co-authored-by: Rob Ede --- actix-web/src/app.rs | 11 +- actix-web/src/middleware/mod.rs | 217 ++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+), 10 deletions(-) diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index a4b576b0e..a4cd8d819 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -319,16 +319,7 @@ where /// Middleware can be applied similarly to individual `Scope`s and `Resource`s. /// See [`Scope::wrap`](crate::Scope::wrap) and [`Resource::wrap`]. /// - /// # Middleware Order - /// Notice that the keyword for registering middleware is `wrap`. As you register middleware - /// using `wrap` in the App builder, imagine wrapping layers around an inner App. The first - /// middleware layer exposed to a Request is the outermost layer (i.e., the *last* registered in - /// the builder chain). Consequently, the *first* middleware registered in the builder chain is - /// the *last* to start executing during request processing. - /// - /// Ordering is less obvious when wrapped services also have middleware applied. In this case, - /// middlewares are run in reverse order for `App` _and then_ in reverse order for the - /// wrapped service. + /// For more info on middleware take a look at the [`middleware` module][crate::middleware]. /// /// # Examples /// ``` diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index eb3550b52..8dbd1ff2c 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -1,4 +1,221 @@ //! A collection of common middleware. +//! +//! # What Is Middleware? +//! +//! Actix Web's middleware system allows us to add additional behavior to request/response +//! processing. Middleware can hook into incoming request and outgoing response processes, enabling +//! us to modify requests and responses as well as halt request processing to return a response +//! early. +//! +//! Typically, middleware is involved in the following actions: +//! +//! - Pre-process the request (e.g., [normalizing paths](NormalizePath)) +//! - Post-process a response (e.g., [logging][Logger]) +//! - Modify application state (through [`ServiceRequest`][crate::dev::ServiceRequest]) +//! - Access external services (e.g., [sessions](https://docs.rs/actix-session), etc.) +//! +//! Middleware is registered for each [`App`], [`Scope`](crate::Scope), or +//! [`Resource`](crate::Resource) and executed in opposite order as registration. In general, a +//! middleware is a pair of types that implements the [`Service`] trait and [`Transform`] trait, +//! respectively. The [`new_transform`] and [`call`] methods must return a [`Future`], though it +//! can often be [an immediately-ready one](actix_utils::future::Ready). +//! +//! # Ordering +//! +//! ``` +//! # use actix_web::{web, middleware, get, App, Responder}; +//! # +//! # // some basic types to make sure this compiles +//! # type ExtractorA = web::Json; +//! # type ExtractorB = ExtractorA; +//! #[get("/")] +//! async fn service(a: ExtractorA, b: ExtractorB) -> impl Responder { "Hello, World!" } +//! +//! # fn main() { +//! # // These aren't snake_case, because they are supposed to be unit structs. +//! # let MiddlewareA = middleware::Compress::default(); +//! # let MiddlewareB = middleware::Compress::default(); +//! # let MiddlewareC = middleware::Compress::default(); +//! let app = App::new() +//! .wrap(MiddlewareA) +//! .wrap(MiddlewareB) +//! .wrap(MiddlewareC) +//! .service(service); +//! # } +//! ``` +//! +//! ```plain +//! Request +//! ⭣ +//! ╭────────────────────┼────╮ +//! │ MiddlewareC │ │ +//! │ ╭──────────────────┼───╮│ +//! │ │ MiddlewareB │ ││ +//! │ │ ╭────────────────┼──╮││ +//! │ │ │ MiddlewareA │ │││ +//! │ │ │ ╭──────────────┼─╮│││ +//! │ │ │ │ ExtractorA │ ││││ +//! │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┤│││ +//! │ │ │ │ ExtractorB │ ││││ +//! │ │ │ ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┤│││ +//! │ │ │ │ service │ ││││ +//! │ │ │ ╰──────────────┼─╯│││ +//! │ │ ╰────────────────┼──╯││ +//! │ ╰──────────────────┼───╯│ +//! ╰────────────────────┼────╯ +//! ⭣ +//! Response +//! ``` +//! The request _first_ gets processed by the middleware specified _last_ - `MiddlewareC`. It passes +//! the request (modified a modified one) to the next middleware - `MiddlewareB` - _or_ directly +//! responds to the request (e.g. when the request was invalid or an error occurred). `MiddlewareB` +//! processes the request as well and passes it to `MiddlewareA`, which then passes it to the +//! [`Service`]. In the [`Service`], the extractors will run first. They don't pass the request on, +//! but only view it (see [`FromRequest`]). After the [`Service`] responds to the request, the +//! response it passed back through `MiddlewareA`, `MiddlewareB`, and `MiddlewareC`. +//! +//! As you register middleware using [`wrap`][crate::App::wrap] and [`wrap_fn`][crate::App::wrap_fn] +//! in the [`App`] builder, imagine wrapping layers around an inner [`App`]. The first middleware +//! layer exposed to a Request is the outermost layer (i.e., the _last_ registered in the builder +//! chain, in the example above: `MiddlewareC`). Consequently, the _first_ middleware registered in +//! the builder chain is the _last_ to start executing during request processing (`MiddlewareA`). +//! Ordering is less obvious when wrapped services also have middleware applied. In this case, +//! middleware are run in reverse order for [`App`] _and then_ in reverse order for the wrapped +//! service. +//! +//! # Middleware Traits +//! +//! ## `Transform` +//! +//! The [`Transform`] trait is the builder for the actual [`Service`]s that handle the requests. All +//! the middleware you pass to the `wrap` methods implement this trait. During construction, each +//! thread assembles a chain of [`Service`]s by calling [`new_transform`] and passing the next +//! [`Service`] (`S`) in the chain. The created [`Service`] handles requests of type `Req`. +//! +//! In the example from the [ordering](#ordering) section, the chain would be: +//! +//! ```plain +//! MiddlewareCService { +//! next: MiddlewareBService { +//! next: MiddlewareAService { ... } +//! } +//! } +//! ``` +//! +//! ## `Service` +//! +//! A [`Service`] `S` represents an asynchronous operation that turns a request of type `Req` into a +//! response of type [`S::Response`](crate::dev::Service::Response) or an error of type +//! [`S::Error`](crate::dev::Service::Error). You can think of the service of being roughly: +//! +//! ```ignore +//! async fn(&self, req: Req) -> Result +//! ``` +//! +//! In most cases the [`Service`] implementation will, at some point, call the wrapped [`Service`] +//! in its [`call`] implementation. +//! +//! Note that the [`Service`]s created by [`new_transform`] don't need to be [`Send`] or [`Sync`]. +//! +//! # Example +//! +//! ``` +//! use std::{future::{ready, Ready, Future}, pin::Pin}; +//! +//! use actix_web::{ +//! dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, +//! web, Error, +//! # App +//! }; +//! +//! pub struct SayHi; +//! +//! // `S` - type of the next service +//! // `B` - type of response's body +//! impl Transform for SayHi +//! where +//! S: Service, Error = Error>, +//! S::Future: 'static, +//! B: 'static, +//! { +//! type Response = ServiceResponse; +//! type Error = Error; +//! type InitError = (); +//! type Transform = SayHiMiddleware; +//! type Future = Ready>; +//! +//! fn new_transform(&self, service: S) -> Self::Future { +//! ready(Ok(SayHiMiddleware { service })) +//! } +//! } +//! +//! pub struct SayHiMiddleware { +//! /// The next service to call +//! service: S, +//! } +//! +//! // This future doesn't have the requirement of being `Send`. +//! // See: futures_util::future::LocalBoxFuture +//! type LocalBoxFuture = Pin + 'static>>; +//! +//! // `S`: type of the wrapped service +//! // `B`: type of the body - try to be generic over the body where possible +//! impl Service for SayHiMiddleware +//! where +//! S: Service, Error = Error>, +//! S::Future: 'static, +//! B: 'static, +//! { +//! type Response = ServiceResponse; +//! type Error = Error; +//! type Future = LocalBoxFuture>; +//! +//! // This service is ready when its next service is ready +//! forward_ready!(service); +//! +//! fn call(&self, req: ServiceRequest) -> Self::Future { +//! println!("Hi from start. You requested: {}", req.path()); +//! +//! // A more complex middleware, could return an error or an early response here. +//! +//! let fut = self.service.call(req); +//! +//! Box::pin(async move { +//! let res = fut.await?; +//! +//! println!("Hi from response"); +//! Ok(res) +//! }) +//! } +//! } +//! +//! # fn main() { +//! let app = App::new() +//! .wrap(SayHi) +//! .route("/", web::get().to(|| async { "Hello, middleware!" })); +//! # } +//! ``` +//! +//! # Simpler Middleware +//! +//! In many cases, you _can_ actually use an async function via a helper that will provide a more +//! natural flow for your behavior. +//! +//! The experimental `actix_web_lab` crate provides a [`from_fn`][lab_from_fn] utility which allows +//! an async fn to be wrapped and used in the same way as other middleware. See the +//! [`from_fn`][lab_from_fn] docs for more info and examples of it's use. +//! +//! While [`from_fn`][lab_from_fn] is experimental currently, it's likely this helper will graduate +//! to Actix Web in some form, so feedback is appreciated. +//! +//! [`Future`]: std::future::Future +//! [`App`]: crate::App +//! [`FromRequest`]: crate::FromRequest +//! [`Service`]: crate::dev::Service +//! [`Transform`]: crate::dev::Transform +//! [`call`]: crate::dev::Service::call() +//! [`new_transform`]: crate::dev::Transform::new_transform() +//! [lab_from_fn]: https://docs.rs/actix-web-lab/latest/actix_web_lab/middleware/fn.from_fn.html mod compat; mod condition; From 908fb2606ecd42450b31eb5b19aa186d5b0cd882 Mon Sep 17 00:00:00 2001 From: Kristian Gaylord Date: Wed, 19 Jul 2023 12:48:43 -0400 Subject: [PATCH 079/314] allow configuring number of test server workers (#3069) Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 1 + actix-test/src/lib.rs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index e3a66c663..2a30ee95b 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased - 2023-xx-xx +- Add `TestServerConfig::workers()` setter method - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 0.1.1 - 2023-02-26 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 7781edab4..c667e564d 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -154,7 +154,10 @@ where let srv_cfg = cfg.clone(); let timeout = cfg.client_request_timeout; - let builder = Server::build().workers(1).disable_signals().system_exit(); + let builder = Server::build() + .workers(cfg.workers) + .disable_signals() + .system_exit(); let srv = match srv_cfg.stream { StreamType::Tcp => match srv_cfg.tp { @@ -367,6 +370,7 @@ pub struct TestServerConfig { stream: StreamType, client_request_timeout: Duration, port: u16, + workers: usize, } impl Default for TestServerConfig { @@ -383,6 +387,7 @@ impl TestServerConfig { stream: StreamType::Tcp, client_request_timeout: Duration::from_secs(5), port: 0, + workers: 1, } } @@ -425,6 +430,14 @@ impl TestServerConfig { self.port = port; self } + + /// Sets number of workers in the test server process. + /// + /// By default, the server boots with 1 worker + pub fn workers(mut self, workers: usize) -> Self { + self.workers = workers; + self + } } /// A basic HTTP server controller that simplifies the process of writing integration tests for From 4272510261844dbef1e9ef5c9ee01574bd16a9b7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 19 Jul 2023 19:27:20 +0100 Subject: [PATCH 080/314] doc amendments --- actix-test/CHANGES.md | 2 +- actix-test/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 2a30ee95b..aba27dbfc 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Add `TestServerConfig::workers()` setter method +- Add `TestServerConfig::workers()` setter method. - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 0.1.1 - 2023-02-26 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index c667e564d..751ab3161 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -431,9 +431,9 @@ impl TestServerConfig { self } - /// Sets number of workers in the test server process. + /// Sets number of workers for the test server. /// - /// By default, the server boots with 1 worker + /// By default, the server uses 1 worker pub fn workers(mut self, workers: usize) -> Self { self.workers = workers; self From 80185ce741729108301d26d2cd18598baf1f9af3 Mon Sep 17 00:00:00 2001 From: Nathan Shaaban <86252985+ctrlaltf24@users.noreply.github.com> Date: Wed, 19 Jul 2023 18:51:17 +0000 Subject: [PATCH 081/314] Hide authorization header in httprequest debug output (#2953) Co-authored-by: Nathan Shaaban <86252985+nshaaban-cPacket@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/request.rs | 57 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 6c83d129b..7e82d095a 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -10,6 +10,7 @@ ### Changed - Handler functions can now receive up to 16 extractor parameters. +- Hide sensitive header values in `HttpRequest`'s `Debug` output. - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 4.3.1 - 2023-02-26 diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index 543c9dfbe..ece36a388 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -435,16 +435,28 @@ impl fmt::Debug for HttpRequest { self.inner.head.method, self.path() )?; + if !self.query_string().is_empty() { writeln!(f, " query: ?{:?}", self.query_string())?; } + if !self.match_info().is_empty() { writeln!(f, " params: {:?}", self.match_info())?; } + writeln!(f, " headers:")?; + for (key, val) in self.headers().iter() { - writeln!(f, " {:?}: {:?}", key, val)?; + match key { + // redact sensitive header values from debug output + &crate::http::header::AUTHORIZATION + | &crate::http::header::PROXY_AUTHORIZATION + | &crate::http::header::COOKIE => writeln!(f, " {:?}: {:?}", key, "*redacted*")?, + + _ => writeln!(f, " {:?}: {:?}", key, val)?, + } } + Ok(()) } } @@ -908,4 +920,47 @@ mod tests { let body = read_body(bar_resp).await; assert_eq!(body, "http://localhost:8080/bar/nested"); } + + #[test] + fn authorization_header_hidden_in_debug() { + let authorization_header = "Basic bXkgdXNlcm5hbWU6bXkgcGFzc3dvcmQK"; + let req = TestRequest::get() + .insert_header((crate::http::header::AUTHORIZATION, authorization_header)) + .to_http_request(); + + assert!(!format!("{:?}", req).contains(authorization_header)); + } + + #[test] + fn proxy_authorization_header_hidden_in_debug() { + let proxy_authorization_header = "secret value"; + let req = TestRequest::get() + .insert_header(( + crate::http::header::PROXY_AUTHORIZATION, + proxy_authorization_header, + )) + .to_http_request(); + + assert!(!format!("{:?}", req).contains(proxy_authorization_header)); + } + + #[test] + fn cookie_header_hidden_in_debug() { + let cookie_header = "secret"; + let req = TestRequest::get() + .insert_header((crate::http::header::COOKIE, cookie_header)) + .to_http_request(); + + assert!(!format!("{:?}", req).contains(cookie_header)); + } + + #[test] + fn other_header_visible_in_debug() { + let location_header = "192.0.0.1"; + let req = TestRequest::get() + .insert_header((crate::http::header::LOCATION, location_header)) + .to_http_request(); + + assert!(format!("{:?}", req).contains(location_header)); + } } From db99da5daf8e52f31513921819047fa07a9cf168 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 19 Jul 2023 20:24:32 +0100 Subject: [PATCH 082/314] do not compress media types (#3075) * misc: add temporary nix file * Add test to check content type image/* * misc: add unit test for expected behaviour jpeg * feat(compress): add compress function to middleware * feat(compress): use response content type to decide compress * feat(compress): give more control to the user * misc: improve default compress function * add Compress::with_predicate * remove predicate options * assert auto traits on Compress * fix changelog --------- Co-authored-by: William R. Arellano --- actix-web/CHANGES.md | 1 + actix-web/src/http/header/content_type.rs | 79 ++++++------- actix-web/src/middleware/compress.rs | 129 ++++++++++++++++++++-- 3 files changed, 154 insertions(+), 55 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 7e82d095a..35d695328 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -10,6 +10,7 @@ ### Changed - Handler functions can now receive up to 16 extractor parameters. +- The `Compress` middleware no longer compresses image or video content. - Hide sensitive header values in `HttpRequest`'s `Debug` output. - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. diff --git a/actix-web/src/http/header/content_type.rs b/actix-web/src/http/header/content_type.rs index 41c0c1fc9..bf86afffa 100644 --- a/actix-web/src/http/header/content_type.rs +++ b/actix-web/src/http/header/content_type.rs @@ -3,109 +3,102 @@ use mime::Mime; use super::CONTENT_TYPE; crate::http::header::common_header! { - /// `Content-Type` header, defined - /// in [RFC 7231 §3.1.1.5](https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.5) + /// `Content-Type` header, defined in [RFC 9110 §8.3]. /// - /// The `Content-Type` header field indicates the media type of the - /// associated representation: either the representation enclosed in the - /// message payload or the selected representation, as determined by the - /// message semantics. The indicated media type defines both the data - /// format and how that data is intended to be processed by a recipient, - /// within the scope of the received message semantics, after any content - /// codings indicated by Content-Encoding are decoded. + /// The `Content-Type` header field indicates the media type of the associated representation: + /// either the representation enclosed in the message payload or the selected representation, + /// as determined by the message semantics. The indicated media type defines both the data + /// format and how that data is intended to be processed by a recipient, within the scope of the + /// received message semantics, after any content codings indicated by Content-Encoding are + /// decoded. /// - /// Although the `mime` crate allows the mime options to be any slice, this crate - /// forces the use of Vec. This is to make sure the same header can't have more than 1 type. If - /// this is an issue, it's possible to implement `Header` on a custom struct. + /// Although the `mime` crate allows the mime options to be any slice, this crate forces the use + /// of Vec. This is to make sure the same header can't have more than 1 type. If this is an + /// issue, it's possible to implement `Header` on a custom struct. /// /// # ABNF + /// /// ```plain /// Content-Type = media-type /// ``` /// /// # Example Values - /// * `text/html; charset=utf-8` - /// * `application/json` + /// + /// - `text/html; charset=utf-8` + /// - `application/json` /// /// # Examples - /// ``` - /// use actix_web::HttpResponse; - /// use actix_web::http::header::ContentType; - /// - /// let mut builder = HttpResponse::Ok(); - /// builder.insert_header( - /// ContentType::json() - /// ); - /// ``` /// /// ``` - /// use actix_web::HttpResponse; - /// use actix_web::http::header::ContentType; + /// use actix_web::{http::header::ContentType, HttpResponse}; /// - /// let mut builder = HttpResponse::Ok(); - /// builder.insert_header( - /// ContentType(mime::TEXT_HTML) - /// ); + /// let res_json = HttpResponse::Ok() + /// .insert_header(ContentType::json()); + /// + /// let res_html = HttpResponse::Ok() + /// .insert_header(ContentType(mime::TEXT_HTML)); /// ``` + /// + /// [RFC 9110 §8.3]: https://datatracker.ietf.org/doc/html/rfc9110#section-8.3 (ContentType, CONTENT_TYPE) => [Mime] test_parse_and_format { crate::http::header::common_header_test!( - test1, + test_text_html, vec![b"text/html"], Some(HeaderField(mime::TEXT_HTML))); + crate::http::header::common_header_test!( + test_image_star, + vec![b"image/*"], + Some(HeaderField(mime::IMAGE_STAR))); + } } impl ContentType { - /// A constructor to easily create a `Content-Type: application/json` - /// header. + /// Constructs a `Content-Type: application/json` header. #[inline] pub fn json() -> ContentType { ContentType(mime::APPLICATION_JSON) } - /// A constructor to easily create a `Content-Type: text/plain; - /// charset=utf-8` header. + /// Constructs a `Content-Type: text/plain; charset=utf-8` header. #[inline] pub fn plaintext() -> ContentType { ContentType(mime::TEXT_PLAIN_UTF_8) } - /// A constructor to easily create a `Content-Type: text/html; charset=utf-8` - /// header. + /// Constructs a `Content-Type: text/html; charset=utf-8` header. #[inline] pub fn html() -> ContentType { ContentType(mime::TEXT_HTML_UTF_8) } - /// A constructor to easily create a `Content-Type: text/xml` header. + /// Constructs a `Content-Type: text/xml` header. #[inline] pub fn xml() -> ContentType { ContentType(mime::TEXT_XML) } - /// A constructor to easily create a `Content-Type: - /// application/www-form-url-encoded` header. + /// Constructs a `Content-Type: application/www-form-url-encoded` header. #[inline] pub fn form_url_encoded() -> ContentType { ContentType(mime::APPLICATION_WWW_FORM_URLENCODED) } - /// A constructor to easily create a `Content-Type: image/jpeg` header. + /// Constructs a `Content-Type: image/jpeg` header. #[inline] pub fn jpeg() -> ContentType { ContentType(mime::IMAGE_JPEG) } - /// A constructor to easily create a `Content-Type: image/png` header. + /// Constructs a `Content-Type: image/png` header. #[inline] pub fn png() -> ContentType { ContentType(mime::IMAGE_PNG) } - /// A constructor to easily create a `Content-Type: - /// application/octet-stream` header. + /// Constructs a `Content-Type: application/octet-stream` header. #[inline] pub fn octet_stream() -> ContentType { ContentType(mime::APPLICATION_OCTET_STREAM) diff --git a/actix-web/src/middleware/compress.rs b/actix-web/src/middleware/compress.rs index 51b44c6ef..a55b46264 100644 --- a/actix-web/src/middleware/compress.rs +++ b/actix-web/src/middleware/compress.rs @@ -11,13 +11,14 @@ use actix_http::encoding::Encoder; use actix_service::{Service, Transform}; use actix_utils::future::{ok, Either, Ready}; use futures_core::ready; +use mime::Mime; use once_cell::sync::Lazy; use pin_project_lite::pin_project; use crate::{ body::{EitherBody, MessageBody}, http::{ - header::{self, AcceptEncoding, Encoding, HeaderValue}, + header::{self, AcceptEncoding, ContentEncoding, Encoding, HeaderValue}, StatusCode, }, service::{ServiceRequest, ServiceResponse}, @@ -170,19 +171,40 @@ where { type Output = Result>>, Error>; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let this = self.project(); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.as_mut().project(); match ready!(this.fut.poll(cx)) { Ok(resp) => { let enc = match this.encoding { Encoding::Known(enc) => *enc, Encoding::Unknown(enc) => { - unimplemented!("encoding {} should not be here", enc); + unimplemented!("encoding '{enc}' should not be here"); } }; Poll::Ready(Ok(resp.map_body(move |head, body| { + let content_type = head.headers.get(header::CONTENT_TYPE); + + fn default_compress_predicate(content_type: Option<&HeaderValue>) -> bool { + match content_type { + None => true, + Some(hdr) => { + match hdr.to_str().ok().and_then(|hdr| hdr.parse::().ok()) { + Some(mime) if mime.type_().as_str() == "image" => false, + Some(mime) if mime.type_().as_str() == "video" => false, + _ => true, + } + } + } + } + + let enc = if default_compress_predicate(content_type) { + enc + } else { + ContentEncoding::Identity + }; + EitherBody::left(Encoder::response(enc, head, body)) }))) } @@ -246,8 +268,18 @@ static SUPPORTED_ENCODINGS: &[Encoding] = &[ mod tests { use std::collections::HashSet; + use static_assertions::assert_impl_all; + use super::*; - use crate::{middleware::DefaultHeaders, test, web, App}; + use crate::{http::header::ContentType, middleware::DefaultHeaders, test, web, App}; + + const HTML_DATA_PART: &str = "

hello world

) -> Vec { use std::io::Read as _; @@ -257,23 +289,55 @@ mod tests { buf } + #[track_caller] + fn assert_successful_res_with_content_type(res: &ServiceResponse, ct: &str) { + assert!(res.status().is_success()); + assert!( + res.headers() + .get(header::CONTENT_TYPE) + .expect("content-type header should be present") + .to_str() + .expect("content-type header should be utf-8") + .contains(ct), + "response's content-type did not match {}", + ct + ); + } + + #[track_caller] + fn assert_successful_gzip_res_with_content_type(res: &ServiceResponse, ct: &str) { + assert_successful_res_with_content_type(res, ct); + assert_eq!( + res.headers() + .get(header::CONTENT_ENCODING) + .expect("response should be gzip compressed"), + "gzip", + ); + } + + #[track_caller] + fn assert_successful_identity_res_with_content_type(res: &ServiceResponse, ct: &str) { + assert_successful_res_with_content_type(res, ct); + assert!( + res.headers().get(header::CONTENT_ENCODING).is_none(), + "response should not be compressed", + ); + } + #[actix_rt::test] async fn prevents_double_compressing() { - const D: &str = "hello world "; - const DATA: &str = const_str::repeat!(D, 100); - let app = test::init_service({ App::new() .wrap(Compress::default()) .route( "/single", - web::get().to(move || HttpResponse::Ok().body(DATA)), + web::get().to(move || HttpResponse::Ok().body(TEXT_DATA)), ) .service( web::resource("/double") .wrap(Compress::default()) .wrap(DefaultHeaders::new().add(("x-double", "true"))) - .route(web::get().to(move || HttpResponse::Ok().body(DATA))), + .route(web::get().to(move || HttpResponse::Ok().body(TEXT_DATA))), ) }) .await; @@ -287,7 +351,7 @@ mod tests { assert_eq!(res.headers().get("x-double"), None); assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "gzip"); let bytes = test::read_body(res).await; - assert_eq!(gzip_decode(bytes), DATA.as_bytes()); + assert_eq!(gzip_decode(bytes), TEXT_DATA.as_bytes()); let req = test::TestRequest::default() .uri("/double") @@ -298,7 +362,7 @@ mod tests { assert_eq!(res.headers().get("x-double").unwrap(), "true"); assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "gzip"); let bytes = test::read_body(res).await; - assert_eq!(gzip_decode(bytes), DATA.as_bytes()); + assert_eq!(gzip_decode(bytes), TEXT_DATA.as_bytes()); } #[actix_rt::test] @@ -324,4 +388,45 @@ mod tests { assert!(vary_headers.contains(&HeaderValue::from_static("x-test"))); assert!(vary_headers.contains(&HeaderValue::from_static("accept-encoding"))); } + + fn configure_predicate_test(cfg: &mut web::ServiceConfig) { + cfg.route( + "/html", + web::get().to(|| { + HttpResponse::Ok() + .content_type(ContentType::html()) + .body(HTML_DATA) + }), + ) + .route( + "/image", + web::get().to(|| { + HttpResponse::Ok() + .content_type(ContentType::jpeg()) + .body(TEXT_DATA) + }), + ); + } + + #[actix_rt::test] + async fn prevents_compression_jpeg() { + let app = test::init_service( + App::new() + .wrap(Compress::default()) + .configure(configure_predicate_test), + ) + .await; + + let req = + test::TestRequest::with_uri("/html").insert_header((header::ACCEPT_ENCODING, "gzip")); + let res = test::call_service(&app, req.to_request()).await; + assert_successful_gzip_res_with_content_type(&res, "text/html"); + assert_ne!(test::read_body(res).await, HTML_DATA.as_bytes()); + + let req = + test::TestRequest::with_uri("/image").insert_header((header::ACCEPT_ENCODING, "gzip")); + let res = test::call_service(&app, req.to_request()).await; + assert_successful_identity_res_with_content_type(&res, "image/jpeg"); + assert_eq!(test::read_body(res).await, TEXT_DATA.as_bytes()); + } } From 67cee2915d9bb89b9778f72f5981345deb476977 Mon Sep 17 00:00:00 2001 From: Vasiliy Taranov Date: Thu, 20 Jul 2023 01:37:48 +0300 Subject: [PATCH 083/314] set up dependabot (#3019) Co-authored-by: Rob Ede --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..1a54090f0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 10 + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 10 From 6d452d497795652fde51263db8a49ba7b8ba065d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 23:42:40 +0100 Subject: [PATCH 084/314] Bump codecov/codecov-action from 1 to 3 (#3077) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- .github/workflows/coverage.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d537031c3..42f16450d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -29,5 +29,6 @@ jobs: cargo install cargo-tarpaulin --vers "^0.13" cargo tarpaulin --workspace --features=rustls,openssl --out Xml --verbose - name: Upload to Codecov - uses: codecov/codecov-action@v1 - with: { file: cobertura.xml } + uses: codecov/codecov-action@v3.1.4 + with: + file: cobertura.xml From e25f3f8f1d48cde9f5938dd7cc65c2cd683821a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jul 2023 23:43:25 +0100 Subject: [PATCH 085/314] Bump JamesIves/github-pages-deploy-action from 4.4.1 to 4.4.3 (#3076) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .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 743e14412..05b81411d 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -32,7 +32,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.4.1 + uses: JamesIves/github-pages-deploy-action@v4.4.3 with: folder: target/doc single-commit: true From d22c9f9fb12db30ee1cb7183ce8cf395c707f30d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 20 Jul 2023 10:49:01 +0100 Subject: [PATCH 086/314] update syn to 2 in web codegen (#3081) --- actix-multipart-derive/CHANGES.md | 1 + actix-multipart-derive/Cargo.toml | 4 +- actix-router/src/resource.rs | 3 +- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/Cargo.toml | 4 +- actix-web-codegen/src/route.rs | 223 ++++++++++-------- .../trybuild/routes-missing-args-fail.stderr | 12 +- .../tests/trybuild/simple-fail.stderr | 32 ++- 8 files changed, 164 insertions(+), 116 deletions(-) diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index caf75aeb3..8a78900ec 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 0.6.0 - 2023-02-26 diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index aca6de84a..41e687e50 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -17,11 +17,11 @@ all-features = true proc-macro = true [dependencies] -darling = "0.14" +darling = "0.20" parse-size = "1" proc-macro2 = "1" quote = "1" -syn = "1" +syn = "2" [dev-dependencies] actix-multipart = "0.6" diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index 860993a37..b8aa6c224 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -252,7 +252,7 @@ impl ResourceDef { /// Multi-pattern resources can be constructed by providing a slice (or vec) of patterns. /// /// # Panics - /// Panics if path pattern is malformed. + /// Panics if any path patterns are malformed. /// /// # Examples /// ``` @@ -838,6 +838,7 @@ impl ResourceDef { fn construct(paths: T, is_prefix: bool) -> Self { let patterns = paths.patterns(); + let (pat_type, segments) = match &patterns { Patterns::Single(pattern) => ResourceDef::parse(pattern, is_prefix, false), diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index b9e4b0aad..2c5f17226 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased - 2023-xx-xx +- Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. ## 4.2.0 - 2023-02-26 diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 4f2fdc566..c202c5d6e 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -18,10 +18,10 @@ proc-macro = true actix-router = "0.5" proc-macro2 = "1" quote = "1" -syn = { version = "1", features = ["full", "extra-traits"] } +syn = { version = "2", features = ["full", "extra-traits"] } [dev-dependencies] -actix-macros = "0.2.3" +actix-macros = "0.2.4" actix-rt = "2.2" actix-test = "0.1" actix-utils = "3" diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index e87d37941..525a1c8ba 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -4,7 +4,54 @@ use actix_router::ResourceDef; use proc_macro::TokenStream; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens, TokenStreamExt}; -use syn::{parse_macro_input, AttributeArgs, Ident, LitStr, Meta, NestedMeta, Path}; +use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token}; + +#[derive(Debug)] +pub struct RouteArgs { + path: syn::LitStr, + options: Punctuated, +} + +impl syn::parse::Parse for RouteArgs { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { + // path to match: "/foo" + let path = input.parse::().map_err(|mut err| { + err.combine(syn::Error::new( + err.span(), + r#"invalid service definition, expected #[("")]"#, + )); + + err + })?; + + // verify that path pattern is valid + let _ = ResourceDef::new(path.value()); + + // if there's no comma, assume that no options are provided + if !input.peek(Token![,]) { + return Ok(Self { + path, + options: Punctuated::new(), + }); + } + + // advance past comma separator + input.parse::()?; + + // if next char is a literal, assume that it is a string and show multi-path error + if input.cursor().literal().is_some() { + return Err(syn::Error::new( + Span::call_site(), + r#"Multiple paths specified! There should be only one."#, + )); + } + + // zero or more options: name = "foo" + let options = input.parse_terminated(syn::MetaNameValue::parse, Token![,])?; + + Ok(Self { path, options }) + } +} macro_rules! standard_method_type { ( @@ -182,111 +229,90 @@ struct Args { } impl Args { - fn new(args: AttributeArgs, method: Option) -> syn::Result { - let mut path = None; + fn new(args: RouteArgs, method: Option) -> syn::Result { let mut resource_name = None; let mut guards = Vec::new(); let mut wrappers = Vec::new(); let mut methods = HashSet::new(); - if args.is_empty() { - return Err(syn::Error::new( - Span::call_site(), - format!( - r#"invalid service definition, expected #[{}("")]"#, - method - .map_or("route", |it| it.as_str()) - .to_ascii_lowercase() - ), - )); - } - let is_route_macro = method.is_none(); if let Some(method) = method { methods.insert(MethodTypeExt::Standard(method)); } - for arg in args { - match arg { - NestedMeta::Lit(syn::Lit::Str(lit)) => match path { - None => { - let _ = ResourceDef::new(lit.value()); - path = Some(lit); - } - _ => { - return Err(syn::Error::new_spanned( - lit, - "Multiple paths specified! Should be only one!", - )); - } - }, - - NestedMeta::Meta(syn::Meta::NameValue(nv)) => { - if nv.path.is_ident("name") { - if let syn::Lit::Str(lit) = nv.lit { - resource_name = Some(lit); - } else { - return Err(syn::Error::new_spanned( - nv.lit, - "Attribute name expects literal string!", - )); - } - } else if nv.path.is_ident("guard") { - if let syn::Lit::Str(lit) = nv.lit { - guards.push(lit.parse::()?); - } else { - return Err(syn::Error::new_spanned( - nv.lit, - "Attribute guard expects literal string!", - )); - } - } else if nv.path.is_ident("wrap") { - if let syn::Lit::Str(lit) = nv.lit { - wrappers.push(lit.parse()?); - } else { - return Err(syn::Error::new_spanned( - nv.lit, - "Attribute wrap expects type", - )); - } - } else if nv.path.is_ident("method") { - if !is_route_macro { - return Err(syn::Error::new_spanned( + for nv in args.options { + if nv.path.is_ident("name") { + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) = nv.value + { + resource_name = Some(lit); + } else { + return Err(syn::Error::new_spanned( + nv.value, + "Attribute name expects literal string!", + )); + } + } else if nv.path.is_ident("guard") { + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) = nv.value + { + guards.push(lit.parse::()?); + } else { + return Err(syn::Error::new_spanned( + nv.value, + "Attribute guard expects literal string!", + )); + } + } else if nv.path.is_ident("wrap") { + if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) = nv.value + { + wrappers.push(lit.parse()?); + } else { + return Err(syn::Error::new_spanned( + nv.value, + "Attribute wrap expects type", + )); + } + } else if nv.path.is_ident("method") { + if !is_route_macro { + return Err(syn::Error::new_spanned( &nv, "HTTP method forbidden here. To handle multiple methods, use `route` instead", )); - } else if let syn::Lit::Str(ref lit) = nv.lit { - if !methods.insert(MethodTypeExt::try_from(lit)?) { - return Err(syn::Error::new_spanned( - &nv.lit, - format!( - "HTTP method defined more than once: `{}`", - lit.value() - ), - )); - } - } else { - return Err(syn::Error::new_spanned( - nv.lit, - "Attribute method expects literal string!", - )); - } - } else { + } else if let syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(lit), + .. + }) = nv.value.clone() + { + if !methods.insert(MethodTypeExt::try_from(&lit)?) { return Err(syn::Error::new_spanned( - nv.path, - "Unknown attribute key is specified. Allowed: guard, method and wrap", + nv.value, + format!("HTTP method defined more than once: `{}`", lit.value()), )); } + } else { + return Err(syn::Error::new_spanned( + nv.value, + "Attribute method expects literal string!", + )); } - - arg => { - return Err(syn::Error::new_spanned(arg, "Unknown attribute.")); - } + } else { + return Err(syn::Error::new_spanned( + nv.path, + "Unknown attribute key is specified. Allowed: guard, method and wrap", + )); } } Ok(Args { - path: path.unwrap(), + path: args.path, resource_name, guards, wrappers, @@ -312,11 +338,7 @@ pub struct Route { } impl Route { - pub fn new( - args: AttributeArgs, - ast: syn::ItemFn, - method: Option, - ) -> syn::Result { + pub fn new(args: RouteArgs, ast: syn::ItemFn, method: Option) -> syn::Result { let name = ast.sig.ident.clone(); // Try and pull out the doc comments so that we can reapply them to the generated struct. @@ -324,7 +346,7 @@ impl Route { let doc_attributes = ast .attrs .iter() - .filter(|attr| attr.path.is_ident("doc")) + .filter(|attr| attr.path().is_ident("doc")) .cloned() .collect(); @@ -360,7 +382,7 @@ impl Route { let doc_attributes = ast .attrs .iter() - .filter(|attr| attr.path.is_ident("doc")) + .filter(|attr| attr.path().is_ident("doc")) .cloned() .collect(); @@ -455,7 +477,11 @@ pub(crate) fn with_method( args: TokenStream, input: TokenStream, ) -> TokenStream { - let args = parse_macro_input!(args as syn::AttributeArgs); + let args = match syn::parse(args) { + Ok(args) => args, + // on parse error, make IDEs happy; see fn docs + Err(err) => return input_and_compile_error(input, err), + }; let ast = match syn::parse::(input.clone()) { Ok(ast) => ast, @@ -480,7 +506,7 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream { let (methods, others) = ast .attrs .into_iter() - .map(|attr| match MethodType::from_path(&attr.path) { + .map(|attr| match MethodType::from_path(attr.path()) { Ok(method) => Ok((method, attr)), Err(_) => Err(attr), }) @@ -492,13 +518,8 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream { .into_iter() .map(Result::unwrap) .map(|(method, attr)| { - attr.parse_meta().and_then(|args| { - if let Meta::List(args) = args { - Args::new(args.nested.into_iter().collect(), Some(method)) - } else { - Err(syn::Error::new_spanned(attr, "Invalid input for macro")) - } - }) + attr.parse_args() + .and_then(|args| Args::new(args, Some(method))) }) .collect::, _>>() { diff --git a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr index e845241a4..2e84c296a 100644 --- a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr +++ b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr @@ -1,4 +1,4 @@ -error: invalid service definition, expected #[get("")] +error: unexpected end of input, expected string literal --> tests/trybuild/routes-missing-args-fail.rs:4:1 | 4 | #[get] @@ -6,11 +6,19 @@ error: invalid service definition, expected #[get("")] | = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info) -error: Invalid input for macro +error: invalid service definition, expected #[("")] --> tests/trybuild/routes-missing-args-fail.rs:4:1 | 4 | #[get] | ^^^^^^ + | + = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected attribute arguments in parentheses: #[get(...)] + --> tests/trybuild/routes-missing-args-fail.rs:4:3 + | +4 | #[get] + | ^^^ error[E0277]: the trait bound `fn() -> impl std::future::Future {index}: HttpServiceFactory` is not satisfied --> tests/trybuild/routes-missing-args-fail.rs:13:55 diff --git a/actix-web-codegen/tests/trybuild/simple-fail.stderr b/actix-web-codegen/tests/trybuild/simple-fail.stderr index cffc81ff8..3b3f9d850 100644 --- a/actix-web-codegen/tests/trybuild/simple-fail.stderr +++ b/actix-web-codegen/tests/trybuild/simple-fail.stderr @@ -1,26 +1,42 @@ -error: Unknown attribute. - --> $DIR/simple-fail.rs:3:15 +error: expected `=` + --> $DIR/simple-fail.rs:3:1 | 3 | #[get("/one", other)] - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `get` (in Nightly builds, run with -Z macro-backtrace for more info) -error: expected identifier or literal +error: expected string literal --> $DIR/simple-fail.rs:8:8 | 8 | #[post(/two)] | ^ -error: Unknown attribute. +error: invalid service definition, expected #[("")] + --> $DIR/simple-fail.rs:8:8 + | +8 | #[post(/two)] + | ^ + +error: expected string literal --> $DIR/simple-fail.rs:15:9 | 15 | #[patch(PATCH_PATH)] | ^^^^^^^^^^ -error: Multiple paths specified! Should be only one! - --> $DIR/simple-fail.rs:20:19 +error: invalid service definition, expected #[("")] + --> $DIR/simple-fail.rs:15:9 + | +15 | #[patch(PATCH_PATH)] + | ^^^^^^^^^^ + +error: Multiple paths specified! There should be only one. + --> $DIR/simple-fail.rs:20:1 | 20 | #[delete("/four", "/five")] - | ^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `delete` (in Nightly builds, run with -Z macro-backtrace for more info) error: HTTP method forbidden here. To handle multiple methods, use `route` instead --> $DIR/simple-fail.rs:25:19 From 1040bc3d17e491d133da733c419c00d727846600 Mon Sep 17 00:00:00 2001 From: cyqsimon <28627918+cyqsimon@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:36:49 +0800 Subject: [PATCH 087/314] Add missing status code constructor methods on `HttpResponse` (#3042) --- actix-web/CHANGES.md | 1 + actix-web/src/response/http_codes.rs | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 35d695328..e96f852e5 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -6,6 +6,7 @@ - Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature. - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. +- Add several missing convenience methods on `HttpResponse` for their respective status codes. ### Changed diff --git a/actix-web/src/response/http_codes.rs b/actix-web/src/response/http_codes.rs index 2ac83046a..db5f392c9 100644 --- a/actix-web/src/response/http_codes.rs +++ b/actix-web/src/response/http_codes.rs @@ -25,12 +25,12 @@ impl HttpResponse { NonAuthoritativeInformation, StatusCode::NON_AUTHORITATIVE_INFORMATION ); - static_resp!(NoContent, StatusCode::NO_CONTENT); static_resp!(ResetContent, StatusCode::RESET_CONTENT); static_resp!(PartialContent, StatusCode::PARTIAL_CONTENT); static_resp!(MultiStatus, StatusCode::MULTI_STATUS); static_resp!(AlreadyReported, StatusCode::ALREADY_REPORTED); + static_resp!(ImUsed, StatusCode::IM_USED); static_resp!(MultipleChoices, StatusCode::MULTIPLE_CHOICES); static_resp!(MovedPermanently, StatusCode::MOVED_PERMANENTLY); @@ -42,10 +42,10 @@ impl HttpResponse { static_resp!(PermanentRedirect, StatusCode::PERMANENT_REDIRECT); static_resp!(BadRequest, StatusCode::BAD_REQUEST); - static_resp!(NotFound, StatusCode::NOT_FOUND); static_resp!(Unauthorized, StatusCode::UNAUTHORIZED); static_resp!(PaymentRequired, StatusCode::PAYMENT_REQUIRED); static_resp!(Forbidden, StatusCode::FORBIDDEN); + static_resp!(NotFound, StatusCode::NOT_FOUND); static_resp!(MethodNotAllowed, StatusCode::METHOD_NOT_ALLOWED); static_resp!(NotAcceptable, StatusCode::NOT_ACCEPTABLE); static_resp!( @@ -57,13 +57,18 @@ impl HttpResponse { static_resp!(Gone, StatusCode::GONE); static_resp!(LengthRequired, StatusCode::LENGTH_REQUIRED); static_resp!(PreconditionFailed, StatusCode::PRECONDITION_FAILED); - static_resp!(PreconditionRequired, StatusCode::PRECONDITION_REQUIRED); static_resp!(PayloadTooLarge, StatusCode::PAYLOAD_TOO_LARGE); static_resp!(UriTooLong, StatusCode::URI_TOO_LONG); static_resp!(UnsupportedMediaType, StatusCode::UNSUPPORTED_MEDIA_TYPE); static_resp!(RangeNotSatisfiable, StatusCode::RANGE_NOT_SATISFIABLE); static_resp!(ExpectationFailed, StatusCode::EXPECTATION_FAILED); + static_resp!(ImATeapot, StatusCode::IM_A_TEAPOT); + static_resp!(MisdirectedRequest, StatusCode::MISDIRECTED_REQUEST); static_resp!(UnprocessableEntity, StatusCode::UNPROCESSABLE_ENTITY); + static_resp!(Locked, StatusCode::LOCKED); + static_resp!(FailedDependency, StatusCode::FAILED_DEPENDENCY); + static_resp!(UpgradeRequired, StatusCode::UPGRADE_REQUIRED); + static_resp!(PreconditionRequired, StatusCode::PRECONDITION_REQUIRED); static_resp!(TooManyRequests, StatusCode::TOO_MANY_REQUESTS); static_resp!( RequestHeaderFieldsTooLarge, @@ -83,6 +88,11 @@ impl HttpResponse { static_resp!(VariantAlsoNegotiates, StatusCode::VARIANT_ALSO_NEGOTIATES); static_resp!(InsufficientStorage, StatusCode::INSUFFICIENT_STORAGE); static_resp!(LoopDetected, StatusCode::LOOP_DETECTED); + static_resp!(NotExtended, StatusCode::NOT_EXTENDED); + static_resp!( + NetworkAuthenticationRequired, + StatusCode::NETWORK_AUTHENTICATION_REQUIRED + ); } #[cfg(test)] From 3eb5a059ade249dae4468a8bb6eb5784e1dfdb10 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 20 Jul 2023 11:02:15 +0100 Subject: [PATCH 088/314] chore: address clippy warnings --- actix-http/src/encoding/mod.rs | 2 +- actix-http/src/ws/mask.rs | 2 +- actix-http/tests/test_server.rs | 8 ++--- actix-router/src/resource.rs | 7 +++- actix-web/src/http/header/accept.rs | 8 ++--- actix-web/src/http/header/accept_charset.rs | 2 +- actix-web/src/http/header/accept_encoding.rs | 14 ++++---- actix-web/src/http/header/accept_language.rs | 12 +++---- actix-web/src/http/header/allow.rs | 6 ++-- actix-web/src/http/header/cache_control.rs | 12 +++---- actix-web/src/http/header/content_language.rs | 4 +-- actix-web/src/http/header/content_range.rs | 36 ++++++++----------- actix-web/src/http/header/content_type.rs | 4 +-- actix-web/src/http/header/date.rs | 2 +- actix-web/src/http/header/etag.rs | 30 ++++++++-------- actix-web/src/http/header/expires.rs | 2 +- actix-web/src/http/header/if_match.rs | 6 ++-- .../src/http/header/if_modified_since.rs | 2 +- actix-web/src/http/header/if_none_match.rs | 10 +++--- actix-web/src/http/header/if_range.rs | 6 ++-- .../src/http/header/if_unmodified_since.rs | 2 +- actix-web/src/http/header/last_modified.rs | 2 +- 22 files changed, 87 insertions(+), 92 deletions(-) diff --git a/actix-http/src/encoding/mod.rs b/actix-http/src/encoding/mod.rs index 7823f3979..6801b5fb0 100644 --- a/actix-http/src/encoding/mod.rs +++ b/actix-http/src/encoding/mod.rs @@ -12,7 +12,7 @@ pub use self::{decoder::Decoder, encoder::Encoder}; /// Special-purpose writer for streaming (de-)compression. /// /// Pre-allocates 8KiB of capacity. -pub(self) struct Writer { +struct Writer { buf: BytesMut, } diff --git a/actix-http/src/ws/mask.rs b/actix-http/src/ws/mask.rs index be72e5631..115a8cf9b 100644 --- a/actix-http/src/ws/mask.rs +++ b/actix-http/src/ws/mask.rs @@ -50,7 +50,7 @@ mod tests { #[test] fn test_apply_mask() { let mask = [0x6d, 0xb6, 0xb2, 0x80]; - let unmasked = vec![ + let unmasked = [ 0xf3, 0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x82, 0xff, 0xfe, 0x00, 0x17, 0x74, 0xf9, 0x12, 0x03, ]; diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index cfb4d17b8..f55b1b36c 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::{ convert::Infallible, io::{Read, Write}, @@ -139,7 +137,7 @@ async fn expect_continue_h1() { #[actix_rt::test] async fn chunked_payload() { - let chunk_sizes = vec![32768, 32, 32768]; + let chunk_sizes = [32768, 32, 32768]; let total_size: usize = chunk_sizes.iter().sum(); let mut srv = test_server(|| { @@ -402,7 +400,7 @@ async fn content_length() { let mut srv = test_server(|| { HttpService::build() .h1(|req: Request| { - let indx: usize = req.uri().path()[1..].parse().unwrap(); + let idx: usize = req.uri().path()[1..].parse().unwrap(); let statuses = [ StatusCode::NO_CONTENT, StatusCode::CONTINUE, @@ -411,7 +409,7 @@ async fn content_length() { StatusCode::OK, StatusCode::NOT_FOUND, ]; - ok::<_, Infallible>(Response::new(statuses[indx])) + ok::<_, Infallible>(Response::new(statuses[idx])) }) .tcp() }) diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index b8aa6c224..a3e89a1fe 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -1529,7 +1529,12 @@ mod tests { assert!(!resource.resource_path_from_iter(&mut s, &mut ["item"].iter())); let mut s = String::new(); - assert!(resource.resource_path_from_iter(&mut s, &mut vec!["item", "item2"].iter())); + + assert!(resource.resource_path_from_iter( + &mut s, + #[allow(clippy::useless_vec)] + &mut vec!["item", "item2"].iter() + )); assert_eq!(s, "/user/item/item2/"); } diff --git a/actix-web/src/http/header/accept.rs b/actix-web/src/http/header/accept.rs index 1be136b19..99c95175f 100644 --- a/actix-web/src/http/header/accept.rs +++ b/actix-web/src/http/header/accept.rs @@ -78,7 +78,7 @@ common_header! { // Tests from the RFC crate::http::header::common_header_test!( test1, - vec![b"audio/*; q=0.2, audio/basic"], + [b"audio/*; q=0.2, audio/basic"], Some(Accept(vec![ QualityItem::new("audio/*".parse().unwrap(), q(0.2)), QualityItem::max("audio/basic".parse().unwrap()), @@ -86,7 +86,7 @@ common_header! { crate::http::header::common_header_test!( test2, - vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"], + [b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"], Some(Accept(vec![ QualityItem::new(mime::TEXT_PLAIN, q(0.5)), QualityItem::max(mime::TEXT_HTML), @@ -99,13 +99,13 @@ common_header! { // Custom tests crate::http::header::common_header_test!( test3, - vec![b"text/plain; charset=utf-8"], + [b"text/plain; charset=utf-8"], Some(Accept(vec![ QualityItem::max(mime::TEXT_PLAIN_UTF_8), ]))); crate::http::header::common_header_test!( test4, - vec![b"text/plain; charset=utf-8; q=0.5"], + [b"text/plain; charset=utf-8; q=0.5"], Some(Accept(vec![ QualityItem::new(mime::TEXT_PLAIN_UTF_8, q(0.5)), ]))); diff --git a/actix-web/src/http/header/accept_charset.rs b/actix-web/src/http/header/accept_charset.rs index c7f7e1a68..43a7861fe 100644 --- a/actix-web/src/http/header/accept_charset.rs +++ b/actix-web/src/http/header/accept_charset.rs @@ -57,6 +57,6 @@ common_header! { test_parse_and_format { // Test case from RFC - common_header_test!(test1, vec![b"iso-8859-5, unicode-1-1;q=0.8"]); + common_header_test!(test1, [b"iso-8859-5, unicode-1-1;q=0.8"]); } } diff --git a/actix-web/src/http/header/accept_encoding.rs b/actix-web/src/http/header/accept_encoding.rs index 715126a03..cc80e7bb0 100644 --- a/actix-web/src/http/header/accept_encoding.rs +++ b/actix-web/src/http/header/accept_encoding.rs @@ -50,31 +50,31 @@ common_header! { (AcceptEncoding, header::ACCEPT_ENCODING) => (QualityItem>)* test_parse_and_format { - common_header_test!(no_headers, vec![b""; 0], Some(AcceptEncoding(vec![]))); - common_header_test!(empty_header, vec![b""; 1], Some(AcceptEncoding(vec![]))); + common_header_test!(no_headers, [b""; 0], Some(AcceptEncoding(vec![]))); + common_header_test!(empty_header, [b""; 1], Some(AcceptEncoding(vec![]))); common_header_test!( order_of_appearance, - vec![b"br, gzip"], + [b"br, gzip"], Some(AcceptEncoding(vec![ QualityItem::max(Preference::Specific(Encoding::brotli())), QualityItem::max(Preference::Specific(Encoding::gzip())), ])) ); - common_header_test!(any, vec![b"*"], Some(AcceptEncoding(vec![ + common_header_test!(any, [b"*"], Some(AcceptEncoding(vec![ QualityItem::max(Preference::Any), ]))); // Note: Removed quality 1 from gzip - common_header_test!(implicit_quality, vec![b"gzip, identity; q=0.5, *;q=0"]); + common_header_test!(implicit_quality, [b"gzip, identity; q=0.5, *;q=0"]); // Note: Removed quality 1 from gzip - common_header_test!(implicit_quality_out_of_order, vec![b"compress;q=0.5, gzip"]); + common_header_test!(implicit_quality_out_of_order, [b"compress;q=0.5, gzip"]); common_header_test!( only_gzip_no_identity, - vec![b"gzip, *; q=0"], + [b"gzip, *; q=0"], Some(AcceptEncoding(vec![ QualityItem::max(Preference::Specific(Encoding::gzip())), QualityItem::zero(Preference::Any), diff --git a/actix-web/src/http/header/accept_language.rs b/actix-web/src/http/header/accept_language.rs index 9943e121f..b1d588f8d 100644 --- a/actix-web/src/http/header/accept_language.rs +++ b/actix-web/src/http/header/accept_language.rs @@ -58,19 +58,19 @@ common_header! { (AcceptLanguage, header::ACCEPT_LANGUAGE) => (QualityItem>)* test_parse_and_format { - common_header_test!(no_headers, vec![b""; 0], Some(AcceptLanguage(vec![]))); + common_header_test!(no_headers, [b""; 0], Some(AcceptLanguage(vec![]))); - common_header_test!(empty_header, vec![b""; 1], Some(AcceptLanguage(vec![]))); + common_header_test!(empty_header, [b""; 1], Some(AcceptLanguage(vec![]))); common_header_test!( example_from_rfc, - vec![b"da, en-gb;q=0.8, en;q=0.7"] + [b"da, en-gb;q=0.8, en;q=0.7"] ); common_header_test!( not_ordered_by_weight, - vec![b"en-US, en; q=0.5, fr"], + [b"en-US, en; q=0.5, fr"], Some(AcceptLanguage(vec![ QualityItem::max("en-US".parse().unwrap()), QualityItem::new("en".parse().unwrap(), q(0.5)), @@ -80,7 +80,7 @@ common_header! { common_header_test!( has_wildcard, - vec![b"fr-CH, fr; q=0.9, en; q=0.8, de; q=0.7, *; q=0.5"], + [b"fr-CH, fr; q=0.9, en; q=0.8, de; q=0.7, *; q=0.5"], Some(AcceptLanguage(vec![ QualityItem::max("fr-CH".parse().unwrap()), QualityItem::new("fr".parse().unwrap(), q(0.9)), @@ -137,7 +137,7 @@ impl AcceptLanguage { b.quality.cmp(&a.quality) }); - types.into_iter().map(|qitem| qitem.item).collect() + types.into_iter().map(|q_item| q_item.item).collect() } } diff --git a/actix-web/src/http/header/allow.rs b/actix-web/src/http/header/allow.rs index d0ef96486..1ae8f00dc 100644 --- a/actix-web/src/http/header/allow.rs +++ b/actix-web/src/http/header/allow.rs @@ -51,12 +51,12 @@ crate::http::header::common_header! { // From the RFC crate::http::header::common_header_test!( test1, - vec![b"GET, HEAD, PUT"], + [b"GET, HEAD, PUT"], Some(HeaderField(vec![Method::GET, Method::HEAD, Method::PUT]))); // Own tests crate::http::header::common_header_test!( test2, - vec![b"OPTIONS, GET, PUT, POST, DELETE, HEAD, TRACE, CONNECT, PATCH"], + [b"OPTIONS, GET, PUT, POST, DELETE, HEAD, TRACE, CONNECT, PATCH"], Some(HeaderField(vec![ Method::OPTIONS, Method::GET, @@ -69,7 +69,7 @@ crate::http::header::common_header! { Method::PATCH]))); crate::http::header::common_header_test!( test3, - vec![b""], + [b""], Some(HeaderField(Vec::::new()))); } } diff --git a/actix-web/src/http/header/cache_control.rs b/actix-web/src/http/header/cache_control.rs index 37629313e..77e22d1c3 100644 --- a/actix-web/src/http/header/cache_control.rs +++ b/actix-web/src/http/header/cache_control.rs @@ -47,13 +47,13 @@ common_header! { (CacheControl, header::CACHE_CONTROL) => (CacheDirective)+ test_parse_and_format { - common_header_test!(no_headers, vec![b""; 0], None); - common_header_test!(empty_header, vec![b""; 1], None); - common_header_test!(bad_syntax, vec![b"foo="], None); + common_header_test!(no_headers, [b""; 0], None); + common_header_test!(empty_header, [b""; 1], None); + common_header_test!(bad_syntax, [b"foo="], None); common_header_test!( multiple_headers, - vec![&b"no-cache"[..], &b"private"[..]], + [&b"no-cache"[..], &b"private"[..]], Some(CacheControl(vec![ CacheDirective::NoCache, CacheDirective::Private, @@ -62,7 +62,7 @@ common_header! { common_header_test!( argument, - vec![b"max-age=100, private"], + [b"max-age=100, private"], Some(CacheControl(vec![ CacheDirective::MaxAge(100), CacheDirective::Private, @@ -71,7 +71,7 @@ common_header! { common_header_test!( extension, - vec![b"foo, bar=baz"], + [b"foo, bar=baz"], Some(CacheControl(vec![ CacheDirective::Extension("foo".to_owned(), None), CacheDirective::Extension("bar".to_owned(), Some("baz".to_owned())), diff --git a/actix-web/src/http/header/content_language.rs b/actix-web/src/http/header/content_language.rs index ff317e1de..5b0797ef3 100644 --- a/actix-web/src/http/header/content_language.rs +++ b/actix-web/src/http/header/content_language.rs @@ -48,7 +48,7 @@ common_header! { (ContentLanguage, CONTENT_LANGUAGE) => (QualityItem)+ test_parse_and_format { - crate::http::header::common_header_test!(test1, vec![b"da"]); - crate::http::header::common_header_test!(test2, vec![b"mi, en"]); + crate::http::header::common_header_test!(test1, [b"da"]); + crate::http::header::common_header_test!(test2, [b"mi, en"]); } } diff --git a/actix-web/src/http/header/content_range.rs b/actix-web/src/http/header/content_range.rs index 8befffd95..884926195 100644 --- a/actix-web/src/http/header/content_range.rs +++ b/actix-web/src/http/header/content_range.rs @@ -13,59 +13,59 @@ crate::http::header::common_header! { test_parse_and_format { crate::http::header::common_header_test!(test_bytes, - vec![b"bytes 0-499/500"], + [b"bytes 0-499/500"], Some(ContentRange(ContentRangeSpec::Bytes { range: Some((0, 499)), instance_length: Some(500) }))); crate::http::header::common_header_test!(test_bytes_unknown_len, - vec![b"bytes 0-499/*"], + [b"bytes 0-499/*"], Some(ContentRange(ContentRangeSpec::Bytes { range: Some((0, 499)), instance_length: None }))); crate::http::header::common_header_test!(test_bytes_unknown_range, - vec![b"bytes */500"], + [b"bytes */500"], Some(ContentRange(ContentRangeSpec::Bytes { range: None, instance_length: Some(500) }))); crate::http::header::common_header_test!(test_unregistered, - vec![b"seconds 1-2"], + [b"seconds 1-2"], Some(ContentRange(ContentRangeSpec::Unregistered { unit: "seconds".to_owned(), resp: "1-2".to_owned() }))); crate::http::header::common_header_test!(test_no_len, - vec![b"bytes 0-499"], + [b"bytes 0-499"], None::); crate::http::header::common_header_test!(test_only_unit, - vec![b"bytes"], + [b"bytes"], None::); crate::http::header::common_header_test!(test_end_less_than_start, - vec![b"bytes 499-0/500"], + [b"bytes 499-0/500"], None::); crate::http::header::common_header_test!(test_blank, - vec![b""], + [b""], None::); crate::http::header::common_header_test!(test_bytes_many_spaces, - vec![b"bytes 1-2/500 3"], + [b"bytes 1-2/500 3"], None::); crate::http::header::common_header_test!(test_bytes_many_slashes, - vec![b"bytes 1-2/500/600"], + [b"bytes 1-2/500/600"], None::); crate::http::header::common_header_test!(test_bytes_many_dashes, - vec![b"bytes 1-2-3/500"], + [b"bytes 1-2-3/500"], None::); } @@ -113,21 +113,13 @@ pub enum ContentRangeSpec { }, } -fn split_in_two(s: &str, separator: char) -> Option<(&str, &str)> { - let mut iter = s.splitn(2, separator); - match (iter.next(), iter.next()) { - (Some(a), Some(b)) => Some((a, b)), - _ => None, - } -} - impl FromStr for ContentRangeSpec { type Err = ParseError; fn from_str(s: &str) -> Result { - let res = match split_in_two(s, ' ') { + let res = match s.split_once(' ') { Some(("bytes", resp)) => { - let (range, instance_length) = split_in_two(resp, '/').ok_or(ParseError::Header)?; + let (range, instance_length) = resp.split_once('/').ok_or(ParseError::Header)?; let instance_length = if instance_length == "*" { None @@ -139,7 +131,7 @@ impl FromStr for ContentRangeSpec { None } else { let (first_byte, last_byte) = - split_in_two(range, '-').ok_or(ParseError::Header)?; + range.split_once('-').ok_or(ParseError::Header)?; let first_byte = first_byte.parse().map_err(|_| ParseError::Header)?; let last_byte = last_byte.parse().map_err(|_| ParseError::Header)?; if last_byte < first_byte { diff --git a/actix-web/src/http/header/content_type.rs b/actix-web/src/http/header/content_type.rs index bf86afffa..c43ef8a2f 100644 --- a/actix-web/src/http/header/content_type.rs +++ b/actix-web/src/http/header/content_type.rs @@ -45,11 +45,11 @@ crate::http::header::common_header! { test_parse_and_format { crate::http::header::common_header_test!( test_text_html, - vec![b"text/html"], + [b"text/html"], Some(HeaderField(mime::TEXT_HTML))); crate::http::header::common_header_test!( test_image_star, - vec![b"image/*"], + [b"image/*"], Some(HeaderField(mime::IMAGE_STAR))); } diff --git a/actix-web/src/http/header/date.rs b/actix-web/src/http/header/date.rs index a8ac65660..ac30424f0 100644 --- a/actix-web/src/http/header/date.rs +++ b/actix-web/src/http/header/date.rs @@ -32,7 +32,7 @@ crate::http::header::common_header! { (Date, DATE) => [HttpDate] test_parse_and_format { - crate::http::header::common_header_test!(test1, vec![b"Tue, 15 Nov 1994 08:12:31 GMT"]); + crate::http::header::common_header_test!(test1, [b"Tue, 15 Nov 1994 08:12:31 GMT"]); } } diff --git a/actix-web/src/http/header/etag.rs b/actix-web/src/http/header/etag.rs index 78f5447b3..b82208288 100644 --- a/actix-web/src/http/header/etag.rs +++ b/actix-web/src/http/header/etag.rs @@ -49,50 +49,50 @@ crate::http::header::common_header! { test_parse_and_format { // From the RFC crate::http::header::common_header_test!(test1, - vec![b"\"xyzzy\""], + [b"\"xyzzy\""], Some(ETag(EntityTag::new_strong("xyzzy".to_owned())))); crate::http::header::common_header_test!(test2, - vec![b"W/\"xyzzy\""], + [b"W/\"xyzzy\""], Some(ETag(EntityTag::new_weak("xyzzy".to_owned())))); crate::http::header::common_header_test!(test3, - vec![b"\"\""], + [b"\"\""], Some(ETag(EntityTag::new_strong("".to_owned())))); // Own tests crate::http::header::common_header_test!(test4, - vec![b"\"foobar\""], + [b"\"foobar\""], Some(ETag(EntityTag::new_strong("foobar".to_owned())))); crate::http::header::common_header_test!(test5, - vec![b"\"\""], + [b"\"\""], Some(ETag(EntityTag::new_strong("".to_owned())))); crate::http::header::common_header_test!(test6, - vec![b"W/\"weak-etag\""], + [b"W/\"weak-etag\""], Some(ETag(EntityTag::new_weak("weak-etag".to_owned())))); crate::http::header::common_header_test!(test7, - vec![b"W/\"\x65\x62\""], + [b"W/\"\x65\x62\""], Some(ETag(EntityTag::new_weak("\u{0065}\u{0062}".to_owned())))); crate::http::header::common_header_test!(test8, - vec![b"W/\"\""], + [b"W/\"\""], Some(ETag(EntityTag::new_weak("".to_owned())))); crate::http::header::common_header_test!(test9, - vec![b"no-dquotes"], + [b"no-dquotes"], None::); crate::http::header::common_header_test!(test10, - vec![b"w/\"the-first-w-is-case-sensitive\""], + [b"w/\"the-first-w-is-case-sensitive\""], None::); crate::http::header::common_header_test!(test11, - vec![b""], + [b""], None::); crate::http::header::common_header_test!(test12, - vec![b"\"unmatched-dquotes1"], + [b"\"unmatched-dquotes1"], None::); crate::http::header::common_header_test!(test13, - vec![b"unmatched-dquotes2\""], + [b"unmatched-dquotes2\""], None::); crate::http::header::common_header_test!(test14, - vec![b"matched-\"dquotes\""], + [b"matched-\"dquotes\""], None::); crate::http::header::common_header_test!(test15, - vec![b"\""], + [b"\""], None::); } } diff --git a/actix-web/src/http/header/expires.rs b/actix-web/src/http/header/expires.rs index 55fe5acc5..b677ab527 100644 --- a/actix-web/src/http/header/expires.rs +++ b/actix-web/src/http/header/expires.rs @@ -36,6 +36,6 @@ crate::http::header::common_header! { test_parse_and_format { // Test case from RFC - crate::http::header::common_header_test!(test1, vec![b"Thu, 01 Dec 1994 16:00:00 GMT"]); + crate::http::header::common_header_test!(test1, [b"Thu, 01 Dec 1994 16:00:00 GMT"]); } } diff --git a/actix-web/src/http/header/if_match.rs b/actix-web/src/http/header/if_match.rs index e299d30fe..e0b46a6c3 100644 --- a/actix-web/src/http/header/if_match.rs +++ b/actix-web/src/http/header/if_match.rs @@ -52,17 +52,17 @@ common_header! { test_parse_and_format { crate::http::header::common_header_test!( test1, - vec![b"\"xyzzy\""], + [b"\"xyzzy\""], Some(HeaderField::Items( vec![EntityTag::new_strong("xyzzy".to_owned())]))); crate::http::header::common_header_test!( test2, - vec![b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""], + [b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""], Some(HeaderField::Items( vec![EntityTag::new_strong("xyzzy".to_owned()), EntityTag::new_strong("r2d2xxxx".to_owned()), EntityTag::new_strong("c3piozzzz".to_owned())]))); - crate::http::header::common_header_test!(test3, vec![b"*"], Some(IfMatch::Any)); + crate::http::header::common_header_test!(test3, [b"*"], Some(IfMatch::Any)); } } diff --git a/actix-web/src/http/header/if_modified_since.rs b/actix-web/src/http/header/if_modified_since.rs index 897210944..8547ff490 100644 --- a/actix-web/src/http/header/if_modified_since.rs +++ b/actix-web/src/http/header/if_modified_since.rs @@ -35,6 +35,6 @@ crate::http::header::common_header! { test_parse_and_format { // Test case from RFC - crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]); + crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]); } } diff --git a/actix-web/src/http/header/if_none_match.rs b/actix-web/src/http/header/if_none_match.rs index 86d7da9b2..1a424df96 100644 --- a/actix-web/src/http/header/if_none_match.rs +++ b/actix-web/src/http/header/if_none_match.rs @@ -52,11 +52,11 @@ crate::http::header::common_header! { (IfNoneMatch, IF_NONE_MATCH) => {Any / (EntityTag)+} test_parse_and_format { - crate::http::header::common_header_test!(test1, vec![b"\"xyzzy\""]); - crate::http::header::common_header_test!(test2, vec![b"W/\"xyzzy\""]); - crate::http::header::common_header_test!(test3, vec![b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""]); - crate::http::header::common_header_test!(test4, vec![b"W/\"xyzzy\", W/\"r2d2xxxx\", W/\"c3piozzzz\""]); - crate::http::header::common_header_test!(test5, vec![b"*"]); + crate::http::header::common_header_test!(test1, [b"\"xyzzy\""]); + crate::http::header::common_header_test!(test2, [b"W/\"xyzzy\""]); + crate::http::header::common_header_test!(test3, [b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""]); + crate::http::header::common_header_test!(test4, [b"W/\"xyzzy\", W/\"r2d2xxxx\", W/\"c3piozzzz\""]); + crate::http::header::common_header_test!(test5, [b"*"]); } } diff --git a/actix-web/src/http/header/if_range.rs b/actix-web/src/http/header/if_range.rs index d7375c4c5..3e8727ab0 100644 --- a/actix-web/src/http/header/if_range.rs +++ b/actix-web/src/http/header/if_range.rs @@ -111,7 +111,7 @@ mod test_parse_and_format { use super::IfRange as HeaderField; use crate::http::header::*; - crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]); - crate::http::header::common_header_test!(test2, vec![b"\"abc\""]); - crate::http::header::common_header_test!(test3, vec![b"this-is-invalid"], None::); + crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]); + crate::http::header::common_header_test!(test2, [b"\"abc\""]); + crate::http::header::common_header_test!(test3, [b"this-is-invalid"], None::); } diff --git a/actix-web/src/http/header/if_unmodified_since.rs b/actix-web/src/http/header/if_unmodified_since.rs index 2ee3160b4..afa4eb8e5 100644 --- a/actix-web/src/http/header/if_unmodified_since.rs +++ b/actix-web/src/http/header/if_unmodified_since.rs @@ -35,6 +35,6 @@ crate::http::header::common_header! { test_parse_and_format { // Test case from RFC - crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]); + crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]); } } diff --git a/actix-web/src/http/header/last_modified.rs b/actix-web/src/http/header/last_modified.rs index 59e649bea..724a38bbc 100644 --- a/actix-web/src/http/header/last_modified.rs +++ b/actix-web/src/http/header/last_modified.rs @@ -34,6 +34,6 @@ crate::http::header::common_header! { test_parse_and_format { // Test case from RFC - crate::http::header::common_header_test!(test1, vec![b"Sat, 29 Oct 1994 19:43:31 GMT"]); + crate::http::header::common_header_test!(test1, [b"Sat, 29 Oct 1994 19:43:31 GMT"]); } } From 146011018ef4c71ca9cee1538684a784c619ffac Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 22 Jul 2023 02:02:29 +0100 Subject: [PATCH 089/314] add payload to_bytes helpers (#3083) --- actix-http/src/body/body_stream.rs | 5 +- actix-web/CHANGES.md | 3 +- actix-web/src/types/payload.rs | 116 ++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 7 deletions(-) diff --git a/actix-http/src/body/body_stream.rs b/actix-http/src/body/body_stream.rs index 5a12c1e40..4574b2519 100644 --- a/actix-http/src/body/body_stream.rs +++ b/actix-http/src/body/body_stream.rs @@ -47,9 +47,8 @@ where /// Attempts to pull out the next value of the underlying [`Stream`]. /// - /// Empty values are skipped to prevent [`BodyStream`]'s transmission being - /// ended on a zero-length chunk, but rather proceed until the underlying - /// [`Stream`] ends. + /// Empty values are skipped to prevent [`BodyStream`]'s transmission being ended on a + /// zero-length chunk, but rather proceed until the underlying [`Stream`] ends. fn poll_next( mut self: Pin<&mut Self>, cx: &mut Context<'_>, diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index e96f852e5..f22a815c3 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -6,7 +6,8 @@ - Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature. - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. -- Add several missing convenience methods on `HttpResponse` for their respective status codes. +- Add `web::Payload::to_bytes[_limited]()` helper methods. +- Add missing constructors on `HttpResponse` for several status codes. ### Changed diff --git a/actix-web/src/types/payload.rs b/actix-web/src/types/payload.rs index 1d9c6aba5..abb4e6b7f 100644 --- a/actix-web/src/types/payload.rs +++ b/actix-web/src/types/payload.rs @@ -16,7 +16,8 @@ use futures_core::{ready, stream::Stream}; use mime::Mime; use crate::{ - dev, error::ErrorBadRequest, http::header, web, Error, FromRequest, HttpMessage, HttpRequest, + body, dev, error::ErrorBadRequest, http::header, web, Error, FromRequest, HttpMessage, + HttpRequest, }; /// Extract a request's raw payload stream. @@ -50,6 +51,72 @@ impl Payload { pub fn into_inner(self) -> dev::Payload { self.0 } + + /// Buffers payload from request up to `limit` bytes. + /// + /// This method is preferred over [`Payload::to_bytes()`] since it will not lead to unexpected + /// memory exhaustion from massive payloads. Note that the other primitive extractors such as + /// [`Bytes`] and [`String`], as well as extractors built on top of them, already have this sort + /// of protection according to the configured (or default) [`PayloadConfig`]. + /// + /// # Errors + /// + /// - The outer error type, [`BodyLimitExceeded`](body::BodyLimitExceeded), is returned when the + /// payload is larger than `limit`. + /// - The inner error type is [the normal Actix Web error](crate::Error) and is only returned if + /// the payload stream yields an error for some reason. Such cases are usually caused by + /// unrecoverable connection issues. + /// + /// # Examples + /// + /// ``` + /// use actix_web::{error, web::Payload, Responder}; + /// + /// async fn limited_payload_handler(pl: Payload) -> actix_web::Result { + /// match pl.to_bytes_limited(5).await { + /// Ok(res) => res, + /// Err(err) => Err(error::ErrorPayloadTooLarge(err)), + /// } + /// } + /// ``` + pub async fn to_bytes_limited( + self, + limit: usize, + ) -> Result, body::BodyLimitExceeded> { + let stream = body::BodyStream::new(self.0); + + match body::to_bytes_limited(stream, limit).await { + Ok(Ok(body)) => Ok(Ok(body)), + Ok(Err(err)) => Ok(Err(err.into())), + Err(err) => Err(err), + } + } + + /// Buffers entire payload from request. + /// + /// Use of this method is discouraged unless you know for certain that requests will not be + /// large enough to exhaust memory. If this is not known, prefer [`Payload::to_bytes_limited()`] + /// or one of the higher level extractors like [`Bytes`] or [`String`] that implement size + /// limits according to the configured (or default) [`PayloadConfig`]. + /// + /// # Errors + /// + /// An error is only returned if the payload stream yields an error for some reason. Such cases + /// are usually caused by unrecoverable connection issues. + /// + /// # Examples + /// + /// ``` + /// use actix_web::{error, web::Payload, Responder}; + /// + /// async fn payload_handler(pl: Payload) -> actix_web::Result { + /// pl.to_bytes().await + /// } + /// ``` + pub async fn to_bytes(self) -> crate::Result { + let stream = body::BodyStream::new(self.0); + Ok(body::to_bytes(stream).await?) + } } impl Stream for Payload { @@ -64,7 +131,7 @@ impl Stream for Payload { /// See [here](#Examples) for example of usage as an extractor. impl FromRequest for Payload { type Error = Error; - type Future = Ready>; + type Future = Ready>; #[inline] fn from_request(_: &HttpRequest, payload: &mut dev::Payload) -> Self::Future { @@ -378,10 +445,53 @@ mod tests { use super::*; use crate::{ http::{header, StatusCode}, - test::{call_service, init_service, TestRequest}, + test::{call_service, init_service, read_body, TestRequest}, web, App, Responder, }; + #[actix_rt::test] + async fn payload_to_bytes() { + async fn payload_handler(pl: Payload) -> crate::Result { + pl.to_bytes().await + } + + async fn limited_payload_handler(pl: Payload) -> crate::Result { + match pl.to_bytes_limited(5).await { + Ok(res) => res, + Err(_limited) => Err(ErrorBadRequest("too big")), + } + } + + let srv = init_service( + App::new() + .route("/all", web::to(payload_handler)) + .route("limited", web::to(limited_payload_handler)), + ) + .await; + + let req = TestRequest::with_uri("/all") + .set_payload("1234567890") + .to_request(); + let res = call_service(&srv, req).await; + assert_eq!(res.status(), StatusCode::OK); + let body = read_body(res).await; + assert_eq!(body, "1234567890"); + + let req = TestRequest::with_uri("/limited") + .set_payload("1234567890") + .to_request(); + let res = call_service(&srv, req).await; + assert_eq!(res.status(), StatusCode::BAD_REQUEST); + + let req = TestRequest::with_uri("/limited") + .set_payload("12345") + .to_request(); + let res = call_service(&srv, req).await; + assert_eq!(res.status(), StatusCode::OK); + let body = read_body(res).await; + assert_eq!(body, "12345"); + } + #[actix_rt::test] async fn test_payload_config() { let req = TestRequest::default().to_http_request(); From 8cdbab3416ecc562a6ca5aad6b7bba5b3dce1dfd Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 22 Jul 2023 01:57:44 +0100 Subject: [PATCH 090/314] refactor: remove web dev dep from http-test --- actix-http-test/Cargo.toml | 1 - actix-http-test/src/lib.rs | 25 +++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 87422551d..7f00ba30a 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -50,5 +50,4 @@ tls-openssl = { version = "0.10.55", package = "openssl", optional = true } tokio = { version = "1.24.2", features = ["sync"] } [dev-dependencies] -actix-web = { version = "4", default-features = false, features = ["cookies"] } actix-http = "3" diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs index 8dcbe759d..2f1725d1c 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -31,24 +31,20 @@ use tokio::sync::mpsc; /// for HTTP applications. /// /// # Examples -/// ```no_run -/// use actix_http::HttpService; +/// +/// ``` +/// use actix_http::{HttpService, Response, Error, StatusCode}; /// use actix_http_test::test_server; -/// use actix_service::map_config; -/// use actix_service::ServiceFactoryExt; -/// use actix_web::{dev::AppConfig, web, App, Error, HttpResponse}; +/// use actix_service::{fn_service, map_config, ServiceFactoryExt as _}; /// -/// async fn my_handler() -> Result { -/// Ok(HttpResponse::Ok().into()) -/// } -/// -/// #[actix_web::test] +/// #[actix_rt::test] +/// # async fn hidden_test() {} /// async fn test_example() { /// let srv = test_server(|| { -/// let app = App::new().service(web::resource("/").to(my_handler)); -/// /// HttpService::build() -/// .h1(map_config(app, |_| AppConfig::default())) +/// .h1(fn_service(|req| async move { +/// Ok::<_, Error>(Response::ok()) +/// })) /// .tcp() /// .map_err(|_| ()) /// }) @@ -57,8 +53,9 @@ use tokio::sync::mpsc; /// let req = srv.get("/"); /// let response = req.send().await.unwrap(); /// -/// assert!(response.status().is_success()); +/// assert_eq!(response.status(), StatusCode::OK); /// } +/// # actix_rt::System::new().block_on(test_example()); /// ``` pub async fn test_server>(factory: F) -> TestServer { let tcp = net::TcpListener::bind("127.0.0.1:0").unwrap(); From 6a0ea51b15fc8df2cdbf3438c334486def7a8eda Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 22 Jul 2023 03:16:01 +0100 Subject: [PATCH 091/314] add `ContentLength` typed header (#2490) --- actix-web/CHANGES.md | 1 + actix-web/src/http/header/allow.rs | 8 ++- actix-web/src/http/header/content_length.rs | 56 +++++++++++++++++++++ actix-web/src/http/header/content_range.rs | 1 - actix-web/src/http/header/mod.rs | 2 + actix-web/src/types/json.rs | 8 +-- 6 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 actix-web/src/http/header/content_length.rs diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index f22a815c3..39535d41f 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -8,6 +8,7 @@ - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. - Add `web::Payload::to_bytes[_limited]()` helper methods. - Add missing constructors on `HttpResponse` for several status codes. +- Add `http::header::ContentLength` typed header. ### Changed diff --git a/actix-web/src/http/header/allow.rs b/actix-web/src/http/header/allow.rs index 1ae8f00dc..b1c35c3d7 100644 --- a/actix-web/src/http/header/allow.rs +++ b/actix-web/src/http/header/allow.rs @@ -48,12 +48,15 @@ crate::http::header::common_header! { (Allow, header::ALLOW) => (Method)* test_parse_and_format { - // From the RFC + // from the RFC + crate::http::header::common_header_test!( test1, [b"GET, HEAD, PUT"], Some(HeaderField(vec![Method::GET, Method::HEAD, Method::PUT]))); - // Own tests + + // other tests + crate::http::header::common_header_test!( test2, [b"OPTIONS, GET, PUT, POST, DELETE, HEAD, TRACE, CONNECT, PATCH"], @@ -67,6 +70,7 @@ crate::http::header::common_header! { Method::TRACE, Method::CONNECT, Method::PATCH]))); + crate::http::header::common_header_test!( test3, [b""], diff --git a/actix-web/src/http/header/content_length.rs b/actix-web/src/http/header/content_length.rs new file mode 100644 index 000000000..b2769e5fa --- /dev/null +++ b/actix-web/src/http/header/content_length.rs @@ -0,0 +1,56 @@ +use super::common_header; +use crate::http::header; + +common_header! { + /// `Content-Length` header, defined in [RFC 7230 §3.3.2]. + /// + /// The Content-Length + /// + /// # ABNF + /// + /// ```plain + /// Content-Length = 1*DIGIT + /// ``` + /// + /// # Example Values + /// + /// - `0` + /// - `3495` + /// + /// # Examples + /// + /// ``` + /// use actix_web::{http::header::ContentLength, HttpResponse}; + /// + /// let res_empty = HttpResponse::Ok() + /// .insert_header(ContentLength(0)); + /// + /// let res_fake_cl = HttpResponse::Ok() + /// .insert_header(ContentLength(3_495)); + /// ``` + /// + /// [RFC 7230 §3.3.2]: https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 + (ContentLength, header::CONTENT_LENGTH) => [usize] + + test_parse_and_format { + common_header_test!(no_header, [b""; 0], None); + common_header_test!(empty_header, [b""; 1], None); + + common_header_test!(zero, [b"0"], Some(ContentLength(0))); + common_header_test!(one, [b"1"], Some(ContentLength(1))); + common_header_test!(one_two_three, [b"123"], Some(ContentLength(123))); + common_header_test!( + thirty_two_power_plus_one, + [b"4294967297"], + Some(ContentLength(4_294_967_297)) + ); + common_header_test!( + sixty_four_power_minus_one, + [b"18446744073709551615"], + Some(ContentLength(18_446_744_073_709_551_615)) + ); + + common_header_test!(invalid1, [b"123,567"], None); + common_header_test!(invalid2, [b"123_567"], None); + } +} diff --git a/actix-web/src/http/header/content_range.rs b/actix-web/src/http/header/content_range.rs index 884926195..2604f9ba2 100644 --- a/actix-web/src/http/header/content_range.rs +++ b/actix-web/src/http/header/content_range.rs @@ -67,7 +67,6 @@ crate::http::header::common_header! { crate::http::header::common_header_test!(test_bytes_many_dashes, [b"bytes 1-2-3/500"], None::); - } } diff --git a/actix-web/src/http/header/mod.rs b/actix-web/src/http/header/mod.rs index 65c5c88a0..51ac4fcfd 100644 --- a/actix-web/src/http/header/mod.rs +++ b/actix-web/src/http/header/mod.rs @@ -24,6 +24,7 @@ mod allow; mod cache_control; mod content_disposition; mod content_language; +mod content_length; mod content_range; mod content_type; mod date; @@ -53,6 +54,7 @@ pub use self::{ cache_control::{CacheControl, CacheDirective}, content_disposition::{ContentDisposition, DispositionParam, DispositionType}, content_language::ContentLanguage, + content_length::ContentLength, content_range::{ContentRange, ContentRangeSpec}, content_type::ContentType, date::Date, diff --git a/actix-web/src/types/json.rs b/actix-web/src/types/json.rs index 2523e55f2..59c95da4c 100644 --- a/actix-web/src/types/json.rs +++ b/actix-web/src/types/json.rs @@ -21,7 +21,7 @@ use crate::{ body::EitherBody, error::{Error, JsonPayloadError}, extract::FromRequest, - http::header::CONTENT_LENGTH, + http::header::{ContentLength, Header as _}, request::HttpRequest, web, HttpMessage, HttpResponse, Responder, }; @@ -342,11 +342,7 @@ impl JsonBody { return JsonBody::Error(Some(JsonPayloadError::ContentType)); } - let length = req - .headers() - .get(&CONTENT_LENGTH) - .and_then(|l| l.to_str().ok()) - .and_then(|s| s.parse::().ok()); + let length = ContentLength::parse(req).ok().map(|x| x.0); // Notice the content-length is not checked against limit of json config here. // As the internal usage always call JsonBody::limit after JsonBody::new. From ff8fd2f7b54dce405ede595fae568561a8465d48 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 22 Jul 2023 18:01:59 +0100 Subject: [PATCH 092/314] modernize ContentLength --- actix-web/src/http/header/content_length.rs | 282 ++++++++++++++++---- 1 file changed, 232 insertions(+), 50 deletions(-) diff --git a/actix-web/src/http/header/content_length.rs b/actix-web/src/http/header/content_length.rs index b2769e5fa..ad16dc409 100644 --- a/actix-web/src/http/header/content_length.rs +++ b/actix-web/src/http/header/content_length.rs @@ -1,56 +1,238 @@ -use super::common_header; -use crate::http::header; +use std::{convert::Infallible, str}; -common_header! { - /// `Content-Length` header, defined in [RFC 7230 §3.3.2]. - /// - /// The Content-Length - /// - /// # ABNF - /// - /// ```plain - /// Content-Length = 1*DIGIT - /// ``` - /// - /// # Example Values - /// - /// - `0` - /// - `3495` - /// - /// # Examples - /// - /// ``` - /// use actix_web::{http::header::ContentLength, HttpResponse}; - /// - /// let res_empty = HttpResponse::Ok() - /// .insert_header(ContentLength(0)); - /// - /// let res_fake_cl = HttpResponse::Ok() - /// .insert_header(ContentLength(3_495)); - /// ``` - /// - /// [RFC 7230 §3.3.2]: https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 - (ContentLength, header::CONTENT_LENGTH) => [usize] +use derive_more::{Deref, DerefMut}; - test_parse_and_format { - common_header_test!(no_header, [b""; 0], None); - common_header_test!(empty_header, [b""; 1], None); +use crate::{ + error::ParseError, + http::header::{ + from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue, CONTENT_LENGTH, + }, + HttpMessage, +}; - common_header_test!(zero, [b"0"], Some(ContentLength(0))); - common_header_test!(one, [b"1"], Some(ContentLength(1))); - common_header_test!(one_two_three, [b"123"], Some(ContentLength(123))); - common_header_test!( - thirty_two_power_plus_one, - [b"4294967297"], - Some(ContentLength(4_294_967_297)) - ); - common_header_test!( - sixty_four_power_minus_one, - [b"18446744073709551615"], - Some(ContentLength(18_446_744_073_709_551_615)) - ); +/// `Content-Length` header, defined in [RFC 9110 §8.6]. +/// +/// The Content-Length +/// +/// # ABNF +/// +/// ```plain +/// Content-Length = 1*DIGIT +/// ``` +/// +/// # Example Values +/// +/// - `0` +/// - `3495` +/// +/// # Examples +/// +/// ``` +/// use actix_web::{http::header::ContentLength, HttpResponse}; +/// +/// let res_empty = HttpResponse::Ok() +/// .insert_header(ContentLength(0)); +/// +/// let res_fake_cl = HttpResponse::Ok() +/// .insert_header(ContentLength(3_495)); +/// ``` +/// +/// [RFC 9110 §8.6]: https://www.rfc-editor.org/rfc/rfc9110#name-content-length +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deref, DerefMut)] +pub struct ContentLength(pub usize); - common_header_test!(invalid1, [b"123,567"], None); - common_header_test!(invalid2, [b"123_567"], None); +impl ContentLength { + /// Returns Content-Length value. + pub fn into_inner(&self) -> usize { + self.0 + } +} + +impl str::FromStr for ContentLength { + type Err = ::Err; + + #[inline] + fn from_str(val: &str) -> Result { + let val = val.trim(); + + // decoder prevents this case + debug_assert!(!val.starts_with('+')); + + val.parse().map(Self) + } +} + +impl TryIntoHeaderValue for ContentLength { + type Error = Infallible; + + fn try_into_value(self) -> Result { + Ok(HeaderValue::from(self.0)) + } +} + +impl Header for ContentLength { + fn name() -> HeaderName { + CONTENT_LENGTH + } + + fn parse(msg: &M) -> Result { + let val = from_one_raw_str(msg.headers().get(Self::name()))?; + + // decoder prevents multiple CL headers + debug_assert_eq!(msg.headers().get_all(Self::name()).count(), 1); + + Ok(val) + } +} + +impl From for usize { + fn from(ContentLength(len): ContentLength) -> Self { + len + } +} + +impl From for ContentLength { + fn from(len: usize) -> Self { + ContentLength(len) + } +} + +impl PartialEq for ContentLength { + fn eq(&self, other: &usize) -> bool { + self.0 == *other + } +} + +impl PartialEq for usize { + fn eq(&self, other: &ContentLength) -> bool { + *self == other.0 + } +} + +impl PartialOrd for ContentLength { + fn partial_cmp(&self, other: &usize) -> Option { + self.0.partial_cmp(other) + } +} + +impl PartialOrd for usize { + fn partial_cmp(&self, other: &ContentLength) -> Option { + self.partial_cmp(&other.0) + } +} + +#[cfg(test)] +mod tests { + use std::fmt; + + use super::*; + use crate::{http::header::Header, test::TestRequest, HttpRequest}; + + fn req_from_raw_headers, V: AsRef<[u8]>>( + header_lines: I, + ) -> HttpRequest { + header_lines + .into_iter() + .fold(TestRequest::default(), |req, item| { + req.append_header((H::name(), item.as_ref().to_vec())) + }) + .to_http_request() + } + + #[track_caller] + pub(crate) fn assert_parse_fail< + H: Header + fmt::Debug, + I: IntoIterator, + V: AsRef<[u8]>, + >( + headers: I, + ) { + let req = req_from_raw_headers::(headers); + H::parse(&req).unwrap_err(); + } + + #[track_caller] + pub(crate) fn assert_parse_eq< + H: Header + fmt::Debug + PartialEq, + I: IntoIterator, + V: AsRef<[u8]>, + >( + headers: I, + expect: H, + ) { + let req = req_from_raw_headers::(headers); + assert_eq!(H::parse(&req).unwrap(), expect); + } + + #[test] + fn missing_header() { + assert_parse_fail::([""; 0]); + assert_parse_fail::([""]); + } + + #[test] + fn bad_header() { + assert_parse_fail::(["-123"]); + assert_parse_fail::(["123_456"]); + assert_parse_fail::(["123.456"]); + + // too large for u64 (2^64, 2^64 + 1) + assert_parse_fail::(["18446744073709551616"]); + assert_parse_fail::(["18446744073709551617"]); + + // hex notation + assert_parse_fail::(["0x123"]); + + // multi-value + assert_parse_fail::(["0, 123"]); + } + + #[test] + #[should_panic] + fn bad_header_plus() { + // prevented by HTTP decoder anyway + assert_parse_fail::(["+123"]); + } + + #[test] + #[should_panic] + fn bad_multiple_value() { + // prevented by HTTP decoder anyway + assert_parse_fail::(["0", "123"]); + } + + #[test] + fn good_header() { + assert_parse_eq::(["0"], ContentLength(0)); + assert_parse_eq::(["1"], ContentLength(1)); + assert_parse_eq::(["123"], ContentLength(123)); + + // value that looks like octal notation is not interpreted as such + assert_parse_eq::(["0123"], ContentLength(123)); + + // whitespace variations + assert_parse_eq::([" 0"], ContentLength(0)); + assert_parse_eq::(["0 "], ContentLength(0)); + assert_parse_eq::([" 0 "], ContentLength(0)); + + // large value (2^64 - 1) + assert_parse_eq::( + ["18446744073709551615"], + ContentLength(18_446_744_073_709_551_615), + ); + } + + #[test] + fn equality() { + assert!(ContentLength(0) == ContentLength(0)); + assert!(ContentLength(0) == 0); + assert!(0 != ContentLength(123)); + } + + #[test] + fn ordering() { + assert!(ContentLength(0) < ContentLength(123)); + assert!(ContentLength(0) < 123); + assert!(0 < ContentLength(123)); } } From 75a97f6b329911387a915f29d34a4e7f1ba8d460 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 24 Jul 2023 03:29:56 +0100 Subject: [PATCH 093/314] chore: remove clippy config file --- .github/workflows/ci-post-merge.yml | 5 +++-- .github/workflows/ci.yml | 3 ++- .prettierrc.yaml | 1 - .prettierrc.yml | 5 +++++ actix-web-codegen/src/lib.rs | 2 +- clippy.toml | 1 - 6 files changed, 11 insertions(+), 6 deletions(-) delete mode 100644 .prettierrc.yaml create mode 100644 .prettierrc.yml delete mode 100644 clippy.toml diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d293fea95..06669e31e 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -5,7 +5,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -16,10 +16,11 @@ jobs: strategy: fail-fast: false matrix: + # prettier-ignore target: - { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu } - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - - { name: Windows, os: windows-2022, triple: x86_64-pc-windows-msvc } + - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - nightly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f85548505..468c9b1df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -18,6 +18,7 @@ jobs: strategy: fail-fast: false matrix: + # prettier-ignore target: - { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu } - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } diff --git a/.prettierrc.yaml b/.prettierrc.yaml deleted file mode 100644 index 7b5590248..000000000 --- a/.prettierrc.yaml +++ /dev/null @@ -1 +0,0 @@ -proseWrap: never diff --git a/.prettierrc.yml b/.prettierrc.yml new file mode 100644 index 000000000..b61fd8974 --- /dev/null +++ b/.prettierrc.yml @@ -0,0 +1,5 @@ +overrides: + - files: '*.md' + options: + printWidth: 9999 + proseWrap: never diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 6d6f4f79d..6d6c9ab5c 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -221,7 +221,7 @@ pub fn main(_: TokenStream, item: TokenStream) -> TokenStream { output } -/// Marks async test functions to use the actix system entry-point. +/// Marks async test functions to use the Actix Web system entry-point. /// /// # Examples /// ``` diff --git a/clippy.toml b/clippy.toml deleted file mode 100644 index 04371125d..000000000 --- a/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -msrv = "1.65" From 605cd7c540e196efa50d3e96e9ed3f32b556dd03 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 1 Aug 2023 18:06:59 +0100 Subject: [PATCH 094/314] add startup logging to basic example --- actix-web/examples/basic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web/examples/basic.rs b/actix-web/examples/basic.rs index 60715f477..b8bc09821 100644 --- a/actix-web/examples/basic.rs +++ b/actix-web/examples/basic.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use actix_web::{get, middleware, web, App, HttpRequest, HttpResponse, HttpServer}; #[get("/resource1/{name}/index.html")] @@ -22,6 +20,8 @@ async fn no_params() -> &'static str { async fn main() -> std::io::Result<()> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + log::info!("starting HTTP server at http://localhost:8080"); + HttpServer::new(|| { App::new() .wrap(middleware::DefaultHeaders::new().add(("X-Version", "0.2"))) From b4fcdffdc3243f41236da8d20743a685f0b45045 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 1 Aug 2023 19:33:32 +0100 Subject: [PATCH 095/314] chore: update msrv to 1.68 (#3094) --- .github/workflows/bench.yml | 3 +-- .github/workflows/ci.yml | 4 +++- actix-files/CHANGES.md | 2 +- actix-files/README.md | 4 ++-- actix-http-test/CHANGES.md | 2 +- actix-http-test/README.md | 4 ++-- actix-http/CHANGES.md | 2 +- actix-http/README.md | 4 ++-- actix-multipart-derive/CHANGES.md | 2 +- actix-multipart-derive/README.md | 4 ++-- actix-multipart-derive/tests/trybuild.rs | 2 +- actix-multipart/CHANGES.md | 2 +- actix-multipart/README.md | 4 ++-- actix-router/CHANGES.md | 2 +- actix-router/src/resource.rs | 7 ++++++- actix-test/CHANGES.md | 2 +- actix-web-actors/CHANGES.md | 2 +- actix-web-actors/README.md | 4 ++-- actix-web-codegen/CHANGES.md | 2 +- actix-web-codegen/README.md | 4 ++-- actix-web-codegen/tests/trybuild.rs | 2 +- actix-web/CHANGES.md | 2 +- actix-web/README.md | 4 ++-- awc/CHANGES.md | 2 +- awc/README.md | 2 +- 25 files changed, 40 insertions(+), 34 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index f8bf2abda..f0e4cc8b3 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -2,8 +2,7 @@ name: Benchmark on: push: - branches: - - master + branches: [master] permissions: contents: read # to fetch code (actions/checkout) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 468c9b1df..f073f6afe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: CI on: pull_request: types: [opened, synchronize, reopened] + merge_group: + types: [checks_requested] push: branches: [master] @@ -24,7 +26,7 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - 1.65.0 # MSRV + - 1.68.0 # MSRV - stable name: ${{ matrix.target.name }} / ${{ matrix.version }} diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 4e45ce517..31c0499ed 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.6.3 - 2023-01-21 diff --git a/actix-files/README.md b/actix-files/README.md index f01fc8566..3e656c431 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -4,7 +4,7 @@ [![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.6.3)](https://docs.rs/actix-files/0.6.3) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
[![dependency status](https://deps.rs/crate/actix-files/0.6.3/status.svg)](https://deps.rs/crate/actix-files/0.6.3) @@ -15,4 +15,4 @@ - [API Documentation](https://docs.rs/actix-files) - [Example Project](https://github.com/actix/examples/tree/master/basics/static-files) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index 3b8c83b3c..0fc89214d 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 3.1.0 - 2023-01-21 diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 935be407f..4b286e603 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -4,7 +4,7 @@ [![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=3.1.0)](https://docs.rs/actix-http-test/3.1.0) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
[![Dependency Status](https://deps.rs/crate/actix-http-test/3.1.0/status.svg)](https://deps.rs/crate/actix-http-test/3.1.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http-test) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index a105c02c1..0dedd2c74 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -9,7 +9,7 @@ ### Changed -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 3.3.1 - 2023-03-02 diff --git a/actix-http/README.md b/actix-http/README.md index 0c5fcb6b6..ce2e5cb32 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -4,7 +4,7 @@ [![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=3.3.1)](https://docs.rs/actix-http/3.3.1) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
[![dependency status](https://deps.rs/crate/actix-http/3.3.1/status.svg)](https://deps.rs/crate/actix-http/3.3.1) @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 ## Example diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index 8a78900ec..f90b9e3cf 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -3,7 +3,7 @@ ## Unreleased - Update `syn` dependency to `2`. -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.6.0 - 2023-02-26 diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index b077d355c..2737410f6 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) [![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart-derive/0.5.0) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg)
[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.5.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart-derive) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-multipart-derive/tests/trybuild.rs b/actix-multipart-derive/tests/trybuild.rs index 829c1d771..88aa619c6 100644 --- a/actix-multipart-derive/tests/trybuild.rs +++ b/actix-multipart-derive/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.65)] // MSRV +#[rustversion::stable(1.68)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 410c8af17..1ad5865ec 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.6.0 - 2023-02-26 diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 3e2a7a127..66550668d 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) [![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.0)](https://docs.rs/actix-multipart/0.6.0) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
[![dependency status](https://deps.rs/crate/actix-multipart/0.6.0/status.svg)](https://deps.rs/crate/actix-multipart/0.6.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 1f5552193..786ee12d9 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.5.1 - 2022-09-19 diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index a3e89a1fe..80c0a2d68 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -501,7 +501,12 @@ impl ResourceDef { let patterns = self .pattern_iter() .flat_map(move |this| other.pattern_iter().map(move |other| (this, other))) - .map(|(this, other)| [this, other].join("")) + .map(|(this, other)| { + let mut pattern = String::with_capacity(this.len() + other.len()); + pattern.push_str(this); + pattern.push_str(other); + pattern + }) .collect::>(); match patterns.len() { diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index aba27dbfc..fae8201d2 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -3,7 +3,7 @@ ## Unreleased - 2023-xx-xx - Add `TestServerConfig::workers()` setter method. -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.1.1 - 2023-02-26 diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 4799c7b67..cff27a16d 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 4.2.0 - 2023-01-21 diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index fe6122115..b2c30b954 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) [![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.2.0)](https://docs.rs/actix-web-actors/4.2.0) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
[![dependency status](https://deps.rs/crate/actix-web-actors/4.2.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.2.0) @@ -14,4 +14,4 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-actors) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 2c5f17226..9ff1edf6e 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -3,7 +3,7 @@ ## Unreleased - 2023-xx-xx - Update `syn` dependency to `2`. -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 4.2.0 - 2023-02-26 diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 531f44a5d..e6df8164e 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) [![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.0)](https://docs.rs/actix-web-codegen/4.2.0) -![Version](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.0) @@ -14,7 +14,7 @@ ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-codegen) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 ## Compile Testing diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 9f0aa02f4..8e1f58a4c 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.65)] // MSRV +#[rustversion::stable(1.68)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 39535d41f..518a02507 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -15,7 +15,7 @@ - Handler functions can now receive up to 16 extractor parameters. - The `Compress` middleware no longer compresses image or video content. - Hide sensitive header values in `HttpRequest`'s `Debug` output. -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 4.3.1 - 2023-02-26 diff --git a/actix-web/README.md b/actix-web/README.md index cc2d9abe0..565f2b0f3 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -5,7 +5,7 @@

-[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.65+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) +[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x)

@@ -24,7 +24,7 @@ - SSL support using OpenSSL or Rustls - Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/)) - Integrates with the [`awc` HTTP client](https://docs.rs/awc/) -- Runs on stable Rust 1.65+ +- Runs on stable Rust 1.68+ ## Documentation diff --git a/awc/CHANGES.md b/awc/CHANGES.md index f5bddd04d..3429a84d7 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased - 2023-xx-xx -- Minimum supported Rust version (MSRV) is now 1.65 due to transitive `time` dependency. +- Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 3.1.1 - 2023-02-26 diff --git a/awc/README.md b/awc/README.md index 1a480df12..f2a9c7559 100644 --- a/awc/README.md +++ b/awc/README.md @@ -12,7 +12,7 @@ - [API Documentation](https://docs.rs/awc) - [Example Project](https://github.com/actix/examples/tree/master/https-tls/awc-https) -- Minimum Supported Rust Version (MSRV): 1.65 +- Minimum Supported Rust Version (MSRV): 1.68 ## Example From 1c60978a895d736c53025f2aab88340fb0b3e464 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 3 Aug 2023 06:28:45 +0100 Subject: [PATCH 096/314] chore: move codecov file --- codecov.yml => .codecov.yml | 0 actix-web/README.md | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) rename codecov.yml => .codecov.yml (100%) diff --git a/codecov.yml b/.codecov.yml similarity index 100% rename from codecov.yml rename to .codecov.yml diff --git a/actix-web/README.md b/actix-web/README.md index 565f2b0f3..74b4924d4 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -5,7 +5,20 @@

-[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) ![downloads](https://img.shields.io/crates/d/actix-web.svg) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + +[![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=4.3.1)](https://docs.rs/actix-web/4.3.1) +![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) +[![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1) +
+[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) +[![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) +![downloads](https://img.shields.io/crates/d/actix-web.svg) +[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + +

From 12dbda986ee89726d62edc609f7928307ce5390c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 3 Aug 2023 06:54:50 +0100 Subject: [PATCH 097/314] test: fix test_h2_connection_drop spurious hang fixes #3061 --- awc/src/client/connection.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/awc/src/client/connection.rs b/awc/src/client/connection.rs index 64075eae8..12d00914a 100644 --- a/awc/src/client/connection.rs +++ b/awc/src/client/connection.rs @@ -394,6 +394,8 @@ mod test { #[actix_rt::test] async fn test_h2_connection_drop() { + env_logger::try_init().ok(); + let addr = "127.0.0.1:0".parse::().unwrap(); let listener = net::TcpListener::bind(addr).unwrap(); let local = listener.local_addr().unwrap(); @@ -428,11 +430,18 @@ mod test { if this.start_from.elapsed() > Duration::from_secs(10) { panic!("connection should be gone and can not be ready"); } else { - let _ = this.interval.poll_tick(cx); - Poll::Pending + match this.interval.poll_tick(cx) { + Poll::Ready(_) => { + // prevents spurious test hang + this.interval.reset(); + + Poll::Pending + } + Poll::Pending => Poll::Pending, + } } } - Err(_) => Poll::Ready(()), + Err(err) => Poll::Ready(()), } } } From eaabe7e6869872384dcc6c85fe021f60b25f3f8a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 3 Aug 2023 06:58:31 +0100 Subject: [PATCH 098/314] ci: reinstate coverage --- .github/workflows/coverage.yml | 26 ++++++++++++++------------ .gitignore | 3 +++ awc/src/client/connection.rs | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 42f16450d..1e450d491 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,5 +1,3 @@ -# disabled because `cargo tarpaulin` currently segfaults - name: Coverage on: @@ -14,21 +12,25 @@ concurrency: cancel-in-progress: true jobs: - # job currently (1st Feb 2022) segfaults coverage: - name: coverage runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + components: llvm-tools-preview - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { toolchain: nightly } + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@v2.13.4 + with: + tool: cargo-llvm-cov - - name: Generate coverage file - run: | - cargo install cargo-tarpaulin --vers "^0.13" - cargo tarpaulin --workspace --features=rustls,openssl --out Xml --verbose - - name: Upload to Codecov + - name: Generate code coverage + run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json + + - name: Upload coverage to Codecov uses: codecov/codecov-action@v3.1.4 with: - file: cobertura.xml + files: codecov.json + fail_ci_if_error: true diff --git a/.gitignore b/.gitignore index 543403267..91930acf8 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ guide/build/ # Configuration directory generated by VSCode .vscode + +# code coverage +/codecov.json diff --git a/awc/src/client/connection.rs b/awc/src/client/connection.rs index 12d00914a..5ed965bed 100644 --- a/awc/src/client/connection.rs +++ b/awc/src/client/connection.rs @@ -441,7 +441,7 @@ mod test { } } } - Err(err) => Poll::Ready(()), + Err(_) => Poll::Ready(()), } } } From d8df60bf4c04c3cbb99bcf19a141c202223e07ea Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 3 Aug 2023 07:03:42 +0100 Subject: [PATCH 099/314] build: add justfile --- .cargo/config.toml | 3 --- .github/workflows/coverage.yml | 2 +- justfile | 11 +++++++++++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 justfile diff --git a/.cargo/config.toml b/.cargo/config.toml index deb300749..931b20b2c 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -12,6 +12,3 @@ ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --skip= # testing ci-doctest-default = "test --workspace --doc --no-fail-fast -- --nocapture" ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture" - -# compile docs as docs.rs would -# RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 1e450d491..1feae0432 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,7 +5,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/justfile b/justfile new file mode 100644 index 000000000..f2e449d85 --- /dev/null +++ b/justfile @@ -0,0 +1,11 @@ +_list: + @just --list + +# Document crates in workspace. +doc: + RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl + +# Document crates in workspace and watch for changes. +doc-watch: + RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open + cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl From 14355b94421716dd2a70b7bfe1d863f80c768be8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 26 Aug 2023 18:19:32 +0100 Subject: [PATCH 100/314] ci: name msrv jobs (#3114) --- .github/workflows/ci-post-merge.yml | 8 ++++---- .github/workflows/ci.yml | 17 +++++++++-------- .gitignore | 1 + 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 06669e31e..5460eeec4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -22,9 +22,9 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - nightly + - { name: nightly, version: nightly } - name: ${{ matrix.target.name }} / ${{ matrix.version }} + name: ${{ matrix.target.name }} / ${{ matrix.version.name }} runs-on: ${{ matrix.target.os }} steps: @@ -39,10 +39,10 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - - name: Install Rust (${{ matrix.version }}) + - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: ${{ matrix.version }} + toolchain: ${{ matrix.version.version }} - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f073f6afe..f12202017 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,10 +26,10 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - 1.68.0 # MSRV - - stable + - { name: msrv, version: 1.68.0 } + - { name: stable, version: stable } - name: ${{ matrix.target.name }} / ${{ matrix.version }} + name: ${{ matrix.target.name }} / ${{ matrix.version.name }} runs-on: ${{ matrix.target.os }} steps: @@ -44,17 +44,18 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - - name: Install Rust (${{ matrix.version }}) + - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: ${{ matrix.version }} + toolchain: ${{ matrix.version.version }} - name: Install cargo-hack uses: taiki-e/install-action@cargo-hack - # - name: workaround MSRV issues - # if: matrix.version != 'stable' - # run: | + - name: workaround MSRV issues + if: matrix.version.name != 'stable' + run: | + cargo update -p=clap --precise=4.3.24 - name: check minimal run: cargo ci-check-min diff --git a/.gitignore b/.gitignore index 91930acf8..48ccccb92 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ guide/build/ .vscode # code coverage +/lcov.info /codecov.json From 55c15f5bbf96518738bb440cea84c25551296bec Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 27 Aug 2023 00:07:11 +0100 Subject: [PATCH 101/314] minimum viable rustls v0.21 support (#3112) --- .github/workflows/ci.yml | 1 + Cargo.toml | 5 ++ actix-http/CHANGES.md | 2 + actix-http/Cargo.toml | 29 ++++++--- actix-http/examples/tls_rustls.rs | 73 +++++++++++++++++++++ actix-http/examples/ws.rs | 6 +- actix-http/src/h1/service.rs | 69 ++++++++++++++++++-- actix-http/src/h2/service.rs | 57 +++++++++++++++- actix-http/src/lib.rs | 2 +- actix-http/src/service.rs | 104 ++++++++++++++++++++++++++++-- actix-http/tests/test_rustls.rs | 45 +++++++------ actix-web/Cargo.toml | 3 +- awc/Cargo.toml | 2 +- 13 files changed, 350 insertions(+), 48 deletions(-) create mode 100644 actix-http/examples/tls_rustls.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f12202017..fdd6f0f9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: if: matrix.version.name != 'stable' run: | cargo update -p=clap --precise=4.3.24 + cargo update -p=clap_lex --precise=0.5.0 - name: check minimal run: cargo ci-check-min diff --git a/Cargo.toml b/Cargo.toml index 65e3c6ae8..58fd96935 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,11 @@ members = [ "awc", ] +[workspace.package] +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.68" + [profile.dev] # Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much. debug = 0 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 0dedd2c74..7078adb7e 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,8 @@ ### Added +- Add `rustls-0_20` crate feature. +- Add `{H1Service, H2Service, HttpService}::rustls_021()` and `HttpService::rustls_021_with_config()` service constructors. - Add `body::to_body_limit()` function. - Add `body::BodyLimitExceeded` error type. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 6909b785f..61fba4bce 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -15,8 +15,9 @@ categories = [ "web-programming::http-server", "web-programming::websocket", ] -license = "MIT OR Apache-2.0" -edition = "2021" +license.workspace = true +edition.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] # features that docs.rs will build with @@ -43,15 +44,21 @@ ws = [ # TLS via OpenSSL openssl = ["actix-tls/accept", "actix-tls/openssl"] -# TLS via Rustls -rustls = ["actix-tls/accept", "actix-tls/rustls"] +# TLS via Rustls v0.20 +rustls = ["rustls-0_20"] + +# TLS via Rustls v0.20 +rustls-0_20 = ["actix-tls/accept", "actix-tls/rustls-0_20"] + +# TLS via Rustls v0.21 +rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"] # Compression codecs compress-brotli = ["__compress", "brotli"] compress-gzip = ["__compress", "flate2"] compress-zstd = ["__compress", "zstd"] -# Internal (PRIVATE!) features used to aid testing and cheking feature status. +# Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They are semver-exempt and may disappear at anytime. __compress = [] @@ -91,7 +98,7 @@ rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } # openssl/rustls -actix-tls = { version = "3", default-features = false, optional = true } +actix-tls = { version = "3.1", default-features = false, optional = true } # compress-* brotli = { version = "3.3.3", optional = true } @@ -101,7 +108,7 @@ zstd = { version = "0.12", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-tls = { version = "3", features = ["openssl"] } +actix-tls = { version = "3.1", features = ["openssl"] } actix-web = "4" async-stream = "0.3" @@ -118,12 +125,16 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls = { package = "rustls", version = "0.20" } +tls-rustls_021 = { package = "rustls", version = "0.21" } tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" -required-features = ["ws", "rustls"] +required-features = ["ws", "rustls-0_21"] + +[[example]] +name = "tls_rustls" +required-features = ["http2", "rustls-0_21"] [[bench]] name = "response-body-compression" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs new file mode 100644 index 000000000..fbb55c6a4 --- /dev/null +++ b/actix-http/examples/tls_rustls.rs @@ -0,0 +1,73 @@ +//! Demonstrates TLS configuration (via Rustls) for HTTP/1.1 and HTTP/2 connections. +//! +//! Test using cURL: +//! +//! ```console +//! $ curl --insecure https://127.0.0.1:8443 +//! Hello World! +//! Protocol: HTTP/2.0 +//! +//! $ curl --insecure --http1.1 https://127.0.0.1:8443 +//! Hello World! +//! Protocol: HTTP/1.1 +//! ``` + +extern crate tls_rustls_021 as rustls; + +use std::io; + +use actix_http::{Error, HttpService, Request, Response}; +use actix_utils::future::ok; + +#[actix_rt::main] +async fn main() -> io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + tracing::info!("starting HTTP server at https://127.0.0.1:8443"); + + actix_server::Server::build() + .bind("echo", ("127.0.0.1", 8443), || { + HttpService::build() + .finish(|req: Request| { + let body = format!( + "Hello World!\n\ + Protocol: {:?}", + req.head().version + ); + ok::<_, Error>(Response::ok().set_body(body)) + }) + .rustls_021(rustls_config()) + })? + .run() + .await +} + +fn rustls_config() -> rustls::ServerConfig { + let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); + let cert_file = cert.serialize_pem().unwrap(); + let key_file = cert.serialize_private_key_pem(); + + let cert_file = &mut io::BufReader::new(cert_file.as_bytes()); + let key_file = &mut io::BufReader::new(key_file.as_bytes()); + + let cert_chain = rustls_pemfile::certs(cert_file) + .unwrap() + .into_iter() + .map(rustls::Certificate) + .collect(); + let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap(); + + let mut config = rustls::ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(cert_chain, rustls::PrivateKey(keys.remove(0))) + .unwrap(); + + const H1_ALPN: &[u8] = b"http/1.1"; + const H2_ALPN: &[u8] = b"h2"; + + config.alpn_protocols.push(H2_ALPN.to_vec()); + config.alpn_protocols.push(H1_ALPN.to_vec()); + + config +} diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index 6af6d5095..241175ae2 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -1,7 +1,7 @@ //! Sets up a WebSocket server over TCP and TLS. //! Sends a heartbeat message every 4 seconds but does not respond to any incoming frames. -extern crate tls_rustls as rustls; +extern crate tls_rustls_021 as rustls; use std::{ io, @@ -28,7 +28,9 @@ async fn main() -> io::Result<()> { HttpService::build().h1(handler).tcp() })? .bind("tls", ("127.0.0.1", 8443), || { - HttpService::build().finish(handler).rustls(tls_config()) + HttpService::build() + .finish(handler) + .rustls_021(tls_config()) })? .run() .await diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index fbda7138e..3b27e3db5 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -152,13 +152,13 @@ mod openssl { } } -#[cfg(feature = "rustls")] -mod rustls { +#[cfg(feature = "rustls-0_20")] +mod rustls_020 { use std::io; use actix_service::ServiceFactoryExt as _; use actix_tls::accept::{ - rustls::{reexports::ServerConfig, Acceptor, TlsStream}, + rustls_0_20::{reexports::ServerConfig, Acceptor, TlsStream}, TlsError, }; @@ -188,7 +188,7 @@ mod rustls { U::Error: fmt::Display + Into>, U::InitError: fmt::Debug, { - /// Create Rustls based service. + /// Create Rustls v0.20 based service. pub fn rustls( self, config: ServerConfig, @@ -213,6 +213,67 @@ mod rustls { } } +#[cfg(feature = "rustls-0_21")] +mod rustls_021 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H1Service, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into>, + S::InitError: fmt::Debug, + S::Response: Into>, + + B: MessageBody, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.21 based service. + pub fn rustls_021( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl H1Service where S: ServiceFactory, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 3f742135a..0ae7ea682 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -140,8 +140,8 @@ mod openssl { } } -#[cfg(feature = "rustls")] -mod rustls { +#[cfg(feature = "rustls-0_20")] +mod rustls_020 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -162,7 +162,7 @@ mod rustls { B: MessageBody + 'static, { - /// Create Rustls based service. + /// Create Rustls v0.20 based service. pub fn rustls( self, mut config: ServerConfig, @@ -191,6 +191,57 @@ mod rustls { } } +#[cfg(feature = "rustls-0_21")] +mod rustls_021 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H2Service, S, B> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + { + /// Create Rustls v0.21 based service. + pub fn rustls_021( + self, + mut config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = S::InitError, + > { + let mut protos = vec![b"h2".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Option)> for H2Service where T: AsyncRead + AsyncWrite + Unpin + 'static, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 8b755f2f4..382295fbc 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -58,7 +58,7 @@ pub mod ws; #[allow(deprecated)] pub use self::payload::PayloadStream; -#[cfg(any(feature = "openssl", feature = "rustls"))] +#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] pub use self::service::TlsAcceptorConfig; pub use self::{ builder::HttpServiceBuilder, diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index e118d8361..bb0fda8c4 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -241,13 +241,13 @@ where } /// Configuration options used when accepting TLS connection. -#[cfg(any(feature = "openssl", feature = "rustls"))] +#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] #[derive(Debug, Default)] pub struct TlsAcceptorConfig { pub(crate) handshake_timeout: Option, } -#[cfg(any(feature = "openssl", feature = "rustls"))] +#[cfg(any(feature = "openssl", feature = "rustls", feature = "rustls-0_21"))] impl TlsAcceptorConfig { /// Set TLS handshake timeout duration. pub fn handshake_timeout(self, dur: std::time::Duration) -> Self { @@ -352,8 +352,8 @@ mod openssl { } } -#[cfg(feature = "rustls")] -mod rustls { +#[cfg(feature = "rustls-0_20")] +mod rustls_020 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -448,6 +448,102 @@ mod rustls { } } +#[cfg(feature = "rustls-0_21")] +mod rustls_021 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl HttpService, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::InitError: fmt::Debug, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, h1::Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls based service. + pub fn rustls_021( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + self.rustls_021_with_config(config, TlsAcceptorConfig::default()) + } + + /// Create Rustls based service with custom TLS acceptor configuration. + pub fn rustls_021_with_config( + self, + mut config: ServerConfig, + tls_acceptor_config: TlsAcceptorConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + let mut acceptor = Acceptor::new(config); + + if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout { + acceptor.set_handshake_timeout(handshake_timeout); + } + + acceptor + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .and_then(|io: TlsStream| async { + let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() { + if protos.windows(2).any(|window| window == b"h2") { + Protocol::Http2 + } else { + Protocol::Http1 + } + } else { + Protocol::Http1 + }; + let peer_addr = io.get_ref().0.peer_addr().ok(); + Ok((io, proto, peer_addr)) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Protocol, Option)> for HttpService where diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index 3d9a39cbd..c94e579e5 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -1,7 +1,6 @@ -#![cfg(feature = "rustls")] -#![allow(clippy::uninlined_format_args)] +#![cfg(feature = "rustls-0_21")] -extern crate tls_rustls as rustls; +extern crate tls_rustls_021 as rustls; use std::{ convert::Infallible, @@ -21,7 +20,7 @@ use actix_http::{ use actix_http_test::test_server; use actix_rt::pin; use actix_service::{fn_factory_with_config, fn_service}; -use actix_tls::connect::rustls::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_21::webpki_roots_cert_store; use actix_utils::future::{err, ok, poll_fn}; use bytes::{Bytes, BytesMut}; use derive_more::{Display, Error}; @@ -110,7 +109,7 @@ async fn h1() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -124,7 +123,7 @@ async fn h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -142,7 +141,7 @@ async fn h1_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_11); ok::<_, Error>(Response::ok()) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -160,7 +159,7 @@ async fn h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::ok()) }) - .rustls_with_config( + .rustls_021_with_config( tls_config(), TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)), ) @@ -181,7 +180,7 @@ async fn h2_body1() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -207,7 +206,7 @@ async fn h2_content_length() { ]; ok::<_, Infallible>(Response::new(statuses[indx])) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -279,7 +278,7 @@ async fn h2_headers() { } ok::<_, Infallible>(config.body(data.clone())) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -318,7 +317,7 @@ async fn h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -335,7 +334,7 @@ async fn h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -361,7 +360,7 @@ async fn h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -386,7 +385,7 @@ async fn h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -412,7 +411,7 @@ async fn h2_body_length() { Response::ok().set_body(SizedStream::new(STR.len() as u64, body)), ) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -436,7 +435,7 @@ async fn h2_body_chunked_explicit() { .body(BodyStream::new(body)), ) }) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -465,7 +464,7 @@ async fn h2_response_http_error_handling() { ) })) })) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -495,7 +494,7 @@ async fn h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::, _>(BadRequest)) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -512,7 +511,7 @@ async fn h1_service_error() { let mut srv = test_server(move || { HttpService::build() .h1(|_| err::, _>(BadRequest)) - .rustls(tls_config()) + .rustls_021(tls_config()) }) .await; @@ -535,7 +534,7 @@ async fn alpn_h1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls(config) + .rustls_021(config) }) .await; @@ -557,7 +556,7 @@ async fn alpn_h2() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls(config) + .rustls_021(config) }) .await; @@ -583,7 +582,7 @@ async fn alpn_h2_1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .finish(|_| ok::<_, Error>(Response::ok())) - .rustls(config) + .rustls_021(config) }) .await; diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 4322fb871..7dbaa2a29 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -16,7 +16,8 @@ categories = [ homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" license = "MIT OR Apache-2.0" -edition = "2021" +edition.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] # features that docs.rs will build with diff --git a/awc/Cargo.toml b/awc/Cargo.toml index daec84ab9..2a09a52c4 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -45,7 +45,7 @@ cookies = ["cookie"] # trust-dns as dns resolver trust-dns = ["trust-dns-resolver"] -# Internal (PRIVATE!) features used to aid testing and cheking feature status. +# Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. __compress = [] From cbf5e948db5237c0efc359fac19e116ec4c1d561 Mon Sep 17 00:00:00 2001 From: Wyatt Herkamp Date: Sun, 27 Aug 2023 18:47:05 -0400 Subject: [PATCH 102/314] Implement Deserialize and Default for actix_web::Data (#3109) * Implement Default and Deserialize for Data * FMT * Change Log * tweak changelog * chore: whitespace --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 2 ++ actix-web/src/data.rs | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 518a02507..97bf4ed04 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -9,6 +9,8 @@ - Add `web::Payload::to_bytes[_limited]()` helper methods. - Add missing constructors on `HttpResponse` for several status codes. - Add `http::header::ContentLength` typed header. +- Implement `Default` for `web::Data`. +- Implement `serde::Deserialize` for `web::Data`. ### Changed diff --git a/actix-web/src/data.rs b/actix-web/src/data.rs index 423dd598c..449a24a64 100644 --- a/actix-web/src/data.rs +++ b/actix-web/src/data.rs @@ -3,7 +3,7 @@ use std::{any::type_name, ops::Deref, sync::Arc}; use actix_http::Extensions; use actix_utils::future::{err, ok, Ready}; use futures_core::future::LocalBoxFuture; -use serde::Serialize; +use serde::{de, Serialize}; use crate::{dev::Payload, error, Error, FromRequest, HttpRequest}; @@ -128,6 +128,12 @@ impl From> for Data { } } +impl Default for Data { + fn default() -> Self { + Data::new(T::default()) + } +} + impl Serialize for Data where T: Serialize, @@ -139,6 +145,17 @@ where self.0.serialize(serializer) } } +impl<'de, T> de::Deserialize<'de> for Data +where + T: de::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + Ok(Data::new(T::deserialize(deserializer)?)) + } +} impl FromRequest for Data { type Error = Error; From 905c30af865924b8853eba7149cddd17c114d171 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:11:11 +0100 Subject: [PATCH 103/314] Actix Web Rustls v0.21 support (#3116) --- .github/workflows/ci.yml | 2 +- .github/workflows/clippy-fmt.yml | 5 +- actix-files/src/lib.rs | 7 +- actix-http/Cargo.toml | 2 +- actix-http/src/h1/payload.rs | 7 +- actix-http/src/service.rs | 2 +- actix-multipart/src/server.rs | 4 +- actix-router/benches/quoter.rs | 9 +- actix-router/src/url.rs | 8 +- actix-test/CHANGES.md | 4 +- actix-test/Cargo.toml | 13 ++- actix-test/src/lib.rs | 75 +++++++++++--- actix-web/CHANGES.md | 4 +- actix-web/Cargo.toml | 16 +-- actix-web/src/app_service.rs | 6 +- actix-web/src/handler.rs | 2 +- actix-web/src/route.rs | 2 +- actix-web/src/server.rs | 126 +++++++++++++++++++---- actix-web/tests/test_server.rs | 6 +- awc/CHANGES.md | 2 + awc/Cargo.toml | 27 +++-- awc/src/client/connector.rs | 167 ++++++++++++++++++++++++------- awc/tests/test_rustls_client.rs | 10 +- 23 files changed, 382 insertions(+), 124 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdd6f0f9a..f071ec8f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,7 +69,7 @@ jobs: run: | cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls + cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls cargo test --lib --tests -p=actix-web-codegen --all-features cargo test --lib --tests -p=awc --all-features cargo test --lib --tests -p=actix-http-test --all-features diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 109165ce0..25c05bcbc 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -39,7 +39,7 @@ jobs: with: reporter: 'github-pr-check' github_token: ${{ secrets.GITHUB_TOKEN }} - clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo + clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints lint-docs: runs-on: ubuntu-latest @@ -63,8 +63,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions-rust-lang/setup-rust-toolchain@v1 - # temp: unpin once https://github.com/rust-lang/rust/issues/113152 is fixed - with: { toolchain: nightly-2023-06-28 } + with: { toolchain: nightly-2023-08-25 } - uses: taiki-e/cache-cargo-install-action@v1 with: { tool: cargo-public-api } diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 1d8609889..7871905f6 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -66,6 +66,7 @@ type PathFilter = dyn Fn(&Path, &RequestHead) -> bool; #[cfg(test)] mod tests { use std::{ + fmt::Write as _, fs::{self}, ops::Add, time::{Duration, SystemTime}, @@ -848,8 +849,10 @@ mod tests { let filename_encoded = filename .as_bytes() .iter() - .map(|c| format!("%{:02X}", c)) - .collect::(); + .fold(String::new(), |mut buf, c| { + write!(&mut buf, "%{:02X}", c).unwrap(); + buf + }); std::fs::File::create(tmpdir.path().join(filename)).unwrap(); let srv = test::init_service(App::new().service(Files::new("", tmpdir.path()))).await; diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 61fba4bce..6aaaecfd4 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -21,7 +21,7 @@ rust-version.workspace = true [package.metadata.docs.rs] # features that docs.rs will build with -features = ["http2", "ws", "openssl", "rustls", "compress-brotli", "compress-gzip", "compress-zstd"] +features = ["http2", "ws", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd"] [lib] name = "actix_http" diff --git a/actix-http/src/h1/payload.rs b/actix-http/src/h1/payload.rs index 1ed785a1b..2ad3a14a3 100644 --- a/actix-http/src/h1/payload.rs +++ b/actix-http/src/h1/payload.rs @@ -117,6 +117,7 @@ impl PayloadSender { } } + #[allow(clippy::needless_pass_by_ref_mut)] #[inline] pub fn need_read(&self, cx: &mut Context<'_>) -> PayloadStatus { // we check need_read only if Payload (other side) is alive, @@ -174,7 +175,7 @@ impl Inner { /// Register future waiting data from payload. /// Waker would be used in `Inner::wake` - fn register(&mut self, cx: &mut Context<'_>) { + fn register(&mut self, cx: &Context<'_>) { if self .task .as_ref() @@ -186,7 +187,7 @@ impl Inner { // Register future feeding data to payload. /// Waker would be used in `Inner::wake_io` - fn register_io(&mut self, cx: &mut Context<'_>) { + fn register_io(&mut self, cx: &Context<'_>) { if self .io_task .as_ref() @@ -221,7 +222,7 @@ impl Inner { fn poll_next( mut self: Pin<&mut Self>, - cx: &mut Context<'_>, + cx: &Context<'_>, ) -> Poll>> { if let Some(data) = self.items.pop_front() { self.len -= data.len(); diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index bb0fda8c4..fb38ba636 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -247,7 +247,7 @@ pub struct TlsAcceptorConfig { pub(crate) handshake_timeout: Option, } -#[cfg(any(feature = "openssl", feature = "rustls", feature = "rustls-0_21"))] +#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] impl TlsAcceptorConfig { /// Set TLS handshake timeout duration. pub fn handshake_timeout(self, dur: std::time::Duration) -> Self { diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index b20429040..c08031eba 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -252,7 +252,7 @@ impl InnerMultipart { fn poll( &mut self, safety: &Safety, - cx: &mut Context<'_>, + cx: &Context<'_>, ) -> Poll>> { if self.state == InnerState::Eof { Poll::Ready(None) @@ -740,7 +740,7 @@ impl Safety { self.clean.get() } - fn clone(&self, cx: &mut Context<'_>) -> Safety { + fn clone(&self, cx: &Context<'_>) -> Safety { let payload = Rc::clone(&self.payload); let s = Safety { task: LocalWaker::new(), diff --git a/actix-router/benches/quoter.rs b/actix-router/benches/quoter.rs index 2065fd563..c78240809 100644 --- a/actix-router/benches/quoter.rs +++ b/actix-router/benches/quoter.rs @@ -1,6 +1,6 @@ #![allow(clippy::uninlined_format_args)] -use std::borrow::Cow; +use std::{borrow::Cow, fmt::Write as _}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; @@ -8,9 +8,10 @@ fn compare_quoters(c: &mut Criterion) { let mut group = c.benchmark_group("Compare Quoters"); let quoter = actix_router::Quoter::new(b"", b""); - let path_quoted = (0..=0x7f) - .map(|c| format!("%{:02X}", c)) - .collect::(); + let path_quoted = (0..=0x7f).fold(String::new(), |mut buf, c| { + write!(&mut buf, "%{:02X}", c).unwrap(); + buf + }); let path_unquoted = ('\u{00}'..='\u{7f}').collect::(); group.bench_function("quoter_unquoted", |b| { diff --git a/actix-router/src/url.rs b/actix-router/src/url.rs index 2920e271d..b3d9e1121 100644 --- a/actix-router/src/url.rs +++ b/actix-router/src/url.rs @@ -62,6 +62,8 @@ impl ResourcePath for Url { #[cfg(test)] mod tests { + use std::fmt::Write as _; + use http::Uri; use super::*; @@ -78,7 +80,11 @@ mod tests { } fn percent_encode(data: &[u8]) -> String { - data.iter().map(|c| format!("%{:02X}", c)).collect() + data.iter() + .fold(String::with_capacity(data.len() * 3), |mut buf, c| { + write!(&mut buf, "%{:02X}", c).unwrap(); + buf + }) } #[test] diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index fae8201d2..477ed4c04 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,7 +2,9 @@ ## Unreleased - 2023-xx-xx -- Add `TestServerConfig::workers()` setter method. +- Add `TestServerConfig::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. +- Add `TestServerConfig::workers()` method. +- Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.1.1 - 2023-02-26 diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 9cf5aa76c..dd96084b3 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -21,10 +21,14 @@ edition = "2021" [features] default = [] -# rustls -rustls = ["tls-rustls", "actix-http/rustls", "awc/rustls"] +# TLS via Rustls v0.20 +rustls = ["rustls-0_20"] +# TLS via Rustls v0.20 +rustls-0_20 = ["tls-rustls-0_20", "actix-http/rustls-0_20", "awc/rustls-0_20"] +# TLS via Rustls v0.21 +rustls-0_21 = ["tls-rustls-0_21", "actix-http/rustls-0_21", "awc/rustls-0_21"] -# openssl +# TLS via OpenSSL openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] [dependencies] @@ -44,5 +48,6 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" serde_urlencoded = "0.7" tls-openssl = { package = "openssl", version = "0.10.55", optional = true } -tls-rustls = { package = "rustls", version = "0.20", optional = true } +tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true } +tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true } tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 751ab3161..e570bb266 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -34,8 +34,6 @@ #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; -#[cfg(feature = "rustls")] -extern crate tls_rustls as rustls; use std::{fmt, net, thread, time::Duration}; @@ -141,8 +139,10 @@ where StreamType::Tcp => false, #[cfg(feature = "openssl")] StreamType::Openssl(_) => true, - #[cfg(feature = "rustls")] - StreamType::Rustls(_) => true, + #[cfg(feature = "rustls-0_20")] + StreamType::Rustls020(_) => true, + #[cfg(feature = "rustls-0_21")] + StreamType::Rustls021(_) => true, }; // run server in separate orphaned thread @@ -243,8 +243,8 @@ where .openssl(acceptor.clone()) }), }, - #[cfg(feature = "rustls")] - StreamType::Rustls(config) => match cfg.tp { + #[cfg(feature = "rustls-0_20")] + StreamType::Rustls020(config) => match cfg.tp { HttpVer::Http1 => builder.listen("test", tcp, move || { let app_cfg = AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); @@ -285,6 +285,48 @@ where .rustls(config.clone()) }), }, + #[cfg(feature = "rustls-0_21")] + StreamType::Rustls021(config) => match cfg.tp { + HttpVer::Http1 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h1(map_config(fac, move |_| app_cfg.clone())) + .rustls_021(config.clone()) + }), + HttpVer::Http2 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h2(map_config(fac, move |_| app_cfg.clone())) + .rustls_021(config.clone()) + }), + HttpVer::Both => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .finish(map_config(fac, move |_| app_cfg.clone())) + .rustls_021(config.clone()) + }), + }, } .expect("test server could not be created"); @@ -316,7 +358,7 @@ where builder.set_verify(SslVerifyMode::NONE); let _ = builder .set_alpn_protos(b"\x02h2\x08http/1.1") - .map_err(|e| log::error!("Can not set alpn protocol: {:?}", e)); + .map_err(|err| log::error!("Can not set alpn protocol: {err:?}")); Connector::new() .conn_lifetime(Duration::from_secs(0)) .timeout(Duration::from_millis(30000)) @@ -355,8 +397,10 @@ enum StreamType { Tcp, #[cfg(feature = "openssl")] Openssl(openssl::ssl::SslAcceptor), - #[cfg(feature = "rustls")] - Rustls(rustls::ServerConfig), + #[cfg(feature = "rustls-0_20")] + Rustls020(tls_rustls_0_20::ServerConfig), + #[cfg(feature = "rustls-0_21")] + Rustls021(tls_rustls_0_21::ServerConfig), } /// Create default test server config. @@ -411,9 +455,16 @@ impl TestServerConfig { } /// Accept secure connections via Rustls. - #[cfg(feature = "rustls")] - pub fn rustls(mut self, config: rustls::ServerConfig) -> Self { - self.stream = StreamType::Rustls(config); + #[cfg(feature = "rustls-0_20")] + pub fn rustls(mut self, config: tls_rustls_0_20::ServerConfig) -> Self { + self.stream = StreamType::Rustls020(config); + self + } + + /// Accept secure connections via Rustls. + #[cfg(feature = "rustls-0_21")] + pub fn rustls_021(mut self, config: tls_rustls_0_21::ServerConfig) -> Self { + self.stream = StreamType::Rustls021(config); self } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 97bf4ed04..aaa262e63 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,13 +4,15 @@ ### Added -- Add `HttpServer::{bind, listen}_auto_h2c()` method behind new `http2` crate feature. +- Add `HttpServer::{bind, listen}_auto_h2c()` methods behind new `http2` crate feature. +- Add `HttpServer::{bind, listen}_rustls_021()` methods for Rustls v0.21 support behind new `rustls-0_21` crate feature. - Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. - Add `web::Payload::to_bytes[_limited]()` helper methods. - Add missing constructors on `HttpResponse` for several status codes. - Add `http::header::ContentLength` typed header. - Implement `Default` for `web::Data`. - Implement `serde::Deserialize` for `web::Data`. +- Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. ### Changed diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 7dbaa2a29..e85a0c90e 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -21,7 +21,7 @@ rust-version.workspace = true [package.metadata.docs.rs] # features that docs.rs will build with -features = ["macros", "openssl", "rustls", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "secure-cookies"] +features = ["macros", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "secure-cookies"] rustdoc-args = ["--cfg", "docsrs"] [lib] @@ -52,8 +52,12 @@ http2 = ["actix-http/http2"] # TLS via OpenSSL openssl = ["http2", "actix-http/openssl", "actix-tls/accept", "actix-tls/openssl"] -# TLS via Rustls -rustls = ["http2", "actix-http/rustls", "actix-tls/accept", "actix-tls/rustls"] +# TLS via Rustls v0.20 +rustls = ["rustls-0_20"] +# TLS via Rustls v0.20 +rustls-0_20 = ["http2", "actix-http/rustls-0_20", "actix-tls/accept", "actix-tls/rustls-0_20"] +# TLS via Rustls v0.21 +rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"] # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. @@ -69,7 +73,7 @@ actix-rt = { version = "2.6", default-features = false } actix-server = "2" actix-service = "2" actix-utils = "3" -actix-tls = { version = "3", default-features = false, optional = true } +actix-tls = { version = "3.1", default-features = false, optional = true } actix-http = { version = "3.3", features = ["ws"] } actix-router = "0.5" @@ -101,7 +105,7 @@ url = "2.1" [dev-dependencies] actix-files = "0.6" -actix-test = { version = "0.1", features = ["openssl", "rustls"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } awc = { version = "3", features = ["openssl"] } brotli = "3.3.3" @@ -116,7 +120,7 @@ rustls-pemfile = "1" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls = { package = "rustls", version = "0.20" } +tls-rustls = { package = "rustls", version = "0.21" } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.12" diff --git a/actix-web/src/app_service.rs b/actix-web/src/app_service.rs index 513e7a8a1..f2dca954c 100644 --- a/actix-web/src/app_service.rs +++ b/actix-web/src/app_service.rs @@ -112,11 +112,7 @@ where let endpoint_fut = self.endpoint.new_service(()); // take extensions or create new one as app data container. - let mut app_data = self - .extensions - .borrow_mut() - .take() - .unwrap_or_else(Extensions::new); + let mut app_data = self.extensions.borrow_mut().take().unwrap_or_default(); Box::pin(async move { // async data factories diff --git a/actix-web/src/handler.rs b/actix-web/src/handler.rs index 0c5e58e28..3d6b7f039 100644 --- a/actix-web/src/handler.rs +++ b/actix-web/src/handler.rs @@ -167,7 +167,7 @@ mod tests { async fn handler_min() {} #[rustfmt::skip] - #[allow(clippy::too_many_arguments, clippy::just_underscores_and_digits)] + #[allow(clippy::too_many_arguments, clippy::just_underscores_and_digits, clippy::let_unit_value)] async fn handler_max( _01: (), _02: (), _03: (), _04: (), _05: (), _06: (), _07: (), _08: (), _09: (), _10: (), _11: (), _12: (), diff --git a/actix-web/src/route.rs b/actix-web/src/route.rs index 674d0082a..a46c1fdd4 100644 --- a/actix-web/src/route.rs +++ b/actix-web/src/route.rs @@ -92,7 +92,7 @@ pub struct RouteService { } impl RouteService { - // TODO: does this need to take &mut ? + #[allow(clippy::needless_pass_by_ref_mut)] pub fn check(&self, req: &mut ServiceRequest) -> bool { let guard_ctx = req.guard_ctx(); diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index a540da7c8..879b269a0 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -7,7 +7,7 @@ use std::{ time::Duration, }; -#[cfg(any(feature = "openssl", feature = "rustls"))] +#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] use actix_http::TlsAcceptorConfig; use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response}; use actix_server::{Server, ServerBuilder}; @@ -16,8 +16,6 @@ use actix_service::{ }; #[cfg(feature = "openssl")] use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder}; -#[cfg(feature = "rustls")] -use actix_tls::accept::rustls::reexports::ServerConfig as RustlsServerConfig; use crate::{config::AppConfig, Error}; @@ -31,7 +29,7 @@ struct Config { keep_alive: KeepAlive, client_request_timeout: Duration, client_disconnect_timeout: Duration, - #[cfg(any(feature = "openssl", feature = "rustls"))] + #[allow(dead_code)] // only dead when no TLS features are enabled tls_handshake_timeout: Option, } @@ -109,7 +107,6 @@ where keep_alive: KeepAlive::default(), client_request_timeout: Duration::from_secs(5), client_disconnect_timeout: Duration::from_secs(1), - #[cfg(any(feature = "rustls", feature = "openssl"))] tls_handshake_timeout: None, })), backlog: 1024, @@ -170,7 +167,7 @@ where /// By default max connections is set to a 256. #[allow(unused_variables)] pub fn max_connection_rate(self, num: usize) -> Self { - #[cfg(any(feature = "rustls", feature = "openssl"))] + #[cfg(any(feature = "rustls-0_20", feature = "rustls-0_21", feature = "openssl"))] actix_tls::accept::max_concurrent_tls_connect(num); self } @@ -222,8 +219,8 @@ where /// Defines a timeout for TLS handshake. If the TLS handshake does not complete within this /// time, the connection is closed. /// - /// By default handshake timeout is set to 3000 milliseconds. - #[cfg(any(feature = "openssl", feature = "rustls"))] + /// By default, the handshake timeout is 3 seconds. + #[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] pub fn tls_handshake_timeout(self, dur: Duration) -> Self { self.config .lock() @@ -247,7 +244,10 @@ where /// /// # Connection Types /// - `actix_tls::accept::openssl::TlsStream` when using OpenSSL. - /// - `actix_tls::accept::rustls::TlsStream` when using Rustls. + /// - `actix_tls::accept::rustls_0_20::TlsStream` when using + /// Rustls v0.20. + /// - `actix_tls::accept::rustls_0_21::TlsStream` when using + /// Rustls v0.21. /// - `actix_web::rt::net::TcpStream` when no encryption is used. /// /// See the `on_connect` example for additional details. @@ -368,20 +368,39 @@ where } /// Resolves socket address(es) and binds server to created listener(s) for TLS connections - /// using Rustls. + /// using Rustls v0.20. /// /// See [`bind()`](Self::bind) for more details on `addrs` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. - #[cfg(feature = "rustls")] + #[cfg(feature = "rustls-0_20")] pub fn bind_rustls( mut self, addrs: A, - config: RustlsServerConfig, + config: actix_tls::accept::rustls_0_20::reexports::ServerConfig, ) -> io::Result { let sockets = bind_addrs(addrs, self.backlog)?; for lst in sockets { - self = self.listen_rustls_inner(lst, config.clone())?; + self = self.listen_rustls_0_20_inner(lst, config.clone())?; + } + Ok(self) + } + + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections + /// using Rustls v0.21. + /// + /// See [`bind()`](Self::bind) for more details on `addrs` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_21")] + pub fn bind_rustls_021( + mut self, + addrs: A, + config: actix_tls::accept::rustls_0_21::reexports::ServerConfig, + ) -> io::Result { + let sockets = bind_addrs(addrs, self.backlog)?; + for lst in sockets { + self = self.listen_rustls_0_21_inner(lst, config.clone())?; } Ok(self) } @@ -497,25 +516,41 @@ where Ok(self) } - /// Binds to existing listener for accepting incoming TLS connection requests using Rustls. + /// Binds to existing listener for accepting incoming TLS connection requests using Rustls + /// v0.20. /// /// See [`listen()`](Self::listen) for more details on the `lst` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. - #[cfg(feature = "rustls")] + #[cfg(feature = "rustls-0_20")] pub fn listen_rustls( self, lst: net::TcpListener, - config: RustlsServerConfig, + config: actix_tls::accept::rustls_0_20::reexports::ServerConfig, ) -> io::Result { - self.listen_rustls_inner(lst, config) + self.listen_rustls_0_20_inner(lst, config) } - #[cfg(feature = "rustls")] - fn listen_rustls_inner( + /// Binds to existing listener for accepting incoming TLS connection requests using Rustls + /// v0.21. + /// + /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_21")] + pub fn listen_rustls_0_21( + self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_21::reexports::ServerConfig, + ) -> io::Result { + self.listen_rustls_0_21_inner(lst, config) + } + + #[cfg(feature = "rustls-0_20")] + fn listen_rustls_0_20_inner( mut self, lst: net::TcpListener, - config: RustlsServerConfig, + config: actix_tls::accept::rustls_0_20::reexports::ServerConfig, ) -> io::Result { let factory = self.factory.clone(); let cfg = self.config.clone(); @@ -562,6 +597,57 @@ where Ok(self) } + #[cfg(feature = "rustls-0_21")] + fn listen_rustls_0_21_inner( + mut self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_21::reexports::ServerConfig, + ) -> io::Result { + let factory = self.factory.clone(); + let cfg = self.config.clone(); + let addr = lst.local_addr().unwrap(); + self.sockets.push(Socket { + addr, + scheme: "https", + }); + + let on_connect_fn = self.on_connect_fn.clone(); + + self.builder = + self.builder + .listen(format!("actix-web-service-{}", addr), lst, move || { + let c = cfg.lock().unwrap(); + let host = c.host.clone().unwrap_or_else(|| format!("{}", addr)); + + let svc = HttpService::build() + .keep_alive(c.keep_alive) + .client_request_timeout(c.client_request_timeout) + .client_disconnect_timeout(c.client_disconnect_timeout); + + let svc = if let Some(handler) = on_connect_fn.clone() { + svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)) + } else { + svc + }; + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + let acceptor_config = match c.tls_handshake_timeout { + Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur), + None => TlsAcceptorConfig::default(), + }; + + svc.finish(map_config(fac, move |_| { + AppConfig::new(true, host.clone(), addr) + })) + .rustls_021_with_config(config.clone(), acceptor_config) + })?; + + Ok(self) + } + /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL. /// /// See [`listen()`](Self::listen) for more details on the `lst` argument. diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 8ce889396..a268cb6e3 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -1,6 +1,6 @@ #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; -#[cfg(feature = "rustls")] +#[cfg(feature = "rustls-0_21")] extern crate tls_rustls as rustls; use std::{ @@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() { srv.stop().await; } -#[cfg(feature = "rustls")] +#[cfg(feature = "rustls-0_21")] mod plus_rustls { use std::io::BufReader; @@ -743,7 +743,7 @@ mod plus_rustls { .map(char::from) .collect::(); - let srv = actix_test::start_with(actix_test::config().rustls(tls_config()), || { + let srv = actix_test::start_with(actix_test::config().rustls_021(tls_config()), || { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { // echo decompressed request body back in response HttpResponse::Ok() diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 3429a84d7..c998cd97a 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Add `awc::Connector::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. +- Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 3.1.1 - 2023-02-26 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 2a09a52c4..67d6b06f5 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -21,16 +21,20 @@ path = "src/lib.rs" [package.metadata.docs.rs] # features that docs.rs will build with -features = ["openssl", "rustls", "compress-brotli", "compress-gzip", "compress-zstd", "cookies"] +features = ["openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd", "cookies"] [features] default = ["compress-brotli", "compress-gzip", "compress-zstd", "cookies"] -# openssl +# TLS via OpenSSL openssl = ["tls-openssl", "actix-tls/openssl"] -# rustls -rustls = ["tls-rustls", "actix-tls/rustls"] +# TLS via Rustls v0.20 +rustls = ["rustls-0_20"] +# TLS via Rustls v0.20 +rustls-0_20 = ["tls-rustls-0_20", "actix-tls/rustls-0_20"] +# TLS via Rustls v0.21 +rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -39,10 +43,10 @@ compress-gzip = ["actix-http/compress-gzip", "__compress"] # Zstd algorithm content-encoding support compress-zstd = ["actix-http/compress-zstd", "__compress"] -# cookie parsing and cookie jar +# Cookie parsing and cookie jar cookies = ["cookie"] -# trust-dns as dns resolver +# Use `trust-dns-resolver` crate as DNS resolver trust-dns = ["trust-dns-resolver"] # Internal (PRIVATE!) features used to aid testing and checking feature status. @@ -59,7 +63,7 @@ actix-codec = "0.5" actix-service = "2" actix-http = { version = "3.3", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } -actix-tls = { version = "3", features = ["connect", "uri"] } +actix-tls = { version = "3.1", features = ["connect", "uri"] } actix-utils = "3" base64 = "0.21" @@ -84,7 +88,8 @@ tokio = { version = "1.24.2", features = ["sync"] } cookie = { version = "0.16", features = ["percent-encode"], optional = true } tls-openssl = { package = "openssl", version = "0.10.55", optional = true } -tls-rustls = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } +tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } +tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } trust-dns-resolver = { version = "0.22", optional = true } @@ -92,8 +97,8 @@ trust-dns-resolver = { version = "0.22", optional = true } actix-http = { version = "3", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-test = { version = "0.1", features = ["openssl", "rustls"] } -actix-tls = { version = "3", features = ["openssl", "rustls"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } +actix-tls = { version = "3", features = ["openssl", "rustls-0_21"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } @@ -110,4 +115,4 @@ zstd = "0.12" [[example]] name = "client" -required-features = ["rustls"] +required-features = ["rustls-0_21"] diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 1ecaf9947..538b64ffd 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -43,20 +43,22 @@ enum OurTlsConnector { #[allow(dead_code)] // false positive; used in build_ssl OpensslBuilder(actix_tls::connect::openssl::reexports::SslConnectorBuilder), - #[cfg(feature = "rustls")] - Rustls(std::sync::Arc), + #[cfg(feature = "rustls-0_20")] + Rustls020(std::sync::Arc), + + #[cfg(feature = "rustls-0_21")] + Rustls021(std::sync::Arc), } /// Manages HTTP client network connectivity. /// -/// The `Connector` type uses a builder-like combinator pattern for service -/// construction that finishes by calling the `.finish()` method. +/// The `Connector` type uses a builder-like combinator pattern for service construction that +/// finishes by calling the `.finish()` method. /// -/// ```ignore +/// ```no_run /// use std::time::Duration; -/// use actix_http::client::Connector; /// -/// let connector = Connector::new() +/// let connector = awc::Connector::new() /// .timeout(Duration::from_secs(5)) /// .finish(); /// ``` @@ -80,22 +82,22 @@ impl Connector<()> { Connector { connector: TcpConnector::new(resolver::resolver()).service(), config: ConnectorConfig::default(), - tls: Self::build_ssl(vec![b"h2".to_vec(), b"http/1.1".to_vec()]), + tls: Self::build_tls(vec![b"h2".to_vec(), b"http/1.1".to_vec()]), } } /// Provides an empty TLS connector when no TLS feature is enabled. - #[cfg(not(any(feature = "openssl", feature = "rustls")))] - fn build_ssl(_: Vec>) -> OurTlsConnector { + #[cfg(not(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21")))] + fn build_tls(_: Vec>) -> OurTlsConnector { OurTlsConnector::None } - /// Build TLS connector with rustls, based on supplied ALPN protocols + /// Build TLS connector with Rustls v0.21, based on supplied ALPN protocols /// - /// Note that if both `openssl` and `rustls` features are enabled, rustls will be used. - #[cfg(feature = "rustls")] - fn build_ssl(protocols: Vec>) -> OurTlsConnector { - use actix_tls::connect::rustls::{reexports::ClientConfig, webpki_roots_cert_store}; + /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. + #[cfg(feature = "rustls-0_21")] + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_21::{reexports::ClientConfig, webpki_roots_cert_store}; let mut config = ClientConfig::builder() .with_safe_defaults() @@ -104,12 +106,55 @@ impl Connector<()> { config.alpn_protocols = protocols; - OurTlsConnector::Rustls(std::sync::Arc::new(config)) + OurTlsConnector::Rustls021(std::sync::Arc::new(config)) } - /// Build TLS connector with openssl, based on supplied ALPN protocols - #[cfg(all(feature = "openssl", not(feature = "rustls")))] - fn build_ssl(protocols: Vec>) -> OurTlsConnector { + /// Build TLS connector with Rustls v0.21, based on supplied ALPN protocols + /// + /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. + #[cfg(all( + all(feature = "rustls-0_20", feature = "openssl"), + not(feature = "rustls-0_21"), + ))] + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; + + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(webpki_roots_cert_store()) + .with_no_client_auth(); + + config.alpn_protocols = protocols; + + OurTlsConnector::Rustls020(std::sync::Arc::new(config)) + } + + /// Build TLS connector with Rustls v0.20, based on supplied ALPN protocols + /// + /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. + #[cfg(all( + feature = "rustls-0_20", + not(any(feature = "rustls-0_21", feature = "openssl")), + ))] + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; + + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(webpki_roots_cert_store()) + .with_no_client_auth(); + + config.alpn_protocols = protocols; + + OurTlsConnector::Rustls020(std::sync::Arc::new(config)) + } + + /// Build TLS connector with OpenSSL, based on supplied ALPN protocols + #[cfg(all( + feature = "openssl", + not(any(feature = "rustls-0_20", feature = "rustls-0_21")), + ))] + fn build_tls(protocols: Vec>) -> OurTlsConnector { use actix_tls::connect::openssl::reexports::{SslConnector, SslMethod}; use bytes::{BufMut, BytesMut}; @@ -129,7 +174,7 @@ impl Connector<()> { } impl Connector { - /// Use custom connector. + /// Sets custom connector. pub fn connector(self, connector: S1) -> Connector where Io1: ActixStream + fmt::Debug + 'static, @@ -158,21 +203,28 @@ where + Clone + 'static, { - /// Tcp connection timeout, i.e. max time to connect to remote host including dns name - /// resolution. Set to 5 second by default. + /// Sets TCP connection timeout. + /// + /// This is the max time allowed to connect to remote host, including DNS name resolution. + /// + /// By default, the timeout is 5 seconds. pub fn timeout(mut self, timeout: Duration) -> Self { self.config.timeout = timeout; self } - /// Tls handshake timeout, i.e. max time to do tls handshake with remote host after tcp - /// connection established. Set to 5 second by default. + /// Sets TLS handshake timeout. + /// + /// This is the max time allowed to perform the TLS handshake with remote host after TCP + /// connection is established. + /// + /// By default, the timeout is 5 seconds. pub fn handshake_timeout(mut self, timeout: Duration) -> Self { self.config.handshake_timeout = timeout; self } - /// Use custom OpenSSL `SslConnector` instance. + /// Sets custom OpenSSL `SslConnector` instance. #[cfg(feature = "openssl")] pub fn openssl( mut self, @@ -191,13 +243,23 @@ where self } - /// Use custom Rustls `ClientConfig` instance. - #[cfg(feature = "rustls")] + /// Sets custom Rustls v0.20 `ClientConfig` instance. + #[cfg(feature = "rustls-0_20")] pub fn rustls( mut self, - connector: std::sync::Arc, + connector: std::sync::Arc, ) -> Self { - self.tls = OurTlsConnector::Rustls(connector); + self.tls = OurTlsConnector::Rustls020(connector); + self + } + + /// Sets custom Rustls v0.21 `ClientConfig` instance. + #[cfg(feature = "rustls-0_21")] + pub fn rustls_021( + mut self, + connector: std::sync::Arc, + ) -> Self { + self.tls = OurTlsConnector::Rustls021(connector); self } @@ -212,12 +274,12 @@ where unimplemented!("actix-http client only supports versions http/1.1 & http/2") } }; - self.tls = Connector::build_ssl(versions); + self.tls = Connector::build_tls(versions); self } - /// Sets the initial window size (in octets) for HTTP/2 stream-level flow control for - /// received data. + /// Sets the initial window size (in bytes) for HTTP/2 stream-level flow control for received + /// data. /// /// The default value is 65,535 and is good for APIs, but not for big objects. pub fn initial_window_size(mut self, size: u32) -> Self { @@ -225,7 +287,7 @@ where self } - /// Sets the initial window size (in octets) for HTTP/2 connection-level flow control for + /// Sets the initial window size (in bytes) for HTTP/2 connection-level flow control for /// received data. /// /// The default value is 65,535 and is good for APIs, but not for big objects. @@ -405,11 +467,44 @@ where unreachable!("OpenSSL builder is built before this match."); } - #[cfg(feature = "rustls")] - OurTlsConnector::Rustls(tls) => { + #[cfg(feature = "rustls-0_20")] + OurTlsConnector::Rustls020(tls) => { const H2: &[u8] = b"h2"; - use actix_tls::connect::rustls::{reexports::AsyncTlsStream, TlsConnector}; + use actix_tls::connect::rustls_0_20::{reexports::AsyncTlsStream, TlsConnector}; + + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let sock = self.into_parts().0; + let h2 = sock + .get_ref() + .1 + .alpn_protocol() + .map_or(false, |protos| protos.windows(2).any(|w| w == H2)); + if h2 { + (Box::new(sock), Protocol::Http2) + } else { + (Box::new(sock), Protocol::Http1) + } + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: TlsConnector::service(tls), + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } + + #[cfg(feature = "rustls-0_21")] + OurTlsConnector::Rustls021(tls) => { + const H2: &[u8] = b"h2"; + + use actix_tls::connect::rustls_0_21::{reexports::AsyncTlsStream, TlsConnector}; impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index 652997de6..d758f93d8 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls")] +#![cfg(feature = "rustls-0_21")] -extern crate tls_rustls as rustls; +extern crate tls_rustls_0_21 as rustls; use std::{ io::BufReader, @@ -14,7 +14,7 @@ use std::{ use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{fn_service, map_config, ServiceFactoryExt}; -use actix_tls::connect::rustls::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_21::webpki_roots_cert_store; use actix_utils::future::ok; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use rustls::{ @@ -82,7 +82,7 @@ async fn test_connection_reuse_h2() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .rustls(tls_config()) + .rustls_021(tls_config()) .map_err(|_| ()), ) }) @@ -102,7 +102,7 @@ async fn test_connection_reuse_h2() { .set_certificate_verifier(Arc::new(danger::NoCertificateVerification)); let client = awc::Client::builder() - .connector(awc::Connector::new().rustls(Arc::new(config))) + .connector(awc::Connector::new().rustls_021(Arc::new(config))) .finish(); // req 1 From 384ca0a2cd60e2023852579c69b0c56e099c06b7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 28 Aug 2023 23:44:35 +0100 Subject: [PATCH 104/314] chore: remove dates from changelogs --- actix-files/CHANGES.md | 88 ++++++++--------- actix-http-test/CHANGES.md | 64 ++++++------- actix-http/CHANGES.md | 152 +++++++++++++++--------------- actix-multipart-derive/CHANGES.md | 2 +- actix-multipart/CHANGES.md | 62 ++++++------ actix-router/CHANGES.md | 52 +++++----- actix-test/CHANGES.md | 32 +++---- actix-web-actors/CHANGES.md | 60 ++++++------ actix-web-codegen/CHANGES.md | 54 +++++------ actix-web/CHANGES.md | 152 +++++++++++++++--------------- awc/CHANGES.md | 110 ++++++++++----------- 11 files changed, 414 insertions(+), 414 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 31c0499ed..15c2958f0 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -1,10 +1,10 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 0.6.3 - 2023-01-21 +## 0.6.3 - XHTML files now use `Content-Disposition: inline` instead of `attachment`. [#2903] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. @@ -12,14 +12,14 @@ [#2903]: https://github.com/actix/actix-web/pull/2903 -## 0.6.2 - 2022-07-23 +## 0.6.2 - Allow partial range responses for video content to start streaming sooner. [#2817] - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. [#2817]: https://github.com/actix/actix-web/pull/2817 -## 0.6.1 - 2022-06-11 +## 0.6.1 - Add `NamedFile::{modified, metadata, content_type, content_disposition, encoding}()` getters. [#2021] - Update `tokio-uring` dependency to `0.3`. @@ -29,25 +29,25 @@ [#2021]: https://github.com/actix/actix-web/pull/2021 [#2645]: https://github.com/actix/actix-web/pull/2645 -## 0.6.0 - 2022-02-25 +## 0.6.0 - No significant changes since `0.6.0-beta.16`. -## 0.6.0-beta.16 - 2022-01-31 +## 0.6.0-beta.16 - No significant changes since `0.6.0-beta.15`. -## 0.6.0-beta.15 - 2022-01-21 +## 0.6.0-beta.15 - No significant changes since `0.6.0-beta.14`. -## 0.6.0-beta.14 - 2022-01-14 +## 0.6.0-beta.14 - The `prefer_utf8` option introduced in `0.4.0` is now true by default. [#2583] [#2583]: https://github.com/actix/actix-web/pull/2583 -## 0.6.0-beta.13 - 2022-01-04 +## 0.6.0-beta.13 - The `Files` service now rejects requests with URL paths that include `%2F` (decoded: `/`). [#2398] - The `Files` service now correctly decodes `%25` in the URL path to `%` for the file path. [#2398] @@ -55,19 +55,19 @@ [#2398]: https://github.com/actix/actix-web/pull/2398 -## 0.6.0-beta.12 - 2021-12-29 +## 0.6.0-beta.12 - No significant changes since `0.6.0-beta.11`. -## 0.6.0-beta.11 - 2021-12-27 +## 0.6.0-beta.11 - No significant changes since `0.6.0-beta.10`. -## 0.6.0-beta.10 - 2021-12-11 +## 0.6.0-beta.10 - No significant changes since `0.6.0-beta.9`. -## 0.6.0-beta.9 - 2021-11-22 +## 0.6.0-beta.9 - Add crate feature `experimental-io-uring`, enabling async file I/O to be utilized. This feature is only available on Linux OSes with recent kernel versions. This feature is semver-exempt. [#2408] - Add `NamedFile::open_async`. [#2408] @@ -79,15 +79,15 @@ [#2408]: https://github.com/actix/actix-web/pull/2408 [#2453]: https://github.com/actix/actix-web/pull/2453 -## 0.6.0-beta.8 - 2021-10-20 +## 0.6.0-beta.8 - Minimum supported Rust version (MSRV) is now 1.52. -## 0.6.0-beta.7 - 2021-09-09 +## 0.6.0-beta.7 - Minimum supported Rust version (MSRV) is now 1.51. -## 0.6.0-beta.6 - 2021-06-26 +## 0.6.0-beta.6 - Added `Files::path_filter()`. [#2274] - `Files::show_files_listing()` can now be used with `Files::index_file()` to show files listing as a fallback when the index file is not found. [#2228] @@ -95,7 +95,7 @@ [#2274]: https://github.com/actix/actix-web/pull/2274 [#2228]: https://github.com/actix/actix-web/pull/2228 -## 0.6.0-beta.5 - 2021-06-17 +## 0.6.0-beta.5 - `NamedFile` now implements `ServiceFactory` and `HttpServiceFactory` making it much more useful in routing. For example, it can be used directly as a default service. [#2135] - For symbolic links, `Content-Disposition` header no longer shows the filename of the original file. [#2156] @@ -107,17 +107,17 @@ [#2225]: https://github.com/actix/actix-web/pull/2225 [#2257]: https://github.com/actix/actix-web/pull/2257 -## 0.6.0-beta.4 - 2021-04-02 +## 0.6.0-beta.4 - Add support for `.guard` in `Files` to selectively filter `Files` services. [#2046] [#2046]: https://github.com/actix/actix-web/pull/2046 -## 0.6.0-beta.3 - 2021-03-09 +## 0.6.0-beta.3 - No notable changes. -## 0.6.0-beta.2 - 2021-02-10 +## 0.6.0-beta.2 - Fix If-Modified-Since and If-Unmodified-Since to not compare using sub-second timestamps. [#1887] - Replace `v_htmlescape` with `askama_escape`. [#1953] @@ -125,39 +125,39 @@ [#1887]: https://github.com/actix/actix-web/pull/1887 [#1953]: https://github.com/actix/actix-web/pull/1953 -## 0.6.0-beta.1 - 2021-01-07 +## 0.6.0-beta.1 - `HttpRange::parse` now has its own error type. - Update `bytes` to `1.0`. [#1813] [#1813]: https://github.com/actix/actix-web/pull/1813 -## 0.5.0 - 2020-12-26 +## 0.5.0 - Optionally support hidden files/directories. [#1811] [#1811]: https://github.com/actix/actix-web/pull/1811 -## 0.4.1 - 2020-11-24 +## 0.4.1 - Clarify order of parameters in `Files::new` and improve docs. -## 0.4.0 - 2020-10-06 +## 0.4.0 - Add `Files::prefer_utf8` option that adds UTF-8 charset on certain response types. [#1714] [#1714]: https://github.com/actix/actix-web/pull/1714 -## 0.3.0 - 2020-09-11 +## 0.3.0 - No significant changes from 0.3.0-beta.1. -## 0.3.0-beta.1 - 2020-07-15 +## 0.3.0-beta.1 - Update `v_htmlescape` to 0.10 - Update `actix-web` and `actix-http` dependencies to beta.1 -## 0.3.0-alpha.1 - 2020-05-23 +## 0.3.0-alpha.1 - Update `actix-web` and `actix-http` dependencies to alpha - Fix some typos in the docs @@ -166,73 +166,73 @@ [#1384]: https://github.com/actix/actix-web/pull/1384 -## 0.2.1 - 2019-12-22 +## 0.2.1 - Use the same format for file URLs regardless of platforms -## 0.2.0 - 2019-12-20 +## 0.2.0 - Fix BodyEncoding trait import #1220 -## 0.2.0-alpha.1 - 2019-12-07 +## 0.2.0-alpha.1 - Migrate to `std::future` -## 0.1.7 - 2019-11-06 +## 0.1.7 - Add an additional `filename*` param in the `Content-Disposition` header of `actix_files::NamedFile` to be more compatible. (#1151) -## 0.1.6 - 2019-10-14 +## 0.1.6 - Add option to redirect to a slash-ended path `Files` #1132 -## 0.1.5 - 2019-10-08 +## 0.1.5 - Bump up `mime_guess` crate version to 2.0.1 - Bump up `percent-encoding` crate version to 2.1 - Allow user defined request guards for `Files` #1113 -## 0.1.4 - 2019-07-20 +## 0.1.4 - Allow to disable `Content-Disposition` header #686 -## 0.1.3 - 2019-06-28 +## 0.1.3 - Do not set `Content-Length` header, let actix-http set it #930 -## 0.1.2 - 2019-06-13 +## 0.1.2 - 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 +## 0.1.1 - Static files are incorrectly served as both chunked and with length #812 -## 0.1.0 - 2019-05-25 +## 0.1.0 - NamedFile last-modified check always fails due to nano-seconds in file modified date #820 -## 0.1.0-beta.4 - 2019-05-12 +## 0.1.0-beta.4 - Update actix-web to beta.4 -## 0.1.0-beta.1 - 2019-04-20 +## 0.1.0-beta.1 - Update actix-web to beta.1 -## 0.1.0-alpha.6 - 2019-04-14 +## 0.1.0-alpha.6 - Update actix-web to alpha6 -## 0.1.0-alpha.4 - 2019-04-08 +## 0.1.0-alpha.4 - Update actix-web to alpha4 -## 0.1.0-alpha.2 - 2019-04-02 +## 0.1.0-alpha.2 - Add default handler support -## 0.1.0-alpha.1 - 2019-03-28 +## 0.1.0-alpha.1 - Initial impl diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index 0fc89214d..065141b20 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -1,14 +1,14 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 3.1.0 - 2023-01-21 +## 3.1.0 - Minimum supported Rust version (MSRV) is now 1.59. -## 3.0.0 - 2022-07-24 +## 3.0.0 - `TestServer::stop` is now async and will wait for the server and system to shutdown. [#2442] - Added `TestServer::client_headers` method. [#2097] @@ -24,41 +24,41 @@
3.0.0 Pre-Releases -## 3.0.0-beta.13 - 2022-02-16 +## 3.0.0-beta.13 - No significant changes since `3.0.0-beta.12`. -## 3.0.0-beta.12 - 2022-01-31 +## 3.0.0-beta.12 - No significant changes since `3.0.0-beta.11`. -## 3.0.0-beta.11 - 2022-01-04 +## 3.0.0-beta.11 - Minimum supported Rust version (MSRV) is now 1.54. -## 3.0.0-beta.10 - 2021-12-27 +## 3.0.0-beta.10 - Update `actix-server` to `2.0.0-rc.2`. [#2550] [#2550]: https://github.com/actix/actix-web/pull/2550 -## 3.0.0-beta.9 - 2021-12-11 +## 3.0.0-beta.9 - No significant changes since `3.0.0-beta.8`. -## 3.0.0-beta.8 - 2021-11-30 +## 3.0.0-beta.8 - Update `actix-tls` to `3.0.0-rc.1`. [#2474] [#2474]: https://github.com/actix/actix-web/pull/2474 -## 3.0.0-beta.7 - 2021-11-22 +## 3.0.0-beta.7 - Fix compatibility with experimental `io-uring` feature of `actix-rt`. [#2408] [#2408]: https://github.com/actix/actix-web/pull/2408 -## 3.0.0-beta.6 - 2021-11-15 +## 3.0.0-beta.6 - `TestServer::stop` is now async and will wait for the server and system to shutdown. [#2442] - Update `actix-server` to `2.0.0-beta.9`. [#2442] @@ -66,25 +66,25 @@ [#2442]: https://github.com/actix/actix-web/pull/2442 -## 3.0.0-beta.5 - 2021-09-09 +## 3.0.0-beta.5 - Minimum supported Rust version (MSRV) is now 1.51. -## 3.0.0-beta.4 - 2021-04-02 +## 3.0.0-beta.4 - Added `TestServer::client_headers` method. [#2097] [#2097]: https://github.com/actix/actix-web/pull/2097 -## 3.0.0-beta.3 - 2021-03-09 +## 3.0.0-beta.3 - No notable changes. -## 3.0.0-beta.2 - 2021-02-10 +## 3.0.0-beta.2 - No notable changes. -## 3.0.0-beta.1 - 2021-01-07 +## 3.0.0-beta.1 - Update `bytes` to `1.0`. [#1813] @@ -92,7 +92,7 @@
-## 2.1.0 - 2020-11-25 +## 2.1.0 - Add ability to set address for `TestServer`. [#1645] - Upgrade `base64` to `0.13`. @@ -101,11 +101,11 @@ [#1773]: https://github.com/actix/actix-web/pull/1773 [#1645]: https://github.com/actix/actix-web/pull/1645 -## 2.0.0 - 2020-09-11 +## 2.0.0 - Update actix-codec and actix-utils dependencies. -## 2.0.0-alpha.1 - 2020-05-23 +## 2.0.0-alpha.1 - Update the `time` dependency to 0.2.7 - Update `actix-connect` dependency to 2.0.0-alpha.2 @@ -115,57 +115,57 @@ - Update `base64` dependency to 0.12 - Update `env_logger` dependency to 0.7 -## 1.0.0 - 2019-12-13 +## 1.0.0 - Replaced `TestServer::start()` with `test_server()` -## 1.0.0-alpha.3 - 2019-12-07 +## 1.0.0-alpha.3 - Migrate to `std::future` -## 0.2.5 - 2019-09-17 +## 0.2.5 - Update serde_urlencoded to "0.6.1" - Increase TestServerRuntime timeouts from 500ms to 3000ms - Do not override current `System` -## 0.2.4 - 2019-07-18 +## 0.2.4 - Update actix-server to 0.6 -## 0.2.3 - 2019-07-16 +## 0.2.3 - Add `delete`, `options`, `patch` methods to `TestServerRunner` -## 0.2.2 - 2019-06-16 +## 0.2.2 - Add .put() and .sput() methods -## 0.2.1 - 2019-06-05 +## 0.2.1 - Add license files -## 0.2.0 - 2019-05-12 +## 0.2.0 - Update awc and actix-http deps -## 0.1.1 - 2019-04-24 +## 0.1.1 - Always make new connection for http client -## 0.1.0 - 2019-04-16 +## 0.1.0 - No changes -## 0.1.0-alpha.3 - 2019-04-02 +## 0.1.0-alpha.3 - Request functions accept path #743 -## 0.1.0-alpha.2 - 2019-03-29 +## 0.1.0-alpha.2 - Added TestServerRuntime::load_body() method - Update actix-http and awc libraries -## 0.1.0-alpha.1 - 2019-03-28 +## 0.1.0-alpha.1 - Initial impl diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 7078adb7e..5252f3fbf 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased ### Added @@ -13,13 +13,13 @@ - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 3.3.1 - 2023-03-02 +## 3.3.1 ### Fixed - Use correct `http` version requirement to ensure support for const `HeaderName` definitions. -## 3.3.0 - 2023-01-21 +## 3.3.0 ### Added @@ -55,7 +55,7 @@ [#2956]: https://github.com/actix/actix-web/pull/2956 [#2968]: https://github.com/actix/actix-web/pull/2968 -## 3.2.2 - 2022-09-11 +## 3.2.2 ### Changed @@ -67,7 +67,7 @@ [#2369]: https://github.com/actix/actix-web/pull/2369 -## 3.2.1 - 2022-07-02 +## 3.2.1 ### Fixed @@ -75,7 +75,7 @@ [#2794]: https://github.com/actix/actix-web/pull/2794 -## 3.2.0 - 2022-06-30 +## 3.2.0 ### Changed @@ -89,7 +89,7 @@ [#2790]: https://github.com/actix/actix-web/pull/2790 [#2798]: https://github.com/actix/actix-web/pull/2798 -## 3.1.0 - 2022-06-11 +## 3.1.0 ### Changed @@ -103,13 +103,13 @@ [#2357]: https://github.com/actix/actix-web/issues/2357 [#2779]: https://github.com/actix/actix-web/pull/2779 -## 3.0.4 - 2022-03-09 +## 3.0.4 ### Fixed - Document on docs.rs with `ws` feature enabled. -## 3.0.3 - 2022-03-08 +## 3.0.3 ### Fixed @@ -117,7 +117,7 @@ [#2684]: https://github.com/actix/actix-web/pull/2684 -## 3.0.2 - 2022-03-05 +## 3.0.2 ### Fixed @@ -125,13 +125,13 @@ [#2683]: https://github.com/actix/actix-web/pull/2683 -## 3.0.1 - 2022-03-04 +## 3.0.1 - Fix panic in H1 dispatcher when pipelining is used with keep-alive. [#2678] [#2678]: https://github.com/actix/actix-web/issues/2678 -## 3.0.0 - 2022-02-25 +## 3.0.0 ### Dependencies @@ -419,7 +419,7 @@
3.0.0 Pre-Releases -## 3.0.0-rc.4 - 2022-02-22 +## 3.0.0-rc.4 ### Fixed @@ -427,11 +427,11 @@ [1ce58ecb]: https://github.com/actix/actix-web/commit/1ce58ecb305c60e51db06e6c913b7a1344e229ca -## 3.0.0-rc.3 - 2022-02-16 +## 3.0.0-rc.3 - No significant changes since `3.0.0-rc.2`. -## 3.0.0-rc.2 - 2022-02-08 +## 3.0.0-rc.2 ### Added @@ -448,7 +448,7 @@ [#2624]: https://github.com/actix/actix-web/pull/2624 [#2625]: https://github.com/actix/actix-web/pull/2625 -## 3.0.0-rc.1 - 2022-01-31 +## 3.0.0-rc.1 ### Added @@ -484,7 +484,7 @@ [#2611]: https://github.com/actix/actix-web/pull/2611 [#2618]: https://github.com/actix/actix-web/pull/2618 -## 3.0.0-beta.19 - 2022-01-21 +## 3.0.0-beta.19 ### Added @@ -504,7 +504,7 @@ [#2585]: https://github.com/actix/actix-web/pull/2585 [#2587]: https://github.com/actix/actix-web/pull/2587 -## 3.0.0-beta.18 - 2022-01-04 +## 3.0.0-beta.18 ### Added @@ -535,7 +535,7 @@ [#2501]: https://github.com/actix/actix-web/pull/2501 [#2565]: https://github.com/actix/actix-web/pull/2565 -## 3.0.0-beta.17 - 2021-12-27 +## 3.0.0-beta.17 ### Changed @@ -553,7 +553,7 @@ [#2527]: https://github.com/actix/actix-web/pull/2527 [#2545]: https://github.com/actix/actix-web/pull/2545 -## 3.0.0-beta.16 - 2021-12-17 +## 3.0.0-beta.16 ### Added @@ -572,7 +572,7 @@ [#2510]: https://github.com/actix/actix-web/pull/2510 [#2522]: https://github.com/actix/actix-web/pull/2522 -## 3.0.0-beta.15 - 2021-12-11 +## 3.0.0-beta.15 ### Added @@ -626,7 +626,7 @@ [#2497]: https://github.com/actix/actix-web/pull/2497 [#2520]: https://github.com/actix/actix-web/pull/2520 -## 3.0.0-beta.14 - 2021-11-30 +## 3.0.0-beta.14 ### Changed @@ -639,7 +639,7 @@ [#2470]: https://github.com/actix/actix-web/pull/2470 [#2474]: https://github.com/actix/actix-web/pull/2474 -## 3.0.0-beta.13 - 2021-11-22 +## 3.0.0-beta.13 ### Added @@ -668,7 +668,7 @@ [#2448]: https://github.com/actix/actix-web/pull/2448 [#2456]: https://github.com/actix/actix-web/pull/2456 -## 3.0.0-beta.12 - 2021-11-15 +## 3.0.0-beta.12 ### Changed @@ -682,7 +682,7 @@ [#2425]: https://github.com/actix/actix-web/pull/2425 [#2442]: https://github.com/actix/actix-web/pull/2442 -## 3.0.0-beta.11 - 2021-10-20 +## 3.0.0-beta.11 ### Changed @@ -691,7 +691,7 @@ [#2414]: https://github.com/actix/actix-web/pull/2414 -## 3.0.0-beta.10 - 2021-09-09 +## 3.0.0-beta.10 ### Changed @@ -709,13 +709,13 @@ [#2344]: https://github.com/actix/actix-web/pull/2344 [#2377]: https://github.com/actix/actix-web/pull/2377 -## 3.0.0-beta.9 - 2021-08-09 +## 3.0.0-beta.9 ### Fixed - Potential HTTP request smuggling vulnerabilities. [RUSTSEC-2021-0081](https://github.com/rustsec/advisory-db/pull/977) -## 3.0.0-beta.8 - 2021-06-26 +## 3.0.0-beta.8 ### Changed @@ -728,7 +728,7 @@ [#2291]: https://github.com/actix/actix-web/pull/2291 [#2250]: https://github.com/actix/actix-web/pull/2250 -## 3.0.0-beta.7 - 2021-06-17 +## 3.0.0-beta.7 ### Added @@ -775,7 +775,7 @@ [#2253]: https://github.com/actix/actix-web/pull/2253 [#2244]: https://github.com/actix/actix-web/pull/2244 -## 3.0.0-beta.6 - 2021-04-17 +## 3.0.0-beta.6 ### Added @@ -810,7 +810,7 @@ [#2158]: https://github.com/actix/actix-web/pull/2158 [#2161]: https://github.com/actix/actix-web/pull/2161 -## 3.0.0-beta.5 - 2021-04-02 +## 3.0.0-beta.5 ### Added @@ -832,7 +832,7 @@ [#2094]: https://github.com/actix/actix-web/pull/2094 [#2127]: https://github.com/actix/actix-web/pull/2127 -## 3.0.0-beta.4 - 2021-03-08 +## 3.0.0-beta.4 ### Changed @@ -850,11 +850,11 @@ [#2035]: https://github.com/actix/actix-web/pull/2035 [#2052]: https://github.com/actix/actix-web/pull/2052 -## 3.0.0-beta.3 - 2021-02-10 +## 3.0.0-beta.3 - No notable changes. -## 3.0.0-beta.2 - 2021-02-10 +## 3.0.0-beta.2 ### Added @@ -906,7 +906,7 @@ [#1964]: https://github.com/actix/actix-web/pull/1964 [#1969]: https://github.com/actix/actix-web/pull/1969 -## 3.0.0-beta.1 - 2021-01-07 +## 3.0.0-beta.1 ### Added @@ -934,7 +934,7 @@
-## 2.2.2 - 2022-01-21 +## 2.2.2 ### Changed @@ -942,13 +942,13 @@ [ad7e3c06]: https://github.com/actix/actix-web/commit/ad7e3c06 -## 2.2.1 - 2021-08-09 +## 2.2.1 ### Fixed - Potential HTTP request smuggling vulnerabilities. [RUSTSEC-2021-0081](https://github.com/rustsec/advisory-db/pull/977) -## 2.2.0 - 2020-11-25 +## 2.2.0 ### Added @@ -970,7 +970,7 @@ [#1793]: https://github.com/actix/actix-web/pull/1793 [#1797]: https://github.com/actix/actix-web/pull/1797 -## 2.1.0 - 2020-10-30 +## 2.1.0 ### Added @@ -987,18 +987,18 @@ [#1733]: https://github.com/actix/actix-web/pull/1733 [#1744]: https://github.com/actix/actix-web/pull/1744 -## 2.0.0 - 2020-09-11 +## 2.0.0 - No significant changes from `2.0.0-beta.4`. -## 2.0.0-beta.4 - 2020-09-09 +## 2.0.0-beta.4 ### Changed - Update actix-codec and actix-utils dependencies. - Update actix-connect and actix-tls dependencies. -## 2.0.0-beta.3 - 2020-08-14 +## 2.0.0-beta.3 ### Fixed @@ -1006,7 +1006,7 @@ [#1626]: https://github.com/actix/actix-web/pull/1626 -## 2.0.0-beta.2 - 2020-07-21 +## 2.0.0-beta.2 ### Fixed @@ -1019,7 +1019,7 @@ [#1614]: https://github.com/actix/actix-web/pull/1614 [#1615]: https://github.com/actix/actix-web/pull/1615 -## 2.0.0-beta.1 - 2020-07-11 +## 2.0.0-beta.1 ### Changed @@ -1032,7 +1032,7 @@ [#1586]: https://github.com/actix/actix-web/pull/1586 [#1580]: https://github.com/actix/actix-web/pull/1580 -## 2.0.0-alpha.4 - 2020-05-21 +## 2.0.0-alpha.4 ### Changed @@ -1048,7 +1048,7 @@ [#1439]: https://github.com/actix/actix-web/pull/1439 [#1503]: https://github.com/actix/actix-web/pull/1503 -## 2.0.0-alpha.3 - 2020-05-08 +## 2.0.0-alpha.3 ### Fixed @@ -1063,7 +1063,7 @@ [#1422]: https://github.com/actix/actix-web/pull/1422 [#1487]: https://github.com/actix/actix-web/pull/1487 -## 2.0.0-alpha.2 - 2020-03-07 +## 2.0.0-alpha.2 ### Changed @@ -1075,7 +1075,7 @@ [#1394]: https://github.com/actix/actix-web/pull/1394 [#1395]: https://github.com/actix/actix-web/pull/1395 -## 2.0.0-alpha.1 - 2020-02-27 +## 2.0.0-alpha.1 ### Changed @@ -1088,14 +1088,14 @@ - Allow `SameSite=None` cookies to be sent in a response. -## 1.0.1 - 2019-12-20 +## 1.0.1 ### Fixed - Poll upgrade service's readiness from HTTP service handlers - Replace brotli with brotli2 #1224 -## 1.0.0 - 2019-12-13 +## 1.0.0 ### Added @@ -1105,7 +1105,7 @@ - Replace `flate2-xxx` features with `compress` -## 1.0.0-alpha.5 - 2019-12-09 +## 1.0.0-alpha.5 ### Fixed @@ -1116,7 +1116,7 @@ - Websockets: Ping and Pong should have binary data #1049 -## 1.0.0-alpha.4 - 2019-12-08 +## 1.0.0-alpha.4 ### Added @@ -1126,14 +1126,14 @@ - Use rust based brotli compression library -## 1.0.0-alpha.3 - 2019-12-07 +## 1.0.0-alpha.3 ### Changed - Migrate to tokio 0.2 - Migrate to `std::future` -## 0.2.11 - 2019-11-06 +## 0.2.11 ### Added @@ -1147,7 +1147,7 @@ [#1878]: https://github.com/actix/actix-web/pull/1878 -## 0.2.10 - 2019-09-11 +## 0.2.10 ### Added @@ -1158,7 +1158,7 @@ - h2 will use error response #1080 - on_connect result isn't added to request extensions for http2 requests #1009 -## 0.2.9 - 2019-08-13 +## 0.2.9 ### Changed @@ -1170,7 +1170,7 @@ - Fixed a panic in the HTTP2 handshake in client HTTP requests (#1031) -## 0.2.8 - 2019-08-01 +## 0.2.8 ### Added @@ -1182,20 +1182,20 @@ - awc client panic #1016 - Invalid response with compression middleware enabled, but compression-related features disabled #997 -## 0.2.7 - 2019-07-18 +## 0.2.7 ### Added - Add support for downcasting response errors #986 -## 0.2.6 - 2019-07-17 +## 0.2.6 ### Changed - Replace `ClonableService` with local copy - Upgrade `rand` dependency version to 0.7 -## 0.2.5 - 2019-06-28 +## 0.2.5 ### Added @@ -1206,13 +1206,13 @@ - Use `encoding_rs` crate instead of unmaintained `encoding` crate - Add `Copy` and `Clone` impls for `ws::Codec` -## 0.2.4 - 2019-06-16 +## 0.2.4 ### Fixed - Do not compress NoContent (204) responses #918 -## 0.2.3 - 2019-06-02 +## 0.2.3 ### Added @@ -1223,19 +1223,19 @@ - SizedStream uses u64 -## 0.2.2 - 2019-05-29 +## 0.2.2 ### Fixed - Parse incoming stream before closing stream on disconnect #868 -## 0.2.1 - 2019-05-25 +## 0.2.1 ### Fixed - Handle socket read disconnect -## 0.2.0 - 2019-05-12 +## 0.2.0 ### Changed @@ -1246,13 +1246,13 @@ - `OneRequest` service -## 0.1.5 - 2019-05-04 +## 0.1.5 ### Fixed - Clean up response extensions in response pool #817 -## 0.1.4 - 2019-04-24 +## 0.1.4 ### Added @@ -1262,20 +1262,20 @@ - Read until eof for http/1.0 responses #771 -## 0.1.3 - 2019-04-23 +## 0.1.3 ### Fixed - Fix http client pool management - Fix http client wait queue management #794 -## 0.1.2 - 2019-04-23 +## 0.1.2 ### Fixed - Fix BorrowMutError panic in client connector #793 -## 0.1.1 - 2019-04-19 +## 0.1.1 ### Changed @@ -1283,7 +1283,7 @@ - Cookie::max_age_time() accepts value in time::Duration - Allow to specify server address for client connector -## 0.1.0 - 2019-04-16 +## 0.1.0 ### Added @@ -1294,7 +1294,7 @@ - `actix_http::encoding` always available - use trust-dns-resolver 0.11.0 -## 0.1.0-alpha.5 - 2019-04-12 +## 0.1.0-alpha.5 ### Added @@ -1306,7 +1306,7 @@ - MessageBody::length() renamed to MessageBody::size() for consistency - ws handshake verification functions take RequestHead instead of Request -## 0.1.0-alpha.4 - 2019-04-08 +## 0.1.0-alpha.4 ### Added @@ -1323,7 +1323,7 @@ - Removed PayloadBuffer -## 0.1.0-alpha.3 - 2019-04-02 +## 0.1.0-alpha.3 ### Added @@ -1335,7 +1335,7 @@ - Preallocate read buffer for h1 codec - Detect socket disconnection during protocol selection -## 0.1.0-alpha.2 - 2019-03-29 +## 0.1.0-alpha.2 ### Added @@ -1345,6 +1345,6 @@ - Do not use thread pool for decompression if chunk size is smaller than 2048. -## 0.1.0-alpha.1 - 2019-03-28 +## 0.1.0-alpha.1 - Initial impl diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index f90b9e3cf..04f31e0f3 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -5,6 +5,6 @@ - Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 0.6.0 - 2023-02-26 +## 0.6.0 - Add `MultipartForm` derive macro. diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 1ad5865ec..dc4cb8373 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -1,49 +1,49 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 0.6.0 - 2023-02-26 +## 0.6.0 - Added `MultipartForm` typed data extractor. [#2883] [#2883]: https://github.com/actix/actix-web/pull/2883 -## 0.5.0 - 2023-01-21 +## 0.5.0 - `Field::content_type()` now returns `Option<&mime::Mime>`. [#2885] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2885]: https://github.com/actix/actix-web/pull/2885 -## 0.4.0 - 2022-02-25 +## 0.4.0 - No significant changes since `0.4.0-beta.13`. -## 0.4.0-beta.13 - 2022-01-31 +## 0.4.0-beta.13 - No significant changes since `0.4.0-beta.12`. -## 0.4.0-beta.12 - 2022-01-04 +## 0.4.0-beta.12 - Minimum supported Rust version (MSRV) is now 1.54. -## 0.4.0-beta.11 - 2021-12-27 +## 0.4.0-beta.11 - No significant changes since `0.4.0-beta.10`. -## 0.4.0-beta.10 - 2021-12-11 +## 0.4.0-beta.10 - No significant changes since `0.4.0-beta.9`. -## 0.4.0-beta.9 - 2021-12-01 +## 0.4.0-beta.9 - Polling `Field` after dropping `Multipart` now fails immediately instead of hanging forever. [#2463] [#2463]: https://github.com/actix/actix-web/pull/2463 -## 0.4.0-beta.8 - 2021-11-22 +## 0.4.0-beta.8 - Ensure a correct Content-Disposition header is included in every part of a multipart message. [#2451] - Added `MultipartError::NoContentDisposition` variant. [#2451] @@ -54,31 +54,31 @@ [#2451]: https://github.com/actix/actix-web/pull/2451 -## 0.4.0-beta.7 - 2021-10-20 +## 0.4.0-beta.7 - Minimum supported Rust version (MSRV) is now 1.52. -## 0.4.0-beta.6 - 2021-09-09 +## 0.4.0-beta.6 - Minimum supported Rust version (MSRV) is now 1.51. -## 0.4.0-beta.5 - 2021-06-17 +## 0.4.0-beta.5 - No notable changes. -## 0.4.0-beta.4 - 2021-04-02 +## 0.4.0-beta.4 - No notable changes. -## 0.4.0-beta.3 - 2021-03-09 +## 0.4.0-beta.3 - No notable changes. -## 0.4.0-beta.2 - 2021-02-10 +## 0.4.0-beta.2 - No notable changes. -## 0.4.0-beta.1 - 2021-01-07 +## 0.4.0-beta.1 - Fix multipart consuming payload before header checks. [#1513] - Update `bytes` to `1.0`. [#1813] @@ -86,19 +86,19 @@ [#1813]: https://github.com/actix/actix-web/pull/1813 [#1513]: https://github.com/actix/actix-web/pull/1513 -## 0.3.0 - 2020-09-11 +## 0.3.0 - No significant changes from `0.3.0-beta.2`. -## 0.3.0-beta.2 - 2020-09-10 +## 0.3.0-beta.2 - Update `actix-*` dependencies to latest versions. -## 0.3.0-beta.1 - 2020-07-15 +## 0.3.0-beta.1 - Update `actix-web` to 3.0.0-beta.1 -## 0.3.0-alpha.1 - 2020-05-25 +## 0.3.0-alpha.1 - Update `actix-web` to 3.0.0-alpha.3 - Bump minimum supported Rust version to 1.40 @@ -106,45 +106,45 @@ - Remove the unused `time` dependency - Fix missing `std::error::Error` implement for `MultipartError`. -## [0.2.0] - 2019-12-20 +## [0.2.0] - Release -## [0.2.0-alpha.4] - 2019-12-xx +## [0.2.0-alpha.4] - Multipart handling now handles Pending during read of boundary #1205 -## [0.2.0-alpha.2] - 2019-12-03 +## [0.2.0-alpha.2] - Migrate to `std::future` -## [0.1.4] - 2019-09-12 +## [0.1.4] - Multipart handling now parses requests which do not end in CRLF #1038 -## [0.1.3] - 2019-08-18 +## [0.1.3] - Fix ring dependency from actix-web default features for #741. -## [0.1.2] - 2019-06-02 +## [0.1.2] - Fix boundary parsing #876 -## [0.1.1] - 2019-05-25 +## [0.1.1] - Fix disconnect handling #834 -## [0.1.0] - 2019-05-18 +## [0.1.0] - Release -## [0.1.0-beta.4] - 2019-05-12 +## [0.1.0-beta.4] - Handle cancellation of uploads #736 - Upgrade to actix-web 1.0.0-beta.4 -## [0.1.0-beta.1] - 2019-04-21 +## [0.1.0-beta.1] - Do not support nested multipart diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 786ee12d9..31316ff47 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -1,17 +1,17 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 0.5.1 - 2022-09-19 +## 0.5.1 - Correct typo in error string for `i32` deserialization. [#2876] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2876]: https://github.com/actix/actix-web/pull/2876 -## 0.5.0 - 2022-02-22 +## 0.5.0 ### Added @@ -86,7 +86,7 @@
0.5.0 Pre-Releases -## 0.5.0-rc.3 - 2022-01-31 +## 0.5.0-rc.3 - Remove unused `ResourceInfo`. [#2612] - Add `RouterBuilder::push`. [#2612] @@ -98,32 +98,32 @@ [#2612]: https://github.com/actix/actix-web/pull/2612 [#2613]: https://github.com/actix/actix-web/pull/2613 -## 0.5.0-rc.2 - 2022-01-21 +## 0.5.0-rc.2 - Add `Path::as_str`. [#2590] - Deprecate `Path::path`. [#2590] [#2590]: https://github.com/actix/actix-web/pull/2590 -## 0.5.0-rc.1 - 2022-01-14 +## 0.5.0-rc.1 - `Resource` trait now have an associated type, `Path`, instead of the generic parameter. [#2568] - `Resource` is now implemented for `&mut Path<_>` and `RefMut>`. [#2568] [#2568]: https://github.com/actix/actix-web/pull/2568 -## 0.5.0-beta.4 - 2022-01-04 +## 0.5.0-beta.4 - `PathDeserializer` now decodes all percent encoded characters in dynamic segments. [#2566] - Minimum supported Rust version (MSRV) is now 1.54. [#2566]: https://github.com/actix/actix-net/pull/2566 -## 0.5.0-beta.3 - 2021-12-17 +## 0.5.0-beta.3 - Minimum supported Rust version (MSRV) is now 1.52. -## 0.5.0-beta.2 - 2021-09-09 +## 0.5.0-beta.2 - Introduce `ResourceDef::join`. [#380][net#380] - Disallow prefix routes with tail segments. [#379][net#379] @@ -143,7 +143,7 @@ [#2355]: https://github.com/actix/actix-web/pull/2355 [#2356]: https://github.com/actix/actix-web/pull/2356 -## 0.5.0-beta.1 - 2021-07-20 +## 0.5.0-beta.1 - Fix a bug in multi-patterns where static patterns are interpreted as regex. [#366][net#366] - Introduce `ResourceDef::pattern_iter` to get an iterator over all patterns in a multi-pattern resource. [#373][net#373] @@ -173,7 +173,7 @@
-## 0.4.0 - 2021-06-06 +## 0.4.0 - When matching path parameters, `%25` is now kept in the percent-encoded form; no longer decoded to `%`. [#357][net#357] - Path tail patterns now match new lines (`\n`) in request URL. [#360][net#360] @@ -185,70 +185,70 @@ [net#359]: https://github.com/actix/actix-net/pull/359 [net#360]: https://github.com/actix/actix-net/pull/360 -## 0.3.0 - 2019-12-31 +## 0.3.0 - Version was yanked previously. See https://crates.io/crates/actix-router/0.3.0 -## 0.2.7 - 2021-02-06 +## 0.2.7 - Add `Router::recognize_checked` [#247][net#247] [net#247]: https://github.com/actix/actix-net/pull/247 -## 0.2.6 - 2021-01-09 +## 0.2.6 - Use `bytestring` version range compatible with Bytes v1.0. [#246][net#246] [net#246]: https://github.com/actix/actix-net/pull/246 -## 0.2.5 - 2020-09-20 +## 0.2.5 - Fix `from_hex()` method -## 0.2.4 - 2019-12-31 +## 0.2.4 - Add `ResourceDef::resource_path_named()` path generation method -## 0.2.3 - 2019-12-25 +## 0.2.3 - Add impl `IntoPattern` for `&String` -## 0.2.2 - 2019-12-25 +## 0.2.2 - Use `IntoPattern` for `RouterBuilder::path()` -## 0.2.1 - 2019-12-25 +## 0.2.1 - Add `IntoPattern` trait - Add multi-pattern resources -## 0.2.0 - 2019-12-07 +## 0.2.0 - Update http to 0.2 - Update regex to 1.3 - Use bytestring instead of string -## 0.1.5 - 2019-05-15 +## 0.1.5 - Remove debug prints -## 0.1.4 - 2019-05-15 +## 0.1.4 - Fix checked resource match -## 0.1.3 - 2019-04-22 +## 0.1.3 - Added support for `remainder match` (i.e "/path/{tail}\*") -## 0.1.2 - 2019-04-07 +## 0.1.2 - Export `Quoter` type - Allow to reset `Path` instance -## 0.1.1 - 2019-04-03 +## 0.1.1 - Get dynamic segment by name instead of iterator. -## 0.1.0 - 2019-03-09 +## 0.1.0 - Initial release diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 477ed4c04..c33927fa4 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -1,80 +1,80 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Add `TestServerConfig::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. - Add `TestServerConfig::workers()` method. - Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 0.1.1 - 2023-02-26 +## 0.1.1 - Add `TestServerConfig::port()` setter method. - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. -## 0.1.0 - 2022-07-24 +## 0.1.0 - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. -## 0.1.0-beta.13 - 2022-02-16 +## 0.1.0-beta.13 - No significant changes since `0.1.0-beta.12`. -## 0.1.0-beta.12 - 2022-01-31 +## 0.1.0-beta.12 - Rename `TestServerConfig::{client_timeout => client_request_timeout}`. [#2611] [#2611]: https://github.com/actix/actix-web/pull/2611 -## 0.1.0-beta.11 - 2022-01-04 +## 0.1.0-beta.11 - Minimum supported Rust version (MSRV) is now 1.54. -## 0.1.0-beta.10 - 2021-12-27 +## 0.1.0-beta.10 - No significant changes since `0.1.0-beta.9`. -## 0.1.0-beta.9 - 2021-12-17 +## 0.1.0-beta.9 - Re-export `actix_http::body::to_bytes`. [#2518] - Update `actix_web::test` re-exports. [#2518] [#2518]: https://github.com/actix/actix-web/pull/2518 -## 0.1.0-beta.8 - 2021-12-11 +## 0.1.0-beta.8 - No significant changes since `0.1.0-beta.7`. -## 0.1.0-beta.7 - 2021-11-22 +## 0.1.0-beta.7 - Fix compatibility with experimental `io-uring` feature of `actix-rt`. [#2408] [#2408]: https://github.com/actix/actix-web/pull/2408 -## 0.1.0-beta.6 - 2021-11-15 +## 0.1.0-beta.6 - No significant changes from `0.1.0-beta.5`. -## 0.1.0-beta.5 - 2021-10-20 +## 0.1.0-beta.5 - Updated rustls to v0.20. [#2414] - Minimum supported Rust version (MSRV) is now 1.52. [#2414]: https://github.com/actix/actix-web/pull/2414 -## 0.1.0-beta.4 - 2021-09-09 +## 0.1.0-beta.4 - Minimum supported Rust version (MSRV) is now 1.51. -## 0.1.0-beta.3 - 2021-06-20 +## 0.1.0-beta.3 - No significant changes from `0.1.0-beta.2`. -## 0.1.0-beta.2 - 2021-04-17 +## 0.1.0-beta.2 - No significant changes from `0.1.0-beta.1`. -## 0.1.0-beta.1 - 2021-04-02 +## 0.1.0-beta.1 - Move integration testing structs from `actix-web`. [#2112] diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index cff27a16d..563bc210f 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -1,40 +1,40 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 4.2.0 - 2023-01-21 +## 4.2.0 - Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency. -## 4.1.0 - 2022-03-02 +## 4.1.0 - Add support for `actix` version `0.13`. [#2675] [#2675]: https://github.com/actix/actix-web/pull/2675 -## 4.0.0 - 2022-02-25 +## 4.0.0 - No significant changes since `4.0.0-beta.12`. -## 4.0.0-beta.12 - 2022-02-16 +## 4.0.0-beta.12 - No significant changes since `4.0.0-beta.11`. -## 4.0.0-beta.11 - 2022-01-31 +## 4.0.0-beta.11 - No significant changes since `4.0.0-beta.10`. -## 4.0.0-beta.10 - 2022-01-04 +## 4.0.0-beta.10 - Minimum supported Rust version (MSRV) is now 1.54. -## 4.0.0-beta.9 - 2021-12-27 +## 4.0.0-beta.9 - No significant changes since `4.0.0-beta.8`. -## 4.0.0-beta.8 - 2021-12-11 +## 4.0.0-beta.8 - Add `ws:WsResponseBuilder` for building WebSocket session response. [#1920] - Deprecate `ws::{start_with_addr, start_with_protocols}`. [#1920] @@ -42,33 +42,33 @@ [#1920]: https://github.com/actix/actix-web/pull/1920 -## 4.0.0-beta.7 - 2021-09-09 +## 4.0.0-beta.7 - Minimum supported Rust version (MSRV) is now 1.51. -## 4.0.0-beta.6 - 2021-06-26 +## 4.0.0-beta.6 - Update `actix` to `0.12`. [#2277] [#2277]: https://github.com/actix/actix-web/pull/2277 -## 4.0.0-beta.5 - 2021-06-17 +## 4.0.0-beta.5 - No notable changes. -## 4.0.0-beta.4 - 2021-04-02 +## 4.0.0-beta.4 - No notable changes. -## 4.0.0-beta.3 - 2021-03-09 +## 4.0.0-beta.3 - No notable changes. -## 4.0.0-beta.2 - 2021-02-10 +## 4.0.0-beta.2 - No notable changes. -## 4.0.0-beta.1 - 2021-01-07 +## 4.0.0-beta.1 - Update `pin-project` to `1.0`. - Update `bytes` to `1.0`. [#1813] @@ -77,63 +77,63 @@ [#1813]: https://github.com/actix/actix-web/pull/1813 [#1864]: https://github.com/actix/actix-web/pull/1864 -## 3.0.0 - 2020-09-11 +## 3.0.0 - No significant changes from `3.0.0-beta.2`. -## 3.0.0-beta.2 - 2020-09-10 +## 3.0.0-beta.2 - Update `actix-*` dependencies to latest versions. -## [3.0.0-beta.1] - 2020-xx-xx +## [3.0.0-beta.1] - Update `actix-web` & `actix-http` dependencies to beta.1 - Bump minimum supported Rust version to 1.40 -## [3.0.0-alpha.1] - 2020-05-08 +## [3.0.0-alpha.1] - Update the actix-web dependency to 3.0.0-alpha.1 - Update the actix dependency to 0.10.0-alpha.2 - Update the actix-http dependency to 2.0.0-alpha.3 -## [2.0.0] - 2019-12-20 +## [2.0.0] - Release -## [2.0.0-alpha.1] - 2019-12-15 +## [2.0.0-alpha.1] - Migrate to actix-web 2.0.0 -## [1.0.4] - 2019-12-07 +## [1.0.4] - Allow comma-separated websocket subprotocols without spaces (#1172) -## [1.0.3] - 2019-11-14 +## [1.0.3] - Update actix-web and actix-http dependencies -## [1.0.2] - 2019-07-20 +## [1.0.2] - Add `ws::start_with_addr()`, returning the address of the created actor, along with the `HttpResponse`. - Add support for specifying protocols on websocket handshake #835 -## [1.0.1] - 2019-06-28 +## [1.0.1] - Allow to use custom ws codec with `WebsocketContext` #925 -## [1.0.0] - 2019-05-29 +## [1.0.0] - Update actix-http and actix-web -## [0.1.0-alpha.3] - 2019-04-02 +## [0.1.0-alpha.3] - Update actix-http and actix-web -## [0.1.0-alpha.2] - 2019-03-29 +## [0.1.0-alpha.2] - Update actix-http and actix-web -## [0.1.0-alpha.1] - 2019-03-28 +## [0.1.0-alpha.1] - Initial impl diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 9ff1edf6e..4b3205d7c 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -1,52 +1,52 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 4.2.0 - 2023-02-26 +## 4.2.0 - Add support for custom methods with the `#[route]` macro. [#2969] [#2969]: https://github.com/actix/actix-web/pull/2969 -## 4.1.0 - 2022-09-11 +## 4.1.0 - Add `#[routes]` macro to support multiple paths for one handler. [#2718] - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. [#2718]: https://github.com/actix/actix-web/pull/2718 -## 4.0.1 - 2022-06-11 +## 4.0.1 - Fix support for guard paths in route handler macros. [#2771] - Minimum supported Rust version (MSRV) is now 1.56 due to transitive `hashbrown` dependency. [#2771]: https://github.com/actix/actix-web/pull/2771 -## 4.0.0 - 2022-02-24 +## 4.0.0 - Version aligned with `actix-web` and will remain in sync going forward. - No significant changes since `0.5.0`. -## 0.5.0 - 2022-02-24 +## 0.5.0 - No significant changes since `0.5.0-rc.2`. -## 0.5.0-rc.2 - 2022-02-01 +## 0.5.0-rc.2 - No significant changes since `0.5.0-rc.1`. -## 0.5.0-rc.1 - 2022-01-04 +## 0.5.0-rc.1 - Minimum supported Rust version (MSRV) is now 1.54. -## 0.5.0-beta.6 - 2021-12-11 +## 0.5.0-beta.6 - No significant changes since `0.5.0-beta.5`. -## 0.5.0-beta.5 - 2021-10-20 +## 0.5.0-beta.5 - Improve error recovery potential when macro input is invalid. [#2410] - Add `#[actix_web::test]` macro for setting up tests with a runtime. [#2409] @@ -55,18 +55,18 @@ [#2410]: https://github.com/actix/actix-web/pull/2410 [#2409]: https://github.com/actix/actix-web/pull/2409 -## 0.5.0-beta.4 - 2021-09-09 +## 0.5.0-beta.4 - In routing macros, paths are now validated at compile time. [#2350] - Minimum supported Rust version (MSRV) is now 1.51. [#2350]: https://github.com/actix/actix-web/pull/2350 -## 0.5.0-beta.3 - 2021-06-17 +## 0.5.0-beta.3 - No notable changes. -## 0.5.0-beta.2 - 2021-03-09 +## 0.5.0-beta.2 - Preserve doc comments when using route macros. [#2022] - Add `name` attribute to `route` macro. [#1934] @@ -74,11 +74,11 @@ [#2022]: https://github.com/actix/actix-web/pull/2022 [#1934]: https://github.com/actix/actix-web/pull/1934 -## 0.5.0-beta.1 - 2021-02-10 +## 0.5.0-beta.1 - Use new call signature for `System::new`. -## 0.4.0 - 2020-09-20 +## 0.4.0 - Added compile success and failure testing. [#1677] - Add `route` macro for supporting multiple HTTP methods guards. [#1674] @@ -86,23 +86,23 @@ [#1677]: https://github.com/actix/actix-web/pull/1677 [#1674]: https://github.com/actix/actix-web/pull/1674 -## 0.3.0 - 2020-09-11 +## 0.3.0 - No significant changes from `0.3.0-beta.1`. -## 0.3.0-beta.1 - 2020-07-14 +## 0.3.0-beta.1 - Add main entry-point macro that uses re-exported runtime. [#1559] [#1559]: https://github.com/actix/actix-web/pull/1559 -## 0.2.2 - 2020-05-23 +## 0.2.2 - Add resource middleware on actix-web-codegen [#1467] [#1467]: https://github.com/actix/actix-web/pull/1467 -## 0.2.1 - 2020-02-25 +## 0.2.1 - Add `#[allow(missing_docs)]` attribute to generated structs [#1368] - Allow the handler function to be named as `config` [#1290] @@ -110,35 +110,35 @@ [#1368]: https://github.com/actix/actix-web/issues/1368 [#1290]: https://github.com/actix/actix-web/issues/1290 -## 0.2.0 - 2019-12-13 +## 0.2.0 - Generate code for actix-web 2.0 -## 0.1.3 - 2019-10-14 +## 0.1.3 - Bump up `syn` & `quote` to 1.0 - Provide better error message -## 0.1.2 - 2019-06-04 +## 0.1.2 - Add macros for head, options, trace, connect and patch http methods -## 0.1.1 - 2019-06-01 +## 0.1.1 - Add syn "extra-traits" feature -## 0.1.0 - 2019-05-18 +## 0.1.0 - Release -## 0.1.0-beta.1 - 2019-04-20 +## 0.1.0-beta.1 - Gen code for actix-web 1.0.0-beta.1 -## 0.1.0-alpha.6 - 2019-04-14 +## 0.1.0-alpha.6 - Gen code for actix-web 1.0.0-alpha.6 -## 0.1.0-alpha.1 - 2019-03-28 +## 0.1.0-alpha.1 - Initial impl diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index aaa262e63..289f8698f 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased - 2023-xx-xx +## Unreleased ### Added @@ -21,7 +21,7 @@ - Hide sensitive header values in `HttpRequest`'s `Debug` output. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 4.3.1 - 2023-02-26 +## 4.3.1 ### Added @@ -29,7 +29,7 @@ [#2969]: https://github.com/actix/actix-web/pull/2969 -## 4.3.0 - 2023-01-21 +## 4.3.0 ### Added @@ -52,7 +52,7 @@ [#2949]: https://github.com/actix/actix-web/pull/2949 [#2961]: https://github.com/actix/actix-web/pull/2961 -## 4.2.1 - 2022-09-12 +## 4.2.1 ### Fixed @@ -60,7 +60,7 @@ [#2871]: https://github.com/actix/actix-web/pull/2871 -## 4.2.0 - 2022-09-11 +## 4.2.0 ### Added @@ -76,7 +76,7 @@ [#2752]: https://github.com/actix/actix-web/pull/2752 [#2786]: https://github.com/actix/actix-web/pull/2786 -## 4.1.0 - 2022-06-11 +## 4.1.0 ### Added @@ -99,13 +99,13 @@ [#2742]: https://github.com/actix/actix-web/pull/2742 [#2743]: https://github.com/actix/actix-web/pull/2743 -## 4.0.1 - 2022-02-25 +## 4.0.1 ### Fixed - Use stable version in readme example. -## 4.0.0 - 2022-02-25 +## 4.0.0 ### Dependencies @@ -383,7 +383,7 @@
4.0.0 Pre-Releases -## 4.0.0-rc.3 - 2022-02-08 +## 4.0.0-rc.3 ### Changed @@ -397,7 +397,7 @@ [#2625]: https://github.com/actix/actix-web/pull/2625 [#2635]: https://github.com/actix/actix-web/pull/2635 -## 4.0.0-rc.2 - 2022-02-02 +## 4.0.0-rc.2 ### Added @@ -409,7 +409,7 @@ [#2619]: https://github.com/actix/actix-web/pull/2619 -## 4.0.0-rc.1 - 2022-01-31 +## 4.0.0-rc.1 ### Changed @@ -423,7 +423,7 @@ [#2601]: https://github.com/actix/actix-web/pull/2601 [#2611]: https://github.com/actix/actix-web/pull/2611 -## 4.0.0-beta.21 - 2022-01-21 +## 4.0.0-beta.21 ### Added @@ -440,7 +440,7 @@ [#2591]: https://github.com/actix/actix-web/pull/2591 [#2594]: https://github.com/actix/actix-web/pull/2594 -## 4.0.0-beta.20 - 2022-01-14 +## 4.0.0-beta.20 ### Added @@ -462,7 +462,7 @@ [#2582]: https://github.com/actix/actix-web/pull/2582 [#2584]: https://github.com/actix/actix-web/pull/2584 -## 4.0.0-beta.19 - 2022-01-04 +## 4.0.0-beta.19 ### Added @@ -487,7 +487,7 @@ [#2501]: https://github.com/actix/actix-web/pull/2501 [#2565]: https://github.com/actix/actix-web/pull/2565 -## 4.0.0-beta.18 - 2021-12-29 +## 4.0.0-beta.18 ### Changed @@ -501,7 +501,7 @@ [#2555]: https://github.com/actix/actix-web/pull/2555 [`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html -## 4.0.0-beta.17 - 2021-12-29 +## 4.0.0-beta.17 ### Added @@ -524,7 +524,7 @@ [#2552]: https://github.com/actix/actix-web/pull/2552 [#2554]: https://github.com/actix/actix-web/pull/2554 -## 4.0.0-beta.16 - 2021-12-27 +## 4.0.0-beta.16 ### Changed @@ -534,7 +534,7 @@ [#2523]: https://github.com/actix/actix-web/pull/2523 [#2526]: https://github.com/actix/actix-web/pull/2526 -## 4.0.0-beta.15 - 2021-12-17 +## 4.0.0-beta.15 ### Added @@ -562,7 +562,7 @@ [#2516]: https://github.com/actix/actix-web/pull/2516 [#2518]: https://github.com/actix/actix-web/pull/2518 -## 4.0.0-beta.14 - 2021-12-11 +## 4.0.0-beta.14 ### Added @@ -607,7 +607,7 @@ [#2493]: https://github.com/actix/actix-web/pull/2493 [#2499]: https://github.com/actix/actix-web/pull/2499 -## 4.0.0-beta.13 - 2021-11-30 +## 4.0.0-beta.13 ### Changed @@ -615,7 +615,7 @@ [#2474]: https://github.com/actix/actix-web/pull/2474 -## 4.0.0-beta.12 - 2021-11-22 +## 4.0.0-beta.12 ### Changed @@ -632,7 +632,7 @@ [#2446]: https://github.com/actix/actix-web/pull/2446 [#2448]: https://github.com/actix/actix-web/pull/2448 -## 4.0.0-beta.11 - 2021-11-15 +## 4.0.0-beta.11 ### Added @@ -646,7 +646,7 @@ [#2423]: https://github.com/actix/actix-web/pull/2423 [#2442]: https://github.com/actix/actix-web/pull/2442 -## 4.0.0-beta.10 - 2021-10-20 +## 4.0.0-beta.10 ### Added @@ -673,7 +673,7 @@ [#2409]: https://github.com/actix/actix-web/pull/2409 [#2414]: https://github.com/actix/actix-web/pull/2414 -## 4.0.0-beta.9 - 2021-09-09 +## 4.0.0-beta.9 ### Added @@ -696,7 +696,7 @@ [#2344]: https://github.com/actix/actix-web/pull/2344 [#2379]: https://github.com/actix/actix-web/pull/2379 -## 4.0.0-beta.8 - 2021-06-26 +## 4.0.0-beta.8 ### Added @@ -723,7 +723,7 @@ [#2282]: https://github.com/actix/actix-web/pull/2282 [#2288]: https://github.com/actix/actix-web/pull/2288 -## 4.0.0-beta.7 - 2021-06-17 +## 4.0.0-beta.7 ### Added @@ -752,7 +752,7 @@ [#2253]: https://github.com/actix/actix-web/pull/2253 [#2246]: https://github.com/actix/actix-web/pull/2246 -## 4.0.0-beta.6 - 2021-04-17 +## 4.0.0-beta.6 ### Added @@ -766,7 +766,7 @@ [#2065]: https://github.com/actix/actix-web/pull/2065 [#2148]: https://github.com/actix/actix-web/pull/2148 -## 4.0.0-beta.5 - 2021-04-02 +## 4.0.0-beta.5 ### Added @@ -792,7 +792,7 @@ [#2097]: https://github.com/actix/actix-web/pull/2097 [#2112]: https://github.com/actix/actix-web/pull/2112 -## 4.0.0-beta.4 - 2021-03-09 +## 4.0.0-beta.4 ### Changed @@ -802,11 +802,11 @@ [#1981]: https://github.com/actix/actix-web/pull/1981 [#2010]: https://github.com/actix/actix-web/pull/2010 -## 4.0.0-beta.3 - 2021-02-10 +## 4.0.0-beta.3 - Update `actix-web-codegen` to `0.5.0-beta.1`. -## 4.0.0-beta.2 - 2021-02-10 +## 4.0.0-beta.2 ### Added @@ -844,7 +844,7 @@ [#1933]: https://github.com/actix/actix-web/pull/1933 [#1957]: https://github.com/actix/actix-web/pull/1957 -## 4.0.0-beta.1 - 2021-01-07 +## 4.0.0-beta.1 ### Added @@ -878,7 +878,7 @@
-## 3.3.3 - 2021-12-18 +## 3.3.3 ### Changed @@ -886,7 +886,7 @@ [#2529]: https://github.com/actix/actix-web/pull/2529 -## 3.3.2 - 2020-12-01 +## 3.3.2 ### Fixed @@ -898,11 +898,11 @@ [#1798]: https://github.com/actix/actix-web/pull/1798 [#1803]: https://github.com/actix/actix-web/pull/1803 -## 3.3.1 - 2020-11-29 +## 3.3.1 - Ensure `actix-http` dependency uses same `serde_urlencoded`. -## 3.3.0 - 2020-11-25 +## 3.3.0 ### Added @@ -915,7 +915,7 @@ [#1773]: https://github.com/actix/actix-web/pull/1773 [#1788]: https://github.com/actix/actix-web/pull/1788 -## 3.2.0 - 2020-10-30 +## 3.2.0 ### Added @@ -940,7 +940,7 @@ [#1757]: https://github.com/actix/actix-web/pull/1757 [#1749]: https://github.com/actix/actix-web/pull/1749 -## 3.1.0 - 2020-09-29 +## 3.1.0 ### Changed @@ -955,7 +955,7 @@ [#1708]: https://github.com/actix/actix-web/pull/1708 [#1710]: https://github.com/actix/actix-web/pull/1710 -## 3.0.2 - 2020-09-15 +## 3.0.2 ### Fixed @@ -963,7 +963,7 @@ [#1678]: https://github.com/actix/actix-web/pull/1678 -## 3.0.1 - 2020-09-13 +## 3.0.1 ### Changed @@ -971,11 +971,11 @@ [#1673]: https://github.com/actix/actix-web/pull/1673 -## 3.0.0 - 2020-09-11 +## 3.0.0 - No significant changes from `3.0.0-beta.4`. -## 3.0.0-beta.4 - 2020-09-09 +## 3.0.0-beta.4 ### Added @@ -993,13 +993,13 @@ [#1634]: https://github.com/actix/actix-web/pull/1634 [#1655]: https://github.com/actix/actix-web/pull/1655 -## 3.0.0-beta.3 - 2020-08-17 +## 3.0.0-beta.3 ### Changed - Update `rustls` to 0.18 -## 3.0.0-beta.2 - 2020-08-17 +## 3.0.0-beta.2 ### Changed @@ -1019,7 +1019,7 @@ [#1618]: https://github.com/actix/actix-web/pull/1618 [#1621]: https://github.com/actix/actix-web/pull/1621 -## 3.0.0-beta.1 - 2020-07-13 +## 3.0.0-beta.1 ### Added @@ -1037,7 +1037,7 @@ - `NormalizePath` improved consistency when path needs slashes added _and_ removed. -## 3.0.0-alpha.3 - 2020-05-21 +## 3.0.0-alpha.3 ### Added @@ -1053,7 +1053,7 @@ [#1485]: https://github.com/actix/actix-web/pull/1485 [#1509]: https://github.com/actix/actix-web/pull/1509 -## [3.0.0-alpha.2] - 2020-05-08 +## [3.0.0-alpha.2] ### Changed @@ -1067,7 +1067,7 @@ [#1452]: https://github.com/actix/actix-web/pull/1452 [#1486]: https://github.com/actix/actix-web/pull/1486 -## [3.0.0-alpha.1] - 2020-03-11 +## [3.0.0-alpha.1] ### Added @@ -1084,7 +1084,7 @@ [#1308]: https://github.com/actix/actix-web/pull/1308 -## [2.0.0] - 2019-12-25 +## [2.0.0] ### Changed @@ -1094,7 +1094,7 @@ - Allow to specify multi-patterns for resources -## [2.0.0-rc] - 2019-12-20 +## [2.0.0-rc] ### Changed @@ -1112,31 +1112,31 @@ - Fix `AppConfig::secure()` is always false. #1202 -## [2.0.0-alpha.6] - 2019-12-15 +## [2.0.0-alpha.6] ### Fixed - Fixed compilation with default features off -## [2.0.0-alpha.5] - 2019-12-13 +## [2.0.0-alpha.5] ### Added - Add test server, `test::start()` and `test::start_with()` -## [2.0.0-alpha.4] - 2019-12-08 +## [2.0.0-alpha.4] ### Deleted - Delete HttpServer::run(), it is not useful with async/await -## [2.0.0-alpha.3] - 2019-12-07 +## [2.0.0-alpha.3] ### Changed - Migrate to tokio 0.2 -## [2.0.0-alpha.1] - 2019-11-22 +## [2.0.0-alpha.1] ### Changed @@ -1144,7 +1144,7 @@ - Remove implementation of `Responder` for `()`. (#1167) -## [1.0.9] - 2019-11-14 +## [1.0.9] ### Added @@ -1154,7 +1154,7 @@ - Support `Host` guards when the `Host` header is unset (e.g. HTTP/2 requests) (#1129) -## [1.0.8] - 2019-09-25 +## [1.0.8] ### Added @@ -1172,13 +1172,13 @@ - Use actix-testing for testing utils -## [1.0.7] - 2019-08-29 +## [1.0.7] ### Fixed - Request Extensions leak #1062 -## [1.0.6] - 2019-08-28 +## [1.0.6] ### Added @@ -1200,7 +1200,7 @@ - Update url to 2.1 -## [1.0.5] - 2019-07-18 +## [1.0.5] ### Added @@ -1212,7 +1212,7 @@ - Restored logging of errors through the `Logger` middleware -## [1.0.4] - 2019-07-17 +## [1.0.4] ### Added @@ -1224,7 +1224,7 @@ - Upgrade `rand` dependency version to 0.7 -## [1.0.3] - 2019-06-28 +## [1.0.3] ### Added @@ -1234,7 +1234,7 @@ - Use `encoding_rs` crate instead of unmaintained `encoding` crate -## [1.0.2] - 2019-06-17 +## [1.0.2] ### Changed @@ -1242,7 +1242,7 @@ - Move identity middleware to `actix-identity` crate. -## [1.0.1] - 2019-06-17 +## [1.0.1] ### Added @@ -1266,7 +1266,7 @@ - HttpRequest::url_for is broken with nested scopes #915 -## [1.0.0] - 2019-06-05 +## [1.0.0] ### Added @@ -1288,7 +1288,7 @@ - Clear http requests pool on app service drop #860 -## [1.0.0-rc] - 2019-05-18 +## [1.0.0-rc] ### Added @@ -1303,7 +1303,7 @@ - Codegen with parameters in the path only resolves the first registered endpoint #841 -## [1.0.0-beta.4] - 2019-05-12 +## [1.0.0-beta.4] ### Added @@ -1314,7 +1314,7 @@ - `App::configure` take an `FnOnce` instead of `Fn` - Upgrade actix-net crates -## [1.0.0-beta.3] - 2019-05-04 +## [1.0.0-beta.3] ### Added @@ -1338,7 +1338,7 @@ - `App::data_factory()` is deleted. -## [1.0.0-beta.2] - 2019-04-24 +## [1.0.0-beta.2] ### Added @@ -1360,7 +1360,7 @@ - Fix async web::Data factory handling -## [1.0.0-beta.1] - 2019-04-20 +## [1.0.0-beta.1] ### Added @@ -1384,7 +1384,7 @@ - Fixed `TestRequest::app_data()` -## [1.0.0-alpha.6] - 2019-04-14 +## [1.0.0-alpha.6] ### Changed @@ -1396,7 +1396,7 @@ - Make extractor config type explicit. Add `FromRequest::Config` associated type. -## [1.0.0-alpha.5] - 2019-04-12 +## [1.0.0-alpha.5] ### Added @@ -1406,7 +1406,7 @@ - Removed native-tls support -## [1.0.0-alpha.4] - 2019-04-08 +## [1.0.0-alpha.4] ### Added @@ -1428,7 +1428,7 @@ - Fix body propagation in Response::from_error. #760 -## [1.0.0-alpha.3] - 2019-04-02 +## [1.0.0-alpha.3] ### Changed @@ -1442,7 +1442,7 @@ - Removed unused `actix_web::web::md()` -## [1.0.0-alpha.2] - 2019-03-29 +## [1.0.0-alpha.2] ### Added @@ -1454,7 +1454,7 @@ - Multipart::Field renamed to MultipartField -## [1.0.0-alpha.1] - 2019-03-28 +## [1.0.0-alpha.1] ### Changed diff --git a/awc/CHANGES.md b/awc/CHANGES.md index c998cd97a..606199131 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,24 +1,24 @@ # Changes -## Unreleased - 2023-xx-xx +## Unreleased - Add `awc::Connector::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. - Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -## 3.1.1 - 2023-02-26 +## 3.1.1 ### Changed - `client::Connect` is now public to allow tunneling connection with `client::Connector`. -## 3.1.0 - 2023-01-21 +## 3.1.0 ### Changed - Minimum supported Rust version (MSRV) is now 1.59 due to transitive `time` dependency. -## 3.0.1 - 2022-08-25 +## 3.0.1 ### Changed @@ -30,7 +30,7 @@ [#2840]: https://github.com/actix/actix-web/pull/2840 -## 3.0.0 - 2022-03-07 +## 3.0.0 ### Dependencies @@ -132,23 +132,23 @@
3.0.0 Pre-Releases -## 3.0.0-beta.21 - 2022-02-16 +## 3.0.0-beta.21 - No significant changes since `3.0.0-beta.20`. -## 3.0.0-beta.20 - 2022-01-31 +## 3.0.0-beta.20 - No significant changes since `3.0.0-beta.19`. -## 3.0.0-beta.19 - 2022-01-21 +## 3.0.0-beta.19 - No significant changes since `3.0.0-beta.18`. -## 3.0.0-beta.18 - 2022-01-04 +## 3.0.0-beta.18 - Minimum supported Rust version (MSRV) is now 1.54. -## 3.0.0-beta.17 - 2021-12-29 +## 3.0.0-beta.17 ### Changed @@ -161,7 +161,7 @@ [#2555]: https://github.com/actix/actix-web/pull/2555 [`rustsec-2020-0071`]: https://rustsec.org/advisories/RUSTSEC-2020-0071.html -## 3.0.0-beta.16 - 2021-12-29 +## 3.0.0-beta.16 - `*::send_json` and `*::send_form` methods now receive `impl Serialize`. [#2553] - `FrozenClientRequest::extra_header` now uses receives an `impl TryIntoHeaderPair`. [#2553] @@ -169,7 +169,7 @@ [#2553]: https://github.com/actix/actix-web/pull/2553 -## 3.0.0-beta.15 - 2021-12-27 +## 3.0.0-beta.15 - Rename `Connector::{ssl => openssl}`. [#2503] - Improve `Client` instantiation efficiency when using `openssl` by only building connectors once. [#2503] @@ -182,37 +182,37 @@ [#2503]: https://github.com/actix/actix-web/pull/2503 [#2546]: https://github.com/actix/actix-web/pull/2546 -## 3.0.0-beta.14 - 2021-12-17 +## 3.0.0-beta.14 - Add `ClientBuilder::add_default_header` and deprecate `ClientBuilder::header`. [#2510] [#2510]: https://github.com/actix/actix-web/pull/2510 -## 3.0.0-beta.13 - 2021-12-11 +## 3.0.0-beta.13 - No significant changes since `3.0.0-beta.12`. -## 3.0.0-beta.12 - 2021-11-30 +## 3.0.0-beta.12 - Update `actix-tls` to `3.0.0-rc.1`. [#2474] [#2474]: https://github.com/actix/actix-web/pull/2474 -## 3.0.0-beta.11 - 2021-11-22 +## 3.0.0-beta.11 - No significant changes from `3.0.0-beta.10`. -## 3.0.0-beta.10 - 2021-11-15 +## 3.0.0-beta.10 - No significant changes from `3.0.0-beta.9`. -## 3.0.0-beta.9 - 2021-10-20 +## 3.0.0-beta.9 - Updated rustls to v0.20. [#2414] [#2414]: https://github.com/actix/actix-web/pull/2414 -## 3.0.0-beta.8 - 2021-09-09 +## 3.0.0-beta.8 ### Changed @@ -220,7 +220,7 @@ [#2310]: https://github.com/actix/actix-web/pull/2310 -## 3.0.0-beta.7 - 2021-06-26 +## 3.0.0-beta.7 ### Changed @@ -228,11 +228,11 @@ [#2250]: https://github.com/actix/actix-web/pull/2250 -## 3.0.0-beta.6 - 2021-06-17 +## 3.0.0-beta.6 - No significant changes since 3.0.0-beta.5. -## 3.0.0-beta.5 - 2021-04-17 +## 3.0.0-beta.5 ### Removed @@ -240,7 +240,7 @@ [#2148]: https://github.com/actix/actix-web/pull/2148 -## 3.0.0-beta.4 - 2021-04-02 +## 3.0.0-beta.4 ### Added @@ -257,7 +257,7 @@ [#2114]: https://github.com/actix/actix-web/pull/2114 [#2116]: https://github.com/actix/actix-web/pull/2116 -## 3.0.0-beta.3 - 2021-03-08 +## 3.0.0-beta.3 ### Added @@ -280,7 +280,7 @@ [#2024]: https://github.com/actix/actix-web/pull/2024 [#2050]: https://github.com/actix/actix-web/pull/2050 -## 3.0.0-beta.2 - 2021-02-10 +## 3.0.0-beta.2 ### Added @@ -303,7 +303,7 @@ [#1905]: https://github.com/actix/actix-web/pull/1905 [#1969]: https://github.com/actix/actix-web/pull/1969 -## 3.0.0-beta.1 - 2021-01-07 +## 3.0.0-beta.1 ### Changed @@ -315,13 +315,13 @@
-## 2.0.3 - 2020-11-29 +## 2.0.3 ### Fixed - Ensure `actix-http` dependency uses same `serde_urlencoded`. -## 2.0.2 - 2020-11-25 +## 2.0.2 ### Changed @@ -329,7 +329,7 @@ [#1773]: https://github.com/actix/actix-web/pull/1773 -## 2.0.1 - 2020-10-30 +## 2.0.1 ### Changed @@ -344,37 +344,37 @@ [#1760]: https://github.com/actix/actix-web/pull/1760 [#1744]: https://github.com/actix/actix-web/pull/1744 -## 2.0.0 - 2020-09-11 +## 2.0.0 ### Changed - `Client::build` was renamed to `Client::builder`. -## 2.0.0-beta.4 - 2020-09-09 +## 2.0.0-beta.4 ### Changed - Update actix-codec & actix-tls dependencies. -## 2.0.0-beta.3 - 2020-08-17 +## 2.0.0-beta.3 ### Changed - Update `rustls` to 0.18 -## 2.0.0-beta.2 - 2020-07-21 +## 2.0.0-beta.2 ### Changed - Update `actix-http` dependency to 2.0.0-beta.2 -## [2.0.0-beta.1] - 2020-07-14 +## [2.0.0-beta.1] ### Changed - Update `actix-http` dependency to 2.0.0-beta.1 -## [2.0.0-alpha.2] - 2020-05-21 +## [2.0.0-alpha.2] ### Changed @@ -384,18 +384,18 @@ [#1422]: https://github.com/actix/actix-web/pull/1422 -## [2.0.0-alpha.1] - 2020-03-11 +## [2.0.0-alpha.1] - Update `actix-http` dependency to 2.0.0-alpha.2 - Update `rustls` dependency to 0.17 - ClientBuilder accepts initial_window_size and initial_connection_window_size HTTP2 configuration - ClientBuilder allowing to set max_http_version to limit HTTP version to be used -## [1.0.1] - 2019-12-15 +## [1.0.1] - Fix compilation with default features off -## [1.0.0] - 2019-12-13 +## [1.0.0] - Release @@ -403,23 +403,23 @@ - Migrate to `std::future` -## [0.2.8] - 2019-11-06 +## [0.2.8] - Add support for setting query from Serialize type for client request. -## [0.2.7] - 2019-09-25 +## [0.2.7] ### Added - Remaining getter methods for `ClientRequest`'s private `head` field #1101 -## [0.2.6] - 2019-09-12 +## [0.2.6] ### Added - Export frozen request related types. -## [0.2.5] - 2019-09-11 +## [0.2.5] ### Added @@ -429,7 +429,7 @@ - Ensure that the `Host` header is set when initiating a WebSocket client connection. -## [0.2.4] - 2019-08-13 +## [0.2.4] ### Changed @@ -437,13 +437,13 @@ - Update serde_urlencoded to "0.6.1" -## [0.2.3] - 2019-08-01 +## [0.2.3] ### Added - Add `rustls` support -## [0.2.2] - 2019-07-01 +## [0.2.2] ### Changed @@ -451,13 +451,13 @@ - Upgrade `rand` dependency version to 0.7 -## [0.2.1] - 2019-06-05 +## [0.2.1] ### Added - Add license files -## [0.2.0] - 2019-05-12 +## [0.2.0] ### Added @@ -467,7 +467,7 @@ - Upgrade actix-http dependency. -## [0.1.1] - 2019-04-19 +## [0.1.1] ### Added @@ -477,17 +477,17 @@ - `ClientRequest::if_true()` and `ClientRequest::if_some()` use instance instead of ref -## [0.1.0] - 2019-04-16 +## [0.1.0] - No changes -## [0.1.0-alpha.6] - 2019-04-14 +## [0.1.0-alpha.6] ### Changed - Do not set default headers for websocket request -## [0.1.0-alpha.5] - 2019-04-12 +## [0.1.0-alpha.5] ### Changed @@ -497,13 +497,13 @@ - Add Debug impl for BoxedSocket -## [0.1.0-alpha.4] - 2019-04-08 +## [0.1.0-alpha.4] ### Changed - Update actix-http dependency -## [0.1.0-alpha.3] - 2019-04-02 +## [0.1.0-alpha.3] ### Added @@ -519,7 +519,7 @@ - Renamed `ClientRequest::close_connection()` to `ClientRequest::force_close()` -## [0.1.0-alpha.2] - 2019-03-29 +## [0.1.0-alpha.2] ### Added @@ -537,6 +537,6 @@ - Export `ws` sub-module with websockets related types -## [0.1.0-alpha.1] - 2019-03-28 +## [0.1.0-alpha.1] - Initial impl From 84eb8b306c8be989339b513600a5c09838cd97ec Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 28 Aug 2023 23:46:02 +0100 Subject: [PATCH 105/314] chore: remove broken links from changelogs --- actix-multipart/CHANGES.md | 20 ++++++------- actix-web-actors/CHANGES.md | 24 +++++++-------- actix-web/CHANGES.md | 60 ++++++++++++++++++------------------- awc/CHANGES.md | 46 ++++++++++++++-------------- 4 files changed, 75 insertions(+), 75 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index dc4cb8373..e5a746e8c 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -106,45 +106,45 @@ - Remove the unused `time` dependency - Fix missing `std::error::Error` implement for `MultipartError`. -## [0.2.0] +## 0.2.0 - Release -## [0.2.0-alpha.4] +## 0.2.0-alpha.4 - Multipart handling now handles Pending during read of boundary #1205 -## [0.2.0-alpha.2] +## 0.2.0-alpha.2 - Migrate to `std::future` -## [0.1.4] +## 0.1.4 - Multipart handling now parses requests which do not end in CRLF #1038 -## [0.1.3] +## 0.1.3 - Fix ring dependency from actix-web default features for #741. -## [0.1.2] +## 0.1.2 - Fix boundary parsing #876 -## [0.1.1] +## 0.1.1 - Fix disconnect handling #834 -## [0.1.0] +## 0.1.0 - Release -## [0.1.0-beta.4] +## 0.1.0-beta.4 - Handle cancellation of uploads #736 - Upgrade to actix-web 1.0.0-beta.4 -## [0.1.0-beta.1] +## 0.1.0-beta.1 - Do not support nested multipart diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 563bc210f..5c516db56 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -85,55 +85,55 @@ - Update `actix-*` dependencies to latest versions. -## [3.0.0-beta.1] +## 3.0.0-beta.1 - Update `actix-web` & `actix-http` dependencies to beta.1 - Bump minimum supported Rust version to 1.40 -## [3.0.0-alpha.1] +## 3.0.0-alpha.1 - Update the actix-web dependency to 3.0.0-alpha.1 - Update the actix dependency to 0.10.0-alpha.2 - Update the actix-http dependency to 2.0.0-alpha.3 -## [2.0.0] +## 2.0.0 - Release -## [2.0.0-alpha.1] +## 2.0.0-alpha.1 - Migrate to actix-web 2.0.0 -## [1.0.4] +## 1.0.4 - Allow comma-separated websocket subprotocols without spaces (#1172) -## [1.0.3] +## 1.0.3 - Update actix-web and actix-http dependencies -## [1.0.2] +## 1.0.2 - Add `ws::start_with_addr()`, returning the address of the created actor, along with the `HttpResponse`. - Add support for specifying protocols on websocket handshake #835 -## [1.0.1] +## 1.0.1 - Allow to use custom ws codec with `WebsocketContext` #925 -## [1.0.0] +## 1.0.0 - Update actix-http and actix-web -## [0.1.0-alpha.3] +## 0.1.0-alpha.3 - Update actix-http and actix-web -## [0.1.0-alpha.2] +## 0.1.0-alpha.2 - Update actix-http and actix-web -## [0.1.0-alpha.1] +## 0.1.0-alpha.1 - Initial impl diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 289f8698f..dcf6279fb 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -1053,7 +1053,7 @@ [#1485]: https://github.com/actix/actix-web/pull/1485 [#1509]: https://github.com/actix/actix-web/pull/1509 -## [3.0.0-alpha.2] +## 3.0.0-alpha.2 ### Changed @@ -1067,7 +1067,7 @@ [#1452]: https://github.com/actix/actix-web/pull/1452 [#1486]: https://github.com/actix/actix-web/pull/1486 -## [3.0.0-alpha.1] +## 3.0.0-alpha.1 ### Added @@ -1084,7 +1084,7 @@ [#1308]: https://github.com/actix/actix-web/pull/1308 -## [2.0.0] +## 2.0.0 ### Changed @@ -1094,7 +1094,7 @@ - Allow to specify multi-patterns for resources -## [2.0.0-rc] +## 2.0.0-rc ### Changed @@ -1112,31 +1112,31 @@ - Fix `AppConfig::secure()` is always false. #1202 -## [2.0.0-alpha.6] +## 2.0.0-alpha.6 ### Fixed - Fixed compilation with default features off -## [2.0.0-alpha.5] +## 2.0.0-alpha.5 ### Added - Add test server, `test::start()` and `test::start_with()` -## [2.0.0-alpha.4] +## 2.0.0-alpha.4 ### Deleted - Delete HttpServer::run(), it is not useful with async/await -## [2.0.0-alpha.3] +## 2.0.0-alpha.3 ### Changed - Migrate to tokio 0.2 -## [2.0.0-alpha.1] +## 2.0.0-alpha.1 ### Changed @@ -1144,7 +1144,7 @@ - Remove implementation of `Responder` for `()`. (#1167) -## [1.0.9] +## 1.0.9 ### Added @@ -1154,7 +1154,7 @@ - Support `Host` guards when the `Host` header is unset (e.g. HTTP/2 requests) (#1129) -## [1.0.8] +## 1.0.8 ### Added @@ -1172,13 +1172,13 @@ - Use actix-testing for testing utils -## [1.0.7] +## 1.0.7 ### Fixed - Request Extensions leak #1062 -## [1.0.6] +## 1.0.6 ### Added @@ -1200,7 +1200,7 @@ - Update url to 2.1 -## [1.0.5] +## 1.0.5 ### Added @@ -1212,7 +1212,7 @@ - Restored logging of errors through the `Logger` middleware -## [1.0.4] +## 1.0.4 ### Added @@ -1224,7 +1224,7 @@ - Upgrade `rand` dependency version to 0.7 -## [1.0.3] +## 1.0.3 ### Added @@ -1234,7 +1234,7 @@ - Use `encoding_rs` crate instead of unmaintained `encoding` crate -## [1.0.2] +## 1.0.2 ### Changed @@ -1242,7 +1242,7 @@ - Move identity middleware to `actix-identity` crate. -## [1.0.1] +## 1.0.1 ### Added @@ -1266,7 +1266,7 @@ - HttpRequest::url_for is broken with nested scopes #915 -## [1.0.0] +## 1.0.0 ### Added @@ -1288,7 +1288,7 @@ - Clear http requests pool on app service drop #860 -## [1.0.0-rc] +## 1.0.0-rc ### Added @@ -1303,7 +1303,7 @@ - Codegen with parameters in the path only resolves the first registered endpoint #841 -## [1.0.0-beta.4] +## 1.0.0-beta.4 ### Added @@ -1314,7 +1314,7 @@ - `App::configure` take an `FnOnce` instead of `Fn` - Upgrade actix-net crates -## [1.0.0-beta.3] +## 1.0.0-beta.3 ### Added @@ -1338,7 +1338,7 @@ - `App::data_factory()` is deleted. -## [1.0.0-beta.2] +## 1.0.0-beta.2 ### Added @@ -1360,7 +1360,7 @@ - Fix async web::Data factory handling -## [1.0.0-beta.1] +## 1.0.0-beta.1 ### Added @@ -1384,7 +1384,7 @@ - Fixed `TestRequest::app_data()` -## [1.0.0-alpha.6] +## 1.0.0-alpha.6 ### Changed @@ -1396,7 +1396,7 @@ - Make extractor config type explicit. Add `FromRequest::Config` associated type. -## [1.0.0-alpha.5] +## 1.0.0-alpha.5 ### Added @@ -1406,7 +1406,7 @@ - Removed native-tls support -## [1.0.0-alpha.4] +## 1.0.0-alpha.4 ### Added @@ -1428,7 +1428,7 @@ - Fix body propagation in Response::from_error. #760 -## [1.0.0-alpha.3] +## 1.0.0-alpha.3 ### Changed @@ -1442,7 +1442,7 @@ - Removed unused `actix_web::web::md()` -## [1.0.0-alpha.2] +## 1.0.0-alpha.2 ### Added @@ -1454,7 +1454,7 @@ - Multipart::Field renamed to MultipartField -## [1.0.0-alpha.1] +## 1.0.0-alpha.1 ### Changed diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 606199131..8b1248733 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -368,13 +368,13 @@ - Update `actix-http` dependency to 2.0.0-beta.2 -## [2.0.0-beta.1] +## 2.0.0-beta.1 ### Changed - Update `actix-http` dependency to 2.0.0-beta.1 -## [2.0.0-alpha.2] +## 2.0.0-alpha.2 ### Changed @@ -384,42 +384,42 @@ [#1422]: https://github.com/actix/actix-web/pull/1422 -## [2.0.0-alpha.1] +## 2.0.0-alpha.1 - Update `actix-http` dependency to 2.0.0-alpha.2 - Update `rustls` dependency to 0.17 - ClientBuilder accepts initial_window_size and initial_connection_window_size HTTP2 configuration - ClientBuilder allowing to set max_http_version to limit HTTP version to be used -## [1.0.1] +## 1.0.1 - Fix compilation with default features off -## [1.0.0] +## 1.0.0 - Release -## [1.0.0-alpha.3] +## 1.0.0-alpha.3 - Migrate to `std::future` -## [0.2.8] +## 0.2.8 - Add support for setting query from Serialize type for client request. -## [0.2.7] +## 0.2.7 ### Added - Remaining getter methods for `ClientRequest`'s private `head` field #1101 -## [0.2.6] +## 0.2.6 ### Added - Export frozen request related types. -## [0.2.5] +## 0.2.5 ### Added @@ -429,7 +429,7 @@ - Ensure that the `Host` header is set when initiating a WebSocket client connection. -## [0.2.4] +## 0.2.4 ### Changed @@ -437,13 +437,13 @@ - Update serde_urlencoded to "0.6.1" -## [0.2.3] +## 0.2.3 ### Added - Add `rustls` support -## [0.2.2] +## 0.2.2 ### Changed @@ -451,13 +451,13 @@ - Upgrade `rand` dependency version to 0.7 -## [0.2.1] +## 0.2.1 ### Added - Add license files -## [0.2.0] +## 0.2.0 ### Added @@ -467,7 +467,7 @@ - Upgrade actix-http dependency. -## [0.1.1] +## 0.1.1 ### Added @@ -477,17 +477,17 @@ - `ClientRequest::if_true()` and `ClientRequest::if_some()` use instance instead of ref -## [0.1.0] +## 0.1.0 - No changes -## [0.1.0-alpha.6] +## 0.1.0-alpha.6 ### Changed - Do not set default headers for websocket request -## [0.1.0-alpha.5] +## 0.1.0-alpha.5 ### Changed @@ -497,13 +497,13 @@ - Add Debug impl for BoxedSocket -## [0.1.0-alpha.4] +## 0.1.0-alpha.4 ### Changed - Update actix-http dependency -## [0.1.0-alpha.3] +## 0.1.0-alpha.3 ### Added @@ -519,7 +519,7 @@ - Renamed `ClientRequest::close_connection()` to `ClientRequest::force_close()` -## [0.1.0-alpha.2] +## 0.1.0-alpha.2 ### Added @@ -537,6 +537,6 @@ - Export `ws` sub-module with websockets related types -## [0.1.0-alpha.1] +## 0.1.0-alpha.1 - Initial impl From ac95362340c195b60639e48a610e9d7f3677ba18 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:14:54 +0100 Subject: [PATCH 106/314] refactor: simplify connector feature combos --- .github/workflows/ci-post-merge.yml | 2 +- awc/src/client/connector.rs | 25 +------------------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 5460eeec4..a34dd27ba 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -58,7 +58,7 @@ jobs: run: | cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls + cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls cargo test --lib --tests -p=actix-web-codegen --all-features cargo test --lib --tests -p=awc --all-features cargo test --lib --tests -p=actix-http-test --all-features diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 538b64ffd..1a8715bf9 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -109,33 +109,10 @@ impl Connector<()> { OurTlsConnector::Rustls021(std::sync::Arc::new(config)) } - /// Build TLS connector with Rustls v0.21, based on supplied ALPN protocols - /// - /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. - #[cfg(all( - all(feature = "rustls-0_20", feature = "openssl"), - not(feature = "rustls-0_21"), - ))] - fn build_tls(protocols: Vec>) -> OurTlsConnector { - use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; - - let mut config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(webpki_roots_cert_store()) - .with_no_client_auth(); - - config.alpn_protocols = protocols; - - OurTlsConnector::Rustls020(std::sync::Arc::new(config)) - } - /// Build TLS connector with Rustls v0.20, based on supplied ALPN protocols /// /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. - #[cfg(all( - feature = "rustls-0_20", - not(any(feature = "rustls-0_21", feature = "openssl")), - ))] + #[cfg(all(feature = "rustls-0_20", not(feature = "rustls-0_21")))] fn build_tls(protocols: Vec>) -> OurTlsConnector { use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; From 4ed61466e79776ca4e4b7df3b8365dcc023f45ff Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:17:32 +0100 Subject: [PATCH 107/314] chore(actix-multipart-derive): prepare release 0.6.1 --- actix-multipart-derive/CHANGES.md | 2 ++ actix-multipart-derive/Cargo.toml | 2 +- actix-multipart/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index 04f31e0f3..e36a13d04 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.1 + - Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index 41e687e50..75b4c723b 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart-derive" -version = "0.6.0" +version = "0.6.1" authors = ["Jacob Halsey "] description = "Multipart form derive macro for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 9220e793c..31c792fc0 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -22,7 +22,7 @@ derive = ["actix-multipart-derive"] tempfile = ["dep:tempfile", "tokio/fs"] [dependencies] -actix-multipart-derive = { version = "=0.6.0", optional = true } +actix-multipart-derive = { version = "=0.6.1", optional = true } actix-utils = "3" actix-web = { version = "4", default-features = false } From b422745b6c2fa8c8b68da501c112bf1bd0420d1e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:18:37 +0100 Subject: [PATCH 108/314] chore(actix-multipart): prepare release 0.6.1 --- actix-multipart/CHANGES.md | 2 ++ actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 ++-- scripts/bump | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index e5a746e8c..50faf7cfa 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.1 + - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.6.0 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 31c792fc0..455d7db78 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.6.0" +version = "0.6.1" authors = [ "Nikolay Kim ", "Jacob Halsey ", diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 66550668d..8fe0328ab 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -3,11 +3,11 @@ > Multipart form support for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) -[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.0)](https://docs.rs/actix-multipart/0.6.0) +[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart/0.6.0/status.svg)](https://deps.rs/crate/actix-multipart/0.6.0) +[![dependency status](https://deps.rs/crate/actix-multipart/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart/0.6.1) [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/scripts/bump b/scripts/bump index b09d9d196..baf3fb4d8 100755 --- a/scripts/bump +++ b/scripts/bump @@ -128,11 +128,11 @@ if [ "$UPDATE_REFERENCES" = 'y' ] || [ "$UPDATE_REFERENCES" = 'Y' ]; then fi if [ $MACOS ]; then - printf "prepare $PACKAGE_NAME release $NEW_VERSION" | pbcopy + printf "chore($PACKAGE_NAME): prepare release $NEW_VERSION" | pbcopy else echo echo "commit message:" - echo "prepare $PACKAGE_NAME release $NEW_VERSION" + echo "chore($PACKAGE_NAME): prepare release $NEW_VERSION" fi SHORT_PACKAGE_NAME="$(echo $PACKAGE_NAME | sed 's/^actix-web-//' | sed 's/^actix-//')" From a12d39c93edc83d32fb62a53b14c4422e1b4774d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:19:56 +0100 Subject: [PATCH 109/314] chore(actix-web-codegen): prepare release 4.2.1 --- actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 4b3205d7c..d5a3f5d31 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.2.1 + - Update `syn` dependency to `2`. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index c202c5d6e..0eee5004a 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "4.2.0" +version = "4.2.1" description = "Routing and runtime macros for Actix Web" homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index e6df8164e..a53159e03 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -3,11 +3,11 @@ > Routing and runtime macros for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) -[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.0)](https://docs.rs/actix-web-codegen/4.2.0) +[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.1)](https://docs.rs/actix-web-codegen/4.2.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
-[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.0) +[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.1/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.1) [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 45fdc08788b8c0294e399f856027066476e6e4f9 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:51:54 +0100 Subject: [PATCH 110/314] chore(actix-http): prepare release 3.4.0 --- actix-http/CHANGES.md | 4 +++- actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 5252f3fbf..f3720b784 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,10 +2,12 @@ ## Unreleased +## 3.4.0 + ### Added - Add `rustls-0_20` crate feature. -- Add `{H1Service, H2Service, HttpService}::rustls_021()` and `HttpService::rustls_021_with_config()` service constructors. +- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_021()` and `HttpService::rustls_021_with_config()` service constructors. - Add `body::to_body_limit()` function. - Add `body::BodyLimitExceeded` error type. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 6aaaecfd4..c19ce0161 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.3.1" +version = "3.4.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index ce2e5cb32..049de9278 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -3,11 +3,11 @@ > 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=3.3.1)](https://docs.rs/actix-http/3.3.1) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.4.0)](https://docs.rs/actix-http/3.4.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.3.1/status.svg)](https://deps.rs/crate/actix-http/3.3.1) +[![dependency status](https://deps.rs/crate/actix-http/3.4.0/status.svg)](https://deps.rs/crate/actix-http/3.4.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index e85a0c90e..8221aaa90 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -75,7 +75,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3.1", default-features = false, optional = true } -actix-http = { version = "3.3", features = ["ws"] } +actix-http = { version = "3.4", features = ["ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 67d6b06f5..a0f933b40 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -61,7 +61,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3.3", features = ["http2", "ws"] } +actix-http = { version = "3.4", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.1", features = ["connect", "uri"] } actix-utils = "3" @@ -94,7 +94,7 @@ tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, featu trust-dns-resolver = { version = "0.22", optional = true } [dev-dependencies] -actix-http = { version = "3", features = ["openssl"] } +actix-http = { version = "3.4", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } From d2c0d472e97f0baaa0b2b734f99b32e0d4c43615 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:53:14 +0100 Subject: [PATCH 111/314] chore(awc): prepare release 3.2.0 --- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 8b1248733..f649a37c8 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.2.0 + - Add `awc::Connector::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. - Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index a0f933b40..22f87ae3e 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.1.1" +version = "3.2.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index f2a9c7559..1f31167eb 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=3.1.1)](https://docs.rs/awc/3.1.1) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.2.0)](https://docs.rs/awc/3.2.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.1.1/status.svg)](https://deps.rs/crate/awc/3.1.1) +[![Dependency Status](https://deps.rs/crate/awc/3.2.0/status.svg)](https://deps.rs/crate/awc/3.2.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) ## Documentation & Resources From 2b40033a9cd3c8dbc813bc6ee4a385a44236994d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:54:40 +0100 Subject: [PATCH 112/314] chore(actix-web): prepare release 4.4.0 --- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index dcf6279fb..6ed97b671 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.0 + ### Added - Add `HttpServer::{bind, listen}_auto_h2c()` methods behind new `http2` crate feature. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 8221aaa90..19ac6c8ae 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.3.1" +version = "4.4.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-web/README.md b/actix-web/README.md index 74b4924d4..e83397657 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.3.1)](https://docs.rs/actix-web/4.3.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.4.0)](https://docs.rs/actix-web/4.4.0) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.3.1/status.svg)](https://deps.rs/crate/actix-web/4.3.1) +[![Dependency Status](https://deps.rs/crate/actix-web/4.4.0/status.svg)](https://deps.rs/crate/actix-web/4.4.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From e6636f1279510a8f0b1d62c2981288bb845f8ef5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:55:17 +0100 Subject: [PATCH 113/314] chore(actix-test): prepare release 0.1.2 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index c33927fa4..a3ca7fe10 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.2 + - Add `TestServerConfig::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. - Add `TestServerConfig::workers()` method. - Add `rustls-0_20` crate feature, which the existing `rustls` feature now aliases. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index dd96084b3..38b40ccfa 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.1" +version = "0.1.2" authors = [ "Nikolay Kim ", "Rob Ede ", From 39abe3ae5e318c11135bb36cfc29472a33e60af2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 01:57:19 +0100 Subject: [PATCH 114/314] docs: fix -http changelog --- actix-http/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index f3720b784..860ee3b6c 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -8,7 +8,7 @@ - Add `rustls-0_20` crate feature. - Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_021()` and `HttpService::rustls_021_with_config()` service constructors. -- Add `body::to_body_limit()` function. +- Add `body::to_bytes_limited()` function. - Add `body::BodyLimitExceeded` error type. ### Changed From 76f6106f8fe8b8d4827698d8132624080ae189aa Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 29 Aug 2023 21:27:36 +0100 Subject: [PATCH 115/314] fix: wrap attribute codegen regression when using expression (#3119) --- actix-web-codegen/CHANGES.md | 4 ++++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 ++-- actix-web-codegen/src/route.rs | 16 ++++++++-------- actix-web-codegen/tests/test_macro.rs | 13 +++++++++++++ .../tests/trybuild/simple-fail.stderr | 2 +- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index d5a3f5d31..00e36b037 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +## 4.2.2 + +- Fix regression when declaring `wrap` attribute using an expression. + ## 4.2.1 - Update `syn` dependency to `2`. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 0eee5004a..748984b49 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "4.2.1" +version = "4.2.2" description = "Routing and runtime macros for Actix Web" homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web.git" diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index a53159e03..e9a1f9c7e 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -3,11 +3,11 @@ > Routing and runtime macros for Actix Web. [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) -[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.1)](https://docs.rs/actix-web-codegen/4.2.1) +[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
-[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.1/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.1) +[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.2/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.2) [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 525a1c8ba..7a2dfc051 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -224,7 +224,7 @@ struct Args { path: syn::LitStr, resource_name: Option, guards: Vec, - wrappers: Vec, + wrappers: Vec, methods: HashSet, } @@ -251,7 +251,7 @@ impl Args { } else { return Err(syn::Error::new_spanned( nv.value, - "Attribute name expects literal string!", + "Attribute name expects literal string", )); } } else if nv.path.is_ident("guard") { @@ -264,7 +264,7 @@ impl Args { } else { return Err(syn::Error::new_spanned( nv.value, - "Attribute guard expects literal string!", + "Attribute guard expects literal string", )); } } else if nv.path.is_ident("wrap") { @@ -283,9 +283,9 @@ impl Args { } else if nv.path.is_ident("method") { if !is_route_macro { return Err(syn::Error::new_spanned( - &nv, - "HTTP method forbidden here. To handle multiple methods, use `route` instead", - )); + &nv, + "HTTP method forbidden here; to handle multiple methods, use `route` instead", + )); } else if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit), .. @@ -300,13 +300,13 @@ impl Args { } else { return Err(syn::Error::new_spanned( nv.value, - "Attribute method expects literal string!", + "Attribute method expects literal string", )); } } else { return Err(syn::Error::new_spanned( nv.path, - "Unknown attribute key is specified. Allowed: guard, method and wrap", + "Unknown attribute key is specified; allowed: guard, method and wrap", )); } } diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs index f28654cd9..fb50d4ae0 100644 --- a/actix-web-codegen/tests/test_macro.rs +++ b/actix-web-codegen/tests/test_macro.rs @@ -212,6 +212,19 @@ async fn get_wrap(_: web::Path) -> impl Responder { HttpResponse::Ok() } +/// Using expression, not just path to type, in wrap attribute. +/// +/// Regression from . +#[route( + "/catalog", + method = "GET", + method = "HEAD", + wrap = "actix_web::middleware::Compress::default()" +)] +async fn get_catalog() -> impl Responder { + HttpResponse::Ok().body("123123123") +} + #[actix_rt::test] async fn test_params() { let srv = actix_test::start(|| { diff --git a/actix-web-codegen/tests/trybuild/simple-fail.stderr b/actix-web-codegen/tests/trybuild/simple-fail.stderr index 3b3f9d850..ab81599ed 100644 --- a/actix-web-codegen/tests/trybuild/simple-fail.stderr +++ b/actix-web-codegen/tests/trybuild/simple-fail.stderr @@ -38,7 +38,7 @@ error: Multiple paths specified! There should be only one. | = note: this error originates in the attribute macro `delete` (in Nightly builds, run with -Z macro-backtrace for more info) -error: HTTP method forbidden here. To handle multiple methods, use `route` instead +error: HTTP method forbidden here; to handle multiple methods, use `route` instead --> $DIR/simple-fail.rs:25:19 | 25 | #[delete("/five", method="GET")] From d4457429741d46abad0b726fd884d7301691ada2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 3 Sep 2023 04:40:41 +0000 Subject: [PATCH 116/314] Update trust-dns-resolver requirement from 0.22 to 0.23 (#3121) * Update trust-dns-resolver requirement from 0.22 to 0.23 Updates the requirements on [trust-dns-resolver](https://github.com/bluejekyll/trust-dns) to permit the latest version. - [Release notes](https://github.com/bluejekyll/trust-dns/releases) - [Changelog](https://github.com/bluejekyll/trust-dns/blob/main/CHANGELOG.md) - [Commits](https://github.com/bluejekyll/trust-dns/compare/v0.22.0...v0.23.0) --- updated-dependencies: - dependency-name: trust-dns-resolver dependency-type: direct:production ... Signed-off-by: dependabot[bot] * fixup post-upgrade --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/src/client/connector.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index f649a37c8..1032e196c 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Update `trust-dns-resolver` dependency to `0.23`. + ## 3.2.0 - Add `awc::Connector::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 22f87ae3e..027bb161e 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -91,7 +91,7 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } -trust-dns-resolver = { version = "0.22", optional = true } +trust-dns-resolver = { version = "0.23", optional = true } [dev-dependencies] actix-http = { version = "3.4", features = ["openssl"] } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 1a8715bf9..de39e1a4a 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -915,7 +915,7 @@ mod resolver { } }; - let resolver = TokioAsyncResolver::tokio(cfg, opts).unwrap(); + let resolver = TokioAsyncResolver::tokio(cfg, opts); // box trust dns resolver and put it in thread local. let resolver = Resolver::custom(TrustDnsResolver(resolver)); From 215a52f56535a8ab104159c84d02461841d5d340 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 3 Sep 2023 19:09:42 +0100 Subject: [PATCH 117/314] chore: avoid single char error bindings --- actix-http/src/encoding/decoder.rs | 16 ++++++++-------- actix-http/src/h1/decoder.rs | 2 +- actix-http/src/responses/builder.rs | 6 +++--- actix-http/src/ws/codec.rs | 2 +- actix-http/tests/test_server.rs | 2 +- actix-web-actors/src/ws.rs | 4 ++-- actix-web/Cargo.toml | 2 +- actix-web/src/app.rs | 4 ++-- actix-web/src/extract.rs | 10 +++++----- actix-web/src/middleware/logger.rs | 2 +- actix-web/src/response/builder.rs | 6 +++--- actix-web/src/server.rs | 2 +- actix-web/src/types/header.rs | 6 +++--- awc/src/client/connector.rs | 4 ++-- awc/src/client/h1proto.rs | 2 +- awc/src/client/h2proto.rs | 18 +++++++++--------- awc/src/request.rs | 24 ++++++++++++------------ awc/src/sender.rs | 16 ++++++++-------- awc/src/ws.rs | 18 +++++++++--------- 19 files changed, 73 insertions(+), 73 deletions(-) diff --git a/actix-http/src/encoding/decoder.rs b/actix-http/src/encoding/decoder.rs index e9aba25e7..cda534d60 100644 --- a/actix-http/src/encoding/decoder.rs +++ b/actix-http/src/encoding/decoder.rs @@ -191,7 +191,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-gzip")] @@ -205,7 +205,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-gzip")] @@ -218,7 +218,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-zstd")] @@ -231,7 +231,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, } } @@ -250,7 +250,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-gzip")] @@ -265,7 +265,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-gzip")] @@ -280,7 +280,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, #[cfg(feature = "compress-zstd")] @@ -295,7 +295,7 @@ impl ContentDecoder { Ok(None) } } - Err(e) => Err(e), + Err(err) => Err(err), }, } } diff --git a/actix-http/src/h1/decoder.rs b/actix-http/src/h1/decoder.rs index 9e9b253d6..5c26515f7 100644 --- a/actix-http/src/h1/decoder.rs +++ b/actix-http/src/h1/decoder.rs @@ -532,7 +532,7 @@ impl Decoder for PayloadDecoder { *state = match state.step(src, size, &mut buf) { Poll::Pending => return Ok(None), Poll::Ready(Ok(state)) => state, - Poll::Ready(Err(e)) => return Err(e), + Poll::Ready(Err(err)) => return Err(err), }; if *state == ChunkedState::End { diff --git a/actix-http/src/responses/builder.rs b/actix-http/src/responses/builder.rs index 063af92da..91c69ba54 100644 --- a/actix-http/src/responses/builder.rs +++ b/actix-http/src/responses/builder.rs @@ -93,7 +93,7 @@ impl ResponseBuilder { Ok((key, value)) => { parts.headers.insert(key, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; } @@ -119,7 +119,7 @@ impl ResponseBuilder { if let Some(parts) = self.inner() { match header.try_into_pair() { Ok((key, value)) => parts.headers.append(key, value), - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; } @@ -193,7 +193,7 @@ impl ResponseBuilder { Ok(value) => { parts.headers.insert(header::CONTENT_TYPE, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; } self diff --git a/actix-http/src/ws/codec.rs b/actix-http/src/ws/codec.rs index 681649a7e..ad487e400 100644 --- a/actix-http/src/ws/codec.rs +++ b/actix-http/src/ws/codec.rs @@ -296,7 +296,7 @@ impl Decoder for Codec { } } Ok(None) => Ok(None), - Err(e) => Err(e), + Err(err) => Err(err), } } } diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index f55b1b36c..4ba64a53c 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -147,7 +147,7 @@ async fn chunked_payload() { .take_payload() .map(|res| match res { Ok(pl) => pl, - Err(e) => panic!("Error reading payload: {}", e), + Err(err) => panic!("Error reading payload: {err}"), }) .fold(0usize, |acc, chunk| ready(acc + chunk.len())) .map(|req_size| { diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 6ce3e69a1..04dbf5e17 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -775,10 +775,10 @@ where break; } Poll::Pending => break, - Poll::Ready(Some(Err(e))) => { + Poll::Ready(Some(Err(err))) => { return Poll::Ready(Some(Err(ProtocolError::Io(io::Error::new( io::ErrorKind::Other, - format!("{}", e), + format!("{err}"), ))))); } } diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 19ac6c8ae..0f874d3f8 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "actix-web" version = "4.4.0" +description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", "Rob Ede ", ] -description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" keywords = ["actix", "http", "web", "framework", "async"] categories = [ "network-programming", diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index a4cd8d819..06b66f62c 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -141,8 +141,8 @@ where let fut = data(); async move { match fut.await { - Err(e) => { - log::error!("Can not construct data instance: {:?}", e); + Err(err) => { + log::error!("Can not construct data instance: {err:?}"); Err(()) } Ok(data) => { diff --git a/actix-web/src/extract.rs b/actix-web/src/extract.rs index a2afd3827..249b56114 100644 --- a/actix-web/src/extract.rs +++ b/actix-web/src/extract.rs @@ -175,8 +175,8 @@ where let res = ready!(this.fut.poll(cx)); match res { Ok(t) => Poll::Ready(Ok(Some(t))), - Err(e) => { - log::debug!("Error for Option extractor: {}", e.into()); + Err(err) => { + log::debug!("Error for Option extractor: {}", err.into()); Poll::Ready(Ok(None)) } } @@ -217,8 +217,8 @@ where /// /// extract `Thing` from request /// async fn index(supplied_thing: Result) -> String { /// match supplied_thing { -/// Ok(thing) => format!("Got thing: {:?}", thing), -/// Err(e) => format!("Error extracting thing: {}", e) +/// Ok(thing) => format!("Got thing: {thing:?}"), +/// Err(err) => format!("Error extracting thing: {err}"), /// } /// } /// @@ -355,7 +355,7 @@ mod tuple_from_req { Poll::Ready(Ok(output)) => { let _ = this.$T.as_mut().project_replace(ExtractFuture::Done { output }); }, - Poll::Ready(Err(e)) => return Poll::Ready(Err(e.into())), + Poll::Ready(Err(err)) => return Poll::Ready(Err(err.into())), Poll::Pending => ready = false, }, ExtractProj::Done { .. } => {}, diff --git a/actix-web/src/middleware/logger.rs b/actix-web/src/middleware/logger.rs index 06d26617a..ce2caacd9 100644 --- a/actix-web/src/middleware/logger.rs +++ b/actix-web/src/middleware/logger.rs @@ -356,7 +356,7 @@ where let res = match ready!(this.fut.poll(cx)) { Ok(res) => res, - Err(e) => return Poll::Ready(Err(e)), + Err(err) => return Poll::Ready(Err(err)), }; if let Some(error) = res.response().error() { diff --git a/actix-web/src/response/builder.rs b/actix-web/src/response/builder.rs index 2c06941cd..28a0adffd 100644 --- a/actix-web/src/response/builder.rs +++ b/actix-web/src/response/builder.rs @@ -64,7 +64,7 @@ impl HttpResponseBuilder { Ok((key, value)) => { parts.headers.insert(key, value); } - Err(e) => self.error = Some(e.into()), + Err(err) => self.error = Some(err.into()), }; } @@ -86,7 +86,7 @@ impl HttpResponseBuilder { if let Some(parts) = self.inner() { match header.try_into_pair() { Ok((key, value)) => parts.headers.append(key, value), - Err(e) => self.error = Some(e.into()), + Err(err) => self.error = Some(err.into()), }; } @@ -210,7 +210,7 @@ impl HttpResponseBuilder { Ok(value) => { parts.headers.insert(header::CONTENT_TYPE, value); } - Err(e) => self.error = Some(e.into()), + Err(err) => self.error = Some(err.into()), }; } self diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 879b269a0..e92985d39 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -853,7 +853,7 @@ fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result err = Some(e), + Err(error) => err = Some(error), } } diff --git a/actix-web/src/types/header.rs b/actix-web/src/types/header.rs index 8b1740e6c..977dc032e 100644 --- a/actix-web/src/types/header.rs +++ b/actix-web/src/types/header.rs @@ -2,7 +2,7 @@ use std::{fmt, ops}; -use actix_utils::future::{err, ok, Ready}; +use actix_utils::future::{ready, Ready}; use crate::{ dev::Payload, error::ParseError, extract::FromRequest, http::header::Header as ParseHeader, @@ -66,8 +66,8 @@ where #[inline] fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { match ParseHeader::parse(req) { - Ok(header) => ok(Header(header)), - Err(e) => err(e), + Ok(header) => ready(Ok(Header(header))), + Err(err) => ready(Err(err)), } } } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index de39e1a4a..879d1895b 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -909,8 +909,8 @@ mod resolver { None => { let (cfg, opts) = match read_system_conf() { Ok((cfg, opts)) => (cfg, opts), - Err(e) => { - log::error!("TRust-DNS can not load system config: {}", e); + Err(err) => { + log::error!("Trust-DNS can not load system config: {err}"); (ResolverConfig::default(), ResolverOpts::default()) } }; diff --git a/awc/src/client/h1proto.rs b/awc/src/client/h1proto.rs index c756179a4..3f4c9f979 100644 --- a/awc/src/client/h1proto.rs +++ b/awc/src/client/h1proto.rs @@ -56,7 +56,7 @@ where headers.insert(HOST, value); } }, - Err(e) => log::error!("Can not set HOST header {}", e), + Err(err) => log::error!("Can not set HOST header {err}"), } } } diff --git a/awc/src/client/h2proto.rs b/awc/src/client/h2proto.rs index d18db1410..c3f801f20 100644 --- a/awc/src/client/h2proto.rs +++ b/awc/src/client/h2proto.rs @@ -106,9 +106,9 @@ where } let res = poll_fn(|cx| io.poll_ready(cx)).await; - if let Err(e) = res { - io.on_release(e.is_io()); - return Err(SendRequestError::from(e)); + if let Err(err) = res { + io.on_release(err.is_io()); + return Err(SendRequestError::from(err)); } let resp = match io.send_request(req, eof) { @@ -120,9 +120,9 @@ where } fut.await.map_err(SendRequestError::from)? } - Err(e) => { - io.on_release(e.is_io()); - return Err(e.into()); + Err(err) => { + io.on_release(err.is_io()); + return Err(err.into()); } }; @@ -169,8 +169,8 @@ where let len = b.len(); let bytes = b.split_to(std::cmp::min(cap, len)); - if let Err(e) = send.send_data(bytes, false) { - return Err(e.into()); + if let Err(err) = send.send_data(bytes, false) { + return Err(err.into()); } if !b.is_empty() { send.reserve_capacity(b.len()); @@ -179,7 +179,7 @@ where } continue; } - Some(Err(e)) => return Err(e.into()), + Some(Err(err)) => return Err(err.into()), } } } diff --git a/awc/src/request.rs b/awc/src/request.rs index 4e34e5771..28ed8b5f5 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -83,7 +83,7 @@ impl ClientRequest { { match Uri::try_from(uri) { Ok(uri) => self.head.uri = uri, - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } @@ -152,7 +152,7 @@ impl ClientRequest { Ok((key, value)) => { self.head.headers.insert(key, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; self @@ -166,7 +166,7 @@ impl ClientRequest { self.head.headers.insert(key, value); } } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; self @@ -185,7 +185,7 @@ impl ClientRequest { pub fn append_header(mut self, header: impl TryIntoHeaderPair) -> Self { match header.try_into_pair() { Ok((key, value)) => self.head.headers.append(key, value), - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }; self @@ -217,7 +217,7 @@ impl ClientRequest { Ok(value) => { self.head.headers.insert(header::CONTENT_TYPE, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } @@ -299,7 +299,7 @@ impl ClientRequest { match Uri::from_parts(parts) { Ok(uri) => self.head.uri = uri, - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } } @@ -311,7 +311,7 @@ impl ClientRequest { pub fn freeze(self) -> Result { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return Err(e.into()), + Err(err) => return Err(err.into()), }; let request = FrozenClientRequest { @@ -332,7 +332,7 @@ impl ClientRequest { { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return e.into(), + Err(err) => return err.into(), }; RequestSender::Owned(slf.head).send_body( @@ -348,7 +348,7 @@ impl ClientRequest { pub fn send_json(self, value: &T) -> SendClientRequest { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return e.into(), + Err(err) => return err.into(), }; RequestSender::Owned(slf.head).send_json( @@ -366,7 +366,7 @@ impl ClientRequest { pub fn send_form(self, value: &T) -> SendClientRequest { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return e.into(), + Err(err) => return err.into(), }; RequestSender::Owned(slf.head).send_form( @@ -386,7 +386,7 @@ impl ClientRequest { { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return e.into(), + Err(err) => return err.into(), }; RequestSender::Owned(slf.head).send_stream( @@ -402,7 +402,7 @@ impl ClientRequest { pub fn send(self) -> SendClientRequest { let slf = match self.prep_for_sending() { Ok(slf) => slf, - Err(e) => return e.into(), + Err(err) => return err.into(), }; RequestSender::Owned(slf.head).send( diff --git a/awc/src/sender.rs b/awc/src/sender.rs index c2191d11b..8de1033a3 100644 --- a/awc/src/sender.rs +++ b/awc/src/sender.rs @@ -122,8 +122,8 @@ impl Future for SendClientRequest { Poll::Ready(res) } - SendClientRequest::Err(ref mut e) => match e.take() { - Some(e) => Poll::Ready(Err(e)), + SendClientRequest::Err(ref mut err) => match err.take() { + Some(err) => Poll::Ready(Err(err)), None => panic!("Attempting to call completed future"), }, } @@ -147,8 +147,8 @@ impl Future for SendClientRequest { .poll(cx) .map_ok(|res| res.into_client_response()._timeout(delay.take())) } - SendClientRequest::Err(ref mut e) => match e.take() { - Some(e) => Poll::Ready(Err(e)), + SendClientRequest::Err(ref mut err) => match err.take() { + Some(err) => Poll::Ready(Err(err)), None => panic!("Attempting to call completed future"), }, } @@ -219,8 +219,8 @@ impl RequestSender { Err(err) => return PrepForSendingError::Json(err).into(), }; - if let Err(e) = self.set_header_if_none(header::CONTENT_TYPE, "application/json") { - return e.into(); + if let Err(err) = self.set_header_if_none(header::CONTENT_TYPE, "application/json") { + return err.into(); } self.send_body(addr, response_decompress, timeout, config, body) @@ -291,7 +291,7 @@ impl RequestSender { Ok(value) => { head.headers.insert(key, value); } - Err(e) => return Err(e.into()), + Err(err) => return Err(err.into()), } } } @@ -304,7 +304,7 @@ impl RequestSender { let h = extra_headers.get_or_insert(HeaderMap::new()); h.insert(key, v) } - Err(e) => return Err(e.into()), + Err(err) => return Err(err.into()), }; } } diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 836ff2024..c3340206d 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -64,7 +64,7 @@ pub struct WebsocketsRequest { } impl WebsocketsRequest { - /// Create new WebSocket connection + /// Create new WebSocket connection. pub(crate) fn new(uri: U, config: ClientConfig) -> Self where Uri: TryFrom, @@ -82,7 +82,7 @@ impl WebsocketsRequest { match Uri::try_from(uri) { Ok(uri) => head.uri = uri, - Err(e) => err = Some(e.into()), + Err(error) => err = Some(error.into()), } WebsocketsRequest { @@ -143,7 +143,7 @@ impl WebsocketsRequest { { match HeaderValue::try_from(origin) { Ok(value) => self.origin = Some(value), - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } @@ -177,9 +177,9 @@ impl WebsocketsRequest { Ok(value) => { self.head.headers.append(key, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }, - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } @@ -196,9 +196,9 @@ impl WebsocketsRequest { Ok(value) => { self.head.headers.insert(key, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), }, - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } @@ -217,11 +217,11 @@ impl WebsocketsRequest { Ok(value) => { self.head.headers.insert(key, value); } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } } } - Err(e) => self.err = Some(e.into()), + Err(err) => self.err = Some(err.into()), } self } From a7983351be4aeebfa2baba7e6a8c3a765a25b785 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 12 Sep 2023 04:45:36 +0100 Subject: [PATCH 118/314] docs: fix Data doc --- .github/dependabot.yml | 14 ++++++-------- actix-web/src/data.rs | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1a54090f0..23f6c3ea8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,12 +1,10 @@ version: 2 updates: - - package-ecosystem: "cargo" - directory: "/" + - package-ecosystem: cargo + directory: / schedule: - interval: "monthly" - open-pull-requests-limit: 10 - - package-ecosystem: "github-actions" - directory: "/" + interval: weekly + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" - open-pull-requests-limit: 10 + interval: daily diff --git a/actix-web/src/data.rs b/actix-web/src/data.rs index 449a24a64..ebb98af3f 100644 --- a/actix-web/src/data.rs +++ b/actix-web/src/data.rs @@ -32,8 +32,8 @@ pub(crate) type FnDataFactory = /// Since the Actix Web router layers application data, the returned object will reference the /// "closest" instance of the type. For example, if an `App` stores a `u32`, a nested `Scope` /// also stores a `u32`, and the delegated request handler falls within that `Scope`, then -/// extracting a `web::>` for that handler will return the `Scope`'s instance. -/// However, using the same router set up and a request that does not get captured by the `Scope`, +/// extracting a `web::Data` for that handler will return the `Scope`'s instance. However, +/// using the same router set up and a request that does not get captured by the `Scope`, /// `web::>` would return the `App`'s instance. /// /// If route data is not set for a handler, using `Data` extractor would cause a `500 Internal From d50eccb3f7cdec186b7c9398258748cb91395231 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 12 Sep 2023 05:16:41 +0100 Subject: [PATCH 119/314] ci: workaround anstyle msrv --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f071ec8f3..2d5c879dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,10 +53,11 @@ jobs: uses: taiki-e/install-action@cargo-hack - name: workaround MSRV issues - if: matrix.version.name != 'stable' + if: matrix.version.name == 'msrv' run: | cargo update -p=clap --precise=4.3.24 cargo update -p=clap_lex --precise=0.5.0 + cargo update -p=anstyle --precise=1.0.2 - name: check minimal run: cargo ci-check-min From 81ac30f3df37c9dee69decb89fe2e80ad55217e7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 12 Sep 2023 05:24:55 +0100 Subject: [PATCH 120/314] ci: overspecify actions versions --- .github/workflows/ci-post-merge.yml | 18 ++++++++++----- .github/workflows/ci.yml | 16 ++++++++----- .github/workflows/clippy-fmt.yml | 36 +++++++++++++++++------------ .github/workflows/coverage.yml | 1 + .github/workflows/upload-doc.yml | 10 ++++---- 5 files changed, 50 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index a34dd27ba..7acb2b73f 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -40,12 +40,14 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@cargo-hack + uses: taiki-e/install-action@v2.18.9 + with: + tool: cargo-hack - name: check minimal run: cargo ci-check-min @@ -80,10 +82,12 @@ jobs: - uses: actions/checkout@v3 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@cargo-hack + uses: taiki-e/install-action@v2.18.9 + with: + tool: cargo-hack - name: check feature combinations run: cargo ci-check-all-feature-powerset @@ -99,10 +103,12 @@ jobs: - uses: actions/checkout@v3 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@nextest + uses: taiki-e/install-action@v2.18.9 + with: + tool: nextest - name: Test with cargo-nextest run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d5c879dd..c079e10c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,12 +45,14 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@cargo-hack + uses: taiki-e/install-action@v2.18.9 + with: + tool: cargo-hack - name: workaround MSRV issues if: matrix.version.name == 'msrv' @@ -91,8 +93,9 @@ jobs: - uses: actions/checkout@v3 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { toolchain: nightly } + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + toolchain: nightly - name: tests (io-uring) timeout-minutes: 60 @@ -106,8 +109,9 @@ jobs: - uses: actions/checkout@v3 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { toolchain: nightly } + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + toolchain: nightly - name: doc tests run: cargo ci-doctest diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 25c05bcbc..19b4fe6a3 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -5,7 +5,7 @@ on: types: [opened, synchronize, reopened] permissions: - contents: read # to fetch code (actions/checkout) + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions-rust-lang/setup-rust-toolchain@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: toolchain: nightly components: rustfmt @@ -32,12 +32,13 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { components: clippy } - - - uses: giraffate/clippy-action@v1 + - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: - reporter: 'github-pr-check' + components: clippy + + - uses: giraffate/clippy-action@v1.0.1 + with: + reporter: github-pr-check github_token: ${{ secrets.GITHUB_TOKEN }} clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints @@ -46,12 +47,15 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { components: rust-docs } + - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + toolchain: nightly + components: rust-docs - name: Check for broken intra-doc links - env: { RUSTDOCFLAGS: "-D warnings" } - run: cargo doc --no-deps --all-features --workspace + env: + RUSTDOCFLAGS: -D warnings + run: cargo +nightly doc --no-deps --workspace --all-features public-api-diff: runs-on: ubuntu-latest @@ -62,11 +66,13 @@ jobs: - uses: actions/checkout@v3 - - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: { toolchain: nightly-2023-08-25 } + - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + toolchain: nightly-2023-08-25 - - uses: taiki-e/cache-cargo-install-action@v1 - with: { tool: cargo-public-api } + - uses: taiki-e/cache-cargo-install-action@v1.2.1 + with: + tool: cargo-public-api - name: generate API diff run: | diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 1feae0432..de31907a9 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -16,6 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 05b81411d..0efe36816 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -5,8 +5,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) - + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -14,14 +13,17 @@ concurrency: jobs: build: permissions: - contents: write # to push changes in repo (jamesives/github-pages-deploy-action) + contents: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: dtolnay/rust-toolchain@nightly + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + with: + toolchain: nightly - name: Build Docs run: cargo +nightly doc --no-deps --workspace --all-features From 835a57afc61584feecfb73fe0865ccd0b4758ee4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 04:44:47 +0000 Subject: [PATCH 121/314] build(deps): bump actions/checkout from 3 to 4 (#3130) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/bench.yml | 2 +- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 6 +++--- .github/workflows/clippy-fmt.yml | 10 +++++----- .github/workflows/coverage.yml | 2 +- .github/workflows/upload-doc.yml | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index f0e4cc8b3..910cb24b9 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust run: | diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 7acb2b73f..9f205410e 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -28,7 +28,7 @@ jobs: runs-on: ${{ matrix.target.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install OpenSSL if: matrix.target.os == 'windows-latest' @@ -79,7 +79,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 @@ -100,7 +100,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c079e10c9..4c4977ac8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: runs-on: ${{ matrix.target.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install OpenSSL if: matrix.target.os == 'windows-latest' @@ -90,7 +90,7 @@ jobs: name: io-uring tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 @@ -106,7 +106,7 @@ jobs: name: doc tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust (nightly) uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 19b4fe6a3..4146e5661 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -15,7 +15,7 @@ jobs: fmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: @@ -45,7 +45,7 @@ jobs: lint-docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: @@ -60,11 +60,11 @@ jobs: public-api-diff: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.base_ref }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index de31907a9..6fc1eabb0 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -15,7 +15,7 @@ jobs: coverage: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 0efe36816..2037e34f5 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 From e1c48dba267ff0321f22fc7c6e4a4916a2408961 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 01:06:53 +0000 Subject: [PATCH 122/314] build(deps): bump taiki-e/install-action from 2.13.4 to 2.18.9 (#3133) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.13.4 to 2.18.9. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.13.4...v2.18.9) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6fc1eabb0..a516f1c29 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.13.4 + uses: taiki-e/install-action@v2.18.9 with: tool: cargo-llvm-cov From 043bc88f73f07a15a39e072e1130caf0ba84ab2c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 15 Sep 2023 22:20:43 +0100 Subject: [PATCH 123/314] docs: add note about rt::spawn compat with tokio::main --- actix-web/src/rt.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/actix-web/src/rt.rs b/actix-web/src/rt.rs index 629ffe3a0..e370e2c0b 100644 --- a/actix-web/src/rt.rs +++ b/actix-web/src/rt.rs @@ -5,6 +5,7 @@ //! architecture in [`actix-rt`]'s docs. //! //! # Running Actix Web Without Macros +//! //! ```no_run //! use actix_web::{middleware, rt, web, App, HttpRequest, HttpServer}; //! @@ -25,6 +26,7 @@ //! ``` //! //! # Running Actix Web Using `#[tokio::main]` +//! //! If you need to run something that uses Tokio's work stealing functionality alongside Actix Web, //! you can run Actix Web under `#[tokio::main]`. The [`Server`](crate::dev::Server) object returned //! from [`HttpServer::run`](crate::HttpServer::run) can also be [`spawn`]ed, if preferred. @@ -32,6 +34,10 @@ //! Note that `actix` actor support (and therefore WebSocket support through `actix-web-actors`) //! still require `#[actix_web::main]` since they require a [`System`] to be set up. //! +//! Also note that calls to this module's [`spawn()`] re-export require an `#[actix_web::main]` +//! runtime (or a manually configured `LocalSet`) since it makes calls into to the current thread's +//! `LocalSet`, which `#[tokio::main]` does not set up. +//! //! ```no_run //! use actix_web::{get, middleware, rt, web, App, HttpRequest, HttpServer}; //! From b28e0fff4b598200a801572c862f5cdb500cde1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 01:15:19 +0000 Subject: [PATCH 124/314] build(deps): bump taiki-e/install-action from 2.18.9 to 2.18.13 (#3138) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.18.9 to 2.18.13. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.18.9...v2.18.13) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 9f205410e..713be92d6 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.9 + uses: taiki-e/install-action@v2.18.13 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.9 + uses: taiki-e/install-action@v2.18.13 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.18.9 + uses: taiki-e/install-action@v2.18.13 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c4977ac8..ad92c8a0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.9 + uses: taiki-e/install-action@v2.18.13 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a516f1c29..e4daf3328 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.18.9 + uses: taiki-e/install-action@v2.18.13 with: tool: cargo-llvm-cov From 801a51b3125bc8d14bf2c6f9fc363cf97be74577 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 01:17:47 +0000 Subject: [PATCH 125/314] build(deps): bump taiki-e/cache-cargo-install-action from 1.2.1 to 1.2.2 (#3139) Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/taiki-e/cache-cargo-install-action/releases) - [Changelog](https://github.com/taiki-e/cache-cargo-install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/cache-cargo-install-action/compare/v1.2.1...v1.2.2) --- updated-dependencies: - dependency-name: taiki-e/cache-cargo-install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/clippy-fmt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 4146e5661..084b88b24 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -70,7 +70,7 @@ jobs: with: toolchain: nightly-2023-08-25 - - uses: taiki-e/cache-cargo-install-action@v1.2.1 + - uses: taiki-e/cache-cargo-install-action@v1.2.2 with: tool: cargo-public-api From 8bd4b36ffe9b5c1283b8b4cb13926536c920c352 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 05:36:18 +0100 Subject: [PATCH 126/314] build(deps): bump taiki-e/install-action from 2.18.13 to 2.18.14 (#3142) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.18.13 to 2.18.14. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.18.13...v2.18.14) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 713be92d6..7de8e297a 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.13 + uses: taiki-e/install-action@v2.18.14 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.13 + uses: taiki-e/install-action@v2.18.14 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.18.13 + uses: taiki-e/install-action@v2.18.14 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad92c8a0c..f277fe80e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.13 + uses: taiki-e/install-action@v2.18.14 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index e4daf3328..930a92093 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.18.13 + uses: taiki-e/install-action@v2.18.14 with: tool: cargo-llvm-cov From 13fed45bfaa2c66885c535e7af91c2fbecda39e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Sep 2023 02:28:45 +0100 Subject: [PATCH 127/314] build(deps): bump taiki-e/install-action from 2.18.14 to 2.18.16 (#3144) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.18.14 to 2.18.16. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.18.14...v2.18.16) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 7de8e297a..28f594f15 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.14 + uses: taiki-e/install-action@v2.18.16 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.14 + uses: taiki-e/install-action@v2.18.16 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.18.14 + uses: taiki-e/install-action@v2.18.16 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f277fe80e..1cbe438d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.14 + uses: taiki-e/install-action@v2.18.16 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 930a92093..208dd65ca 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.18.14 + uses: taiki-e/install-action@v2.18.16 with: tool: cargo-llvm-cov From ccabcd83c0466cb96cad56b769cb45fd98d7da6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 02:25:32 +0100 Subject: [PATCH 128/314] build(deps): bump taiki-e/install-action from 2.18.16 to 2.18.17 (#3149) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.18.16 to 2.18.17. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.18.16...v2.18.17) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 28f594f15..e38c9cc25 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.16 + uses: taiki-e/install-action@v2.18.17 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.16 + uses: taiki-e/install-action@v2.18.17 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.18.16 + uses: taiki-e/install-action@v2.18.17 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cbe438d7..69eaf2b90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.16 + uses: taiki-e/install-action@v2.18.17 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 208dd65ca..f7eccad95 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.18.16 + uses: taiki-e/install-action@v2.18.17 with: tool: cargo-llvm-cov From 2cfe257fc25f82b1fc5a79e44b62addfbe028f9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Sep 2023 02:58:58 +0100 Subject: [PATCH 129/314] build(deps): bump taiki-e/install-action from 2.18.17 to 2.19.1 (#3151) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.18.17 to 2.19.1. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.18.17...v2.19.1) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index e38c9cc25..de85fe166 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.17 + uses: taiki-e/install-action@v2.19.1 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.17 + uses: taiki-e/install-action@v2.19.1 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.18.17 + uses: taiki-e/install-action@v2.19.1 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69eaf2b90..231ef5585 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.18.17 + uses: taiki-e/install-action@v2.19.1 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f7eccad95..19477b258 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.18.17 + uses: taiki-e/install-action@v2.19.1 with: tool: cargo-llvm-cov From 55ddded3159c78a384ab7f2ab963d694d161a6db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 00:43:19 +0000 Subject: [PATCH 130/314] build(deps): bump taiki-e/install-action from 2.19.1 to 2.19.2 (#3154) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.19.1 to 2.19.2. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.19.1...v2.19.2) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index de85fe166..10d40f9c4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.1 + uses: taiki-e/install-action@v2.19.2 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.1 + uses: taiki-e/install-action@v2.19.2 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.19.1 + uses: taiki-e/install-action@v2.19.2 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 231ef5585..59fc21f2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.1 + uses: taiki-e/install-action@v2.19.2 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 19477b258..50ef53cf7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.19.1 + uses: taiki-e/install-action@v2.19.2 with: tool: cargo-llvm-cov From f1c9b93b8780eb853531b737fd9399c166a7c8a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:45:32 +0100 Subject: [PATCH 131/314] build(deps): bump taiki-e/install-action from 2.19.2 to 2.19.3 (#3156) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.19.2 to 2.19.3. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.19.2...v2.19.3) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 10d40f9c4..b8449d2ec 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.2 + uses: taiki-e/install-action@v2.19.3 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.2 + uses: taiki-e/install-action@v2.19.3 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.19.2 + uses: taiki-e/install-action@v2.19.3 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 59fc21f2e..2bcb7b142 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.2 + uses: taiki-e/install-action@v2.19.3 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 50ef53cf7..556db45fc 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.19.2 + uses: taiki-e/install-action@v2.19.3 with: tool: cargo-llvm-cov From 76a0385f9428d5cc416f5ac9800ce7789d802067 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 02:51:36 +0100 Subject: [PATCH 132/314] build(deps): bump taiki-e/install-action from 2.19.3 to 2.19.4 (#3159) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index b8449d2ec..59a7cbe41 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.3 + uses: taiki-e/install-action@v2.19.4 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.3 + uses: taiki-e/install-action@v2.19.4 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.19.3 + uses: taiki-e/install-action@v2.19.4 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bcb7b142..2e5a79577 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.3 + uses: taiki-e/install-action@v2.19.4 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 556db45fc..a8267a0e6 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.19.3 + uses: taiki-e/install-action@v2.19.4 with: tool: cargo-llvm-cov From fba766b4beb92278665d58815c94d336015225c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 02:48:46 +0100 Subject: [PATCH 133/314] build(deps): bump taiki-e/install-action from 2.19.4 to 2.20.1 (#3160) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.19.4 to 2.20.1. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.19.4...v2.20.1) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 59a7cbe41..c9692e8e2 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.4 + uses: taiki-e/install-action@v2.20.1 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.4 + uses: taiki-e/install-action@v2.20.1 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.19.4 + uses: taiki-e/install-action@v2.20.1 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e5a79577..66e0bdbf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.19.4 + uses: taiki-e/install-action@v2.20.1 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a8267a0e6..fb16a4b61 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.19.4 + uses: taiki-e/install-action@v2.20.1 with: tool: cargo-llvm-cov From 05b4c4964f2b26e44bc1cd95409ef92018f59fd8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 11 Oct 2023 16:07:15 +0200 Subject: [PATCH 134/314] update handler failure mode docs --- actix-web/src/handler.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/actix-web/src/handler.rs b/actix-web/src/handler.rs index 3d6b7f039..6e4e2250a 100644 --- a/actix-web/src/handler.rs +++ b/actix-web/src/handler.rs @@ -10,10 +10,12 @@ use crate::{ /// The interface for request handlers. /// /// # What Is A Request Handler +/// /// In short, a handler is just an async function that receives request-based arguments, in any /// order, and returns something that can be converted to a response. /// /// In particular, a request handler has three requirements: +/// /// 1. It is an async function (or a function/closure that returns an appropriate future); /// 1. The function parameters (up to 12) implement [`FromRequest`]; /// 1. The async function (or future) resolves to a type that can be converted into an @@ -21,11 +23,15 @@ use crate::{ /// /// /// # Compiler Errors +/// /// If you get the error `the trait Handler<_> is not implemented`, then your handler does not -/// fulfill the _first_ of the above requirements. Missing other requirements manifest as errors on -/// implementing [`FromRequest`] and [`Responder`], respectively. +/// fulfill the _first_ of the above requirements. (It could also mean that you're attempting to use +/// a macro-routed handler in a manual routing context like `web::get().to(handler)`, which is not +/// supported). Breaking the other requirements manifests as errors on implementing [`FromRequest`] +/// and [`Responder`], respectively. /// /// # How Do Handlers Receive Variable Numbers Of Arguments +/// /// Rest assured there is no macro magic here; it's just traits. /// /// The first thing to note is that [`FromRequest`] is implemented for tuples (up to 12 in length). @@ -40,6 +46,7 @@ use crate::{ /// destructures the tuple into its component types and calls your handler function with them. /// /// In pseudo-code the process looks something like this: +/// /// ```ignore /// async fn my_handler(body: String, state: web::Data) -> impl Responder { /// ... From 935d36c4410f5a745b17d7793965ec5e230a29e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 09:41:10 +0100 Subject: [PATCH 135/314] build(deps): bump taiki-e/install-action from 2.20.1 to 2.20.2 (#3163) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.20.1 to 2.20.2. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.20.1...v2.20.2) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index c9692e8e2..56749dd9c 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.1 + uses: taiki-e/install-action@v2.20.2 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.1 + uses: taiki-e/install-action@v2.20.2 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.20.1 + uses: taiki-e/install-action@v2.20.2 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66e0bdbf5..65a070869 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.1 + uses: taiki-e/install-action@v2.20.2 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index fb16a4b61..f5c4c07eb 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.20.1 + uses: taiki-e/install-action@v2.20.2 with: tool: cargo-llvm-cov From 3acdda48e0e5440d426cc81602201b2f1104662f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 13 Oct 2023 17:41:21 +0200 Subject: [PATCH 136/314] ci: reduce dependabot rate for Cargo updater --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 23f6c3ea8..c7ecf5eaa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,4 +7,4 @@ updates: - package-ecosystem: github-actions directory: / schedule: - interval: daily + interval: weekly From 3193b81a3e2d8adc1b8741d51d25d24b21273abf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 01:21:06 +0000 Subject: [PATCH 137/314] build(deps): bump taiki-e/install-action from 2.20.2 to 2.20.14 (#3173) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.20.2 to 2.20.14. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.20.2...v2.20.14) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 56749dd9c..6db41efdd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.2 + uses: taiki-e/install-action@v2.20.14 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.2 + uses: taiki-e/install-action@v2.20.14 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.20.2 + uses: taiki-e/install-action@v2.20.14 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65a070869..418ca5a73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.2 + uses: taiki-e/install-action@v2.20.14 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f5c4c07eb..ddfc2fe03 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.20.2 + uses: taiki-e/install-action@v2.20.14 with: tool: cargo-llvm-cov From 9e51116da21c3c1320fc9f2fd65b4c79332dc138 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 29 Oct 2023 01:53:03 +0000 Subject: [PATCH 138/314] chore: remove unusable re-export --- actix-web/src/response/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/actix-web/src/response/mod.rs b/actix-web/src/response/mod.rs index 11fd28301..16bdc619c 100644 --- a/actix-web/src/response/mod.rs +++ b/actix-web/src/response/mod.rs @@ -5,8 +5,6 @@ mod responder; #[allow(clippy::module_inception)] mod response; -#[cfg(feature = "cookies")] -pub use self::response::CookieIter; pub use self::{ builder::HttpResponseBuilder, customize_responder::CustomizeResponder, responder::Responder, response::HttpResponse, From d3d0208cbd6cbbd7c92f1b1bcbf6784662de6a0a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 29 Oct 2023 01:56:10 +0000 Subject: [PATCH 139/314] chore: fmt workflows --- .github/workflows/bench.yml | 2 +- .github/workflows/upload-doc.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 910cb24b9..fd6bc6d73 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -5,7 +5,7 @@ on: branches: [master] permissions: - contents: read # to fetch code (actions/checkout) + contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 2037e34f5..7dcc8255c 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -6,6 +6,7 @@ on: permissions: contents: read + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true From ce18f35e0344bee88d4422b5ccb81c23523ddb75 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 29 Oct 2023 18:48:03 +0000 Subject: [PATCH 140/314] docs: improve HttpServer docs on worker / bind relationship wrt factory instantiations --- actix-web/src/server.rs | 53 ++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index e92985d39..2cc00cb9f 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -99,6 +99,12 @@ where B: MessageBody + 'static, { /// Create new HTTP server with application factory + /// + /// # Worker Count + /// + /// The `factory` will be instantiated multiple times in most configurations. See + /// [`bind()`](Self::bind()) docs for more on how worker count and bind address resolution + /// causes multiple server factory instantiations. pub fn new(factory: F) -> Self { HttpServer { factory, @@ -119,7 +125,18 @@ where /// Sets number of workers to start (per bind address). /// - /// By default, the number of available physical CPUs is used as the worker count. + /// The default worker count is the determined by [`std::thread::available_parallelism()`]. See + /// its documentation to determine what behavior you should expect when server is run. + /// + /// Note that the server factory passed to [`new`](Self::new()) will be instantiated **at least + /// once per worker**. See [`bind()`](Self::bind()) docs for more on how worker count and bind + /// address resolution causes multiple server factory instantiations. + /// + /// `num` must be greater than 0. + /// + /// # Panics + /// + /// Panics if `num` is 0. pub fn workers(mut self, num: usize) -> Self { self.builder = self.builder.workers(num); self @@ -319,23 +336,41 @@ where /// Resolves socket address(es) and binds server to created listener(s). /// /// # Hostname Resolution - /// When `addr` includes a hostname, it is possible for this method to bind to both the IPv4 and - /// IPv6 addresses that result from a DNS lookup. You can test this by passing `localhost:8080` - /// and noting that the server binds to `127.0.0.1:8080` _and_ `[::1]:8080`. To bind additional - /// addresses, call this method multiple times. + /// + /// When `addrs` includes a hostname, it is possible for this method to bind to both the IPv4 + /// and IPv6 addresses that result from a DNS lookup. You can test this by passing + /// `localhost:8080` and noting that the server binds to `127.0.0.1:8080` _and_ `[::1]:8080`. To + /// bind additional addresses, call this method multiple times. /// /// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation. /// + /// # Worker Count + /// + /// The `factory` will be instantiated multiple times in most scenarios. The number of + /// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by + /// `addrs`. + /// + /// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1` + /// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost` + /// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing + /// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses). + /// + /// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple + /// the number of instantiations in a similar way. + /// /// # Typical Usage + /// /// In general, use `127.0.0.1:` when testing locally and `0.0.0.0:` when deploying /// (with or without a reverse proxy or load balancer) so that the server is accessible. /// /// # Errors + /// /// Returns an `io::Error` if: /// - `addrs` cannot be resolved into one or more socket addresses; /// - all the resolved socket addresses are already bound. /// /// # Example + /// /// ``` /// # use actix_web::{App, HttpServer}; /// # fn inner() -> std::io::Result<()> { @@ -356,6 +391,8 @@ where /// Resolves socket address(es) and binds server to created listener(s) for plaintext HTTP/1.x /// or HTTP/2 connections. + /// + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. #[cfg(feature = "http2")] pub fn bind_auto_h2c(mut self, addrs: A) -> io::Result { let sockets = bind_addrs(addrs, self.backlog)?; @@ -370,7 +407,7 @@ where /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using Rustls v0.20. /// - /// See [`bind()`](Self::bind) for more details on `addrs` argument. + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls-0_20")] @@ -389,7 +426,7 @@ where /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using Rustls v0.21. /// - /// See [`bind()`](Self::bind) for more details on `addrs` argument. + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls-0_21")] @@ -408,7 +445,7 @@ where /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using OpenSSL. /// - /// See [`bind()`](Self::bind) for more details on `addrs` argument. + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "openssl")] From 32ddf972c6be7221b190dbdff43d5d082a334cbd Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 30 Oct 2023 00:03:22 +0000 Subject: [PATCH 141/314] docs: add guarded-listings example --- actix-files/Cargo.toml | 1 + actix-files/examples/guarded-listing.rs | 33 +++++++++++++++++++++++++ actix-files/src/files.rs | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 actix-files/examples/guarded-listing.rs diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 80c609d1d..efecb0889 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -47,4 +47,5 @@ actix-server = { version = "2.2", optional = true } # ensure matching tokio-urin actix-rt = "2.7" actix-test = "0.1" actix-web = "4" +env_logger = "0.10" tempfile = "3.2" diff --git a/actix-files/examples/guarded-listing.rs b/actix-files/examples/guarded-listing.rs new file mode 100644 index 000000000..e8cde0c85 --- /dev/null +++ b/actix-files/examples/guarded-listing.rs @@ -0,0 +1,33 @@ +use actix_files::Files; +use actix_web::{get, guard, middleware, App, HttpServer, Responder}; + +const EXAMPLES_DIR: &str = concat![env!("CARGO_MANIFEST_DIR"), "/examples"]; + +#[get("/")] +async fn index() -> impl Responder { + "Hello world!" +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + log::info!("starting HTTP server at http://localhost:8080"); + + HttpServer::new(|| { + App::new() + .service(index) + .service( + Files::new("/assets", EXAMPLES_DIR) + .show_files_listing() + .guard(guard::Header("show-listing", "?1")), + ) + .service(Files::new("/assets", EXAMPLES_DIR)) + .wrap(middleware::Compress::default()) + .wrap(middleware::Logger::default()) + }) + .bind(("127.0.0.1", 8080))? + .workers(2) + .run() + .await +} diff --git a/actix-files/src/files.rs b/actix-files/src/files.rs index e34b5f26a..cfd3b9c22 100644 --- a/actix-files/src/files.rs +++ b/actix-files/src/files.rs @@ -235,7 +235,7 @@ impl Files { /// request starts being handled by the file service, it will not be able to back-out and try /// the next service, you will simply get a 404 (or 405) error response. /// - /// To allow `POST` requests to retrieve files, see [`Files::use_guards`]. + /// To allow `POST` requests to retrieve files, see [`Files::method_guard()`]. /// /// # Examples /// ``` From 40196f16be819e58c185069b4b1b3fd24f97694c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 00:05:50 +0000 Subject: [PATCH 142/314] build(deps): bump taiki-e/cache-cargo-install-action from 1.2.2 to 1.3.0 (#3167) Bumps [taiki-e/cache-cargo-install-action](https://github.com/taiki-e/cache-cargo-install-action) from 1.2.2 to 1.3.0. - [Release notes](https://github.com/taiki-e/cache-cargo-install-action/releases) - [Changelog](https://github.com/taiki-e/cache-cargo-install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/cache-cargo-install-action/compare/v1.2.2...v1.3.0) --- updated-dependencies: - dependency-name: taiki-e/cache-cargo-install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/clippy-fmt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml index 084b88b24..854944995 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/clippy-fmt.yml @@ -70,7 +70,7 @@ jobs: with: toolchain: nightly-2023-08-25 - - uses: taiki-e/cache-cargo-install-action@v1.2.2 + - uses: taiki-e/cache-cargo-install-action@v1.3.0 with: tool: cargo-public-api From 3b8d4de0e04dcd97bd430868fe697d0ba713235a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:12:42 +0000 Subject: [PATCH 143/314] build(deps): bump taiki-e/install-action from 2.20.14 to 2.21.3 (#3179) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.20.14 to 2.21.3. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.20.14...v2.21.3) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 6db41efdd..cb3ea77ca 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.14 + uses: taiki-e/install-action@v2.21.3 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.14 + uses: taiki-e/install-action@v2.21.3 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.20.14 + uses: taiki-e/install-action@v2.21.3 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 418ca5a73..ca9673da4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.20.14 + uses: taiki-e/install-action@v2.21.3 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ddfc2fe03..73931c238 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.20.14 + uses: taiki-e/install-action@v2.21.3 with: tool: cargo-llvm-cov From b78f6da05f16de9c8f6bf20b377daa964904ef3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Oct 2023 01:18:45 +0000 Subject: [PATCH 144/314] build(deps): update zstd requirement from 0.12 to 0.13 (#3165) * build(deps): update zstd requirement from 0.12 to 0.13 Updates the requirements on [zstd](https://github.com/gyscos/zstd-rs) to permit the latest version. - [Release notes](https://github.com/gyscos/zstd-rs/releases) - [Commits](https://github.com/gyscos/zstd-rs/compare/v0.12.0...v0.13.0) --- updated-dependencies: - dependency-name: zstd dependency-type: direct:production ... Signed-off-by: dependabot[bot] * chore: update changelogs --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 4 ++++ actix-http/Cargo.toml | 2 +- actix-web/CHANGES.md | 4 ++++ actix-web/Cargo.toml | 2 +- awc/CHANGES.md | 1 + awc/Cargo.toml | 2 +- 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 860ee3b6c..318df5a4d 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- Updated `zstd` dependency to `0.13`. + ## 3.4.0 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index c19ce0161..9e116c964 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -103,7 +103,7 @@ actix-tls = { version = "3.1", default-features = false, optional = true } # compress-* brotli = { version = "3.3.3", optional = true } flate2 = { version = "1.0.13", optional = true } -zstd = { version = "0.12", optional = true } +zstd = { version = "0.13", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 6ed97b671..50728a839 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- Updated `zstd` dependency to `0.13`. + ## 4.4.0 ### Added diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 0f874d3f8..994f6359f 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -122,7 +122,7 @@ static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } tls-rustls = { package = "rustls", version = "0.21" } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } -zstd = "0.12" +zstd = "0.13" [[test]] name = "test_server" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 1032e196c..3a1996cba 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Update `trust-dns-resolver` dependency to `0.23`. +- Updated `zstd` dependency to `0.13`. ## 3.2.0 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 027bb161e..90f68e4c4 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -111,7 +111,7 @@ static_assertions = "1.1" rcgen = "0.11" rustls-pemfile = "1" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } -zstd = "0.12" +zstd = "0.13" [[example]] name = "client" From 7d2349afb93a676695decad2829e103a049247d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 02:17:07 +0000 Subject: [PATCH 145/314] build(deps): bump taiki-e/install-action from 2.21.3 to 2.21.7 (#3183) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.3 to 2.21.7. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.3...v2.21.7) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index cb3ea77ca..b388444cf 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.3 + uses: taiki-e/install-action@v2.21.7 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.3 + uses: taiki-e/install-action@v2.21.7 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.3 + uses: taiki-e/install-action@v2.21.7 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca9673da4..095333f78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.3 + uses: taiki-e/install-action@v2.21.7 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 73931c238..ed2ef99ac 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.3 + uses: taiki-e/install-action@v2.21.7 with: tool: cargo-llvm-cov From 989548e36aca33c55e860f46302d1287e37ffa73 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 6 Nov 2023 23:54:38 +0000 Subject: [PATCH 146/314] chore: remove git from repo URLs --- actix-http-test/Cargo.toml | 2 +- actix-http/Cargo.toml | 2 +- actix-multipart-derive/Cargo.toml | 2 +- actix-multipart/Cargo.toml | 2 +- actix-router/Cargo.toml | 2 +- actix-test/Cargo.toml | 2 +- actix-web-codegen/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 7f00ba30a..0881e0bc4 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Nikolay Kim "] description = "Various helpers for Actix applications to use during testing" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" categories = [ "network-programming", "asynchronous", diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 9e116c964..f483ea093 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -8,7 +8,7 @@ authors = [ description = "HTTP primitives for the Actix ecosystem" keywords = ["actix", "http", "framework", "async", "futures"] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" categories = [ "network-programming", "asynchronous", diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index 75b4c723b..2f049a3fb 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Jacob Halsey "] description = "Multipart form derive macro for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 455d7db78..257d56132 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -8,7 +8,7 @@ authors = [ description = "Multipart form support for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index adf43a086..8a404dd20 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -8,7 +8,7 @@ authors = [ ] description = "Resource path matching and router" keywords = ["actix", "router", "routing"] -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 38b40ccfa..46d65abdc 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -8,7 +8,7 @@ authors = [ description = "Integration testing tools for Actix Web applications" keywords = ["http", "web", "framework", "async", "futures"] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" categories = [ "network-programming", "asynchronous", diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 748984b49..7039ea7df 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -3,7 +3,7 @@ name = "actix-web-codegen" version = "4.2.2" description = "Routing and runtime macros for Actix Web" homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 994f6359f..c9aab17b2 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -14,7 +14,7 @@ categories = [ "web-programming::websocket" ] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition.workspace = true rust-version.workspace = true diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 90f68e4c4..07811c979 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -11,7 +11,7 @@ categories = [ "web-programming::websocket", ] homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web.git" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" From f5655721aa3f07a679072241c59415506cbc716d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 10 Nov 2023 14:06:35 +0000 Subject: [PATCH 147/314] ci: rename lint workflow --- .github/workflows/{clippy-fmt.yml => lint.yml} | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) rename .github/workflows/{clippy-fmt.yml => lint.yml} (80%) diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/lint.yml similarity index 80% rename from .github/workflows/clippy-fmt.yml rename to .github/workflows/lint.yml index 854944995..cbdd4acf0 100644 --- a/.github/workflows/clippy-fmt.yml +++ b/.github/workflows/lint.yml @@ -22,25 +22,31 @@ jobs: toolchain: nightly components: rustfmt - - run: cargo fmt --all -- --check + - name: Check with rustfmt + run: cargo fmt --all -- --check clippy: permissions: + contents: read checks: write # to add clippy checks to PR diffs runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 with: components: clippy - - uses: giraffate/clippy-action@v1.0.1 + - name: Check with Clippy + uses: giraffate/clippy-action@v1.0.1 with: reporter: github-pr-check github_token: ${{ secrets.GITHUB_TOKEN }} - clippy_flags: --workspace --all-features --tests --examples --bins -- -Dclippy::todo -Aunknown_lints + clippy_flags: >- + --workspace --all-features --tests --examples --bins -- + -A unknown_lints -D clippy::todo -D clippy::dbg_macro lint-docs: runs-on: ubuntu-latest From e50bceb91493087d4059e605d94c13a11b09e747 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 02:00:08 +0000 Subject: [PATCH 148/314] build(deps): bump taiki-e/install-action from 2.21.7 to 2.21.11 (#3185) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.7 to 2.21.11. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.7...v2.21.11) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index b388444cf..51eddaa0c 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.7 + uses: taiki-e/install-action@v2.21.11 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.7 + uses: taiki-e/install-action@v2.21.11 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.7 + uses: taiki-e/install-action@v2.21.11 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 095333f78..cd10915aa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.7 + uses: taiki-e/install-action@v2.21.11 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ed2ef99ac..7d696b8af 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.7 + uses: taiki-e/install-action@v2.21.11 with: tool: cargo-llvm-cov From 9d1f75d349dd6ad8451b8d2dbc619561868dba4d Mon Sep 17 00:00:00 2001 From: Marcio Ordonez Date: Sun, 19 Nov 2023 08:22:55 -0300 Subject: [PATCH 149/314] fix: content type required flag (#3168) * fix: content type required flag * clarify comments for invalid json mime type * remove pr reference --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/types/json.rs | 40 +++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 50728a839..0079a4120 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -6,6 +6,10 @@ - Updated `zstd` dependency to `0.13`. +### Fixed + +- Fix validation of `Json` extractor when `JsonConfig::validate_content_type()` is set to false. + ## 4.4.0 ### Added diff --git a/actix-web/src/types/json.rs b/actix-web/src/types/json.rs index 59c95da4c..6b75c0cfe 100644 --- a/actix-web/src/types/json.rs +++ b/actix-web/src/types/json.rs @@ -328,14 +328,19 @@ impl JsonBody { ctype_required: bool, ) -> Self { // check content-type - let can_parse_json = if let Ok(Some(mime)) = req.mime_type() { - mime.subtype() == mime::JSON - || mime.suffix() == Some(mime::JSON) - || ctype_fn.map_or(false, |predicate| predicate(mime)) - } else { - // if `ctype_required` is false, assume payload is - // json even when content-type header is missing - !ctype_required + let can_parse_json = match (ctype_required, req.mime_type()) { + (true, Ok(Some(mime))) => { + mime.subtype() == mime::JSON + || mime.suffix() == Some(mime::JSON) + || ctype_fn.map_or(false, |predicate| predicate(mime)) + } + + // if content-type is expected but not parsable as mime type, bail + (true, _) => false, + + // if content-type validation is disabled, assume payload is JSON + // even when content-type header is missing or invalid mime type + (false, _) => true, }; if !can_parse_json { @@ -725,6 +730,25 @@ mod tests { assert!(s.is_ok()) } + #[actix_rt::test] + async fn test_json_ignoring_content_type() { + let (req, mut pl) = TestRequest::default() + .insert_header(( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + )) + .insert_header(( + header::CONTENT_TYPE, + header::HeaderValue::from_static("invalid/value"), + )) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .app_data(JsonConfig::default().content_type_required(false)) + .to_http_parts(); + + let s = Json::::from_request(&req, &mut pl).await; + assert!(s.is_ok()); + } + #[actix_rt::test] async fn test_with_config_in_data_wrapper() { let (req, mut pl) = TestRequest::default() From c0615f28edba69cbd51f2eb60100c1de8fbbb9f7 Mon Sep 17 00:00:00 2001 From: Amit Upadhyay Date: Mon, 20 Nov 2023 00:24:08 +0530 Subject: [PATCH 150/314] Make compression middleware prefer brotli over zstd over gzip (#3189) * AcceptEncoding.preference() prefers brotli > zstd > gzip * AcceptEncoding.{ranked,negotiate}() prefers brotli > zstd > gzip * changelog entry * use browser-realistic encoding tests * fix choosing identity when q=0 --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/http/header/accept_encoding.rs | 50 +++++++++++++++++--- actix-web/tests/compression.rs | 32 ++++++++++--- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 0079a4120..953befb7f 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -5,6 +5,7 @@ ### Changed - Updated `zstd` dependency to `0.13`. +- Compression middleware now prefers brotli over zstd over gzip. ### Fixed diff --git a/actix-web/src/http/header/accept_encoding.rs b/actix-web/src/http/header/accept_encoding.rs index cc80e7bb0..19d649926 100644 --- a/actix-web/src/http/header/accept_encoding.rs +++ b/actix-web/src/http/header/accept_encoding.rs @@ -149,7 +149,7 @@ impl AcceptEncoding { /// Extracts the most preferable encoding, accounting for [q-factor weighting]. /// - /// If no q-factors are provided, the first encoding is chosen. Note that items without + /// If no q-factors are provided, we prefer brotli > zstd > gzip. Note that items without /// q-factors are given the maximum preference value. /// /// As per the spec, returns [`Preference::Any`] if acceptable list is empty. Though, if this is @@ -167,6 +167,7 @@ impl AcceptEncoding { let mut max_item = None; let mut max_pref = Quality::ZERO; + let mut max_rank = 0; // uses manual max lookup loop since we want the first occurrence in the case of same // preference but `Iterator::max_by_key` would give us the last occurrence @@ -174,9 +175,13 @@ impl AcceptEncoding { for pref in &self.0 { // only change if strictly greater // equal items, even while unsorted, still have higher preference if they appear first - if pref.quality > max_pref { + + let rank = encoding_rank(pref); + + if (pref.quality, rank) > (max_pref, max_rank) { max_pref = pref.quality; max_item = Some(pref.item.clone()); + max_rank = rank; } } @@ -203,6 +208,8 @@ impl AcceptEncoding { /// Returns a sorted list of encodings from highest to lowest precedence, accounting /// for [q-factor weighting]. /// + /// If no q-factors are provided, we prefer brotli > zstd > gzip. + /// /// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2 pub fn ranked(&self) -> Vec> { self.ranked_items().map(|q| q.item).collect() @@ -210,21 +217,44 @@ impl AcceptEncoding { fn ranked_items(&self) -> impl Iterator>> { if self.0.is_empty() { - return vec![].into_iter(); + return Vec::new().into_iter(); } let mut types = self.0.clone(); // use stable sort so items with equal q-factor retain listed order types.sort_by(|a, b| { - // sort by q-factor descending - b.quality.cmp(&a.quality) + // sort by q-factor descending then server ranking descending + + b.quality + .cmp(&a.quality) + .then(encoding_rank(b).cmp(&encoding_rank(a))) }); types.into_iter() } } +/// Returns server-defined encoding ranking. +fn encoding_rank(qv: &QualityItem>) -> u8 { + // ensure that q=0 items are never sorted above identity encoding + // invariant: sorting methods calling this fn use first-on-equal approach + if qv.quality == Quality::ZERO { + return 0; + } + + match qv.item { + Preference::Specific(Encoding::Known(ContentEncoding::Brotli)) => 5, + Preference::Specific(Encoding::Known(ContentEncoding::Zstd)) => 4, + Preference::Specific(Encoding::Known(ContentEncoding::Gzip)) => 3, + Preference::Specific(Encoding::Known(ContentEncoding::Deflate)) => 2, + Preference::Any => 0, + Preference::Specific(Encoding::Known(ContentEncoding::Identity)) => 0, + Preference::Specific(Encoding::Known(_)) => 1, + Preference::Specific(Encoding::Unknown(_)) => 1, + } +} + /// Returns true if "identity" is an acceptable encoding. /// /// Internal algorithm relies on item list being in descending order of quality. @@ -377,11 +407,11 @@ mod tests { ); assert_eq!( test.negotiate([Encoding::gzip(), Encoding::brotli(), Encoding::identity()].iter()), - Some(Encoding::gzip()) + Some(Encoding::brotli()) ); assert_eq!( test.negotiate([Encoding::brotli(), Encoding::gzip(), Encoding::identity()].iter()), - Some(Encoding::gzip()) + Some(Encoding::brotli()) ); } @@ -398,6 +428,9 @@ mod tests { let test = accept_encoding!("br", "gzip", "*"); assert_eq!(test.ranked(), vec![enc("br"), enc("gzip"), enc("*")]); + + let test = accept_encoding!("gzip", "br", "*"); + assert_eq!(test.ranked(), vec![enc("br"), enc("gzip"), enc("*")]); } #[test] @@ -420,5 +453,8 @@ mod tests { let test = accept_encoding!("br", "gzip", "*"); assert_eq!(test.preference().unwrap(), enc("br")); + + let test = accept_encoding!("gzip", "br", "*"); + assert_eq!(test.preference().unwrap(), enc("br")); } } diff --git a/actix-web/tests/compression.rs b/actix-web/tests/compression.rs index b911b9d1f..61ff1bff5 100644 --- a/actix-web/tests/compression.rs +++ b/actix-web/tests/compression.rs @@ -96,7 +96,7 @@ async fn negotiate_encoding_gzip() { let req = srv .post("/static") - .insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd")) + .insert_header((header::ACCEPT_ENCODING, "gzip, br;q=0.8, zstd;q=0.5")) .send(); let mut res = req.await.unwrap(); @@ -109,7 +109,7 @@ async fn negotiate_encoding_gzip() { let mut res = srv .post("/static") .no_decompress() - .insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd")) + .insert_header((header::ACCEPT_ENCODING, "gzip, br;q=0.8, zstd;q=0.5")) .send() .await .unwrap(); @@ -123,9 +123,11 @@ async fn negotiate_encoding_gzip() { async fn negotiate_encoding_br() { let srv = test_server!(); + // check that brotli content-encoding header is returned + let req = srv .post("/static") - .insert_header((header::ACCEPT_ENCODING, "br,zstd,gzip")) + .insert_header((header::ACCEPT_ENCODING, "br, zstd, gzip")) .send(); let mut res = req.await.unwrap(); @@ -135,10 +137,26 @@ async fn negotiate_encoding_br() { let bytes = res.body().await.unwrap(); assert_eq!(bytes, Bytes::from_static(LOREM)); + // check that brotli is preferred even when later in (q-less) list + + let req = srv + .post("/static") + .insert_header((header::ACCEPT_ENCODING, "gzip, zstd, br")) + .send(); + + let mut res = req.await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); + assert_eq!(res.headers().get(header::CONTENT_ENCODING).unwrap(), "br"); + + let bytes = res.body().await.unwrap(); + assert_eq!(bytes, Bytes::from_static(LOREM)); + + // check that returned content is actually brotli encoded + let mut res = srv .post("/static") .no_decompress() - .insert_header((header::ACCEPT_ENCODING, "br,zstd,gzip")) + .insert_header((header::ACCEPT_ENCODING, "br, zstd, gzip")) .send() .await .unwrap(); @@ -154,7 +172,7 @@ async fn negotiate_encoding_zstd() { let req = srv .post("/static") - .insert_header((header::ACCEPT_ENCODING, "zstd,gzip,br")) + .insert_header((header::ACCEPT_ENCODING, "zstd, gzip, br;q=0.8")) .send(); let mut res = req.await.unwrap(); @@ -167,7 +185,7 @@ async fn negotiate_encoding_zstd() { let mut res = srv .post("/static") .no_decompress() - .insert_header((header::ACCEPT_ENCODING, "zstd,gzip,br")) + .insert_header((header::ACCEPT_ENCODING, "zstd, gzip, br;q=0.8")) .send() .await .unwrap(); @@ -207,7 +225,7 @@ async fn gzip_no_decompress() { // don't decompress response body .no_decompress() // signal that we want a compressed body - .insert_header((header::ACCEPT_ENCODING, "gzip,br,zstd")) + .insert_header((header::ACCEPT_ENCODING, "gzip, br;q=0.8, zstd;q=0.5")) .send(); let mut res = req.await.unwrap(); From 4accfab196fbf88e2f39da6306b7f8c7bc8dcc0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Nov 2023 00:29:35 +0000 Subject: [PATCH 151/314] build(deps): bump taiki-e/install-action from 2.21.11 to 2.21.17 (#3195) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.11 to 2.21.17. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.11...v2.21.17) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 51eddaa0c..86a09e0cd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.11 + uses: taiki-e/install-action@v2.21.17 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.11 + uses: taiki-e/install-action@v2.21.17 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.11 + uses: taiki-e/install-action@v2.21.17 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd10915aa..bc8026f96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.11 + uses: taiki-e/install-action@v2.21.17 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7d696b8af..4e02735c7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.11 + uses: taiki-e/install-action@v2.21.17 with: tool: cargo-llvm-cov From 2fe518995491da430c17316f3b9a2741cacf22cd Mon Sep 17 00:00:00 2001 From: Paul <135009186+phooijenga@users.noreply.github.com> Date: Sun, 26 Nov 2023 21:57:19 +0100 Subject: [PATCH 152/314] Do not encode zero-sized response bodies (#3199) * Do not encode zero-sized response bodies * Test empty response remains empty after compression --- actix-http/CHANGES.md | 4 +++ actix-http/src/encoding/encoder.rs | 2 +- actix-web/src/middleware/compress.rs | 45 +++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 318df5a4d..fc49bc931 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -6,6 +6,10 @@ - Updated `zstd` dependency to `0.13`. +### Fixed + +- Do not encode zero-sized response bodies + ## 3.4.0 ### Added diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index 527bfebaa..e084aa564 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -52,7 +52,7 @@ impl Encoder { pub fn response(encoding: ContentEncoding, head: &mut ResponseHead, body: B) -> Self { // no need to compress an empty body - if matches!(body.size(), BodySize::None) { + if matches!(body.size(), BodySize::None | BodySize::Sized(0)) { return Self::none(); } diff --git a/actix-web/src/middleware/compress.rs b/actix-web/src/middleware/compress.rs index a55b46264..8ff518cd3 100644 --- a/actix-web/src/middleware/compress.rs +++ b/actix-web/src/middleware/compress.rs @@ -373,7 +373,7 @@ mod tests { .default_service(web::to(move || { HttpResponse::Ok() .insert_header((header::VARY, "x-test")) - .finish() + .body(TEXT_DATA) })) }) .await; @@ -429,4 +429,47 @@ mod tests { assert_successful_identity_res_with_content_type(&res, "image/jpeg"); assert_eq!(test::read_body(res).await, TEXT_DATA.as_bytes()); } + + #[actix_rt::test] + async fn prevents_compression_empty() { + let app = test::init_service({ + App::new() + .wrap(Compress::default()) + .default_service(web::to(move || HttpResponse::Ok().finish())) + }) + .await; + + let req = test::TestRequest::default() + .insert_header((header::ACCEPT_ENCODING, "gzip")) + .to_request(); + let res = test::call_service(&app, req).await; + assert_eq!(res.status(), StatusCode::OK); + assert!(!res.headers().contains_key(header::CONTENT_ENCODING)); + assert!(test::read_body(res).await.is_empty()); + } +} + +#[cfg(feature = "compress-brotli")] +#[cfg(test)] +mod tests_brotli { + use super::*; + use crate::{test, web, App}; + + #[actix_rt::test] + async fn prevents_compression_empty() { + let app = test::init_service({ + App::new() + .wrap(Compress::default()) + .default_service(web::to(move || HttpResponse::Ok().finish())) + }) + .await; + + let req = test::TestRequest::default() + .insert_header((header::ACCEPT_ENCODING, "br")) + .to_request(); + let res = test::call_service(&app, req).await; + assert_eq!(res.status(), StatusCode::OK); + assert!(!res.headers().contains_key(header::CONTENT_ENCODING)); + assert!(test::read_body(res).await.is_empty()); + } } From e95c8fe5a6d466ba674ea2ea35c0c4d18e1bb9d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 02:54:42 +0000 Subject: [PATCH 153/314] build(deps): bump taiki-e/install-action from 2.21.17 to 2.21.19 (#3205) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.17 to 2.21.19. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.17...v2.21.19) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 86a09e0cd..bff9908e5 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.17 + uses: taiki-e/install-action@v2.21.19 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.17 + uses: taiki-e/install-action@v2.21.19 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.17 + uses: taiki-e/install-action@v2.21.19 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc8026f96..f9e93dddf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.17 + uses: taiki-e/install-action@v2.21.19 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 4e02735c7..015cc7968 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.17 + uses: taiki-e/install-action@v2.21.19 with: tool: cargo-llvm-cov From 929ceb5eb53dddcdd0a0194602e57604c6105be3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 01:02:25 +0000 Subject: [PATCH 154/314] build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.5.0 to 1.6.0 (#3212) build(deps): bump actions-rust-lang/setup-rust-toolchain Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases) - [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.5.0...v1.6.0) --- updated-dependencies: - dependency-name: actions-rust-lang/setup-rust-toolchain dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 6 +++--- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 8 ++++---- .github/workflows/upload-doc.yml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index bff9908e5..e8443f0a5 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -40,7 +40,7 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: ${{ matrix.version.version }} @@ -82,7 +82,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack uses: taiki-e/install-action@v2.21.19 @@ -103,7 +103,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest uses: taiki-e/install-action@v2.21.19 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9e93dddf..69049ffa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: ${{ matrix.version.version }} @@ -93,7 +93,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly @@ -109,7 +109,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 015cc7968..a7d5baf73 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: components: llvm-tools-preview diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cbdd4acf0..13362dbb0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly components: rustfmt @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: components: clippy @@ -53,7 +53,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly components: rust-docs @@ -72,7 +72,7 @@ jobs: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly-2023-08-25 diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index 7dcc8255c..2c6c88bb5 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.5.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 with: toolchain: nightly From 039f8fb193cda0a72862af1eb9442601e37006bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 01:03:29 +0000 Subject: [PATCH 155/314] build(deps): bump JamesIves/github-pages-deploy-action from 4.4.3 to 4.5.0 (#3211) build(deps): bump JamesIves/github-pages-deploy-action Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.4.3 to 4.5.0. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.4.3...v4.5.0) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .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 2c6c88bb5..f4bd0ceeb 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -35,7 +35,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.4.3 + uses: JamesIves/github-pages-deploy-action@v4.5.0 with: folder: target/doc single-commit: true From 37d304b0f2b673e7b009902ecdd9c5bbb86aea2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 01:20:11 +0000 Subject: [PATCH 156/314] build(deps): bump taiki-e/install-action from 2.21.19 to 2.21.26 (#3210) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.19 to 2.21.26. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.19...v2.21.26) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index e8443f0a5..ae7d94dab 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.19 + uses: taiki-e/install-action@v2.21.26 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.19 + uses: taiki-e/install-action@v2.21.26 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.19 + uses: taiki-e/install-action@v2.21.26 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69049ffa4..2914ae1f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.19 + uses: taiki-e/install-action@v2.21.26 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a7d5baf73..f470dff1d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.19 + uses: taiki-e/install-action@v2.21.26 with: tool: cargo-llvm-cov From 0a312037ea1ad6ed205e79ecb9ab7b66aef05b48 Mon Sep 17 00:00:00 2001 From: Hangyuan <59467867+llhyuan@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:53:05 +0100 Subject: [PATCH 157/314] Corrected a typo in mod.rs (#3218) --- actix-web/src/middleware/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index 8dbd1ff2c..ed61556a3 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -72,7 +72,7 @@ //! processes the request as well and passes it to `MiddlewareA`, which then passes it to the //! [`Service`]. In the [`Service`], the extractors will run first. They don't pass the request on, //! but only view it (see [`FromRequest`]). After the [`Service`] responds to the request, the -//! response it passed back through `MiddlewareA`, `MiddlewareB`, and `MiddlewareC`. +//! response is passed back through `MiddlewareA`, `MiddlewareB`, and `MiddlewareC`. //! //! As you register middleware using [`wrap`][crate::App::wrap] and [`wrap_fn`][crate::App::wrap_fn] //! in the [`App`] builder, imagine wrapping layers around an inner [`App`]. The first middleware From 1114a51b222e017c530b3d09a1cf595729205e15 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 01:11:53 +0000 Subject: [PATCH 158/314] build(deps): bump taiki-e/install-action from 2.21.26 to 2.22.0 (#3219) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.21.26 to 2.22.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.21.26...v2.22.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index ae7d94dab..4c4a3404f 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.26 + uses: taiki-e/install-action@v2.22.0 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.26 + uses: taiki-e/install-action@v2.22.0 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest - uses: taiki-e/install-action@v2.21.26 + uses: taiki-e/install-action@v2.22.0 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2914ae1f6..5627865c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.21.26 + uses: taiki-e/install-action@v2.22.0 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f470dff1d..c451df22a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.21.26 + uses: taiki-e/install-action@v2.22.0 with: tool: cargo-llvm-cov From eefe8b0733118d0cc8d6ddeafddace79f0d4baca Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 Date: Sat, 16 Dec 2023 10:08:45 +0000 Subject: [PATCH 159/314] Implement From for http::HeaderMap (#3222) * Implement From for http::HeaderMap * Update changelog * Apply clippy fix * doc tweak --------- Co-authored-by: SleeplessOne1917 Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 1 + actix-http/src/header/map.rs | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index fc49bc931..eadd5c515 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -5,6 +5,7 @@ ### Changed - Updated `zstd` dependency to `0.13`. +- Implemented `From` for `http::HeaderMap`. ### Fixed diff --git a/actix-http/src/header/map.rs b/actix-http/src/header/map.rs index e8118be93..d8a63b573 100644 --- a/actix-http/src/header/map.rs +++ b/actix-http/src/header/map.rs @@ -636,10 +636,17 @@ impl<'a> IntoIterator for &'a HeaderMap { } } -/// Convert `http::HeaderMap` to our `HeaderMap`. +/// Convert a `http::HeaderMap` to our `HeaderMap`. impl From for HeaderMap { - fn from(mut map: http::HeaderMap) -> HeaderMap { - HeaderMap::from_drain(map.drain()) + fn from(mut map: http::HeaderMap) -> Self { + Self::from_drain(map.drain()) + } +} + +/// Convert our `HeaderMap` to a `http::HeaderMap`. +impl From for http::HeaderMap { + fn from(map: HeaderMap) -> Self { + Self::from_iter(map) } } From c7a0af31d3bb05f08e2b22100d8c835273d029f1 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 16 Dec 2023 10:20:28 +0000 Subject: [PATCH 160/314] docs: doc and metadata tweaks --- actix-http/Cargo.toml | 2 +- actix-http/README.md | 10 +++++++--- actix-http/src/lib.rs | 3 ++- actix-router/src/resource.rs | 4 ++-- actix-web/Cargo.toml | 2 +- actix-web/src/redirect.rs | 2 +- scripts/bump | 5 ++++- 7 files changed, 18 insertions(+), 10 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index f483ea093..8476d9086 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -5,7 +5,7 @@ authors = [ "Nikolay Kim ", "Rob Ede ", ] -description = "HTTP primitives for the Actix ecosystem" +description = "HTTP types and services for the Actix ecosystem" keywords = ["actix", "http", "framework", "async", "futures"] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web" diff --git a/actix-http/README.md b/actix-http/README.md index 049de9278..7d499f4b3 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -1,6 +1,8 @@ -# actix-http +# `actix-http` -> HTTP primitives for the Actix ecosystem. +> HTTP types and services 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=3.4.0)](https://docs.rs/actix-http/3.4.0) @@ -11,12 +13,14 @@ [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http) - Minimum Supported Rust Version (MSRV): 1.68 -## Example +## Examples ```rust use std::{env, io}; diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 382295fbc..976697ca6 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -1,6 +1,7 @@ -//! HTTP primitives for the Actix ecosystem. +//! HTTP types and services for the Actix ecosystem. //! //! ## Crate Features +//! //! | Feature | Functionality | //! | ------------------- | ------------------------------------------- | //! | `http2` | HTTP/2 support via [h2]. | diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index 80c0a2d68..abd132211 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -193,8 +193,8 @@ const REGEX_FLAGS: &str = "(?s-m)"; /// # Trailing Slashes /// It should be noted that this library takes no steps to normalize intra-path or trailing slashes. /// As such, all resource definitions implicitly expect a pre-processing step to normalize paths if -/// they you wish to accommodate "recoverable" path errors. Below are several examples of -/// resource-path pairs that would not be compatible. +/// you wish to accommodate "recoverable" path errors. Below are several examples of resource-path +/// pairs that would not be compatible. /// /// ## Examples /// ``` diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index c9aab17b2..d9cf0b94f 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -15,7 +15,7 @@ categories = [ ] homepage = "https://actix.rs" repository = "https://github.com/actix/actix-web" -license = "MIT OR Apache-2.0" +license.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/actix-web/src/redirect.rs b/actix-web/src/redirect.rs index f9e9f2d7a..5ce960aa4 100644 --- a/actix-web/src/redirect.rs +++ b/actix-web/src/redirect.rs @@ -171,7 +171,7 @@ impl Responder for Redirect { } else { log::error!( "redirect target location can not be converted to header value: {:?}", - self.to + self.to, ); } diff --git a/scripts/bump b/scripts/bump index baf3fb4d8..9d90542c6 100755 --- a/scripts/bump +++ b/scripts/bump @@ -93,9 +93,12 @@ fi # done; remove backup files rm -f $CARGO_MANIFEST.bak -rm -f $CHANGELOG_FILE.bak rm -f $README_FILE.bak +if [ -n "${CHANGELOG_FILE-}" ]; then + rm -f $CHANGELOG_FILE.bak +fi + echo "manifest, changelog, and readme updated" echo echo "check other references:" From 5e5e5d8315791cda46a3d02a392f18c391e8179e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 16 Dec 2023 10:26:32 +0000 Subject: [PATCH 161/314] chore: remove allow(uninlined_format_args) --- actix-files/src/lib.rs | 1 - actix-http-test/src/lib.rs | 1 - actix-http/benches/response-body-compression.rs | 2 -- actix-http/src/lib.rs | 3 +-- actix-http/tests/test_openssl.rs | 1 - actix-http/tests/test_ws.rs | 2 -- actix-multipart/src/lib.rs | 2 +- actix-router/benches/quoter.rs | 2 -- actix-router/src/lib.rs | 1 - actix-router/src/router.rs | 5 +++-- actix-web-actors/src/lib.rs | 1 - actix-web/benches/server.rs | 2 -- actix-web/examples/macroless.rs | 2 -- actix-web/examples/uds.rs | 2 -- actix-web/src/lib.rs | 1 - actix-web/tests/test_httpserver.rs | 2 -- awc/examples/client.rs | 2 -- awc/src/lib.rs | 3 +-- awc/tests/test_client.rs | 2 -- 19 files changed, 6 insertions(+), 31 deletions(-) diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 7871905f6..943130e16 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -13,7 +13,6 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible, missing_docs, missing_debug_implementations)] -#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs index 2f1725d1c..554af9102 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -2,7 +2,6 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] -#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-http/benches/response-body-compression.rs b/actix-http/benches/response-body-compression.rs index d128bf75b..53279e312 100644 --- a/actix-http/benches/response-body-compression.rs +++ b/actix-http/benches/response-body-compression.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::convert::Infallible; use actix_http::{encoding::Encoder, ContentEncoding, Request, Response, StatusCode}; diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 976697ca6..888c3e06f 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -22,8 +22,7 @@ #![allow( clippy::type_complexity, clippy::too_many_arguments, - clippy::borrow_interior_mutable_const, - clippy::uninlined_format_args + clippy::borrow_interior_mutable_const )] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs index b4d8ed1a5..cb16a4fec 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -1,5 +1,4 @@ #![cfg(feature = "openssl")] -#![allow(clippy::uninlined_format_args)] extern crate tls_openssl as openssl; diff --git a/actix-http/tests/test_ws.rs b/actix-http/tests/test_ws.rs index a2866613b..9a78074c4 100644 --- a/actix-http/tests/test_ws.rs +++ b/actix-http/tests/test_ws.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::{ cell::Cell, convert::Infallible, diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index 615a8e6de..495bae9c0 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -2,7 +2,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] -#![allow(clippy::borrow_interior_mutable_const, clippy::uninlined_format_args)] +#![allow(clippy::borrow_interior_mutable_const)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-router/benches/quoter.rs b/actix-router/benches/quoter.rs index c78240809..2428a767d 100644 --- a/actix-router/benches/quoter.rs +++ b/actix-router/benches/quoter.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::{borrow::Cow, fmt::Write as _}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; diff --git a/actix-router/src/lib.rs b/actix-router/src/lib.rs index 53c0ad82a..f10093436 100644 --- a/actix-router/src/lib.rs +++ b/actix-router/src/lib.rs @@ -2,7 +2,6 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] -#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-router/src/router.rs b/actix-router/src/router.rs index d31d10ce8..1dd4449da 100644 --- a/actix-router/src/router.rs +++ b/actix-router/src/router.rs @@ -97,6 +97,7 @@ impl RouterBuilder { ctx: U, ) -> (&mut ResourceDef, &mut T, &mut U) { self.routes.push((rdef, val, ctx)); + #[allow(clippy::map_identity)] // map is used to distribute &mut-ness to tuple elements self.routes .last_mut() .map(|(rdef, val, ctx)| (rdef, val, ctx)) @@ -186,11 +187,11 @@ mod tests { assert_eq!(path.get("file").unwrap(), "file"); assert_eq!(path.get("ext").unwrap(), "gz"); - let mut path = Path::new("/vtest/ttt/index.html"); + let mut path = Path::new("/v2/ttt/index.html"); let (h, info) = router.recognize_mut(&mut path).unwrap(); assert_eq!(*h, 14); assert_eq!(info, ResourceId(4)); - assert_eq!(path.get("val").unwrap(), "test"); + assert_eq!(path.get("val").unwrap(), "2"); assert_eq!(path.get("val2").unwrap(), "ttt"); let mut path = Path::new("/v/blah-blah/index.html"); diff --git a/actix-web-actors/src/lib.rs b/actix-web-actors/src/lib.rs index cf2eb3645..d89b0ee35 100644 --- a/actix-web-actors/src/lib.rs +++ b/actix-web-actors/src/lib.rs @@ -57,7 +57,6 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] -#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-web/benches/server.rs b/actix-web/benches/server.rs index 2c9f71dc5..0d45c9403 100644 --- a/actix-web/benches/server.rs +++ b/actix-web/benches/server.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use actix_web::{web, App, HttpResponse}; use awc::Client; use criterion::{criterion_group, criterion_main, Criterion}; diff --git a/actix-web/examples/macroless.rs b/actix-web/examples/macroless.rs index d3589da21..78ffd45c1 100644 --- a/actix-web/examples/macroless.rs +++ b/actix-web/examples/macroless.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use actix_web::{middleware, rt, web, App, HttpRequest, HttpServer}; async fn index(req: HttpRequest) -> &'static str { diff --git a/actix-web/examples/uds.rs b/actix-web/examples/uds.rs index 15e28ba1d..e854bb3b1 100644 --- a/actix-web/examples/uds.rs +++ b/actix-web/examples/uds.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use actix_web::{get, web, HttpRequest}; #[cfg(unix)] use actix_web::{middleware, App, Error, HttpResponse, HttpServer}; diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index e982a43b1..88f0ae9be 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -69,7 +69,6 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] -#![allow(clippy::uninlined_format_args)] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] diff --git a/actix-web/tests/test_httpserver.rs b/actix-web/tests/test_httpserver.rs index 861d76d93..86e0575f3 100644 --- a/actix-web/tests/test_httpserver.rs +++ b/actix-web/tests/test_httpserver.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; diff --git a/awc/examples/client.rs b/awc/examples/client.rs index 26edcfd62..16ad330b8 100644 --- a/awc/examples/client.rs +++ b/awc/examples/client.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::error::Error as StdError; #[tokio::main] diff --git a/awc/src/lib.rs b/awc/src/lib.rs index ce2dfb34f..253b5161a 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -105,8 +105,7 @@ #![allow( clippy::type_complexity, clippy::borrow_interior_mutable_const, - clippy::needless_doctest_main, - clippy::uninlined_format_args + clippy::needless_doctest_main )] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index 6d1459ac0..76915630f 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -1,5 +1,3 @@ -#![allow(clippy::uninlined_format_args)] - use std::{ collections::HashMap, convert::Infallible, From 271edafd4de2616fa3f3e17949badb844412cc5d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 16 Dec 2023 10:37:19 +0000 Subject: [PATCH 162/314] docs: add router readme --- actix-router/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 actix-router/README.md diff --git a/actix-router/README.md b/actix-router/README.md new file mode 100644 index 000000000..15a449c44 --- /dev/null +++ b/actix-router/README.md @@ -0,0 +1,16 @@ +# `actix-router` + +[![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) +[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.1)](https://docs.rs/actix-router/0.5.1) +![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg) +
+[![dependency status](https://deps.rs/crate/actix-router/0.5.1/status.svg)](https://deps.rs/crate/actix-router/0.5.1) +[![Download](https://img.shields.io/crates/d/actix-router.svg)](https://crates.io/crates/actix-router) +[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + + +Resource path matching and router. + + From ede0201aa49edaf68f4e381906e524e437900bb7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 16 Dec 2023 10:42:16 +0000 Subject: [PATCH 163/314] docs: fix derive readme version --- actix-multipart-derive/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index 2737410f6..cd5780c56 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -3,11 +3,11 @@ > The derive macro implementation for actix-multipart-derive. [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) -[![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.5.0)](https://docs.rs/actix-multipart-derive/0.5.0) +[![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart-derive/0.6.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.5.0/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.5.0) +[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.6.1) [![Download](https://img.shields.io/crates/d/actix-multipart-derive.svg)](https://crates.io/crates/actix-multipart-derive) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From fdef224a0691df475337ddfc1693da32148cfba8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Dec 2023 18:49:17 +0000 Subject: [PATCH 164/314] docs: document internal Path fields --- actix-router/src/path.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index dc4150ddc..467420cd3 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -3,7 +3,7 @@ use std::{ ops::{DerefMut, Index}, }; -use serde::de; +use serde::{de, Deserialize}; use crate::{de::PathDeserializer, Resource, ResourcePath}; @@ -24,8 +24,13 @@ impl Default for PathItem { /// If resource path contains variable patterns, `Path` stores them. #[derive(Debug, Clone, Default)] pub struct Path { + /// Full path representation. path: T, + + /// Number of characters in `path` that have been processed into `segments`. pub(crate) skip: u16, + + /// List of processed dynamic segments; name->value pairs. pub(crate) segments: Vec<(Cow<'static, str>, PathItem)>, } @@ -83,8 +88,8 @@ impl Path { /// Set new path. #[inline] pub fn set(&mut self, path: T) { - self.skip = 0; self.path = path; + self.skip = 0; self.segments.clear(); } @@ -103,7 +108,7 @@ impl Path { pub(crate) fn add(&mut self, name: impl Into>, value: PathItem) { match value { - PathItem::Static(s) => self.segments.push((name.into(), PathItem::Static(s))), + PathItem::Static(seg) => self.segments.push((name.into(), PathItem::Static(seg))), PathItem::Segment(begin, end) => self.segments.push(( name.into(), PathItem::Segment(self.skip + begin, self.skip + end), @@ -168,9 +173,13 @@ impl Path { } } - /// Try to deserialize matching parameters to a specified type `U` - pub fn load<'de, U: serde::Deserialize<'de>>(&'de self) -> Result { - de::Deserialize::deserialize(PathDeserializer::new(self)) + /// Deserializes matching parameters to a specified type `U`. + /// + /// # Errors + /// + /// Returns error when dynamic path segments cannot be deserialized into a `U` type. + pub fn load<'de, U: Deserialize<'de>>(&'de self) -> Result { + Deserialize::deserialize(PathDeserializer::new(self)) } } From ff2904ee785698232fbcd01c20a9104ec7122ff2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Dec 2023 19:13:11 +0000 Subject: [PATCH 165/314] ci: prevent cargo-cache install failing MSRV builds --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5627865c1..d71a03d1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - name: Clear the cargo caches run: | - cargo install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean + cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean cargo-cache io-uring: From 0d9ca4d9390a4ae43f836c2e1752dea7b764cb7b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Dec 2023 19:17:56 +0000 Subject: [PATCH 166/314] chore(actix-http): prepare release 3.5.0 --- actix-http/CHANGES.md | 6 ++++-- actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- scripts/bump | 3 ++- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index eadd5c515..3068b4ce2 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,14 +2,16 @@ ## Unreleased +## 3.5.0 + ### Changed +- Implement `From` for `http::HeaderMap`. - Updated `zstd` dependency to `0.13`. -- Implemented `From` for `http::HeaderMap`. ### Fixed -- Do not encode zero-sized response bodies +- Prevent compression of zero-sized response bodies. ## 3.4.0 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 8476d9086..93a6bcbad 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.4.0" +version = "3.5.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 7d499f4b3..790de65fd 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -5,11 +5,11 @@ [![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=3.4.0)](https://docs.rs/actix-http/3.4.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.5.0)](https://docs.rs/actix-http/3.5.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.4.0/status.svg)](https://deps.rs/crate/actix-http/3.4.0) +[![dependency status](https://deps.rs/crate/actix-http/3.5.0/status.svg)](https://deps.rs/crate/actix-http/3.5.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index d9cf0b94f..200524d0c 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -75,7 +75,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3.1", default-features = false, optional = true } -actix-http = { version = "3.4", features = ["ws"] } +actix-http = { version = "3.5", features = ["ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 07811c979..294e1a56d 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -61,7 +61,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3.4", features = ["http2", "ws"] } +actix-http = { version = "3.5", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.1", features = ["connect", "uri"] } actix-utils = "3" @@ -94,7 +94,7 @@ tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, featu trust-dns-resolver = { version = "0.23", optional = true } [dev-dependencies] -actix-http = { version = "3.4", features = ["openssl"] } +actix-http = { version = "3.5", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } diff --git a/scripts/bump b/scripts/bump index 9d90542c6..68f923e75 100755 --- a/scripts/bump +++ b/scripts/bump @@ -5,7 +5,7 @@ # requires github cli tool for automatic release draft creation -set -euo pipefail +set -eEuo pipefail DIR=$1 @@ -132,6 +132,7 @@ fi if [ $MACOS ]; then printf "chore($PACKAGE_NAME): prepare release $NEW_VERSION" | pbcopy + echo "placed the recommended commit message on the clipboard" else echo echo "commit message:" From 17060ed9930dd5cfb46b0c15602e75259265aaf6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Dec 2023 19:18:29 +0000 Subject: [PATCH 167/314] chore(awc): prepare release 3.3.0 --- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 3a1996cba..6f4212f90 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.3.0 + - Update `trust-dns-resolver` dependency to `0.23`. - Updated `zstd` dependency to `0.13`. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 294e1a56d..14009fb4f 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.2.0" +version = "3.3.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 1f31167eb..035348fbd 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=3.2.0)](https://docs.rs/awc/3.2.0) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.3.0)](https://docs.rs/awc/3.3.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.2.0/status.svg)](https://deps.rs/crate/awc/3.2.0) +[![Dependency Status](https://deps.rs/crate/awc/3.3.0/status.svg)](https://deps.rs/crate/awc/3.3.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) ## Documentation & Resources From 9dc3ad754e5a7a044dd6aeeba9d4ba3dd5a90db0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 23 Dec 2023 19:19:10 +0000 Subject: [PATCH 168/314] chore(actix-web): prepare release 4.4.1 --- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 953befb7f..674c834ad 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.4.1 + ### Changed - Updated `zstd` dependency to `0.13`. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 200524d0c..d1fc9c916 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.4.0" +version = "4.4.1" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index e83397657..80ae21238 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.4.0)](https://docs.rs/actix-web/4.4.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.4.1)](https://docs.rs/actix-web/4.4.1) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.4.0/status.svg)](https://deps.rs/crate/actix-web/4.4.0) +[![Dependency Status](https://deps.rs/crate/actix-web/4.4.1/status.svg)](https://deps.rs/crate/actix-web/4.4.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 68597b5426a8ba81bb2674538bec3895cde05a00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 23 Dec 2023 19:54:02 +0000 Subject: [PATCH 169/314] build(deps): bump taiki-e/install-action from 2.22.0 to 2.23.0 (#3228) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.22.0 to 2.23.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.22.0...v2.23.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4c4a3404f..72fb7dcff 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.22.0 + uses: taiki-e/install-action@v2.23.0 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.22.0 + uses: taiki-e/install-action@v2.23.0 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest - uses: taiki-e/install-action@v2.22.0 + uses: taiki-e/install-action@v2.23.0 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d71a03d1d..721fc0378 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.22.0 + uses: taiki-e/install-action@v2.23.0 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c451df22a..927ac86bb 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.22.0 + uses: taiki-e/install-action@v2.23.0 with: tool: cargo-llvm-cov From f4851b39143dbb39587ad98f73da89eb7bab3cba Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 24 Dec 2023 16:47:46 +0000 Subject: [PATCH 170/314] chore(actix-router): prepare release 0.5.2 --- .github/workflows/ci-post-merge.yml | 2 +- actix-router/CHANGES.md | 2 ++ actix-router/Cargo.toml | 2 +- actix-router/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 72fb7dcff..f135cd171 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -71,7 +71,7 @@ jobs: - name: Clear the cargo caches run: | - cargo install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean + cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean cargo-cache ci_feature_powerset_check: diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 31316ff47..a855c0074 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.5.2 + - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 0.5.1 diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index 8a404dd20..de39944cc 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-router" -version = "0.5.1" +version = "0.5.2" authors = [ "Nikolay Kim ", "Ali MJ Al-Nasrawy ", diff --git a/actix-router/README.md b/actix-router/README.md index 15a449c44..7dc0c9010 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -1,11 +1,11 @@ # `actix-router` [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) -[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.1)](https://docs.rs/actix-router/0.5.1) +[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg)
-[![dependency status](https://deps.rs/crate/actix-router/0.5.1/status.svg)](https://deps.rs/crate/actix-router/0.5.1) +[![dependency status](https://deps.rs/crate/actix-router/0.5.2/status.svg)](https://deps.rs/crate/actix-router/0.5.2) [![Download](https://img.shields.io/crates/d/actix-router.svg)](https://crates.io/crates/actix-router) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From d14e98b62b866e75c84baa19e36bf2d0bb7d49e7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 25 Dec 2023 02:27:51 +0000 Subject: [PATCH 171/314] prevent hang when compressing Sized(0) bodies fixes #3229 --- actix-http/CHANGES.md | 4 ++++ actix-http/src/encoding/encoder.rs | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 3068b4ce2..053c4e512 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +## Fixed + +- Prevent hang when returning zero-sized response bodies through compression layer. + ## 3.5.0 ### Changed diff --git a/actix-http/src/encoding/encoder.rs b/actix-http/src/encoding/encoder.rs index e084aa564..180927ac6 100644 --- a/actix-http/src/encoding/encoder.rs +++ b/actix-http/src/encoding/encoder.rs @@ -50,10 +50,21 @@ impl Encoder { } } + fn empty() -> Self { + Encoder { + body: EncoderBody::Full { body: Bytes::new() }, + encoder: None, + fut: None, + eof: true, + } + } + pub fn response(encoding: ContentEncoding, head: &mut ResponseHead, body: B) -> Self { - // no need to compress an empty body - if matches!(body.size(), BodySize::None | BodySize::Sized(0)) { - return Self::none(); + // no need to compress empty bodies + match body.size() { + BodySize::None => return Self::none(), + BodySize::Sized(0) => return Self::empty(), + _ => {} } let should_encode = !(head.headers().contains_key(&CONTENT_ENCODING) From f4f459d4209da58fe0c2794617c95b06fd9d0fc7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 25 Dec 2023 02:30:14 +0000 Subject: [PATCH 172/314] chore(actix-http): prepare release 3.5.1 --- actix-http/CHANGES.md | 2 ++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 053c4e512..8a59f4337 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.1 + ## Fixed - Prevent hang when returning zero-sized response bodies through compression layer. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 93a6bcbad..6c53f35cc 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.5.0" +version = "3.5.1" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 790de65fd..9d80c10c4 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -5,11 +5,11 @@ [![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=3.5.0)](https://docs.rs/actix-http/3.5.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.5.1)](https://docs.rs/actix-http/3.5.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.5.0/status.svg)](https://deps.rs/crate/actix-http/3.5.0) +[![dependency status](https://deps.rs/crate/actix-http/3.5.1/status.svg)](https://deps.rs/crate/actix-http/3.5.1) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 1c88af50c07ef704a8899d7b3eff954d9513a6d2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 25 Dec 2023 02:35:22 +0000 Subject: [PATCH 173/314] docs: fix changelog --- actix-http/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 8a59f4337..bec367994 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,7 +4,7 @@ ## 3.5.1 -## Fixed +### Fixed - Prevent hang when returning zero-sized response bodies through compression layer. From ccb90dd5a195e278d3a00795454063c391daf990 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 25 Dec 2023 02:36:17 +0000 Subject: [PATCH 174/314] docs: update changelog --- actix-http/CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index bec367994..994c91a83 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -10,9 +10,12 @@ ## 3.5.0 -### Changed +### Added - Implement `From` for `http::HeaderMap`. + +### Changed + - Updated `zstd` dependency to `0.13`. ### Fixed From 561cc440b2405746d3de01f6983c9c8616a370fb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 14:10:13 +0000 Subject: [PATCH 175/314] build(deps): bump taiki-e/install-action from 2.23.0 to 2.23.7 (#3232) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.23.0 to 2.23.7. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.23.0...v2.23.7) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index f135cd171..df6f21684 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.0 + uses: taiki-e/install-action@v2.23.7 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.0 + uses: taiki-e/install-action@v2.23.7 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest - uses: taiki-e/install-action@v2.23.0 + uses: taiki-e/install-action@v2.23.7 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 721fc0378..81139fa23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.0 + uses: taiki-e/install-action@v2.23.7 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 927ac86bb..810ea33dd 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.23.0 + uses: taiki-e/install-action@v2.23.7 with: tool: cargo-llvm-cov From febba786fa00a61c6be6c26db148a29261b056c9 Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Sat, 6 Jan 2024 11:11:40 +0100 Subject: [PATCH 176/314] actix-files: Properly handle newlines in file names (#3235) --- actix-files/CHANGES.md | 1 + actix-files/src/lib.rs | 22 +++++++++++++++++++++- actix-files/src/named.rs | 7 ++++--- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 15c2958f0..81e361a21 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. +- Properly handle newlines in filenames. [#3235] ## 0.6.3 diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 943130e16..87914c1ce 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -568,6 +568,26 @@ mod tests { assert_eq!(bytes, data); } + #[actix_rt::test] + async fn test_static_files_with_newlines() { + // Create the file we want to test against ad-hoc. We can't check it in as otherwise + // Windows can't even checkout this repository. + let tmpdir = tempfile::tempdir().unwrap(); + let file_with_newlines = tmpdir.path().join("test\nnewline.text"); + fs::write(&file_with_newlines, "Look at my newlines").unwrap(); + let srv = test::init_service( + App::new().service(Files::new("", tmpdir.path()).index_file("Cargo.toml")), + ) + .await; + let request = TestRequest::get().uri("/test%0Anewline.text").to_request(); + let response = test::call_service(&srv, request).await; + assert_eq!(response.status(), StatusCode::OK); + + let bytes = test::read_body(response).await; + let data = web::Bytes::from(fs::read(file_with_newlines).unwrap()); + assert_eq!(bytes, data); + } + #[actix_rt::test] async fn test_files_not_allowed() { let srv = test::init_service(App::new().service(Files::new("/", "."))).await; @@ -842,7 +862,7 @@ mod tests { async fn test_percent_encoding_2() { let tmpdir = tempfile::tempdir().unwrap(); let filename = match cfg!(unix) { - true => "ض:?#[]{}<>()@!$&'`|*+,;= %20.test", + true => "ض:?#[]{}<>()@!$&'`|*+,;= %20\n.test", false => "ض#[]{}()@!$&'`+,;= %20.test", }; let filename_encoded = filename diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index d7795ba73..02dc701ea 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -24,7 +24,6 @@ use bitflags::bitflags; use derive_more::{Deref, DerefMut}; use futures_core::future::LocalBoxFuture; use mime::Mime; -use mime_guess::from_path; use crate::{encoding::equiv_utf8_text, range::HttpRange}; @@ -128,7 +127,7 @@ impl NamedFile { } }; - let ct = from_path(&path).first_or_octet_stream(); + let ct = mime_guess::from_path(&path).first_or_octet_stream(); let disposition = match ct.type_() { mime::IMAGE | mime::TEXT | mime::AUDIO | mime::VIDEO => DispositionType::Inline, @@ -140,7 +139,9 @@ impl NamedFile { _ => DispositionType::Attachment, }; - let mut parameters = vec![DispositionParam::Filename(String::from(filename.as_ref()))]; + // Replace newlines in filenames which could occur on some filesystems. + let filename_s = filename.replace('\n', "%0A"); + let mut parameters = vec![DispositionParam::Filename(filename_s)]; if !filename.is_ascii() { parameters.push(DispositionParam::FilenameExt(ExtendedValue { From 46dde69d502d6800fadec2bf1401586b6090ee11 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 6 Jan 2024 10:19:15 +0000 Subject: [PATCH 177/314] chore(actix-files): prepare release 0.6.4 --- actix-files/CHANGES.md | 4 +++- actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 ++-- actix-files/src/lib.rs | 13 +++++++------ 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 81e361a21..ac0fbfedc 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,8 +2,10 @@ ## Unreleased +## 0.6.4 + +- Fix handling of newlines in filenames. - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. -- Properly handle newlines in filenames. [#3235] ## 0.6.3 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index efecb0889..b7a272515 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.6.3" +version = "0.6.4" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-files/README.md b/actix-files/README.md index 3e656c431..d8d9e4f1f 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -3,11 +3,11 @@ > Static file serving for Actix Web [![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.6.3)](https://docs.rs/actix-files/0.6.3) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.4)](https://docs.rs/actix-files/0.6.4) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
-[![dependency status](https://deps.rs/crate/actix-files/0.6.3/status.svg)](https://deps.rs/crate/actix-files/0.6.3) +[![dependency status](https://deps.rs/crate/actix-files/0.6.4/status.svg)](https://deps.rs/crate/actix-files/0.6.4) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 87914c1ce..8ceb59bef 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -572,11 +572,12 @@ mod tests { async fn test_static_files_with_newlines() { // Create the file we want to test against ad-hoc. We can't check it in as otherwise // Windows can't even checkout this repository. - let tmpdir = tempfile::tempdir().unwrap(); - let file_with_newlines = tmpdir.path().join("test\nnewline.text"); + let temp_dir = tempfile::tempdir().unwrap(); + let file_with_newlines = temp_dir.path().join("test\nnewline.text"); fs::write(&file_with_newlines, "Look at my newlines").unwrap(); + let srv = test::init_service( - App::new().service(Files::new("", tmpdir.path()).index_file("Cargo.toml")), + App::new().service(Files::new("/", temp_dir.path()).index_file("Cargo.toml")), ) .await; let request = TestRequest::get().uri("/test%0Anewline.text").to_request(); @@ -860,7 +861,7 @@ mod tests { #[actix_rt::test] async fn test_percent_encoding_2() { - let tmpdir = tempfile::tempdir().unwrap(); + let temp_dir = tempfile::tempdir().unwrap(); let filename = match cfg!(unix) { true => "ض:?#[]{}<>()@!$&'`|*+,;= %20\n.test", false => "ض#[]{}()@!$&'`+,;= %20.test", @@ -872,9 +873,9 @@ mod tests { write!(&mut buf, "%{:02X}", c).unwrap(); buf }); - std::fs::File::create(tmpdir.path().join(filename)).unwrap(); + std::fs::File::create(temp_dir.path().join(filename)).unwrap(); - let srv = test::init_service(App::new().service(Files::new("", tmpdir.path()))).await; + let srv = test::init_service(App::new().service(Files::new("/", temp_dir.path()))).await; let req = TestRequest::get() .uri(&format!("/{}", filename_encoded)) From d2bd549eece6328aad7f2cef63881bd8ca1e1cd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 01:25:54 +0000 Subject: [PATCH 178/314] build(deps): bump taiki-e/install-action from 2.23.7 to 2.24.1 (#3239) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.23.7 to 2.24.1. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.23.7...v2.24.1) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index df6f21684..394d447a4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.7 + uses: taiki-e/install-action@v2.24.1 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.7 + uses: taiki-e/install-action@v2.24.1 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 - name: Install nextest - uses: taiki-e/install-action@v2.23.7 + uses: taiki-e/install-action@v2.24.1 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81139fa23..bcab62192 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.23.7 + uses: taiki-e/install-action@v2.24.1 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 810ea33dd..bdd15198b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.23.7 + uses: taiki-e/install-action@v2.24.1 with: tool: cargo-llvm-cov From ac04d80d8e447f229ecef0d44d0b61edbcd4957e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 8 Jan 2024 15:17:36 +0000 Subject: [PATCH 179/314] docs: better docs for peer_addr methods --- actix-http/src/requests/head.rs | 3 ++ actix-http/src/requests/request.rs | 2 +- actix-web/src/service.rs | 7 +-- actix-web/src/test/test_request.rs | 77 ++++++++++++++++-------------- scripts/bump | 16 +++++-- 5 files changed, 60 insertions(+), 45 deletions(-) diff --git a/actix-http/src/requests/head.rs b/actix-http/src/requests/head.rs index 4558801f3..2e0c2dbd4 100644 --- a/actix-http/src/requests/head.rs +++ b/actix-http/src/requests/head.rs @@ -16,7 +16,10 @@ pub struct RequestHead { pub uri: Uri, pub version: Version, pub headers: HeaderMap, + + /// Will only be None when called in unit tests unless [`TestRequest::peer_addr`] is used. pub peer_addr: Option, + flags: Flags, } diff --git a/actix-http/src/requests/request.rs b/actix-http/src/requests/request.rs index 1750fb2f7..6a267a7a6 100644 --- a/actix-http/src/requests/request.rs +++ b/actix-http/src/requests/request.rs @@ -173,7 +173,7 @@ impl

Request

{ /// Peer address is the directly connected peer's socket address. If a proxy is used in front of /// the Actix Web server, then it would be address of this proxy. /// - /// Will only return None when called in unit tests. + /// Will only return None when called in unit tests unless set manually. #[inline] pub fn peer_addr(&self) -> Option { self.head().peer_addr diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index 0e17c9949..451224833 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -221,12 +221,9 @@ impl ServiceRequest { /// Returns peer's socket address. /// - /// Peer address is the directly connected peer's socket address. If a proxy is used in front of - /// the Actix Web server, then it would be address of this proxy. + /// See [`HttpRequest::peer_addr`] for more details. /// - /// To get client connection information `ConnectionInfo` should be used. - /// - /// Will only return None when called in unit tests. + /// [`HttpRequest::peer_addr`]: crate::HttpRequest::peer_addr #[inline] pub fn peer_addr(&self) -> Option { self.head().peer_addr diff --git a/actix-web/src/test/test_request.rs b/actix-web/src/test/test_request.rs index 5491af0ac..a3945456d 100644 --- a/actix-web/src/test/test_request.rs +++ b/actix-web/src/test/test_request.rs @@ -86,76 +86,77 @@ impl Default for TestRequest { #[allow(clippy::wrong_self_convention)] impl TestRequest { - /// Create TestRequest and set request uri - pub fn with_uri(path: &str) -> TestRequest { - TestRequest::default().uri(path) + /// Constructs test request and sets request URI. + pub fn with_uri(uri: &str) -> TestRequest { + TestRequest::default().uri(uri) } - /// Create TestRequest and set method to `Method::GET` + /// Constructs test request with GET method. pub fn get() -> TestRequest { TestRequest::default().method(Method::GET) } - /// Create TestRequest and set method to `Method::POST` + /// Constructs test request with POST method. pub fn post() -> TestRequest { TestRequest::default().method(Method::POST) } - /// Create TestRequest and set method to `Method::PUT` + /// Constructs test request with PUT method. pub fn put() -> TestRequest { TestRequest::default().method(Method::PUT) } - /// Create TestRequest and set method to `Method::PATCH` + /// Constructs test request with PATCH method. pub fn patch() -> TestRequest { TestRequest::default().method(Method::PATCH) } - /// Create TestRequest and set method to `Method::DELETE` + /// Constructs test request with DELETE method. pub fn delete() -> TestRequest { TestRequest::default().method(Method::DELETE) } - /// Set HTTP version of this request + /// Sets HTTP version of this request. pub fn version(mut self, ver: Version) -> Self { self.req.version(ver); self } - /// Set HTTP method of this request + /// Sets method of this request. pub fn method(mut self, meth: Method) -> Self { self.req.method(meth); self } - /// Set HTTP URI of this request + /// Sets URI of this request. pub fn uri(mut self, path: &str) -> Self { self.req.uri(path); self } - /// Insert a header, replacing any that were set with an equivalent field name. + /// Inserts a header, replacing any that were set with an equivalent field name. pub fn insert_header(mut self, header: impl TryIntoHeaderPair) -> Self { self.req.insert_header(header); self } - /// Append a header, keeping any that were set with an equivalent field name. + /// Appends a header, keeping any that were set with an equivalent field name. pub fn append_header(mut self, header: impl TryIntoHeaderPair) -> Self { self.req.append_header(header); self } - /// Set cookie for this request. + /// Sets cookie for this request. #[cfg(feature = "cookies")] pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { self.cookies.add(cookie.into_owned()); self } - /// Set request path pattern parameter. + /// Sets request path pattern parameter. /// /// # Examples + /// /// ``` /// use actix_web::test::TestRequest; /// @@ -171,19 +172,19 @@ impl TestRequest { self } - /// Set peer addr. + /// Sets peer address. pub fn peer_addr(mut self, addr: SocketAddr) -> Self { self.peer_addr = Some(addr); self } - /// Set request payload. + /// Sets request payload. pub fn set_payload(mut self, data: impl Into) -> Self { self.req.set_payload(data); self } - /// Serialize `data` to a URL encoded form and set it as the request payload. + /// Serializes `data` to a URL encoded form and set it as the request payload. /// /// The `Content-Type` header is set to `application/x-www-form-urlencoded`. pub fn set_form(mut self, data: impl Serialize) -> Self { @@ -194,7 +195,7 @@ impl TestRequest { self } - /// Serialize `data` to JSON and set it as the request payload. + /// Serializes `data` to JSON and set it as the request payload. /// /// The `Content-Type` header is set to `application/json`. pub fn set_json(mut self, data: impl Serialize) -> Self { @@ -204,27 +205,33 @@ impl TestRequest { self } - /// Set application data. This is equivalent of `App::data()` method - /// for testing purpose. - pub fn data(mut self, data: T) -> Self { - self.app_data.insert(Data::new(data)); - self - } - - /// Set application data. This is equivalent of `App::app_data()` method - /// for testing purpose. + /// Inserts application data. + /// + /// This is equivalent of `App::app_data()` method for testing purpose. pub fn app_data(mut self, data: T) -> Self { self.app_data.insert(data); self } + /// Inserts application data. + /// + /// This is equivalent of `App::data()` method for testing purpose. + #[doc(hidden)] + pub fn data(mut self, data: T) -> Self { + self.app_data.insert(Data::new(data)); + self + } + + /// Sets resource map. #[cfg(test)] - /// Set request config pub(crate) fn rmap(mut self, rmap: ResourceMap) -> Self { self.rmap = rmap; self } + /// Finalizes test request. + /// + /// This request builder will be useless after calling `finish()`. fn finish(&mut self) -> Request { // mut used when cookie feature is enabled #[allow(unused_mut)] @@ -251,14 +258,14 @@ impl TestRequest { req } - /// Complete request creation and generate `Request` instance + /// Finalizes request creation and returns `Request` instance. pub fn to_request(mut self) -> Request { let mut req = self.finish(); req.head_mut().peer_addr = self.peer_addr; req } - /// Complete request creation and generate `ServiceRequest` instance + /// Finalizes request creation and returns `ServiceRequest` instance. pub fn to_srv_request(mut self) -> ServiceRequest { let (mut head, payload) = self.finish().into_parts(); head.peer_addr = self.peer_addr; @@ -279,12 +286,12 @@ impl TestRequest { ) } - /// Complete request creation and generate `ServiceResponse` instance + /// Finalizes request creation and returns `ServiceResponse` instance. pub fn to_srv_response(self, res: HttpResponse) -> ServiceResponse { self.to_srv_request().into_response(res) } - /// Complete request creation and generate `HttpRequest` instance + /// Finalizes request creation and returns `HttpRequest` instance. pub fn to_http_request(mut self) -> HttpRequest { let (mut head, _) = self.finish().into_parts(); head.peer_addr = self.peer_addr; @@ -302,7 +309,7 @@ impl TestRequest { ) } - /// Complete request creation and generate `HttpRequest` and `Payload` instances + /// Finalizes request creation and returns `HttpRequest` and `Payload` pair. pub fn to_http_parts(mut self) -> (HttpRequest, Payload) { let (mut head, payload) = self.finish().into_parts(); head.peer_addr = self.peer_addr; @@ -322,7 +329,7 @@ impl TestRequest { (req, payload) } - /// Complete request creation, calls service and waits for response future completion. + /// Finalizes request creation, calls service, and waits for response future completion. pub async fn send_request(self, app: &S) -> S::Response where S: Service, Error = E>, diff --git a/scripts/bump b/scripts/bump index 68f923e75..22aa2af95 100755 --- a/scripts/bump +++ b/scripts/bump @@ -112,17 +112,25 @@ echo read -p "Update all references: (y/N) " UPDATE_REFERENCES UPDATE_REFERENCES="${UPDATE_REFERENCES:-n}" + if [ "$UPDATE_REFERENCES" = 'y' ] || [ "$UPDATE_REFERENCES" = 'Y' ]; then + if [[ $NEW_VERSION == *".0.0" ]]; then + NEW_VERSION_SPEC="${NEW_VERSION%.0.0}" + elif [[ $NEW_VERSION == *".0" ]]; then + NEW_VERSION_SPEC="${NEW_VERSION%.0}" + else + NEW_VERSION_SPEC="$NEW_VERSION" + fi for f in $(fd Cargo.toml); do sed -i.bak -E \ - "s/^(${PACKAGE_NAME} ?= ?\")[^\"]+(\")$/\1${NEW_VERSION}\2/g" $f + "s/^(${PACKAGE_NAME} ?= ?\")[^\"]+(\")$/\1${NEW_VERSION_SPEC}\2/g" $f sed -i.bak -E \ - "s/^(${PACKAGE_NAME} ?=.*version ?= ?\")[^\"]+(\".*)$/\1${NEW_VERSION}\2/g" $f + "s/^(${PACKAGE_NAME} ?=.*version ?= ?\")[^\"]+(\".*)$/\1${NEW_VERSION_SPEC}\2/g" $f sed -i.bak -E \ - "s/^(.*package ?= ?\"${PACKAGE_NAME}\".*version ?= ?\")[^\"]+(\".*)$/\1${NEW_VERSION}\2/g" $f + "s/^(.*package ?= ?\"${PACKAGE_NAME}\".*version ?= ?\")[^\"]+(\".*)$/\1${NEW_VERSION_SPEC}\2/g" $f sed -i.bak -E \ - "s/^(.*version ?= ?\")[^\"]+(\".*package ?= ?\"${PACKAGE_NAME}\".*)$/\1${NEW_VERSION}\2/g" $f + "s/^(.*version ?= ?\")[^\"]+(\".*package ?= ?\"${PACKAGE_NAME}\".*)$/\1${NEW_VERSION_SPEC}\2/g" $f # remove backup file rm -f $f.bak From fcfc727295b67abe4568ab580316a62fa302a827 Mon Sep 17 00:00:00 2001 From: Dialga Date: Wed, 10 Jan 2024 16:56:15 +1300 Subject: [PATCH 180/314] actix-files: fix handling linebreaks in filenames (#3237) Co-authored-by: Rob Ede --- actix-files/CHANGES.md | 2 ++ actix-files/src/lib.rs | 8 +++++--- actix-files/src/named.rs | 8 ++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index ac0fbfedc..2958eae66 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Fix handling of special characters in filenames. + ## 0.6.4 - Fix handling of newlines in filenames. diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 8ceb59bef..5b1f14eed 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -569,18 +569,20 @@ mod tests { } #[actix_rt::test] - async fn test_static_files_with_newlines() { + async fn test_static_files_with_special_characters() { // Create the file we want to test against ad-hoc. We can't check it in as otherwise // Windows can't even checkout this repository. let temp_dir = tempfile::tempdir().unwrap(); - let file_with_newlines = temp_dir.path().join("test\nnewline.text"); + let file_with_newlines = temp_dir.path().join("test\n\x0B\x0C\rnewline.text"); fs::write(&file_with_newlines, "Look at my newlines").unwrap(); let srv = test::init_service( App::new().service(Files::new("/", temp_dir.path()).index_file("Cargo.toml")), ) .await; - let request = TestRequest::get().uri("/test%0Anewline.text").to_request(); + let request = TestRequest::get() + .uri("/test%0A%0B%0C%0Dnewline.text") + .to_request(); let response = test::call_service(&srv, request).await; assert_eq!(response.status(), StatusCode::OK); diff --git a/actix-files/src/named.rs b/actix-files/src/named.rs index 02dc701ea..9e4a37737 100644 --- a/actix-files/src/named.rs +++ b/actix-files/src/named.rs @@ -139,8 +139,12 @@ impl NamedFile { _ => DispositionType::Attachment, }; - // Replace newlines in filenames which could occur on some filesystems. - let filename_s = filename.replace('\n', "%0A"); + // replace special characters in filenames which could occur on some filesystems + let filename_s = filename + .replace('\n', "%0A") // \n line break + .replace('\x0B', "%0B") // \v vertical tab + .replace('\x0C', "%0C") // \f form feed + .replace('\r', "%0D"); // \r carriage return let mut parameters = vec![DispositionParam::Filename(filename_s)]; if !filename.is_ascii() { From 33da4807092e39f11ac164d937a8e48b91c85862 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 10 Jan 2024 04:00:20 +0000 Subject: [PATCH 181/314] format project --- .prettierrc.yml | 2 +- actix-files/README.md | 6 +++++- actix-http-test/README.md | 6 +++++- actix-multipart-derive/README.md | 6 +++++- actix-multipart/README.md | 6 +++++- actix-router/README.md | 4 ++++ actix-web-actors/README.md | 6 +++++- actix-web-codegen/README.md | 6 +++++- awc/README.md | 6 +++++- justfile | 5 +++++ 10 files changed, 45 insertions(+), 8 deletions(-) diff --git a/.prettierrc.yml b/.prettierrc.yml index b61fd8974..d70303479 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1,5 +1,5 @@ overrides: - - files: '*.md' + - files: "*.md" options: printWidth: 9999 proseWrap: never diff --git a/actix-files/README.md b/actix-files/README.md index d8d9e4f1f..c2dbc87f9 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -1,7 +1,9 @@ -# actix-files +# `actix-files` > Static file serving for Actix Web + + [![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.6.4)](https://docs.rs/actix-files/0.6.4) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-files) diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 4b286e603..e544c3616 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -1,7 +1,9 @@ -# actix-http-test +# `actix-http-test` > Various helpers for Actix applications to use during testing. + + [![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=3.1.0)](https://docs.rs/actix-http-test/3.1.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-http-test.svg)](https://crates.io/crates/actix-http-test) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-http-test) diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index cd5780c56..2beadefe3 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -1,7 +1,9 @@ -# actix-multipart-derive +# `actix-multipart-derive` > The derive macro implementation for actix-multipart-derive. + + [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) [![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart-derive/0.6.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-multipart-derive.svg)](https://crates.io/crates/actix-multipart-derive) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart-derive) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 8fe0328ab..16068510e 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -1,7 +1,9 @@ -# actix-multipart +# `actix-multipart` > Multipart form support for Actix Web. + + [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) [![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-multipart) diff --git a/actix-router/README.md b/actix-router/README.md index 7dc0c9010..7760b0331 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -1,5 +1,7 @@ # `actix-router` + + [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) [![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -9,6 +11,8 @@ [![Download](https://img.shields.io/crates/d/actix-router.svg)](https://crates.io/crates/actix-router) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + Resource path matching and router. diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index b2c30b954..c81fe64c1 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -1,7 +1,9 @@ -# actix-web-actors +# `actix-web-actors` > Actix actors support for Actix Web. + + [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) [![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.2.0)](https://docs.rs/actix-web-actors/4.2.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-web-actors.svg)](https://crates.io/crates/actix-web-actors) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-actors) diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index e9a1f9c7e..088f35756 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -1,7 +1,9 @@ -# actix-web-codegen +# `actix-web-codegen` > Routing and runtime macros for Actix Web. + + [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) [![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) @@ -11,6 +13,8 @@ [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/actix-web-codegen) diff --git a/awc/README.md b/awc/README.md index 035348fbd..424c86bba 100644 --- a/awc/README.md +++ b/awc/README.md @@ -1,13 +1,17 @@ -# awc (Actix Web Client) +# `awc` (Actix Web Client) > 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=3.3.0)](https://docs.rs/awc/3.3.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) [![Dependency Status](https://deps.rs/crate/awc/3.3.0/status.svg)](https://deps.rs/crate/awc/3.3.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + ## Documentation & Resources - [API Documentation](https://docs.rs/awc) diff --git a/justfile b/justfile index f2e449d85..2142e9bc5 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,11 @@ _list: @just --list +# Format workspace. +fmt: + cargo +nightly fmt + npx -y prettier --write $(fd --type=file --hidden --extension=md --extension=yml) + # Document crates in workspace. doc: RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl From 83be07d77de4d463558769cc571bb16fd082c8af Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 10 Jan 2024 04:01:14 +0000 Subject: [PATCH 182/314] chore(actix-files): prepare release 0.6.5 --- actix-files/CHANGES.md | 2 ++ actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 2958eae66..9aa62ff77 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.5 + - Fix handling of special characters in filenames. ## 0.6.4 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index b7a272515..098d71bd7 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.6.4" +version = "0.6.5" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-files/README.md b/actix-files/README.md index c2dbc87f9..e805d0418 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -5,11 +5,11 @@ [![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.6.4)](https://docs.rs/actix-files/0.6.4) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.5)](https://docs.rs/actix-files/0.6.5) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
-[![dependency status](https://deps.rs/crate/actix-files/0.6.4/status.svg)](https://deps.rs/crate/actix-files/0.6.4) +[![dependency status](https://deps.rs/crate/actix-files/0.6.5/status.svg)](https://deps.rs/crate/actix-files/0.6.5) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 08a9c665680807d9129c4a6fc54fadd498c24e43 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 10 Jan 2024 04:03:29 +0000 Subject: [PATCH 183/314] docs(files: update readme from crate docs --- actix-files/README.md | 22 ++++++++++++++++------ justfile | 5 +++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/actix-files/README.md b/actix-files/README.md index e805d0418..df80e4047 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -1,7 +1,5 @@ # `actix-files` -> Static file serving for Actix Web - [![crates.io](https://img.shields.io/crates/v/actix-files?label=latest)](https://crates.io/crates/actix-files) @@ -15,8 +13,20 @@ -## Documentation & Resources + -- [API Documentation](https://docs.rs/actix-files) -- [Example Project](https://github.com/actix/examples/tree/master/basics/static-files) -- Minimum Supported Rust Version (MSRV): 1.68 +Static file serving for Actix Web. + +Provides a non-blocking service for serving static files from disk. + +## Examples + +```rust +use actix_web::App; +use actix_files::Files; + +let app = App::new() + .service(Files::new("/static", ".").prefer_utf8(true)); +``` + + diff --git a/justfile b/justfile index 2142e9bc5..42979f18c 100644 --- a/justfile +++ b/justfile @@ -14,3 +14,8 @@ doc: doc-watch: RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl + +# Update READMEs from crate root documentation. +update-readmes: && fmt + cd ./actix-files && cargo rdme --force + cd ./actix-router && cargo rdme --force From ba53c4f87512524b5e66fb4bc18becee4313b32a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 01:24:21 +0000 Subject: [PATCH 184/314] build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.6.0 to 1.8.0 (#3247) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 6 +++--- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 8 ++++---- .github/workflows/upload-doc.yml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 394d447a4..904edcdb9 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -40,7 +40,7 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: ${{ matrix.version.version }} @@ -82,7 +82,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack uses: taiki-e/install-action@v2.24.1 @@ -103,7 +103,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest uses: taiki-e/install-action@v2.24.1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bcab62192..562e4d339 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: ${{ matrix.version.version }} @@ -93,7 +93,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly @@ -109,7 +109,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bdd15198b..038c0360e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: components: llvm-tools-preview diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 13362dbb0..5d427aa90 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly components: rustfmt @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: components: clippy @@ -53,7 +53,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly components: rust-docs @@ -72,7 +72,7 @@ jobs: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly-2023-08-25 diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml index f4bd0ceeb..963b7f6b3 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.6.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly From e442b00c8ce1c76ca70131c585d9578785381a03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 01:24:48 +0000 Subject: [PATCH 185/314] build(deps): bump taiki-e/install-action from 2.24.1 to 2.25.1 (#3246) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 904edcdb9..0385f46f8 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.25.1 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.25.1 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.25.1 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 562e4d339..687fc45bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.25.1 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 038c0360e..80d46161b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.25.1 with: tool: cargo-llvm-cov From 2915bb7d90e7c3dc2f511b9608e1330d250a4ea2 Mon Sep 17 00:00:00 2001 From: John Vandenberg Date: Tue, 16 Jan 2024 19:29:06 +0800 Subject: [PATCH 186/314] chore: fix typos (#3248) --- actix-web/MIGRATION-4.0.md | 4 ++-- actix-web/src/data.rs | 2 +- actix-web/src/guard/acceptable.rs | 2 +- actix-web/src/guard/host.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/actix-web/MIGRATION-4.0.md b/actix-web/MIGRATION-4.0.md index 0f0bd3a53..08c89635a 100644 --- a/actix-web/MIGRATION-4.0.md +++ b/actix-web/MIGRATION-4.0.md @@ -372,13 +372,13 @@ You may need to review the [guidance on shared mutable state](https://docs.rs/ac HttpServer::new(|| { - App::new() - .data(MyState::default()) -- .service(hander) +- .service(handler) + let my_state: Data = Data::new(MyState::default()); + + App::new() + .app_data(my_state) -+ .service(hander) ++ .service(handler) }) ``` diff --git a/actix-web/src/data.rs b/actix-web/src/data.rs index ebb98af3f..acbb8e23a 100644 --- a/actix-web/src/data.rs +++ b/actix-web/src/data.rs @@ -69,7 +69,7 @@ pub(crate) type FnDataFactory = /// HttpResponse::Ok() /// } /// -/// /// Alteratively, use the `HttpRequest::app_data` method to access data in a handler. +/// /// Alternatively, use the `HttpRequest::app_data` method to access data in a handler. /// async fn index_alt(req: HttpRequest) -> impl Responder { /// let data = req.app_data::>>().unwrap(); /// let mut my_data = data.lock().unwrap(); diff --git a/actix-web/src/guard/acceptable.rs b/actix-web/src/guard/acceptable.rs index a31494a18..8fa7165c8 100644 --- a/actix-web/src/guard/acceptable.rs +++ b/actix-web/src/guard/acceptable.rs @@ -20,7 +20,7 @@ use crate::http::header::Accept; pub struct Acceptable { mime: mime::Mime, - /// Wether to match `*/*` mime type. + /// Whether to match `*/*` mime type. /// /// Defaults to false because it's not very useful otherwise. match_star_star: bool, diff --git a/actix-web/src/guard/host.rs b/actix-web/src/guard/host.rs index f05c81183..a971a3e30 100644 --- a/actix-web/src/guard/host.rs +++ b/actix-web/src/guard/host.rs @@ -2,7 +2,7 @@ use actix_http::{header, uri::Uri, RequestHead}; use super::{Guard, GuardContext}; -/// Creates a guard that matches requests targetting a specific host. +/// Creates a guard that matches requests targeting a specific host. /// /// # Matching Host /// This guard will: From d453b15dddfbb81ed67237e7e940413328ab7a88 Mon Sep 17 00:00:00 2001 From: Vojtech Kral Date: Thu, 18 Jan 2024 13:32:27 +0100 Subject: [PATCH 187/314] docs: mention result is wrapped in Data in data_factory() docs (#3251) --- actix-web/src/app.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index 06b66f62c..26b278bcc 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -129,6 +129,8 @@ where /// /// Data items are constructed during application initialization, before the server starts /// accepting requests. + /// + /// The returned data value `D` is wrapped as [`Data`]. pub fn data_factory(mut self, data: F) -> Self where F: Fn() -> Out + 'static, From ea8cd6e9763436677bf5efaebdf0b51e864134bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 01:06:55 +0000 Subject: [PATCH 188/314] build(deps): bump taiki-e/install-action from 2.25.1 to 2.25.9 (#3252) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 0385f46f8..e63821892 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.1 + uses: taiki-e/install-action@v2.25.9 with: tool: cargo-hack @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.1 + uses: taiki-e/install-action@v2.25.9 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.25.1 + uses: taiki-e/install-action@v2.25.9 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 687fc45bc..9dcd8fab9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.1 + uses: taiki-e/install-action@v2.25.9 with: tool: cargo-hack diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 80d46161b..2722da084 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.25.1 + uses: taiki-e/install-action@v2.25.9 with: tool: cargo-llvm-cov From a7375b687658790122c72e27e476affdd7bc1cb6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 22 Jan 2024 02:19:19 +0000 Subject: [PATCH 189/314] ci: faster cargo-public-api install (#3255) --- .github/workflows/lint.yml | 22 ++++++++++++++-------- actix-http/src/requests/head.rs | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5d427aa90..adcb257b5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,12 +17,13 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + - name: Install Rust (nightly) + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly components: rustfmt - - name: Check with rustfmt + - name: Check with Rustfmt run: cargo fmt --all -- --check clippy: @@ -53,7 +54,8 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + - name: Install Rust (nightly) + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly components: rust-docs @@ -66,21 +68,25 @@ jobs: public-api-diff: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout main branch + uses: actions/checkout@v4 with: ref: ${{ github.base_ref }} - - uses: actions/checkout@v4 + - name: Checkout PR branch + uses: actions/checkout@v4 - - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + - name: Install Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: nightly-2023-08-25 - - uses: taiki-e/cache-cargo-install-action@v1.3.0 + - name: Install cargo-public-api + uses: taiki-e/install-action@v2.24.1 with: tool: cargo-public-api - - name: generate API diff + - name: Generate API diff run: | for f in $(find -mindepth 2 -maxdepth 2 -name Cargo.toml); do cargo public-api --manifest-path "$f" diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} diff --git a/actix-http/src/requests/head.rs b/actix-http/src/requests/head.rs index 2e0c2dbd4..9ceb2a20c 100644 --- a/actix-http/src/requests/head.rs +++ b/actix-http/src/requests/head.rs @@ -17,7 +17,7 @@ pub struct RequestHead { pub version: Version, pub headers: HeaderMap, - /// Will only be None when called in unit tests unless [`TestRequest::peer_addr`] is used. + /// Will only be None when called in unit tests unless set manually. pub peer_addr: Option, flags: Flags, From 891ab083c6d497db2f6adde7767b41e367ca8907 Mon Sep 17 00:00:00 2001 From: Bruno Paulino Date: Wed, 24 Jan 2024 15:17:42 +0100 Subject: [PATCH 190/314] actix-http: Bump h2 to fix a resource exhaustion vulnerability (#3262) Co-authored-by: Rob Ede --- 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 6c53f35cc..e7d50c313 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -89,7 +89,7 @@ tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } # http2 -h2 = { version = "0.3.17", optional = true } +h2 = { version = "0.3.24", optional = true } # websockets local-channel = { version = "0.1", optional = true } From 643a80bff2dec42f3c9aa287de67c88a505d4638 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 1 Feb 2024 05:41:28 +0000 Subject: [PATCH 191/314] ci: workaround half crate msrv --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9dcd8fab9..7d4d1a4b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,6 +57,8 @@ jobs: - name: workaround MSRV issues if: matrix.version.name == 'msrv' run: | + cargo update -p=ciborium --precise=0.2.1 + cargo update -p=ciborium-ll --precise=0.2.1 cargo update -p=clap --precise=4.3.24 cargo update -p=clap_lex --precise=0.5.0 cargo update -p=anstyle --precise=1.0.2 From 5246d24aba3db150ff9a6c75bb367abb70c9e3e6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 1 Feb 2024 06:01:28 +0000 Subject: [PATCH 192/314] ci: force openssl version 3.2.1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d4d1a4b2..4caa9b1a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: - name: Install OpenSSL if: matrix.target.os == 'windows-latest' - run: choco install openssl -y --forcex64 --no-progress + run: choco install openssl -y --forcex64 --no-progress --version=3.2.1 - name: Set OpenSSL dir in env if: matrix.target.os == 'windows-latest' run: | From e89c881624b290c3c0802d02cc33360cb4c994da Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 1 Feb 2024 06:27:22 +0000 Subject: [PATCH 193/314] ci: use cargo-ci-cache-clean --- .github/workflows/ci-post-merge.yml | 12 ++++++++---- .github/workflows/ci.yml | 12 ++++++++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index e63821892..a08bc2ed4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -58,6 +58,7 @@ jobs: - name: tests timeout-minutes: 60 run: | + set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls @@ -69,10 +70,13 @@ jobs: cargo test --lib --tests -p=actix-multipart --all-features cargo test --lib --tests -p=actix-web-actors --all-features - - name: Clear the cargo caches - run: | - cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean - cargo-cache + - name: Install cargo-ci-cache-clean + uses: taiki-e/install-action@v2.25.9 + with: + tool: cargo-ci-cache-clean + + - name: CI cache clean + run: cargo-ci-cache-clean ci_feature_powerset_check: name: Verify Feature Combinations diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4caa9b1a5..90392892a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,6 +72,7 @@ jobs: - name: tests timeout-minutes: 60 run: | + set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls @@ -83,10 +84,13 @@ jobs: cargo test --lib --tests -p=actix-multipart --all-features cargo test --lib --tests -p=actix-web-actors --all-features - - name: Clear the cargo caches - run: | - cargo --locked install cargo-cache --version 0.8.3 --no-default-features --features ci-autoclean - cargo-cache + - name: Install cargo-ci-cache-clean + uses: taiki-e/install-action@v2.25.9 + with: + tool: cargo-ci-cache-clean + + - name: CI cache clean + run: cargo-ci-cache-clean io-uring: name: io-uring tests From 8e458b34b7b5f63adddf39483755c1a358440040 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 1 Feb 2024 06:33:58 +0000 Subject: [PATCH 194/314] chore: remove set -e --- .github/workflows/ci-post-merge.yml | 1 - .github/workflows/ci.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index a08bc2ed4..fd41819a2 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -58,7 +58,6 @@ jobs: - name: tests timeout-minutes: 60 run: | - set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90392892a..b2128f3e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,6 @@ jobs: - name: tests timeout-minutes: 60 run: | - set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls From 7a76ba73406f9a72c3c76f7e9ccd01ae1640dd33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 07:34:11 +0000 Subject: [PATCH 195/314] build(deps): bump taiki-e/install-action from 2.24.1 to 2.26.8 (#3271) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 8 ++++---- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index fd41819a2..d2f952ec7 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-hack @@ -70,7 +70,7 @@ jobs: cargo test --lib --tests -p=actix-web-actors --all-features - name: Install cargo-ci-cache-clean - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2128f3e2..5d2f5bb1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-hack @@ -84,7 +84,7 @@ jobs: cargo test --lib --tests -p=actix-web-actors --all-features - name: Install cargo-ci-cache-clean - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2722da084..2ad7bf8e0 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.25.9 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index adcb257b5..502bfeb61 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.24.1 + uses: taiki-e/install-action@v2.26.8 with: tool: cargo-public-api From c1f88f718b866d6712d5b98e7dc6be4344944c77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 07:34:23 +0000 Subject: [PATCH 196/314] build(deps): bump codecov/codecov-action from 3.1.4 to 4.0.0 (#3272) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- .github/workflows/coverage.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2ad7bf8e0..d871898f3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,9 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3.1.4 + uses: codecov/codecov-action@v4.0.0 with: files: codecov.json fail_ci_if_error: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} From ae7736f1341aef94d2ed7f52315c3bdea1d2ab3b Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:52:35 +0000 Subject: [PATCH 197/314] Implement `From<&HeaderMap>` for `http::HeaderMap` (#3230) * Add From impl for header map references * Add From impl for header map references * Remove Into via http::HeaderMap * fix changelog --------- Co-authored-by: SleeplessOne1917 Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 4 ++++ actix-http/src/header/map.rs | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 994c91a83..3ce06442e 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Implement `From<&HeaderMap>` for `http::HeaderMap`. + ## 3.5.1 ### Fixed diff --git a/actix-http/src/header/map.rs b/actix-http/src/header/map.rs index d8a63b573..b86798a4c 100644 --- a/actix-http/src/header/map.rs +++ b/actix-http/src/header/map.rs @@ -650,6 +650,13 @@ impl From for http::HeaderMap { } } +/// Convert our `&HeaderMap` to a `http::HeaderMap`. +impl From<&HeaderMap> for http::HeaderMap { + fn from(map: &HeaderMap) -> Self { + map.to_owned().into() + } +} + /// Iterator over removed, owned values with the same associated name. /// /// Returned from methods that remove or replace items. See [`HeaderMap::insert`] From b1eb57ac4f4dce05dd043ab9fca871af8f84f164 Mon Sep 17 00:00:00 2001 From: Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> Date: Sat, 3 Feb 2024 16:20:07 +0000 Subject: [PATCH 198/314] Update Cargo.toml (#3276) --- awc/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 14009fb4f..5c09400a0 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -72,7 +72,7 @@ cfg-if = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.17", default-features = false, features = ["alloc", "sink"] } -h2 = "0.3.17" +h2 = "0.3.24" http = "0.2.7" itoa = "1" log =" 0.4" From 2125aca2c5e0bba99172ce1a00f72531a58cee2a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 3 Feb 2024 23:55:01 +0000 Subject: [PATCH 199/314] Rustls v0.22 support (#3275) --- .cargo/config.toml | 4 +- .github/workflows/ci-post-merge.yml | 23 ++-- .github/workflows/ci.yml | 23 ++-- actix-files/src/lib.rs | 1 + actix-http/CHANGES.md | 2 + actix-http/Cargo.toml | 31 +++-- actix-http/examples/tls_rustls.rs | 20 ++-- actix-http/examples/ws.rs | 21 ++-- actix-http/src/h1/service.rs | 65 +++++++++- actix-http/src/h2/service.rs | 55 ++++++++- actix-http/src/lib.rs | 7 +- actix-http/src/service.rs | 124 ++++++++++++++++++-- actix-http/tests/test_rustls.rs | 63 +++++----- actix-test/CHANGES.md | 2 + actix-test/Cargo.toml | 3 + actix-test/src/lib.rs | 83 +++++++++++-- actix-web/CHANGES.md | 3 + actix-web/Cargo.toml | 19 ++- actix-web/src/server.rs | 85 ++++++++++++++ actix-web/tests/test_server.rs | 2 +- awc/CHANGES.md | 3 + awc/Cargo.toml | 30 +++-- awc/src/client/connector.rs | 176 ++++++++++++++++++++-------- awc/tests/test_rustls_client.rs | 70 +++++++---- 24 files changed, 719 insertions(+), 196 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 931b20b2c..350a924de 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,6 @@ [alias] -lint = "clippy --workspace --tests --examples --bins -- -Dclippy::todo" -lint-all = "clippy --workspace --all-features --tests --examples --bins -- -Dclippy::todo" +lint = "clippy --workspace --all-targets -- -Dclippy::todo" +lint-all = "clippy --workspace --all-features --all-targets -- -Dclippy::todo" # lib checking ci-check-min = "hack --workspace check --no-default-features" diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d2f952ec7..de9b30a59 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -32,22 +32,22 @@ jobs: - name: Install OpenSSL if: matrix.target.os == 'windows-latest' - run: choco install openssl -y --forcex64 --no-progress - - name: Set OpenSSL dir in env - if: matrix.target.os == 'windows-latest' + shell: bash run: | - echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append - echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append + set -e + choco install openssl --version=1.1.1.2100 -y --no-progress + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV + echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack + - name: Install cargo-hack and cargo-ci-cache-clean uses: taiki-e/install-action@v2.26.8 with: - tool: cargo-hack + tool: cargo-hack,cargo-ci-cache-clean - name: check minimal run: cargo ci-check-min @@ -57,10 +57,12 @@ jobs: - name: tests timeout-minutes: 60 + shell: bash run: | + set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls + cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls cargo test --lib --tests -p=actix-web-codegen --all-features cargo test --lib --tests -p=awc --all-features cargo test --lib --tests -p=actix-http-test --all-features @@ -69,11 +71,6 @@ jobs: cargo test --lib --tests -p=actix-multipart --all-features cargo test --lib --tests -p=actix-web-actors --all-features - - name: Install cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.8 - with: - tool: cargo-ci-cache-clean - - name: CI cache clean run: cargo-ci-cache-clean diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d2f5bb1c..79c581b81 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,22 +37,22 @@ jobs: - name: Install OpenSSL if: matrix.target.os == 'windows-latest' - run: choco install openssl -y --forcex64 --no-progress --version=3.2.1 - - name: Set OpenSSL dir in env - if: matrix.target.os == 'windows-latest' + shell: bash run: | - echo 'OPENSSL_DIR=C:\Program Files\OpenSSL-Win64' | Out-File -FilePath $env:GITHUB_ENV -Append - echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' | Out-File -FilePath $env:GITHUB_ENV -Append + set -e + choco install openssl --version=1.1.1.2100 -y --no-progress + echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV + echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack + - name: Install cargo-hack and cargo-ci-cache-clean uses: taiki-e/install-action@v2.26.8 with: - tool: cargo-hack + tool: cargo-hack,cargo-ci-cache-clean - name: workaround MSRV issues if: matrix.version.name == 'msrv' @@ -71,10 +71,12 @@ jobs: - name: tests timeout-minutes: 60 + shell: bash run: | + set -e cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls + cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls cargo test --lib --tests -p=actix-web-codegen --all-features cargo test --lib --tests -p=awc --all-features cargo test --lib --tests -p=actix-http-test --all-features @@ -83,11 +85,6 @@ jobs: cargo test --lib --tests -p=actix-multipart --all-features cargo test --lib --tests -p=actix-web-actors --all-features - - name: Install cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.8 - with: - tool: cargo-ci-cache-clean - - name: CI cache clean run: cargo-ci-cache-clean diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 5b1f14eed..8381519aa 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -568,6 +568,7 @@ mod tests { assert_eq!(bytes, data); } + #[cfg(not(target_os = "windows"))] #[actix_rt::test] async fn test_static_files_with_special_characters() { // Create the file we want to test against ad-hoc. We can't check it in as otherwise diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 3ce06442e..aca2a2573 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,8 @@ ### Added +- Add `rustls-0_22` crate feature. +- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_0_22()` and `HttpService::rustls_0_22_with_config()` service constructors. - Implement `From<&HeaderMap>` for `http::HeaderMap`. ## 3.5.1 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index e7d50c313..3a3000169 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -20,8 +20,18 @@ edition.workspace = true rust-version.workspace = true [package.metadata.docs.rs] -# features that docs.rs will build with -features = ["http2", "ws", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd"] +rustdoc-args = ["--cfg", "docsrs"] +features = [ + "http2", + "ws", + "openssl", + "rustls-0_20", + "rustls-0_21", + "rustls-0_22", + "compress-brotli", + "compress-gzip", + "compress-zstd", +] [lib] name = "actix_http" @@ -53,6 +63,9 @@ rustls-0_20 = ["actix-tls/accept", "actix-tls/rustls-0_20"] # TLS via Rustls v0.21 rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"] +# TLS via Rustls v0.22 +rustls-0_22 = ["actix-tls/accept", "actix-tls/rustls-0_22"] + # Compression codecs compress-brotli = ["__compress", "brotli"] compress-gzip = ["__compress", "flate2"] @@ -98,7 +111,7 @@ rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } # openssl/rustls -actix-tls = { version = "3.1", default-features = false, optional = true } +actix-tls = { version = "3.3", default-features = false, optional = true } # compress-* brotli = { version = "3.3.3", optional = true } @@ -108,7 +121,7 @@ zstd = { version = "0.13", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-tls = { version = "3.1", features = ["openssl"] } +actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22-webpki-roots"] } actix-web = "4" async-stream = "0.3" @@ -117,24 +130,24 @@ env_logger = "0.10" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" -rcgen = "0.11" +rcgen = "0.12" regex = "1.3" rustversion = "1" -rustls-pemfile = "1" +rustls-pemfile = "2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls_021 = { package = "rustls", version = "0.21" } +tls-rustls_022 = { package = "rustls", version = "0.22" } tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" -required-features = ["ws", "rustls-0_21"] +required-features = ["ws", "rustls-0_22"] [[example]] name = "tls_rustls" -required-features = ["http2", "rustls-0_21"] +required-features = ["http2", "rustls-0_22"] [[bench]] name = "response-body-compression" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index fbb55c6a4..47ff061cd 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -12,7 +12,7 @@ //! Protocol: HTTP/1.1 //! ``` -extern crate tls_rustls_021 as rustls; +extern crate tls_rustls_022 as rustls; use std::io; @@ -36,7 +36,7 @@ async fn main() -> io::Result<()> { ); ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_021(rustls_config()) + .rustls_0_22(rustls_config()) })? .run() .await @@ -51,16 +51,18 @@ fn rustls_config() -> rustls::ServerConfig { let key_file = &mut io::BufReader::new(key_file.as_bytes()); let cert_chain = rustls_pemfile::certs(cert_file) - .unwrap() - .into_iter() - .map(rustls::Certificate) - .collect(); - let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap(); + .collect::, _>>() + .unwrap(); + let mut keys = rustls_pemfile::pkcs8_private_keys(key_file) + .collect::, _>>() + .unwrap(); let mut config = rustls::ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(cert_chain, rustls::PrivateKey(keys.remove(0))) + .with_single_cert( + cert_chain, + rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)), + ) .unwrap(); const H1_ALPN: &[u8] = b"http/1.1"; diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index 241175ae2..55085fd73 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -1,7 +1,7 @@ //! Sets up a WebSocket server over TCP and TLS. //! Sends a heartbeat message every 4 seconds but does not respond to any incoming frames. -extern crate tls_rustls_021 as rustls; +extern crate tls_rustls_022 as rustls; use std::{ io, @@ -30,7 +30,7 @@ async fn main() -> io::Result<()> { .bind("tls", ("127.0.0.1", 8443), || { HttpService::build() .finish(handler) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) })? .run() .await @@ -85,7 +85,6 @@ impl Stream for Heartbeat { fn tls_config() -> rustls::ServerConfig { use std::io::BufReader; - use rustls::{Certificate, PrivateKey}; use rustls_pemfile::{certs, pkcs8_private_keys}; let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); @@ -95,17 +94,17 @@ fn tls_config() -> rustls::ServerConfig { let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); - let cert_chain = certs(cert_file) - .unwrap() - .into_iter() - .map(Certificate) - .collect(); - let mut keys = pkcs8_private_keys(key_file).unwrap(); + let cert_chain = certs(cert_file).collect::, _>>().unwrap(); + let mut keys = pkcs8_private_keys(key_file) + .collect::, _>>() + .unwrap(); let mut config = rustls::ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(cert_chain, PrivateKey(keys.remove(0))) + .with_single_cert( + cert_chain, + rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)), + ) .unwrap(); config.alpn_protocols.push(b"http/1.1".to_vec()); diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 3b27e3db5..64eb39c82 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -153,7 +153,7 @@ mod openssl { } #[cfg(feature = "rustls-0_20")] -mod rustls_020 { +mod rustls_0_20 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -214,7 +214,7 @@ mod rustls_020 { } #[cfg(feature = "rustls-0_21")] -mod rustls_021 { +mod rustls_0_21 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -274,6 +274,67 @@ mod rustls_021 { } } +#[cfg(feature = "rustls-0_22")] +mod rustls_0_22 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H1Service, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into>, + S::InitError: fmt::Debug, + S::Response: Into>, + + B: MessageBody, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.22 based service. + pub fn rustls_0_22( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl H1Service where S: ServiceFactory, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index 0ae7ea682..d50ffc4e3 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -141,7 +141,7 @@ mod openssl { } #[cfg(feature = "rustls-0_20")] -mod rustls_020 { +mod rustls_0_20 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -192,7 +192,7 @@ mod rustls_020 { } #[cfg(feature = "rustls-0_21")] -mod rustls_021 { +mod rustls_0_21 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -242,6 +242,57 @@ mod rustls_021 { } } +#[cfg(feature = "rustls-0_22")] +mod rustls_0_22 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H2Service, S, B> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + { + /// Create Rustls v0.22 based service. + pub fn rustls_0_22( + self, + mut config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = S::InitError, + > { + let mut protos = vec![b"h2".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Option)> for H2Service where T: AsyncRead + AsyncWrite + Unpin + 'static, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 888c3e06f..cb82ced00 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -58,7 +58,12 @@ pub mod ws; #[allow(deprecated)] pub use self::payload::PayloadStream; -#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] +#[cfg(any( + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22", +))] pub use self::service::TlsAcceptorConfig; pub use self::{ builder::HttpServiceBuilder, diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index fb38ba636..e24387182 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -241,13 +241,23 @@ where } /// Configuration options used when accepting TLS connection. -#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] +#[cfg(any( + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22", +))] #[derive(Debug, Default)] pub struct TlsAcceptorConfig { pub(crate) handshake_timeout: Option, } -#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] +#[cfg(any( + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22", +))] impl TlsAcceptorConfig { /// Set TLS handshake timeout duration. pub fn handshake_timeout(self, dur: std::time::Duration) -> Self { @@ -353,12 +363,12 @@ mod openssl { } #[cfg(feature = "rustls-0_20")] -mod rustls_020 { +mod rustls_0_20 { use std::io; use actix_service::ServiceFactoryExt as _; use actix_tls::accept::{ - rustls::{reexports::ServerConfig, Acceptor, TlsStream}, + rustls_0_20::{reexports::ServerConfig, Acceptor, TlsStream}, TlsError, }; @@ -389,7 +399,7 @@ mod rustls_020 { U::Error: fmt::Display + Into>, U::InitError: fmt::Debug, { - /// Create Rustls based service. + /// Create Rustls v0.20 based service. pub fn rustls( self, config: ServerConfig, @@ -403,7 +413,7 @@ mod rustls_020 { self.rustls_with_config(config, TlsAcceptorConfig::default()) } - /// Create Rustls based service with custom TLS acceptor configuration. + /// Create Rustls v0.20 based service with custom TLS acceptor configuration. pub fn rustls_with_config( self, mut config: ServerConfig, @@ -449,7 +459,7 @@ mod rustls_020 { } #[cfg(feature = "rustls-0_21")] -mod rustls_021 { +mod rustls_0_21 { use std::io; use actix_service::ServiceFactoryExt as _; @@ -485,7 +495,7 @@ mod rustls_021 { U::Error: fmt::Display + Into>, U::InitError: fmt::Debug, { - /// Create Rustls based service. + /// Create Rustls v0.21 based service. pub fn rustls_021( self, config: ServerConfig, @@ -499,7 +509,7 @@ mod rustls_021 { self.rustls_021_with_config(config, TlsAcceptorConfig::default()) } - /// Create Rustls based service with custom TLS acceptor configuration. + /// Create Rustls v0.21 based service with custom TLS acceptor configuration. pub fn rustls_021_with_config( self, mut config: ServerConfig, @@ -544,6 +554,102 @@ mod rustls_021 { } } +#[cfg(feature = "rustls-0_22")] +mod rustls_0_22 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl HttpService, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::InitError: fmt::Debug, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, h1::Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.22 based service. + pub fn rustls_0_22( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + self.rustls_0_22_with_config(config, TlsAcceptorConfig::default()) + } + + /// Create Rustls v0.22 based service with custom TLS acceptor configuration. + pub fn rustls_0_22_with_config( + self, + mut config: ServerConfig, + tls_acceptor_config: TlsAcceptorConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + let mut acceptor = Acceptor::new(config); + + if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout { + acceptor.set_handshake_timeout(handshake_timeout); + } + + acceptor + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .and_then(|io: TlsStream| async { + let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() { + if protos.windows(2).any(|window| window == b"h2") { + Protocol::Http2 + } else { + Protocol::Http1 + } + } else { + Protocol::Http1 + }; + let peer_addr = io.get_ref().0.peer_addr().ok(); + Ok((io, proto, peer_addr)) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Protocol, Option)> for HttpService where diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index c94e579e5..08b3a249b 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_21")] +#![cfg(feature = "rustls-0_22")] -extern crate tls_rustls_021 as rustls; +extern crate tls_rustls_022 as rustls; use std::{ convert::Infallible, @@ -20,13 +20,13 @@ use actix_http::{ use actix_http_test::test_server; use actix_rt::pin; use actix_service::{fn_factory_with_config, fn_service}; -use actix_tls::connect::rustls_0_21::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_22::webpki_roots_cert_store; use actix_utils::future::{err, ok, poll_fn}; use bytes::{Bytes, BytesMut}; use derive_more::{Display, Error}; use futures_core::{ready, Stream}; use futures_util::stream::once; -use rustls::{Certificate, PrivateKey, ServerConfig as RustlsServerConfig, ServerName}; +use rustls::{pki_types::ServerName, ServerConfig as RustlsServerConfig}; use rustls_pemfile::{certs, pkcs8_private_keys}; async fn load_body(stream: S) -> Result @@ -59,17 +59,17 @@ fn tls_config() -> RustlsServerConfig { let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); - let cert_chain = certs(cert_file) - .unwrap() - .into_iter() - .map(Certificate) - .collect(); - let mut keys = pkcs8_private_keys(key_file).unwrap(); + let cert_chain = certs(cert_file).collect::, _>>().unwrap(); + let mut keys = pkcs8_private_keys(key_file) + .collect::, _>>() + .unwrap(); let mut config = RustlsServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(cert_chain, PrivateKey(keys.remove(0))) + .with_single_cert( + cert_chain, + rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)), + ) .unwrap(); config.alpn_protocols.push(HTTP1_1_ALPN_PROTOCOL.to_vec()); @@ -83,7 +83,6 @@ pub fn get_negotiated_alpn_protocol( client_alpn_protocol: &[u8], ) -> Option> { let mut config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(webpki_roots_cert_store()) .with_no_client_auth(); @@ -109,7 +108,7 @@ async fn h1() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -123,7 +122,7 @@ async fn h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -141,7 +140,7 @@ async fn h1_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_11); ok::<_, Error>(Response::ok()) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -159,7 +158,7 @@ async fn h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::ok()) }) - .rustls_021_with_config( + .rustls_0_22_with_config( tls_config(), TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)), ) @@ -180,7 +179,7 @@ async fn h2_body1() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -206,7 +205,7 @@ async fn h2_content_length() { ]; ok::<_, Infallible>(Response::new(statuses[indx])) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -278,7 +277,7 @@ async fn h2_headers() { } ok::<_, Infallible>(config.body(data.clone())) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -317,7 +316,7 @@ async fn h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -334,7 +333,7 @@ async fn h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -360,7 +359,7 @@ async fn h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -385,7 +384,7 @@ async fn h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -411,7 +410,7 @@ async fn h2_body_length() { Response::ok().set_body(SizedStream::new(STR.len() as u64, body)), ) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -435,7 +434,7 @@ async fn h2_body_chunked_explicit() { .body(BodyStream::new(body)), ) }) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -464,7 +463,7 @@ async fn h2_response_http_error_handling() { ) })) })) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -494,7 +493,7 @@ async fn h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::, _>(BadRequest)) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -511,7 +510,7 @@ async fn h1_service_error() { let mut srv = test_server(move || { HttpService::build() .h1(|_| err::, _>(BadRequest)) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) }) .await; @@ -534,7 +533,7 @@ async fn alpn_h1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_021(config) + .rustls_0_22(config) }) .await; @@ -556,7 +555,7 @@ async fn alpn_h2() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_021(config) + .rustls_0_22(config) }) .await; @@ -582,7 +581,7 @@ async fn alpn_h2_1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .finish(|_| ok::<_, Error>(Response::ok())) - .rustls_021(config) + .rustls_0_22(config) }) .await; diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index a3ca7fe10..bdacc8b2d 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Add `TestServerConfig::rustls_0_22()` method for Rustls v0.22 support behind new `rustls-0_22` crate feature. + ## 0.1.2 - Add `TestServerConfig::rustls_021()` method for Rustls v0.21 support behind new `rustls-0_21` crate feature. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 46d65abdc..d5be25384 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -27,6 +27,8 @@ rustls = ["rustls-0_20"] rustls-0_20 = ["tls-rustls-0_20", "actix-http/rustls-0_20", "awc/rustls-0_20"] # TLS via Rustls v0.21 rustls-0_21 = ["tls-rustls-0_21", "actix-http/rustls-0_21", "awc/rustls-0_21"] +# TLS via Rustls v0.22 +rustls-0_22 = ["tls-rustls-0_22", "actix-http/rustls-0_22", "awc/rustls-0_22-webpki-roots"] # TLS via OpenSSL openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] @@ -50,4 +52,5 @@ serde_urlencoded = "0.7" tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true } +tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index e570bb266..b7aeddad2 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -143,6 +143,8 @@ where StreamType::Rustls020(_) => true, #[cfg(feature = "rustls-0_21")] StreamType::Rustls021(_) => true, + #[cfg(feature = "rustls-0_22")] + StreamType::Rustls022(_) => true, }; // run server in separate orphaned thread @@ -327,6 +329,48 @@ where .rustls_021(config.clone()) }), }, + #[cfg(feature = "rustls-0_22")] + StreamType::Rustls022(config) => match cfg.tp { + HttpVer::Http1 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h1(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_22(config.clone()) + }), + HttpVer::Http2 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h2(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_22(config.clone()) + }), + HttpVer::Both => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .finish(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_22(config.clone()) + }), + }, } .expect("test server could not be created"); @@ -401,6 +445,8 @@ enum StreamType { Rustls020(tls_rustls_0_20::ServerConfig), #[cfg(feature = "rustls-0_21")] Rustls021(tls_rustls_0_21::ServerConfig), + #[cfg(feature = "rustls-0_22")] + Rustls022(tls_rustls_0_22::ServerConfig), } /// Create default test server config. @@ -424,7 +470,7 @@ impl Default for TestServerConfig { } impl TestServerConfig { - /// Create default server configuration + /// Constructs default server configuration. pub(crate) fn new() -> TestServerConfig { TestServerConfig { tp: HttpVer::Both, @@ -435,40 +481,63 @@ impl TestServerConfig { } } - /// Accept HTTP/1.1 only. + /// Accepts HTTP/1.1 only. pub fn h1(mut self) -> Self { self.tp = HttpVer::Http1; self } - /// Accept HTTP/2 only. + /// Accepts HTTP/2 only. pub fn h2(mut self) -> Self { self.tp = HttpVer::Http2; self } - /// Accept secure connections via OpenSSL. + /// Accepts secure connections via OpenSSL. #[cfg(feature = "openssl")] pub fn openssl(mut self, acceptor: openssl::ssl::SslAcceptor) -> Self { self.stream = StreamType::Openssl(acceptor); self } - /// Accept secure connections via Rustls. + #[doc(hidden)] + #[deprecated(note = "Renamed to `rustls_0_20()`.")] #[cfg(feature = "rustls-0_20")] pub fn rustls(mut self, config: tls_rustls_0_20::ServerConfig) -> Self { self.stream = StreamType::Rustls020(config); self } - /// Accept secure connections via Rustls. + /// Accepts secure connections via Rustls v0.20. + #[cfg(feature = "rustls-0_20")] + pub fn rustls_0_20(mut self, config: tls_rustls_0_20::ServerConfig) -> Self { + self.stream = StreamType::Rustls020(config); + self + } + + #[doc(hidden)] + #[deprecated(note = "Renamed to `rustls_0_21()`.")] #[cfg(feature = "rustls-0_21")] pub fn rustls_021(mut self, config: tls_rustls_0_21::ServerConfig) -> Self { self.stream = StreamType::Rustls021(config); self } - /// Set client timeout for first request. + /// Accepts secure connections via Rustls v0.21. + #[cfg(feature = "rustls-0_21")] + pub fn rustls_0_21(mut self, config: tls_rustls_0_21::ServerConfig) -> Self { + self.stream = StreamType::Rustls021(config); + self + } + + /// Accepts secure connections via Rustls v0.22. + #[cfg(feature = "rustls-0_22")] + pub fn rustls_0_22(mut self, config: tls_rustls_0_22::ServerConfig) -> Self { + self.stream = StreamType::Rustls022(config); + self + } + + /// Sets client timeout for first request. pub fn client_request_timeout(mut self, dur: Duration) -> Self { self.client_request_timeout = dur; self diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 674c834ad..072cdc012 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +- Add `rustls-0_22` crate feature. +- Add `HttpServer::{bind_rustls_0_22, listen_rustls_0_22}()` builder methods. + ## 4.4.1 ### Changed diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index d1fc9c916..37299721f 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -20,9 +20,20 @@ edition.workspace = true rust-version.workspace = true [package.metadata.docs.rs] -# features that docs.rs will build with -features = ["macros", "openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "secure-cookies"] rustdoc-args = ["--cfg", "docsrs"] +features = [ + "macros", + "openssl", + "rustls-0_20", + "rustls-0_21", + "rustls-0_22", + "compress-brotli", + "compress-gzip", + "compress-zstd", + "cookies", + "secure-cookies", +] + [lib] name = "actix_web" @@ -58,6 +69,8 @@ rustls = ["rustls-0_20"] rustls-0_20 = ["http2", "actix-http/rustls-0_20", "actix-tls/accept", "actix-tls/rustls-0_20"] # TLS via Rustls v0.21 rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"] +# TLS via Rustls v0.22 +rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"] # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. @@ -73,7 +86,7 @@ actix-rt = { version = "2.6", default-features = false } actix-server = "2" actix-service = "2" actix-utils = "3" -actix-tls = { version = "3.1", default-features = false, optional = true } +actix-tls = { version = "3.3", default-features = false, optional = true } actix-http = { version = "3.5", features = ["ws"] } actix-router = "0.5" diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 2cc00cb9f..193a7cce9 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -442,6 +442,25 @@ where Ok(self) } + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections + /// using Rustls v0.22. + /// + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_22")] + pub fn bind_rustls_0_22( + mut self, + addrs: A, + config: actix_tls::accept::rustls_0_22::reexports::ServerConfig, + ) -> io::Result { + let sockets = bind_addrs(addrs, self.backlog)?; + for lst in sockets { + self = self.listen_rustls_0_22_inner(lst, config.clone())?; + } + Ok(self) + } + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using OpenSSL. /// @@ -685,6 +704,72 @@ where Ok(self) } + /// Binds to existing listener for accepting incoming TLS connection requests using Rustls + /// v0.22. + /// + /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_22")] + pub fn listen_rustls_0_22( + self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_22::reexports::ServerConfig, + ) -> io::Result { + self.listen_rustls_0_22_inner(lst, config) + } + + #[cfg(feature = "rustls-0_22")] + fn listen_rustls_0_22_inner( + mut self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_22::reexports::ServerConfig, + ) -> io::Result { + let factory = self.factory.clone(); + let cfg = self.config.clone(); + let addr = lst.local_addr().unwrap(); + self.sockets.push(Socket { + addr, + scheme: "https", + }); + + let on_connect_fn = self.on_connect_fn.clone(); + + self.builder = + self.builder + .listen(format!("actix-web-service-{}", addr), lst, move || { + let c = cfg.lock().unwrap(); + let host = c.host.clone().unwrap_or_else(|| format!("{}", addr)); + + let svc = HttpService::build() + .keep_alive(c.keep_alive) + .client_request_timeout(c.client_request_timeout) + .client_disconnect_timeout(c.client_disconnect_timeout); + + let svc = if let Some(handler) = on_connect_fn.clone() { + svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)) + } else { + svc + }; + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + let acceptor_config = match c.tls_handshake_timeout { + Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur), + None => TlsAcceptorConfig::default(), + }; + + svc.finish(map_config(fac, move |_| { + AppConfig::new(true, host.clone(), addr) + })) + .rustls_0_22_with_config(config.clone(), acceptor_config) + })?; + + Ok(self) + } + /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL. /// /// See [`listen()`](Self::listen) for more details on the `lst` argument. diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index a268cb6e3..0df6e2124 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -743,7 +743,7 @@ mod plus_rustls { .map(char::from) .collect::(); - let srv = actix_test::start_with(actix_test::config().rustls_021(tls_config()), || { + let srv = actix_test::start_with(actix_test::config().rustls_0_21(tls_config()), || { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { // echo decompressed request body back in response HttpResponse::Ok() diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 6f4212f90..3cef0e139 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +- Add `rustls-0_22-webpki-roots` and `rustls-0_22-native-roots` crate feature. +- Add `awc::Connector::rustls_0_22()` method. + ## 3.3.0 - Update `trust-dns-resolver` dependency to `0.23`. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 5c09400a0..369119c25 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -20,8 +20,17 @@ name = "awc" path = "src/lib.rs" [package.metadata.docs.rs] -# features that docs.rs will build with -features = ["openssl", "rustls-0_20", "rustls-0_21", "compress-brotli", "compress-gzip", "compress-zstd", "cookies"] +rustdoc-args = ["--cfg", "docsrs"] +features = [ + "cookies", + "openssl", + "rustls-0_20", + "rustls-0_21", + "rustls-0_22-webpki-roots", + "compress-brotli", + "compress-gzip", + "compress-zstd", +] [features] default = ["compress-brotli", "compress-gzip", "compress-zstd", "cookies"] @@ -35,6 +44,10 @@ rustls = ["rustls-0_20"] rustls-0_20 = ["tls-rustls-0_20", "actix-tls/rustls-0_20"] # TLS via Rustls v0.21 rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"] +# TLS via Rustls v0.22 (WebPKI roots) +rustls-0_22-webpki-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-webpki-roots"] +# TLS via Rustls v0.22 (Native roots) +rustls-0_22-native-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-native-roots"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -63,7 +76,7 @@ actix-codec = "0.5" actix-service = "2" actix-http = { version = "3.5", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } -actix-tls = { version = "3.1", features = ["connect", "uri"] } +actix-tls = { version = "3.3", features = ["connect", "uri"] } actix-utils = "3" base64 = "0.21" @@ -90,6 +103,7 @@ cookie = { version = "0.16", features = ["percent-encode"], optional = true } tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } +tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } trust-dns-resolver = { version = "0.23", optional = true } @@ -97,8 +111,8 @@ trust-dns-resolver = { version = "0.23", optional = true } actix-http = { version = "3.5", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } -actix-tls = { version = "3", features = ["openssl", "rustls-0_21"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } +actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } @@ -108,11 +122,11 @@ env_logger = "0.10" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" -rcgen = "0.11" -rustls-pemfile = "1" +rcgen = "0.12" +rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" [[example]] name = "client" -required-features = ["rustls-0_21"] +required-features = ["rustls-0_22-webpki-roots"] diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 879d1895b..df6e422f3 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -40,14 +40,23 @@ enum OurTlsConnector { /// Provided because building the OpenSSL context on newer versions can be very slow. /// This prevents unnecessary calls to `.build()` while constructing the client connector. #[cfg(feature = "openssl")] - #[allow(dead_code)] // false positive; used in build_ssl + #[allow(dead_code)] // false positive; used in build_tls OpensslBuilder(actix_tls::connect::openssl::reexports::SslConnectorBuilder), #[cfg(feature = "rustls-0_20")] + #[allow(dead_code)] // false positive; used in build_tls Rustls020(std::sync::Arc), #[cfg(feature = "rustls-0_21")] + #[allow(dead_code)] // false positive; used in build_tls Rustls021(std::sync::Arc), + + #[cfg(any( + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", + ))] + #[allow(dead_code)] // false positive; used in build_tls + Rustls022(std::sync::Arc), } /// Manages HTTP client network connectivity. @@ -86,67 +95,83 @@ impl Connector<()> { } } - /// Provides an empty TLS connector when no TLS feature is enabled. - #[cfg(not(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21")))] - fn build_tls(_: Vec>) -> OurTlsConnector { - OurTlsConnector::None - } + cfg_if::cfg_if! { + if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-webpki-roots"))] { + /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. + /// + /// Note that if other TLS crate features are enabled, Rustls v0.22 will be used. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_22::{self, reexports::ClientConfig}; - /// Build TLS connector with Rustls v0.21, based on supplied ALPN protocols - /// - /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. - #[cfg(feature = "rustls-0_21")] - fn build_tls(protocols: Vec>) -> OurTlsConnector { - use actix_tls::connect::rustls_0_21::{reexports::ClientConfig, webpki_roots_cert_store}; + cfg_if::cfg_if! { + if #[cfg(feature = "rustls-0_22-webpki-roots")] { + let certs = rustls_0_22::webpki_roots_cert_store(); + } else if #[cfg(feature = "rustls-0_22-native-roots")] { + let certs = rustls_0_22::native_roots_cert_store(); + } + } - let mut config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(webpki_roots_cert_store()) - .with_no_client_auth(); + let mut config = ClientConfig::builder() + .with_root_certificates(certs) + .with_no_client_auth(); - config.alpn_protocols = protocols; + config.alpn_protocols = protocols; - OurTlsConnector::Rustls021(std::sync::Arc::new(config)) - } + OurTlsConnector::Rustls022(std::sync::Arc::new(config)) + } + } else if #[cfg(feature = "rustls-0_21")] { + /// Build TLS connector with Rustls v0.21, based on supplied ALPN protocols. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_21::{reexports::ClientConfig, webpki_roots_cert_store}; - /// Build TLS connector with Rustls v0.20, based on supplied ALPN protocols - /// - /// Note that if other TLS crate features are enabled, Rustls v0.21 will be used. - #[cfg(all(feature = "rustls-0_20", not(feature = "rustls-0_21")))] - fn build_tls(protocols: Vec>) -> OurTlsConnector { - use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(webpki_roots_cert_store()) + .with_no_client_auth(); - let mut config = ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(webpki_roots_cert_store()) - .with_no_client_auth(); + config.alpn_protocols = protocols; - config.alpn_protocols = protocols; + OurTlsConnector::Rustls021(std::sync::Arc::new(config)) + } + } else if #[cfg(feature = "rustls-0_20")] { + /// Build TLS connector with Rustls v0.20, based on supplied ALPN protocols. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_20::{reexports::ClientConfig, webpki_roots_cert_store}; - OurTlsConnector::Rustls020(std::sync::Arc::new(config)) - } + let mut config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(webpki_roots_cert_store()) + .with_no_client_auth(); - /// Build TLS connector with OpenSSL, based on supplied ALPN protocols - #[cfg(all( - feature = "openssl", - not(any(feature = "rustls-0_20", feature = "rustls-0_21")), - ))] - fn build_tls(protocols: Vec>) -> OurTlsConnector { - use actix_tls::connect::openssl::reexports::{SslConnector, SslMethod}; - use bytes::{BufMut, BytesMut}; + config.alpn_protocols = protocols; - let mut alpn = BytesMut::with_capacity(20); - for proto in &protocols { - alpn.put_u8(proto.len() as u8); - alpn.put(proto.as_slice()); + OurTlsConnector::Rustls020(std::sync::Arc::new(config)) + } + } else if #[cfg(feature = "openssl")] { + /// Build TLS connector with OpenSSL, based on supplied ALPN protocols. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::openssl::reexports::{SslConnector, SslMethod}; + use bytes::{BufMut, BytesMut}; + + let mut alpn = BytesMut::with_capacity(20); + for proto in &protocols { + alpn.put_u8(proto.len() as u8); + alpn.put(proto.as_slice()); + } + + let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap(); + if let Err(err) = ssl.set_alpn_protos(&alpn) { + log::error!("Can not set ALPN protocol: {err:?}"); + } + + OurTlsConnector::OpensslBuilder(ssl) + } + } else { + /// Provides an empty TLS connector when no TLS feature is enabled. + fn build_tls(_: Vec>) -> OurTlsConnector { + OurTlsConnector::None + } } - - let mut ssl = SslConnector::builder(SslMethod::tls()).unwrap(); - if let Err(err) = ssl.set_alpn_protos(&alpn) { - log::error!("Can not set ALPN protocol: {:?}", err); - } - - OurTlsConnector::OpensslBuilder(ssl) } } @@ -240,6 +265,19 @@ where self } + /// Sets custom Rustls v0.22 `ClientConfig` instance. + #[cfg(any( + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", + ))] + pub fn rustls_0_22( + mut self, + connector: std::sync::Arc, + ) -> Self { + self.tls = OurTlsConnector::Rustls022(connector); + self + } + /// Sets maximum supported HTTP major version. /// /// Supported versions are HTTP/1.1 and HTTP/2. @@ -509,6 +547,42 @@ where Some(actix_service::boxed::rc_service(tls_service)) } + + #[cfg(any( + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", + ))] + OurTlsConnector::Rustls022(tls) => { + const H2: &[u8] = b"h2"; + + use actix_tls::connect::rustls_0_22::{reexports::AsyncTlsStream, TlsConnector}; + + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let sock = self.into_parts().0; + let h2 = sock + .get_ref() + .1 + .alpn_protocol() + .map_or(false, |protos| protos.windows(2).any(|w| w == H2)); + if h2 { + (Box::new(sock), Protocol::Http2) + } else { + (Box::new(sock), Protocol::Http1) + } + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: TlsConnector::service(tls), + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } }; let tcp_config = self.config.no_disconnect_timeout(); diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index d758f93d8..1cc3e8c48 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_21")] +#![cfg(feature = "rustls-0_22-webpki-roots")] -extern crate tls_rustls_0_21 as rustls; +extern crate tls_rustls_0_22 as rustls; use std::{ io::BufReader, @@ -8,18 +8,17 @@ use std::{ atomic::{AtomicUsize, Ordering}, Arc, }, - time::SystemTime, }; use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{fn_service, map_config, ServiceFactoryExt}; -use actix_tls::connect::rustls_0_21::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_22::webpki_roots_cert_store; use actix_utils::future::ok; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use rustls::{ - client::{ServerCertVerified, ServerCertVerifier}, - Certificate, ClientConfig, PrivateKey, ServerConfig, ServerName, + pki_types::{CertificateDer, PrivateKeyDer, ServerName}, + ClientConfig, ServerConfig, }; use rustls_pemfile::{certs, pkcs8_private_keys}; @@ -31,36 +30,62 @@ fn tls_config() -> ServerConfig { let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); - let cert_chain = certs(cert_file) - .unwrap() - .into_iter() - .map(Certificate) - .collect(); - let mut keys = pkcs8_private_keys(key_file).unwrap(); + let cert_chain = certs(cert_file).collect::, _>>().unwrap(); + let mut keys = pkcs8_private_keys(key_file) + .collect::, _>>() + .unwrap(); ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(cert_chain, PrivateKey(keys.remove(0))) + .with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0))) .unwrap() } mod danger { + use rustls::{ + client::danger::{ServerCertVerified, ServerCertVerifier}, + pki_types::UnixTime, + }; + use super::*; + #[derive(Debug)] pub struct NoCertificateVerification; impl ServerCertVerifier for NoCertificateVerification { fn verify_server_cert( &self, - _end_entity: &Certificate, - _intermediates: &[Certificate], - _server_name: &ServerName, - _scts: &mut dyn Iterator, + _end_entity: &CertificateDer<'_>, + _intermediates: &[CertificateDer<'_>], + _server_name: &ServerName<'_>, _ocsp_response: &[u8], - _now: SystemTime, + _now: UnixTime, ) -> Result { - Ok(ServerCertVerified::assertion()) + Ok(rustls::client::danger::ServerCertVerified::assertion()) + } + + fn verify_tls12_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(rustls::client::danger::HandshakeSignatureValid::assertion()) + } + + fn verify_tls13_signature( + &self, + _message: &[u8], + _cert: &CertificateDer<'_>, + _dss: &rustls::DigitallySignedStruct, + ) -> Result { + Ok(rustls::client::danger::HandshakeSignatureValid::assertion()) + } + + fn supported_verify_schemes(&self) -> Vec { + rustls::crypto::ring::default_provider() + .signature_verification_algorithms + .supported_schemes() } } } @@ -82,14 +107,13 @@ async fn test_connection_reuse_h2() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .rustls_021(tls_config()) + .rustls_0_22(tls_config()) .map_err(|_| ()), ) }) .await; let mut config = ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(webpki_roots_cert_store()) .with_no_client_auth(); @@ -102,7 +126,7 @@ async fn test_connection_reuse_h2() { .set_certificate_verifier(Arc::new(danger::NoCertificateVerification)); let client = awc::Client::builder() - .connector(awc::Connector::new().rustls_021(Arc::new(config))) + .connector(awc::Connector::new().rustls_0_22(Arc::new(config))) .finish(); // req 1 From 8db3de6edee25090edb377d4ae858747191e38c6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:31:14 +0000 Subject: [PATCH 200/314] chore(actix-http): prepare release 3.6.0 --- actix-http/CHANGES.md | 2 ++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-test/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- scripts/bump | 1 - 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index aca2a2573..e3805ff7e 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.6.0 + ### Added - Add `rustls-0_22` crate feature. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 3a3000169..14b9bdacb 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.5.1" +version = "3.6.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 9d80c10c4..c9bd1b34c 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -5,11 +5,11 @@ [![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=3.5.1)](https://docs.rs/actix-http/3.5.1) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.6.0)](https://docs.rs/actix-http/3.6.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.5.1/status.svg)](https://deps.rs/crate/actix-http/3.5.1) +[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index d5be25384..c24e1363d 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -35,7 +35,7 @@ openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] [dependencies] actix-codec = "0.5" -actix-http = "3" +actix-http = "3.6" actix-http-test = "3" actix-rt = "2.1" actix-service = "2" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 37299721f..167927263 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -88,7 +88,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3.3", default-features = false, optional = true } -actix-http = { version = "3.5", features = ["ws"] } +actix-http = { version = "3.6", features = ["ws"] } actix-router = "0.5" actix-web-codegen = { version = "4.2", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 369119c25..46603fed2 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -74,7 +74,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3.5", features = ["http2", "ws"] } +actix-http = { version = "3.6", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.3", features = ["connect", "uri"] } actix-utils = "3" @@ -108,7 +108,7 @@ tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } trust-dns-resolver = { version = "0.23", optional = true } [dev-dependencies] -actix-http = { version = "3.5", features = ["openssl"] } +actix-http = { version = "3.6", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } diff --git a/scripts/bump b/scripts/bump index 22aa2af95..6fd879eae 100755 --- a/scripts/bump +++ b/scripts/bump @@ -112,7 +112,6 @@ echo read -p "Update all references: (y/N) " UPDATE_REFERENCES UPDATE_REFERENCES="${UPDATE_REFERENCES:-n}" - if [ "$UPDATE_REFERENCES" = 'y' ] || [ "$UPDATE_REFERENCES" = 'Y' ]; then if [[ $NEW_VERSION == *".0.0" ]]; then NEW_VERSION_SPEC="${NEW_VERSION%.0.0}" From 8e9e9fbcdd727d54361ea165ce64af74375c9f81 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:32:28 +0000 Subject: [PATCH 201/314] chore(actix-web): prepare release 4.5.0 --- actix-test/Cargo.toml | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index c24e1363d..4e6ea0869 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -40,7 +40,7 @@ actix-http-test = "3" actix-rt = "2.1" actix-service = "2" actix-utils = "3" -actix-web = { version = "4", default-features = false, features = ["cookies"] } +actix-web = { version = "4.5", default-features = false, features = ["cookies"] } awc = { version = "3", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 072cdc012..174a70e6f 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.5.0 + - Add `rustls-0_22` crate feature. - Add `HttpServer::{bind_rustls_0_22, listen_rustls_0_22}()` builder methods. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 167927263..985a103f2 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.4.1" +version = "4.5.0" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index 80ae21238..492f06fa3 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.4.1)](https://docs.rs/actix-web/4.4.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.5.0)](https://docs.rs/actix-web/4.5.0) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.4.1/status.svg)](https://deps.rs/crate/actix-web/4.4.1) +[![Dependency Status](https://deps.rs/crate/actix-web/4.5.0/status.svg)](https://deps.rs/crate/actix-web/4.5.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 73fa1184f18bd36668dfb2fbf30ced578b928833 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:32:57 +0000 Subject: [PATCH 202/314] chore(awc): prepare release 3.4.0 --- actix-test/Cargo.toml | 2 +- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 4e6ea0869..49ba22d51 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -41,7 +41,7 @@ actix-rt = "2.1" actix-service = "2" actix-utils = "3" actix-web = { version = "4.5", default-features = false, features = ["cookies"] } -awc = { version = "3", default-features = false, features = ["cookies"] } +awc = { version = "3.4", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } futures-util = { version = "0.3.17", default-features = false, features = [] } diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 3cef0e139..4ed02ada6 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.4.0 + - Add `rustls-0_22-webpki-roots` and `rustls-0_22-native-roots` crate feature. - Add `awc::Connector::rustls_0_22()` method. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 46603fed2..14d93ac30 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.3.0" +version = "3.4.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 424c86bba..d86657564 100644 --- a/awc/README.md +++ b/awc/README.md @@ -5,9 +5,9 @@ [![crates.io](https://img.shields.io/crates/v/awc?label=latest)](https://crates.io/crates/awc) -[![Documentation](https://docs.rs/awc/badge.svg?version=3.3.0)](https://docs.rs/awc/3.3.0) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.4.0)](https://docs.rs/awc/3.4.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.3.0/status.svg)](https://deps.rs/crate/awc/3.3.0) +[![Dependency Status](https://deps.rs/crate/awc/3.4.0/status.svg)](https://deps.rs/crate/awc/3.4.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 17ed73b33e0fb7d3257da4c98039496044154c35 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:33:38 +0000 Subject: [PATCH 203/314] chore(actix-web-actors): prepare release 4.3.0 --- actix-web-actors/CHANGES.md | 2 ++ actix-web-actors/Cargo.toml | 2 +- actix-web-actors/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 5c516db56..85d6b624a 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.3.0 + - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 4.2.0 diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index c6f14554a..0263e9b29 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-actors" -version = "4.2.0" +version = "4.3.0" authors = ["Nikolay Kim "] description = "Actix actors support for Actix Web" keywords = ["actix", "http", "web", "framework", "async"] diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index c81fe64c1..17b947223 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) -[![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.2.0)](https://docs.rs/actix-web-actors/4.2.0) +[![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.3.0)](https://docs.rs/actix-web-actors/4.3.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
-[![dependency status](https://deps.rs/crate/actix-web-actors/4.2.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.2.0) +[![dependency status](https://deps.rs/crate/actix-web-actors/4.3.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.3.0) [![Download](https://img.shields.io/crates/d/actix-web-actors.svg)](https://crates.io/crates/actix-web-actors) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 3f2fd2d59f64c172a944ddf82787e7d31e6a1b95 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:33:42 +0000 Subject: [PATCH 204/314] chore(actix-test): prepare release 0.1.3 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index bdacc8b2d..8604a1265 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.3 + - Add `TestServerConfig::rustls_0_22()` method for Rustls v0.22 support behind new `rustls-0_22` crate feature. ## 0.1.2 diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 49ba22d51..7f48fc2cc 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.2" +version = "0.1.3" authors = [ "Nikolay Kim ", "Rob Ede ", From 59bc85fe0e5961b9e3499a3272737b780904955d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 00:34:00 +0000 Subject: [PATCH 205/314] chore(actix-http-test): prepare release 3.2.0 --- actix-http-test/CHANGES.md | 2 ++ actix-http-test/Cargo.toml | 2 +- actix-http-test/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index 065141b20..ec30b9c4c 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.2.0 + - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. ## 3.1.0 diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index 0881e0bc4..bfb0a3539 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http-test" -version = "3.1.0" +version = "3.2.0" authors = ["Nikolay Kim "] description = "Various helpers for Actix applications to use during testing" keywords = ["http", "web", "framework", "async", "futures"] diff --git a/actix-http-test/README.md b/actix-http-test/README.md index e544c3616..9a87f9ef2 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -5,11 +5,11 @@ [![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=3.1.0)](https://docs.rs/actix-http-test/3.1.0) +[![Documentation](https://docs.rs/actix-http-test/badge.svg?version=3.2.0)](https://docs.rs/actix-http-test/3.2.0) ![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
-[![Dependency Status](https://deps.rs/crate/actix-http-test/3.1.0/status.svg)](https://deps.rs/crate/actix-http-test/3.1.0) +[![Dependency Status](https://deps.rs/crate/actix-http-test/3.2.0/status.svg)](https://deps.rs/crate/actix-http-test/3.2.0) [![Download](https://img.shields.io/crates/d/actix-http-test.svg)](https://crates.io/crates/actix-http-test) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 2b8c528e543a7d663d2e0bcc89dfaffa0d8a77f7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 01:22:36 +0000 Subject: [PATCH 206/314] chore(actix-web): prepare release 4.5.1 --- actix-web/CHANGES.md | 8 ++++++++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- actix-web/src/server.rs | 7 ++++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 174a70e6f..6e2894e40 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,8 +2,16 @@ ## Unreleased +## 4.5.1 + +### Fixed + +- Fix missing import when using enabling Rustls v0.22 support. + ## 4.5.0 +### Added + - Add `rustls-0_22` crate feature. - Add `HttpServer::{bind_rustls_0_22, listen_rustls_0_22}()` builder methods. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 985a103f2..8c1cc9bfe 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.5.0" +version = "4.5.1" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index 492f06fa3..b564c8793 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.5.0)](https://docs.rs/actix-web/4.5.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.5.1)](https://docs.rs/actix-web/4.5.1) ![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.5.0/status.svg)](https://deps.rs/crate/actix-web/4.5.0) +[![Dependency Status](https://deps.rs/crate/actix-web/4.5.1/status.svg)](https://deps.rs/crate/actix-web/4.5.1)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 193a7cce9..6592079bf 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -7,7 +7,12 @@ use std::{ time::Duration, }; -#[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] +#[cfg(any( + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22", +))] use actix_http::TlsAcceptorConfig; use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response}; use actix_server::{Server, ServerBuilder}; From d9b31b80ac4c3e58444248b5e5b531fae557af14 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 03:11:48 +0000 Subject: [PATCH 207/314] fix: standardize body stream error reporting --- actix-http/examples/h2c-detect.rs | 9 +++++++-- actix-http/src/h1/dispatcher.rs | 5 ++++- actix-http/src/h2/dispatcher.rs | 15 ++++++++------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs index aa3dd5d31..b0bde3fe6 100644 --- a/actix-http/examples/h2c-detect.rs +++ b/actix-http/examples/h2c-detect.rs @@ -8,7 +8,7 @@ use std::{convert::Infallible, io}; -use actix_http::{HttpService, Request, Response, StatusCode}; +use actix_http::{body::BodyStream, HttpService, Request, Response, StatusCode}; use actix_server::Server; #[tokio::main(flavor = "current_thread")] @@ -19,7 +19,12 @@ async fn main() -> io::Result<()> { .bind("h2c-detect", ("127.0.0.1", 8080), || { HttpService::build() .finish(|_req: Request| async move { - Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) + Ok::<_, Infallible>(Response::build(StatusCode::OK).body(BodyStream::new( + futures_util::stream::iter([ + Ok::<_, String>("123".into()), + Err("wertyuikmnbvcxdfty6t".to_owned()), + ]), + ))) }) .tcp_auto_h2c() })? diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index 270707807..bfbcaf24c 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -512,8 +512,10 @@ where } Poll::Ready(Some(Err(err))) => { + let err = err.into(); + tracing::error!("Response payload stream error: {err:?}"); this.flags.insert(Flags::FINISHED); - return Err(DispatchError::Body(err.into())); + return Err(DispatchError::Body(err)); } Poll::Pending => return Ok(PollResponse::DoNothing), @@ -549,6 +551,7 @@ where } Poll::Ready(Some(Err(err))) => { + tracing::error!("Response payload stream error: {err:?}"); this.flags.insert(Flags::FINISHED); return Err(DispatchError::Body( Error::new_body().with_cause(err).into(), diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 3e618820e..022239c2d 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -4,7 +4,7 @@ use std::{ future::Future, marker::PhantomData, net, - pin::Pin, + pin::{pin, Pin}, rc::Rc, task::{Context, Poll}, }; @@ -20,7 +20,6 @@ use h2::{ Ping, PingPong, }; use pin_project_lite::pin_project; -use tracing::{error, trace, warn}; use crate::{ body::{BodySize, BoxBody, MessageBody}, @@ -147,11 +146,13 @@ where if let Err(err) = res { match err { DispatchError::SendResponse(err) => { - trace!("Error sending HTTP/2 response: {:?}", err) + tracing::trace!("Error sending response: {err:?}"); + } + DispatchError::SendData(err) => { + tracing::warn!("Send data error: {err:?}"); } - DispatchError::SendData(err) => warn!("{:?}", err), DispatchError::ResponseBody(err) => { - error!("Response payload stream error: {:?}", err) + tracing::error!("Response payload stream error: {err:?}"); } } } @@ -228,9 +229,9 @@ where return Ok(()); } - // poll response body and send chunks to client - actix_rt::pin!(body); + let mut body = pin!(body); + // poll response body and send chunks to client while let Some(res) = poll_fn(|cx| body.as_mut().poll_next(cx)).await { let mut chunk = res.map_err(|err| DispatchError::ResponseBody(err.into()))?; From f5f6132f948ec8d30251cfc13523db1827f25e2e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 03:30:16 +0000 Subject: [PATCH 208/314] test: update rustls for test_server --- actix-web/Cargo.toml | 6 +++--- actix-web/tests/test_server.rs | 19 ++++++++----------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 8c1cc9bfe..aedcb3ef4 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -128,12 +128,12 @@ env_logger = "0.10" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } rand = "0.8" -rcgen = "0.11" -rustls-pemfile = "1" +rcgen = "0.12" +rustls-pemfile = "2" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls = { package = "rustls", version = "0.21" } +tls-rustls = { package = "rustls", version = "0.22" } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 0df6e2124..36f45c146 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -1,6 +1,6 @@ #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; -#[cfg(feature = "rustls-0_21")] +#[cfg(feature = "rustls-0_22")] extern crate tls_rustls as rustls; use std::{ @@ -708,7 +708,7 @@ async fn test_brotli_encoding_large_openssl() { mod plus_rustls { use std::io::BufReader; - use rustls::{Certificate, PrivateKey, ServerConfig as RustlsServerConfig}; + use rustls::{pki_types::PrivateKeyDer, ServerConfig as RustlsServerConfig}; use rustls_pemfile::{certs, pkcs8_private_keys}; use super::*; @@ -721,17 +721,14 @@ mod plus_rustls { let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); - let cert_chain = certs(cert_file) - .unwrap() - .into_iter() - .map(Certificate) - .collect(); - let mut keys = pkcs8_private_keys(key_file).unwrap(); + let cert_chain = certs(cert_file).collect::, _>>().unwrap(); + let mut keys = pkcs8_private_keys(key_file) + .collect::, _>>() + .unwrap(); RustlsServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() - .with_single_cert(cert_chain, PrivateKey(keys.remove(0))) + .with_single_cert(cert_chain, PrivateKeyDer::Pkcs8(keys.remove(0))) .unwrap() } @@ -743,7 +740,7 @@ mod plus_rustls { .map(char::from) .collect::(); - let srv = actix_test::start_with(actix_test::config().rustls_0_21(tls_config()), || { + let srv = actix_test::start_with(actix_test::config().rustls_0_22(tls_config()), || { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { // echo decompressed request body back in response HttpResponse::Ok() From e518170a30e6bd32c6a42b1ff20f46126ca1f8a8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 4 Feb 2024 03:40:58 +0000 Subject: [PATCH 209/314] test: fix test_server --- actix-web/Cargo.toml | 2 +- actix-web/tests/test_server.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index aedcb3ef4..b045589bd 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -118,7 +118,7 @@ url = "2.1" [dev-dependencies] actix-files = "0.6" -actix-test = { version = "0.1", features = ["openssl", "rustls-0_21"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } awc = { version = "3", features = ["openssl"] } brotli = "3.3.3" diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 36f45c146..8fb80216b 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() { srv.stop().await; } -#[cfg(feature = "rustls-0_21")] +#[cfg(feature = "rustls-0_22")] mod plus_rustls { use std::io::BufReader; From 373d4ca970bce4ab68d2c55a82d8e493cc550890 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 01:27:57 +0000 Subject: [PATCH 210/314] build(deps): bump codecov/codecov-action from 4.0.0 to 4.0.1 (#3279) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d871898f3..9fef98dcd 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.0.0 + uses: codecov/codecov-action@v4.0.1 with: files: codecov.json fail_ci_if_error: true From 7e4e12b0aa674c96e8abe9c79b8bd1fe4fcb5cb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:38:02 +0000 Subject: [PATCH 211/314] build(deps): bump taiki-e/install-action from 2.26.8 to 2.26.12 (#3280) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index de9b30a59..1a0437cbe 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: cargo-hack,cargo-ci-cache-clean @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79c581b81..9af6d75f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9fef98dcd..180a9a0e0 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 502bfeb61..bb03acce2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.26.8 + uses: taiki-e/install-action@v2.26.12 with: tool: cargo-public-api From 1e2ef6f92fe8e6a2eca69233644dc3ff1e375150 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 7 Feb 2024 03:47:30 +0000 Subject: [PATCH 212/314] perf: remove unnecessary allocation when writing http dates (#3261) --- .github/workflows/ci.yml | 14 +++++--------- Cargo.toml | 2 +- actix-files/CHANGES.md | 2 ++ actix-files/README.md | 2 +- actix-http-test/CHANGES.md | 2 ++ actix-http-test/README.md | 7 +------ actix-http/CHANGES.md | 4 ++++ actix-http/Cargo.toml | 5 +++++ actix-http/README.md | 7 +------ actix-http/benches/date-formatting.rs | 20 ++++++++++++++++++++ actix-http/src/date.rs | 2 +- actix-http/src/header/shared/http_date.rs | 5 ++--- actix-multipart-derive/CHANGES.md | 2 ++ actix-multipart-derive/README.md | 7 +------ actix-multipart-derive/tests/trybuild.rs | 2 +- actix-multipart/CHANGES.md | 2 ++ actix-multipart/README.md | 7 +------ actix-router/CHANGES.md | 2 ++ actix-router/README.md | 2 +- actix-test/CHANGES.md | 2 ++ actix-web-actors/CHANGES.md | 2 ++ actix-web-actors/README.md | 7 +------ actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/README.md | 7 +------ actix-web-codegen/tests/trybuild.rs | 2 +- actix-web/CHANGES.md | 4 ++++ actix-web/README.md | 4 ++-- awc/CHANGES.md | 2 ++ awc/README.md | 8 +++----- 29 files changed, 75 insertions(+), 61 deletions(-) create mode 100644 actix-http/benches/date-formatting.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9af6d75f9..ee12ebaba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - { name: msrv, version: 1.68.0 } + - { name: msrv, version: 1.70.0 } - { name: stable, version: stable } name: ${{ matrix.target.name }} / ${{ matrix.version.name }} @@ -54,14 +54,10 @@ jobs: with: tool: cargo-hack,cargo-ci-cache-clean - - name: workaround MSRV issues - if: matrix.version.name == 'msrv' - run: | - cargo update -p=ciborium --precise=0.2.1 - cargo update -p=ciborium-ll --precise=0.2.1 - cargo update -p=clap --precise=4.3.24 - cargo update -p=clap_lex --precise=0.5.0 - cargo update -p=anstyle --precise=1.0.2 + # - name: workaround MSRV issues + # if: matrix.version.name == 'msrv' + # run: | + # cargo update -p=anstyle --precise=1.0.2 - name: check minimal run: cargo ci-check-min diff --git a/Cargo.toml b/Cargo.toml index 58fd96935..f90cdbeab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ members = [ [workspace.package] license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.68" +rust-version = "1.70" [profile.dev] # Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much. diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 9aa62ff77..0099dcf35 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 0.6.5 - Fix handling of special characters in filenames. diff --git a/actix-files/README.md b/actix-files/README.md index df80e4047..1f05be186 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -4,7 +4,7 @@ [![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.6.5)](https://docs.rs/actix-files/0.6.5) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
[![dependency status](https://deps.rs/crate/actix-files/0.6.5/status.svg)](https://deps.rs/crate/actix-files/0.6.5) diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index ec30b9c4c..b9b2d9d14 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 3.2.0 - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 9a87f9ef2..6639874d7 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -6,7 +6,7 @@ [![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=3.2.0)](https://docs.rs/actix-http-test/3.2.0) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
[![Dependency Status](https://deps.rs/crate/actix-http-test/3.2.0/status.svg)](https://deps.rs/crate/actix-http-test/3.2.0) @@ -14,8 +14,3 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) - -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-http-test) -- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index e3805ff7e..a50bb9067 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- Minimum supported Rust version (MSRV) is now 1.70. + ## 3.6.0 ### Added diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 14b9bdacb..e8f315cb9 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -126,6 +126,7 @@ actix-web = "4" async-stream = "0.3" criterion = { version = "0.5", features = ["html_reports"] } +divan = "0.1.8" env_logger = "0.10" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" @@ -153,3 +154,7 @@ required-features = ["http2", "rustls-0_22"] name = "response-body-compression" harness = false required-features = ["compress-brotli", "compress-gzip", "compress-zstd"] + +[[bench]] +name = "date-formatting" +harness = false diff --git a/actix-http/README.md b/actix-http/README.md index c9bd1b34c..4f10ba241 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -6,7 +6,7 @@ [![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=3.6.0)](https://docs.rs/actix-http/3.6.0) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.0) @@ -15,11 +15,6 @@ -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-http) -- Minimum Supported Rust Version (MSRV): 1.68 - ## Examples ```rust diff --git a/actix-http/benches/date-formatting.rs b/actix-http/benches/date-formatting.rs new file mode 100644 index 000000000..26d0f3daa --- /dev/null +++ b/actix-http/benches/date-formatting.rs @@ -0,0 +1,20 @@ +use std::time::SystemTime; + +use actix_http::header::HttpDate; +use divan::{black_box, AllocProfiler, Bencher}; + +#[global_allocator] +static ALLOC: AllocProfiler = AllocProfiler::system(); + +#[divan::bench] +fn date_formatting(b: Bencher<'_, '_>) { + let now = SystemTime::now(); + + b.bench(|| { + black_box(HttpDate::from(black_box(now)).to_string()); + }) +} + +fn main() { + divan::main(); +} diff --git a/actix-http/src/date.rs b/actix-http/src/date.rs index 1358bbd8c..735dd9100 100644 --- a/actix-http/src/date.rs +++ b/actix-http/src/date.rs @@ -28,7 +28,7 @@ impl Date { fn update(&mut self) { self.pos = 0; - write!(self, "{}", httpdate::fmt_http_date(SystemTime::now())).unwrap(); + write!(self, "{}", httpdate::HttpDate::from(SystemTime::now())).unwrap(); } } diff --git a/actix-http/src/header/shared/http_date.rs b/actix-http/src/header/shared/http_date.rs index 21ed49f0c..bdfbc7051 100644 --- a/actix-http/src/header/shared/http_date.rs +++ b/actix-http/src/header/shared/http_date.rs @@ -24,8 +24,7 @@ impl FromStr for HttpDate { impl fmt::Display for HttpDate { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let date_str = httpdate::fmt_http_date(self.0); - f.write_str(&date_str) + httpdate::HttpDate::from(self.0).fmt(f) } } @@ -37,7 +36,7 @@ impl TryIntoHeaderValue for HttpDate { let mut wrt = MutWriter(&mut buf); // unwrap: date output is known to be well formed and of known length - write!(wrt, "{}", httpdate::fmt_http_date(self.0)).unwrap(); + write!(wrt, "{}", self).unwrap(); HeaderValue::from_maybe_shared(buf.split().freeze()) } diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index e36a13d04..23dd4f2df 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 0.6.1 - Update `syn` dependency to `2`. diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index 2beadefe3..6845e9dfb 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) [![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart-derive/0.6.1) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg)
[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.6.1) @@ -14,8 +14,3 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) - -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-multipart-derive) -- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-multipart-derive/tests/trybuild.rs b/actix-multipart-derive/tests/trybuild.rs index 88aa619c6..b196868a7 100644 --- a/actix-multipart-derive/tests/trybuild.rs +++ b/actix-multipart-derive/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.68)] // MSRV +#[rustversion::stable(1.70)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 50faf7cfa..214f899e0 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 0.6.1 - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 16068510e..15a701751 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) [![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
[![dependency status](https://deps.rs/crate/actix-multipart/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart/0.6.1) @@ -14,8 +14,3 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) - -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-multipart) -- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index a855c0074..4d77988d1 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 0.5.2 - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-router/README.md b/actix-router/README.md index 7760b0331..506b65016 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) [![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg)
[![dependency status](https://deps.rs/crate/actix-router/0.5.2/status.svg)](https://deps.rs/crate/actix-router/0.5.2) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 8604a1265..99bb21edc 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 0.1.3 - Add `TestServerConfig::rustls_0_22()` method for Rustls v0.22 support behind new `rustls-0_22` crate feature. diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 85d6b624a..c146841f5 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 4.3.0 - Minimum supported Rust version (MSRV) is now 1.68 due to transitive `time` dependency. diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index 17b947223..202d7d4c9 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) [![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.3.0)](https://docs.rs/actix-web-actors/4.3.0) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
[![dependency status](https://deps.rs/crate/actix-web-actors/4.3.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.3.0) @@ -14,8 +14,3 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) - -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-web-actors) -- Minimum Supported Rust Version (MSRV): 1.68 diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 00e36b037..ecab6e094 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 4.2.2 - Fix regression when declaring `wrap` attribute using an expression. diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 088f35756..bd79f9afb 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) [![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) -![Version](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.2/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.2) @@ -15,11 +15,6 @@ -## Documentation & Resources - -- [API Documentation](https://docs.rs/actix-web-codegen) -- Minimum Supported Rust Version (MSRV): 1.68 - ## Compile Testing Uses the [`trybuild`] crate. All compile fail tests should include a stderr file generated by `trybuild`. See the [workflow section](https://github.com/dtolnay/trybuild#workflow) of the trybuild docs for info on how to do this. diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 8e1f58a4c..13b0359f3 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.68)] // MSRV +#[rustversion::stable(1.70)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 6e2894e40..d296e3345 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- Minimum supported Rust version (MSRV) is now 1.70. + ## 4.5.1 ### Fixed diff --git a/actix-web/README.md b/actix-web/README.md index b564c8793..613f7e04e 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -9,7 +9,7 @@ [![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=4.5.1)](https://docs.rs/actix-web/4.5.1) -![MSRV](https://img.shields.io/badge/rustc-1.68+-ab6000.svg) +![MSRV](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.5.1/status.svg)](https://deps.rs/crate/actix-web/4.5.1)
@@ -37,7 +37,7 @@ - SSL support using OpenSSL or Rustls - Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/)) - Integrates with the [`awc` HTTP client](https://docs.rs/awc/) -- Runs on stable Rust 1.68+ +- Runs on stable Rust 1.70+ ## Documentation diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 4ed02ada6..769f896a8 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Minimum supported Rust version (MSRV) is now 1.70. + ## 3.4.0 - Add `rustls-0_22-webpki-roots` and `rustls-0_22-native-roots` crate feature. diff --git a/awc/README.md b/awc/README.md index d86657564..19236b85a 100644 --- a/awc/README.md +++ b/awc/README.md @@ -12,13 +12,11 @@ -## Documentation & Resources +## Examples -- [API Documentation](https://docs.rs/awc) -- [Example Project](https://github.com/actix/examples/tree/master/https-tls/awc-https) -- Minimum Supported Rust Version (MSRV): 1.68 +[Example project using TLS-enabled client →](https://github.com/actix/examples/tree/master/https-tls/awc-https) -## Example +Basic usage: ```rust use actix_rt::System; From 022b052bd97823c56be5cc5f38340ecb9d3cf591 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 12 Feb 2024 23:02:45 +0000 Subject: [PATCH 213/314] chore: clippy --- actix-http/src/h1/dispatcher.rs | 2 +- actix-http/src/h2/dispatcher.rs | 2 +- actix-http/src/header/utils.rs | 6 +++--- actix-http/src/notify_on_drop.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index bfbcaf24c..a24a6bb07 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -706,7 +706,7 @@ where req.head_mut().peer_addr = *this.peer_addr; - req.conn_data = this.conn_data.as_ref().map(Rc::clone); + req.conn_data = this.conn_data.clone(); match this.codec.message_type() { // request has no payload diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 022239c2d..97ceb51e9 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -126,7 +126,7 @@ where head.headers = parts.headers.into(); head.peer_addr = this.peer_addr; - req.conn_data = this.conn_data.as_ref().map(Rc::clone); + req.conn_data = this.conn_data.clone(); let fut = this.flow.service.call(req); let config = this.config.clone(); diff --git a/actix-http/src/header/utils.rs b/actix-http/src/header/utils.rs index f4f34d347..caaab3b1e 100644 --- a/actix-http/src/header/utils.rs +++ b/actix-http/src/header/utils.rs @@ -80,18 +80,18 @@ mod tests { #[test] fn comma_delimited_parsing() { - let headers = vec![]; + let headers = []; let res: Vec = from_comma_delimited(headers.iter()).unwrap(); assert_eq!(res, vec![0; 0]); - let headers = vec![ + let headers = [ HeaderValue::from_static("1, 2"), HeaderValue::from_static("3,4"), ]; let res: Vec = from_comma_delimited(headers.iter()).unwrap(); assert_eq!(res, vec![1, 2, 3, 4]); - let headers = vec![ + let headers = [ HeaderValue::from_static(""), HeaderValue::from_static(","), HeaderValue::from_static(" "), diff --git a/actix-http/src/notify_on_drop.rs b/actix-http/src/notify_on_drop.rs index 98544bb5d..95904b28e 100644 --- a/actix-http/src/notify_on_drop.rs +++ b/actix-http/src/notify_on_drop.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; thread_local! { - static NOTIFY_DROPPED: RefCell> = RefCell::new(None); + static NOTIFY_DROPPED: RefCell> = const { RefCell::new(None) }; } /// Check if the spawned task is dropped. From 1e08ebabf9410ad125947d1bf9a8e8d1fde5ef40 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 13 Feb 2024 01:24:34 +0000 Subject: [PATCH 214/314] build: bump MSRV to 1.72 --- .github/workflows/ci.yml | 2 +- Cargo.toml | 2 +- actix-files/CHANGES.md | 2 +- actix-files/README.md | 2 +- actix-http-test/CHANGES.md | 2 +- actix-http-test/README.md | 2 +- actix-http/CHANGES.md | 2 +- actix-http/README.md | 2 +- actix-multipart-derive/CHANGES.md | 2 +- actix-multipart-derive/README.md | 2 +- actix-multipart-derive/tests/trybuild.rs | 2 +- actix-multipart/CHANGES.md | 2 +- actix-multipart/README.md | 2 +- actix-router/CHANGES.md | 2 +- actix-router/README.md | 2 +- actix-test/CHANGES.md | 2 +- actix-web-actors/CHANGES.md | 2 +- actix-web-actors/README.md | 2 +- actix-web-codegen/CHANGES.md | 2 +- actix-web-codegen/README.md | 2 +- actix-web-codegen/tests/trybuild.rs | 2 +- actix-web/CHANGES.md | 2 +- actix-web/README.md | 4 ++-- awc/CHANGES.md | 2 +- 24 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee12ebaba..a328c74d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - { name: msrv, version: 1.70.0 } + - { name: msrv, version: 1.72.0 } - { name: stable, version: stable } name: ${{ matrix.target.name }} / ${{ matrix.version.name }} diff --git a/Cargo.toml b/Cargo.toml index f90cdbeab..9efeda4d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ members = [ [workspace.package] license = "MIT OR Apache-2.0" edition = "2021" -rust-version = "1.70" +rust-version = "1.72" [profile.dev] # Disabling debug info speeds up builds a bunch and we don't rely on it for debugging that much. diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 0099dcf35..393e7b61a 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.5 diff --git a/actix-files/README.md b/actix-files/README.md index 1f05be186..a6b3f63c6 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -4,7 +4,7 @@ [![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.6.5)](https://docs.rs/actix-files/0.6.5) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
[![dependency status](https://deps.rs/crate/actix-files/0.6.5/status.svg)](https://deps.rs/crate/actix-files/0.6.5) diff --git a/actix-http-test/CHANGES.md b/actix-http-test/CHANGES.md index b9b2d9d14..4d133e3ec 100644 --- a/actix-http-test/CHANGES.md +++ b/actix-http-test/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 3.2.0 diff --git a/actix-http-test/README.md b/actix-http-test/README.md index 6639874d7..ee242d1d5 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -6,7 +6,7 @@ [![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=3.2.0)](https://docs.rs/actix-http-test/3.2.0) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http-test)
[![Dependency Status](https://deps.rs/crate/actix-http-test/3.2.0/status.svg)](https://deps.rs/crate/actix-http-test/3.2.0) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index a50bb9067..fddd1c2c3 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,7 +4,7 @@ ### Changed -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 3.6.0 diff --git a/actix-http/README.md b/actix-http/README.md index 4f10ba241..3881b805d 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -6,7 +6,7 @@ [![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=3.6.0)](https://docs.rs/actix-http/3.6.0) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.0) diff --git a/actix-multipart-derive/CHANGES.md b/actix-multipart-derive/CHANGES.md index 23dd4f2df..1b44ba4b7 100644 --- a/actix-multipart-derive/CHANGES.md +++ b/actix-multipart-derive/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.1 diff --git a/actix-multipart-derive/README.md b/actix-multipart-derive/README.md index 6845e9dfb..ec0afffdd 100644 --- a/actix-multipart-derive/README.md +++ b/actix-multipart-derive/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart-derive?label=latest)](https://crates.io/crates/actix-multipart-derive) [![Documentation](https://docs.rs/actix-multipart-derive/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart-derive/0.6.1) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart-derive.svg)
[![dependency status](https://deps.rs/crate/actix-multipart-derive/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart-derive/0.6.1) diff --git a/actix-multipart-derive/tests/trybuild.rs b/actix-multipart-derive/tests/trybuild.rs index b196868a7..6b25d78df 100644 --- a/actix-multipart-derive/tests/trybuild.rs +++ b/actix-multipart-derive/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.70)] // MSRV +#[rustversion::stable(1.72)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 214f899e0..adf370444 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.1 diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 15a701751..56723bd68 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) [![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
[![dependency status](https://deps.rs/crate/actix-multipart/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart/0.6.1) diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 4d77988d1..a80b15e69 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.5.2 diff --git a/actix-router/README.md b/actix-router/README.md index 506b65016..751c307b1 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -4,7 +4,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) [![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg)
[![dependency status](https://deps.rs/crate/actix-router/0.5.2/status.svg)](https://deps.rs/crate/actix-router/0.5.2) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 99bb21edc..082520447 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.1.3 diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index c146841f5..9a622d8da 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 4.3.0 diff --git a/actix-web-actors/README.md b/actix-web-actors/README.md index 202d7d4c9..feb3d1b33 100644 --- a/actix-web-actors/README.md +++ b/actix-web-actors/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-actors?label=latest)](https://crates.io/crates/actix-web-actors) [![Documentation](https://docs.rs/actix-web-actors/badge.svg?version=4.3.0)](https://docs.rs/actix-web-actors/4.3.0) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-actors.svg)
[![dependency status](https://deps.rs/crate/actix-web-actors/4.3.0/status.svg)](https://deps.rs/crate/actix-web-actors/4.3.0) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index ecab6e094..a5acdd21c 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 4.2.2 diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index bd79f9afb..9229f8f16 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -6,7 +6,7 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) [![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) -![Version](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.2/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.2) diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 13b0359f3..88f77548b 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -1,4 +1,4 @@ -#[rustversion::stable(1.70)] // MSRV +#[rustversion::stable(1.72)] // MSRV #[test] fn compile_macros() { let t = trybuild::TestCases::new(); diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index d296e3345..88215293a 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,7 +4,7 @@ ### Changed -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 4.5.1 diff --git a/actix-web/README.md b/actix-web/README.md index 613f7e04e..35e07fc0b 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -9,7 +9,7 @@ [![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=4.5.1)](https://docs.rs/actix-web/4.5.1) -![MSRV](https://img.shields.io/badge/rustc-1.70+-ab6000.svg) +![MSRV](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) [![Dependency Status](https://deps.rs/crate/actix-web/4.5.1/status.svg)](https://deps.rs/crate/actix-web/4.5.1)
@@ -37,7 +37,7 @@ - SSL support using OpenSSL or Rustls - Middlewares ([Logger, Session, CORS, etc](https://actix.rs/docs/middleware/)) - Integrates with the [`awc` HTTP client](https://docs.rs/awc/) -- Runs on stable Rust 1.70+ +- Runs on stable Rust 1.72+ ## Documentation diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 769f896a8..507c8a080 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -- Minimum supported Rust version (MSRV) is now 1.70. +- Minimum supported Rust version (MSRV) is now 1.72. ## 3.4.0 From 9ce5e33b72e238355683cfbb1815be6ea9fdc78e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 13 Feb 2024 01:42:54 +0000 Subject: [PATCH 215/314] ci: workaround clap MSRV in dev deps --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a328c74d6..915eb7eae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,10 +54,10 @@ jobs: with: tool: cargo-hack,cargo-ci-cache-clean - # - name: workaround MSRV issues - # if: matrix.version.name == 'msrv' - # run: | - # cargo update -p=anstyle --precise=1.0.2 + - name: workaround MSRV issues + if: matrix.version.name == 'msrv' + run: | + cargo update -p=clap --precise=4.4.18 - name: check minimal run: cargo ci-check-min From 3819767fa02850abe654a9e76b53682c39fe9b9c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 13 Feb 2024 02:14:03 +0000 Subject: [PATCH 216/314] test: fix trybuild tests --- .../tests/trybuild/route-custom-lowercase.stderr | 13 ++++++++----- .../trybuild/route-duplicate-method-fail.stderr | 13 ++++++++----- .../tests/trybuild/route-missing-method-fail.stderr | 13 ++++++++----- .../tests/trybuild/routes-missing-args-fail.stderr | 13 ++++++++----- .../trybuild/routes-missing-method-fail.stderr | 13 ++++++++----- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr index 88198a55d..c2a51d005 100644 --- a/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr +++ b/actix-web-codegen/tests/trybuild/route-custom-lowercase.stderr @@ -13,17 +13,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future | required by a bound introduced by this call | = help: the following other types implement trait `HttpServiceFactory`: + Resource + actix_web::Scope + Vec + Redirect + (A,) (A, B) (A, B, C) (A, B, C, D) - (A, B, C, D, E) - (A, B, C, D, E, F) - (A, B, C, D, E, F, G) - (A, B, C, D, E, F, G, H) - (A, B, C, D, E, F, G, H, I) and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | + | pub fn service(mut self, factory: F) -> Self + | ------- required by a bound in this associated function + | where | F: HttpServiceFactory + 'static, | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr b/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr index bda736348..ae18f347f 100644 --- a/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-duplicate-method-fail.stderr @@ -13,17 +13,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future | required by a bound introduced by this call | = help: the following other types implement trait `HttpServiceFactory`: + Resource + actix_web::Scope + Vec + Redirect + (A,) (A, B) (A, B, C) (A, B, C, D) - (A, B, C, D, E) - (A, B, C, D, E, F) - (A, B, C, D, E, F, G) - (A, B, C, D, E, F, G, H) - (A, B, C, D, E, F, G, H, I) and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | + | pub fn service(mut self, factory: F) -> Self + | ------- required by a bound in this associated function + | where | F: HttpServiceFactory + 'static, | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr b/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr index 9f2f788fb..37d8354c9 100644 --- a/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-missing-method-fail.stderr @@ -15,17 +15,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future | required by a bound introduced by this call | = help: the following other types implement trait `HttpServiceFactory`: + Resource + actix_web::Scope + Vec + Redirect + (A,) (A, B) (A, B, C) (A, B, C, D) - (A, B, C, D, E) - (A, B, C, D, E, F) - (A, B, C, D, E, F, G) - (A, B, C, D, E, F, G, H) - (A, B, C, D, E, F, G, H, I) and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | + | pub fn service(mut self, factory: F) -> Self + | ------- required by a bound in this associated function + | where | F: HttpServiceFactory + 'static, | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr index 2e84c296a..40b19fc77 100644 --- a/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr +++ b/actix-web-codegen/tests/trybuild/routes-missing-args-fail.stderr @@ -29,17 +29,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future | required by a bound introduced by this call | = help: the following other types implement trait `HttpServiceFactory`: + Resource + actix_web::Scope + Vec + Redirect + (A,) (A, B) (A, B, C) (A, B, C, D) - (A, B, C, D, E) - (A, B, C, D, E, F) - (A, B, C, D, E, F, G) - (A, B, C, D, E, F, G, H) - (A, B, C, D, E, F, G, H, I) and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | + | pub fn service(mut self, factory: F) -> Self + | ------- required by a bound in this associated function + | where | F: HttpServiceFactory + 'static, | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` diff --git a/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr b/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr index 228dced9c..ff7f00b3b 100644 --- a/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr +++ b/actix-web-codegen/tests/trybuild/routes-missing-method-fail.stderr @@ -15,17 +15,20 @@ error[E0277]: the trait bound `fn() -> impl std::future::Future | required by a bound introduced by this call | = help: the following other types implement trait `HttpServiceFactory`: + Resource + actix_web::Scope + Vec + Redirect + (A,) (A, B) (A, B, C) (A, B, C, D) - (A, B, C, D, E) - (A, B, C, D, E, F) - (A, B, C, D, E, F, G) - (A, B, C, D, E, F, G, H) - (A, B, C, D, E, F, G, H, I) and $N others note: required by a bound in `App::::service` --> $WORKSPACE/actix-web/src/app.rs | + | pub fn service(mut self, factory: F) -> Self + | ------- required by a bound in this associated function + | where | F: HttpServiceFactory + 'static, | ^^^^^^^^^^^^^^^^^^ required by this bound in `App::::service` From 82f8ddc38f279e1b7bea2c1103b784f5fdc1fb8e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Wed, 14 Feb 2024 22:22:07 +0000 Subject: [PATCH 217/314] feat: multipart testing utilities (#3288) --- actix-multipart/CHANGES.md | 1 + actix-multipart/Cargo.toml | 3 + actix-multipart/src/form/json.rs | 51 +++++--- actix-multipart/src/lib.rs | 7 +- actix-multipart/src/server.rs | 32 ++++- actix-multipart/src/test.rs | 217 +++++++++++++++++++++++++++++++ 6 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 actix-multipart/src/test.rs diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index adf370444..196d2ca93 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add testing utilities under new module `test`. - Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.1 diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 257d56132..6e36c3391 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -35,6 +35,7 @@ local-waker = "0.1" log = "0.4" memchr = "2.5" mime = "0.3" +rand = "0.8" serde = "1" serde_json = "1" serde_plain = "1" @@ -46,7 +47,9 @@ actix-http = "3" actix-multipart-rfc7578 = "0.10" actix-rt = "2.2" actix-test = "0.1" +actix-web = "4" awc = "3" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } +multer = "3" tokio = { version = "1.24.2", features = ["sync"] } tokio-stream = "0.1" diff --git a/actix-multipart/src/form/json.rs b/actix-multipart/src/form/json.rs index fb90a82b9..bb4e03bf6 100644 --- a/actix-multipart/src/form/json.rs +++ b/actix-multipart/src/form/json.rs @@ -131,14 +131,13 @@ impl Default for JsonConfig { #[cfg(test)] mod tests { - use std::{collections::HashMap, io::Cursor}; + use std::collections::HashMap; - use actix_multipart_rfc7578::client::multipart; use actix_web::{http::StatusCode, web, App, HttpResponse, Responder}; + use bytes::Bytes; use crate::form::{ json::{Json, JsonConfig}, - tests::send_form, MultipartForm, }; @@ -155,6 +154,8 @@ mod tests { HttpResponse::Ok().finish() } + const TEST_JSON: &str = r#"{"key1": "value1", "key2": "value2"}"#; + #[actix_rt::test] async fn test_json_without_content_type() { let srv = actix_test::start(|| { @@ -163,10 +164,16 @@ mod tests { .app_data(JsonConfig::default().validate_content_type(false)) }); - let mut form = multipart::Form::default(); - form.add_text("json", "{\"key1\": \"value1\", \"key2\": \"value2\"}"); - let response = send_form(&srv, form, "/").await; - assert_eq!(response.status(), StatusCode::OK); + let (body, headers) = crate::test::create_form_data_payload_and_headers( + "json", + None, + None, + Bytes::from_static(TEST_JSON.as_bytes()), + ); + let mut req = srv.post("/"); + *req.headers_mut() = headers; + let res = req.send_body(body).await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); } #[actix_rt::test] @@ -178,17 +185,27 @@ mod tests { }); // Deny because wrong content type - let bytes = Cursor::new("{\"key1\": \"value1\", \"key2\": \"value2\"}"); - let mut form = multipart::Form::default(); - form.add_reader_file_with_mime("json", bytes, "", mime::APPLICATION_OCTET_STREAM); - let response = send_form(&srv, form, "/").await; - assert_eq!(response.status(), StatusCode::BAD_REQUEST); + let (body, headers) = crate::test::create_form_data_payload_and_headers( + "json", + None, + Some(mime::APPLICATION_OCTET_STREAM), + Bytes::from_static(TEST_JSON.as_bytes()), + ); + let mut req = srv.post("/"); + *req.headers_mut() = headers; + let res = req.send_body(body).await.unwrap(); + assert_eq!(res.status(), StatusCode::BAD_REQUEST); // Allow because correct content type - let bytes = Cursor::new("{\"key1\": \"value1\", \"key2\": \"value2\"}"); - let mut form = multipart::Form::default(); - form.add_reader_file_with_mime("json", bytes, "", mime::APPLICATION_JSON); - let response = send_form(&srv, form, "/").await; - assert_eq!(response.status(), StatusCode::OK); + let (body, headers) = crate::test::create_form_data_payload_and_headers( + "json", + None, + Some(mime::APPLICATION_JSON), + Bytes::from_static(TEST_JSON.as_bytes()), + ); + let mut req = srv.post("/"); + *req.headers_mut() = headers; + let res = req.send_body(body).await.unwrap(); + assert_eq!(res.status(), StatusCode::OK); } } diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index 495bae9c0..c06a00ca9 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -13,11 +13,14 @@ extern crate self as actix_multipart; mod error; mod extractor; -mod server; - pub mod form; +mod server; +pub mod test; pub use self::{ error::MultipartError, server::{Field, Multipart}, + test::{ + create_form_data_payload_and_headers, create_form_data_payload_and_headers_with_boundary, + }, }; diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index c08031eba..ae32cf0cd 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -863,13 +863,15 @@ mod tests { test::TestRequest, FromRequest, }; - use bytes::Bytes; + use bytes::{BufMut as _, Bytes}; use futures_util::{future::lazy, StreamExt as _}; use tokio::sync::mpsc; use tokio_stream::wrappers::UnboundedReceiverStream; use super::*; + const BOUNDARY: &str = "abbc761f78ff4d7cb7573b5a23f96ef0"; + #[actix_rt::test] async fn test_boundary() { let headers = HeaderMap::new(); @@ -965,6 +967,26 @@ mod tests { } fn create_simple_request_with_header() -> (Bytes, HeaderMap) { + let (body, headers) = crate::test::create_form_data_payload_and_headers_with_boundary( + BOUNDARY, + "file", + Some("fn.txt".to_owned()), + Some(mime::TEXT_PLAIN_UTF_8), + Bytes::from_static(b"data"), + ); + + let mut buf = BytesMut::with_capacity(body.len() + 14); + + // add junk before form to test pre-boundary data rejection + buf.put("testasdadsad\r\n".as_bytes()); + + buf.put(body); + + (buf.freeze(), headers) + } + + // TODO: use test utility when multi-file support is introduced + fn create_double_request_with_header() -> (Bytes, HeaderMap) { let bytes = Bytes::from( "testasdadsad\r\n\ --abbc761f78ff4d7cb7573b5a23f96ef0\r\n\ @@ -990,7 +1012,7 @@ mod tests { #[actix_rt::test] async fn test_multipart_no_end_crlf() { let (sender, payload) = create_stream(); - let (mut bytes, headers) = create_simple_request_with_header(); + let (mut bytes, headers) = create_double_request_with_header(); let bytes_stripped = bytes.split_to(bytes.len()); // strip crlf sender.send(Ok(bytes_stripped)).unwrap(); @@ -1017,7 +1039,7 @@ mod tests { #[actix_rt::test] async fn test_multipart() { let (sender, payload) = create_stream(); - let (bytes, headers) = create_simple_request_with_header(); + let (bytes, headers) = create_double_request_with_header(); sender.send(Ok(bytes)).unwrap(); @@ -1080,7 +1102,7 @@ mod tests { #[actix_rt::test] async fn test_stream() { - let (bytes, headers) = create_simple_request_with_header(); + let (bytes, headers) = create_double_request_with_header(); let payload = SlowStream::new(bytes); let mut multipart = Multipart::new(&headers, payload); @@ -1319,7 +1341,7 @@ mod tests { #[actix_rt::test] async fn test_drop_field_awaken_multipart() { let (sender, payload) = create_stream(); - let (bytes, headers) = create_simple_request_with_header(); + let (bytes, headers) = create_double_request_with_header(); sender.send(Ok(bytes)).unwrap(); drop(sender); // eof diff --git a/actix-multipart/src/test.rs b/actix-multipart/src/test.rs new file mode 100644 index 000000000..77d918283 --- /dev/null +++ b/actix-multipart/src/test.rs @@ -0,0 +1,217 @@ +use actix_web::http::header::{self, HeaderMap}; +use bytes::{BufMut as _, Bytes, BytesMut}; +use mime::Mime; +use rand::{ + distributions::{Alphanumeric, DistString as _}, + thread_rng, +}; + +const CRLF: &[u8] = b"\r\n"; +const CRLF_CRLF: &[u8] = b"\r\n\r\n"; +const HYPHENS: &[u8] = b"--"; +const BOUNDARY_PREFIX: &str = "------------------------"; + +/// Constructs a `multipart/form-data` payload from bytes and metadata. +/// +/// Returned header map can be extended or merged with existing headers. +/// +/// Multipart boundary used is a random alphanumeric string. +/// +/// # Examples +/// +/// ``` +/// use actix_multipart::test::create_form_data_payload_and_headers; +/// use actix_web::test::TestRequest; +/// use bytes::Bytes; +/// use memchr::memmem::find; +/// +/// let (body, headers) = create_form_data_payload_and_headers( +/// "foo", +/// Some("lorem.txt".to_owned()), +/// Some(mime::TEXT_PLAIN_UTF_8), +/// Bytes::from_static(b"Lorem ipsum."), +/// ); +/// +/// assert!(find(&body, b"foo").is_some()); +/// assert!(find(&body, b"lorem.txt").is_some()); +/// assert!(find(&body, b"text/plain; charset=utf-8").is_some()); +/// assert!(find(&body, b"Lorem ipsum.").is_some()); +/// +/// let req = TestRequest::default(); +/// +/// // merge header map into existing test request and set multipart body +/// let req = headers +/// .into_iter() +/// .fold(req, |req, hdr| req.insert_header(hdr)) +/// .set_payload(body) +/// .to_http_request(); +/// +/// assert!( +/// req.headers() +/// .get("content-type") +/// .unwrap() +/// .to_str() +/// .unwrap() +/// .starts_with("multipart/form-data; boundary=\"") +/// ); +/// ``` +pub fn create_form_data_payload_and_headers( + name: &str, + filename: Option, + content_type: Option, + file: Bytes, +) -> (Bytes, HeaderMap) { + let boundary = Alphanumeric.sample_string(&mut thread_rng(), 32); + + create_form_data_payload_and_headers_with_boundary( + &boundary, + name, + filename, + content_type, + file, + ) +} + +/// Constructs a `multipart/form-data` payload from bytes and metadata with a fixed boundary. +/// +/// See [`create_form_data_payload_and_headers`] for more details. +pub fn create_form_data_payload_and_headers_with_boundary( + boundary: &str, + name: &str, + filename: Option, + content_type: Option, + file: Bytes, +) -> (Bytes, HeaderMap) { + let mut buf = BytesMut::with_capacity(file.len() + 128); + + let boundary_str = [BOUNDARY_PREFIX, boundary].concat(); + let boundary = boundary_str.as_bytes(); + + buf.put(HYPHENS); + buf.put(boundary); + buf.put(CRLF); + + buf.put(format!("Content-Disposition: form-data; name=\"{name}\"").as_bytes()); + if let Some(filename) = filename { + buf.put(format!("; filename=\"{filename}\"").as_bytes()); + } + buf.put(CRLF); + + if let Some(ct) = content_type { + buf.put(format!("Content-Type: {ct}").as_bytes()); + buf.put(CRLF); + } + + buf.put(format!("Content-Length: {}", file.len()).as_bytes()); + buf.put(CRLF_CRLF); + + buf.put(file); + buf.put(CRLF); + + buf.put(HYPHENS); + buf.put(boundary); + buf.put(HYPHENS); + buf.put(CRLF); + + let mut headers = HeaderMap::new(); + headers.insert( + header::CONTENT_TYPE, + format!("multipart/form-data; boundary=\"{boundary_str}\"") + .parse() + .unwrap(), + ); + + (buf.freeze(), headers) +} + +#[cfg(test)] +mod tests { + use std::convert::Infallible; + + use futures_util::stream; + + use super::*; + + fn find_boundary(headers: &HeaderMap) -> String { + headers + .get("content-type") + .unwrap() + .to_str() + .unwrap() + .parse::() + .unwrap() + .get_param(mime::BOUNDARY) + .unwrap() + .as_str() + .to_owned() + } + + #[test] + fn wire_format() { + let (pl, headers) = create_form_data_payload_and_headers_with_boundary( + "qWeRtYuIoP", + "foo", + None, + None, + Bytes::from_static(b"Lorem ipsum dolor\nsit ame."), + ); + + assert_eq!( + find_boundary(&headers), + "------------------------qWeRtYuIoP", + ); + + assert_eq!( + std::str::from_utf8(&pl).unwrap(), + "--------------------------qWeRtYuIoP\r\n\ + Content-Disposition: form-data; name=\"foo\"\r\n\ + Content-Length: 26\r\n\ + \r\n\ + Lorem ipsum dolor\n\ + sit ame.\r\n\ + --------------------------qWeRtYuIoP--\r\n", + ); + + let (pl, _headers) = create_form_data_payload_and_headers_with_boundary( + "qWeRtYuIoP", + "foo", + Some("Lorem.txt".to_owned()), + Some(mime::TEXT_PLAIN_UTF_8), + Bytes::from_static(b"Lorem ipsum dolor\nsit ame."), + ); + + assert_eq!( + std::str::from_utf8(&pl).unwrap(), + "--------------------------qWeRtYuIoP\r\n\ + Content-Disposition: form-data; name=\"foo\"; filename=\"Lorem.txt\"\r\n\ + Content-Type: text/plain; charset=utf-8\r\n\ + Content-Length: 26\r\n\ + \r\n\ + Lorem ipsum dolor\n\ + sit ame.\r\n\ + --------------------------qWeRtYuIoP--\r\n", + ); + } + + /// Test using an external library to prevent the two-wrongs-make-a-right class of errors. + #[actix_web::test] + async fn ecosystem_compat() { + let (pl, headers) = create_form_data_payload_and_headers( + "foo", + None, + None, + Bytes::from_static(b"Lorem ipsum dolor\nsit ame."), + ); + + let boundary = find_boundary(&headers); + + let pl = stream::once(async { Ok::<_, Infallible>(pl) }); + + let mut form = multer::Multipart::new(pl, boundary); + let field = form.next_field().await.unwrap().unwrap(); + assert_eq!(field.name().unwrap(), "foo"); + assert_eq!(field.file_name(), None); + assert_eq!(field.content_type(), None); + assert!(field.bytes().await.unwrap().starts_with(b"Lorem")); + } +} From 289f749e9f29efbfdf5c965794056d441302a75f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:38:38 +0000 Subject: [PATCH 218/314] build(deps): bump taiki-e/install-action from 2.26.12 to 2.26.18 (#3289) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 1a0437cbe..23a6be2f4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: cargo-hack,cargo-ci-cache-clean @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 915eb7eae..e0b4f0986 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 180a9a0e0..be56d0a7c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index bb03acce2..8e5b2881f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.26.12 + uses: taiki-e/install-action@v2.26.18 with: tool: cargo-public-api From 8c31d137aaf9ce8f536e5a71aa04cf68b556a7cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 12:31:10 +0000 Subject: [PATCH 219/314] build(deps): bump taiki-e/install-action from 2.26.18 to 2.27.2 (#3294) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- actix-files/src/lib.rs | 2 +- actix-http/src/body/message_body.rs | 1 - actix-http/src/error.rs | 4 +--- actix-http/src/h1/codec.rs | 3 --- actix-http/src/h1/decoder.rs | 9 +-------- actix-http/src/ws/mod.rs | 2 +- actix-http/src/ws/proto.rs | 5 +---- actix-multipart/src/server.rs | 2 +- actix-router/src/de.rs | 4 ++-- actix-web-actors/src/context.rs | 2 -- actix-web-actors/src/ws.rs | 5 +---- actix-web/src/app.rs | 1 - actix-web/src/guard/mod.rs | 2 +- actix-web/src/http/header/content_length.rs | 2 +- actix-web/src/middleware/condition.rs | 2 +- actix-web/src/middleware/default_headers.rs | 2 -- actix-web/src/middleware/err_handlers.rs | 5 +---- actix-web/src/middleware/logger.rs | 2 +- actix-web/src/middleware/normalize.rs | 1 - actix-web/src/redirect.rs | 2 +- actix-web/src/request.rs | 2 +- actix-web/src/resource.rs | 10 ++-------- actix-web/src/response/builder.rs | 5 +---- actix-web/src/response/customize_responder.rs | 5 +---- actix-web/src/response/responder.rs | 6 +----- actix-web/src/response/response.rs | 2 +- actix-web/src/scope.rs | 2 -- actix-web/src/service.rs | 2 +- actix-web/src/test/test_request.rs | 2 +- actix-web/src/types/either.rs | 5 +---- actix-web/src/types/form.rs | 2 +- actix-web/src/types/payload.rs | 6 ++---- awc/src/client/connection.rs | 2 -- awc/src/client/connector.rs | 1 - awc/src/client/pool.rs | 3 +-- awc/src/middleware/redirect.rs | 5 +---- awc/src/responses/json_body.rs | 2 +- awc/src/responses/response_body.rs | 2 +- awc/src/test.rs | 2 +- 43 files changed, 39 insertions(+), 97 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 23a6be2f4..4d6684159 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: cargo-hack,cargo-ci-cache-clean @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0b4f0986..b40a9f13e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index be56d0a7c..180ba35db 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8e5b2881f..79f53ce10 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.26.18 + uses: taiki-e/install-action@v2.27.2 with: tool: cargo-public-api diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 8381519aa..167f996c0 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -75,7 +75,7 @@ mod tests { dev::ServiceFactory, guard, http::{ - header::{self, ContentDisposition, DispositionParam, DispositionType}, + header::{self, ContentDisposition, DispositionParam}, Method, StatusCode, }, middleware::Compress, diff --git a/actix-http/src/body/message_body.rs b/actix-http/src/body/message_body.rs index c3f55ce7d..739fe5027 100644 --- a/actix-http/src/body/message_body.rs +++ b/actix-http/src/body/message_body.rs @@ -531,7 +531,6 @@ where mod tests { use actix_rt::pin; use actix_utils::future::poll_fn; - use bytes::{Bytes, BytesMut}; use futures_util::stream; use super::*; diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index fbd2eb7ae..69e2f14a1 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -399,9 +399,7 @@ pub enum ContentTypeError { #[cfg(test)] mod tests { - use std::io; - - use http::{Error as HttpError, StatusCode}; + use http::Error as HttpError; use super::*; diff --git a/actix-http/src/h1/codec.rs b/actix-http/src/h1/codec.rs index 8dae2e43e..2b452f8f8 100644 --- a/actix-http/src/h1/codec.rs +++ b/actix-http/src/h1/codec.rs @@ -198,9 +198,6 @@ impl Encoder, BodySize)>> for Codec { #[cfg(test)] mod tests { - use bytes::BytesMut; - use http::Method; - use super::*; use crate::HttpMessage as _; diff --git a/actix-http/src/h1/decoder.rs b/actix-http/src/h1/decoder.rs index 5c26515f7..af64e8802 100644 --- a/actix-http/src/h1/decoder.rs +++ b/actix-http/src/h1/decoder.rs @@ -563,15 +563,8 @@ impl Decoder for PayloadDecoder { #[cfg(test)] mod tests { - use bytes::{Bytes, BytesMut}; - use http::{Method, Version}; - use super::*; - use crate::{ - error::ParseError, - header::{HeaderName, SET_COOKIE}, - HttpMessage as _, - }; + use crate::{header::SET_COOKIE, HttpMessage as _}; impl PayloadType { pub(crate) fn unwrap(self) -> PayloadDecoder { diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs index 87f9b38f3..3ed53b70a 100644 --- a/actix-http/src/ws/mod.rs +++ b/actix-http/src/ws/mod.rs @@ -221,7 +221,7 @@ pub fn handshake_response(req: &RequestHead) -> ResponseBuilder { #[cfg(test)] mod tests { use super::*; - use crate::{header, test::TestRequest, Method}; + use crate::{header, test::TestRequest}; #[test] fn test_handshake() { diff --git a/actix-http/src/ws/proto.rs b/actix-http/src/ws/proto.rs index 0653c00b0..27815eaf2 100644 --- a/actix-http/src/ws/proto.rs +++ b/actix-http/src/ws/proto.rs @@ -1,7 +1,4 @@ -use std::{ - convert::{From, Into}, - fmt, -}; +use std::fmt; use base64::prelude::*; use tracing::error; diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index ae32cf0cd..d0f833318 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -863,7 +863,7 @@ mod tests { test::TestRequest, FromRequest, }; - use bytes::{BufMut as _, Bytes}; + use bytes::BufMut as _; use futures_util::{future::lazy, StreamExt as _}; use tokio::sync::mpsc; use tokio_stream::wrappers::UnboundedReceiverStream; diff --git a/actix-router/src/de.rs b/actix-router/src/de.rs index e8c7c658e..ce2dcf8f3 100644 --- a/actix-router/src/de.rs +++ b/actix-router/src/de.rs @@ -500,10 +500,10 @@ impl<'de> de::VariantAccess<'de> for UnitVariant { #[cfg(test)] mod tests { - use serde::{de, Deserialize}; + use serde::Deserialize; use super::*; - use crate::{path::Path, router::Router, ResourceDef}; + use crate::{router::Router, ResourceDef}; #[derive(Deserialize)] struct MyStruct { diff --git a/actix-web-actors/src/context.rs b/actix-web-actors/src/context.rs index be8fd387c..23e336459 100644 --- a/actix-web-actors/src/context.rs +++ b/actix-web-actors/src/context.rs @@ -248,13 +248,11 @@ where mod tests { use std::time::Duration; - use actix::Actor; use actix_web::{ http::StatusCode, test::{call_service, init_service, read_body, TestRequest}, web, App, HttpResponse, }; - use bytes::Bytes; use super::*; diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 04dbf5e17..1fb903225 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -817,10 +817,7 @@ where #[cfg(test)] mod tests { - use actix_web::{ - http::{header, Method}, - test::TestRequest, - }; + use actix_web::test::TestRequest; use super::*; diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index 26b278bcc..1a3b79086 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -471,7 +471,6 @@ mod tests { Method, StatusCode, }, middleware::DefaultHeaders, - service::ServiceRequest, test::{call_service, init_service, read_body, try_init_service, TestRequest}, web, HttpRequest, HttpResponse, }; diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index 35294a3c4..9451a60f9 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -380,7 +380,7 @@ impl Guard for HeaderGuard { #[cfg(test)] mod tests { - use actix_http::{header, Method}; + use actix_http::Method; use super::*; use crate::test::TestRequest; diff --git a/actix-web/src/http/header/content_length.rs b/actix-web/src/http/header/content_length.rs index ad16dc409..557c7c9f5 100644 --- a/actix-web/src/http/header/content_length.rs +++ b/actix-web/src/http/header/content_length.rs @@ -126,7 +126,7 @@ mod tests { use std::fmt; use super::*; - use crate::{http::header::Header, test::TestRequest, HttpRequest}; + use crate::{test::TestRequest, HttpRequest}; fn req_from_raw_headers, V: AsRef<[u8]>>( header_lines: I, diff --git a/actix-web/src/middleware/condition.rs b/actix-web/src/middleware/condition.rs index 5e106c11f..55c56d494 100644 --- a/actix-web/src/middleware/condition.rs +++ b/actix-web/src/middleware/condition.rs @@ -135,7 +135,7 @@ mod tests { use super::*; use crate::{ body::BoxBody, - dev::{ServiceRequest, ServiceResponse}, + dev::ServiceRequest, error::Result, http::{ header::{HeaderValue, CONTENT_TYPE}, diff --git a/actix-web/src/middleware/default_headers.rs b/actix-web/src/middleware/default_headers.rs index b5a5a6998..f21afe6eb 100644 --- a/actix-web/src/middleware/default_headers.rs +++ b/actix-web/src/middleware/default_headers.rs @@ -190,8 +190,6 @@ mod tests { use super::*; use crate::{ - dev::ServiceRequest, - http::header::CONTENT_TYPE, test::{self, TestRequest}, HttpResponse, }; diff --git a/actix-web/src/middleware/err_handlers.rs b/actix-web/src/middleware/err_handlers.rs index e640bba08..aa6d1c8a4 100644 --- a/actix-web/src/middleware/err_handlers.rs +++ b/actix-web/src/middleware/err_handlers.rs @@ -407,10 +407,7 @@ mod tests { use super::*; use crate::{ body, - http::{ - header::{HeaderValue, CONTENT_TYPE}, - StatusCode, - }, + http::header::{HeaderValue, CONTENT_TYPE}, test::{self, TestRequest}, }; diff --git a/actix-web/src/middleware/logger.rs b/actix-web/src/middleware/logger.rs index ce2caacd9..ce42c3af1 100644 --- a/actix-web/src/middleware/logger.rs +++ b/actix-web/src/middleware/logger.rs @@ -716,7 +716,7 @@ impl<'a> fmt::Display for FormatDisplay<'a> { #[cfg(test)] mod tests { - use actix_service::{IntoService, Service, Transform}; + use actix_service::IntoService; use actix_utils::future::ok; use super::*; diff --git a/actix-web/src/middleware/normalize.rs b/actix-web/src/middleware/normalize.rs index afcc0faac..3f20431c0 100644 --- a/actix-web/src/middleware/normalize.rs +++ b/actix-web/src/middleware/normalize.rs @@ -205,7 +205,6 @@ mod tests { use super::*; use crate::{ - dev::ServiceRequest, guard::fn_guard, test::{call_service, init_service, TestRequest}, web, App, HttpResponse, diff --git a/actix-web/src/redirect.rs b/actix-web/src/redirect.rs index 5ce960aa4..bd29a1403 100644 --- a/actix-web/src/redirect.rs +++ b/actix-web/src/redirect.rs @@ -182,7 +182,7 @@ impl Responder for Redirect { #[cfg(test)] mod tests { use super::*; - use crate::{dev::Service, http::StatusCode, test, App}; + use crate::{dev::Service, test, App}; #[actix_rt::test] async fn absolute_redirects() { diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index ece36a388..08a222c86 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -523,7 +523,7 @@ mod tests { use super::*; use crate::{ - dev::{ResourceDef, ResourceMap, Service}, + dev::{ResourceDef, Service}, http::{header, StatusCode}, test::{self, call_service, init_service, read_body, TestRequest}, web, App, HttpResponse, diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 95185b80a..291d67460 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -540,20 +540,14 @@ mod tests { use std::time::Duration; use actix_rt::time::sleep; - use actix_service::Service; use actix_utils::future::ok; use super::*; use crate::{ - guard, - http::{ - header::{self, HeaderValue}, - Method, StatusCode, - }, + http::{header::HeaderValue, Method, StatusCode}, middleware::DefaultHeaders, - service::{ServiceRequest, ServiceResponse}, test::{call_service, init_service, TestRequest}, - web, App, Error, HttpMessage, HttpResponse, + App, HttpMessage, }; #[test] diff --git a/actix-web/src/response/builder.rs b/actix-web/src/response/builder.rs index 28a0adffd..023842ee5 100644 --- a/actix-web/src/response/builder.rs +++ b/actix-web/src/response/builder.rs @@ -408,10 +408,7 @@ mod tests { use super::*; use crate::{ body, - http::{ - header::{self, HeaderValue, CONTENT_TYPE}, - StatusCode, - }, + http::header::{HeaderValue, CONTENT_TYPE}, test::assert_body_eq, }; diff --git a/actix-web/src/response/customize_responder.rs b/actix-web/src/response/customize_responder.rs index aad0039e0..4cbd96e20 100644 --- a/actix-web/src/response/customize_responder.rs +++ b/actix-web/src/response/customize_responder.rs @@ -175,10 +175,7 @@ mod tests { use super::*; use crate::{ - http::{ - header::{HeaderValue, CONTENT_TYPE}, - StatusCode, - }, + http::header::{HeaderValue, CONTENT_TYPE}, test::TestRequest, }; diff --git a/actix-web/src/response/responder.rs b/actix-web/src/response/responder.rs index 7d0b0e585..90d8f6e52 100644 --- a/actix-web/src/response/responder.rs +++ b/actix-web/src/response/responder.rs @@ -188,15 +188,11 @@ impl_into_string_responder!(Cow<'_, str>); pub(crate) mod tests { use actix_http::body::to_bytes; use actix_service::Service; - use bytes::{Bytes, BytesMut}; use super::*; use crate::{ error, - http::{ - header::{HeaderValue, CONTENT_TYPE}, - StatusCode, - }, + http::header::{HeaderValue, CONTENT_TYPE}, test::{assert_body_eq, init_service, TestRequest}, web, App, }; diff --git a/actix-web/src/response/response.rs b/actix-web/src/response/response.rs index fbd87e10c..e16dc0cd9 100644 --- a/actix-web/src/response/response.rs +++ b/actix-web/src/response/response.rs @@ -399,7 +399,7 @@ mod tests { use static_assertions::assert_impl_all; use super::*; - use crate::http::header::{HeaderValue, COOKIE}; + use crate::http::header::COOKIE; assert_impl_all!(HttpResponse: Responder); assert_impl_all!(HttpResponse: Responder); diff --git a/actix-web/src/scope.rs b/actix-web/src/scope.rs index e7c4e047a..27a2827a6 100644 --- a/actix-web/src/scope.rs +++ b/actix-web/src/scope.rs @@ -547,7 +547,6 @@ impl ServiceFactory for ScopeEndpoint { #[cfg(test)] mod tests { - use actix_service::Service; use actix_utils::future::ok; use bytes::Bytes; @@ -559,7 +558,6 @@ mod tests { Method, StatusCode, }, middleware::DefaultHeaders, - service::{ServiceRequest, ServiceResponse}, test::{assert_body_eq, call_service, init_service, read_body, TestRequest}, web, App, HttpMessage, HttpRequest, HttpResponse, }; diff --git a/actix-web/src/service.rs b/actix-web/src/service.rs index 451224833..a1672eba2 100644 --- a/actix-web/src/service.rs +++ b/actix-web/src/service.rs @@ -700,7 +700,7 @@ mod tests { use crate::{ guard, http, test::{self, init_service, TestRequest}, - web, App, HttpResponse, + web, App, }; #[actix_rt::test] diff --git a/actix-web/src/test/test_request.rs b/actix-web/src/test/test_request.rs index a3945456d..f178d6f43 100644 --- a/actix-web/src/test/test_request.rs +++ b/actix-web/src/test/test_request.rs @@ -350,7 +350,7 @@ mod tests { use std::time::SystemTime; use super::*; - use crate::{http::header, test::init_service, web, App, Error, HttpResponse, Responder}; + use crate::{http::header, test::init_service, web, App, Error, Responder}; #[actix_rt::test] async fn test_basics() { diff --git a/actix-web/src/types/either.rs b/actix-web/src/types/either.rs index db244fd9a..7883e89f6 100644 --- a/actix-web/src/types/either.rs +++ b/actix-web/src/types/either.rs @@ -287,10 +287,7 @@ mod tests { use serde::{Deserialize, Serialize}; use super::*; - use crate::{ - test::TestRequest, - web::{Form, Json}, - }; + use crate::test::TestRequest; #[derive(Debug, Clone, Serialize, Deserialize)] struct TestForm { diff --git a/actix-web/src/types/form.rs b/actix-web/src/types/form.rs index 7096b1e9c..d6381b990 100644 --- a/actix-web/src/types/form.rs +++ b/actix-web/src/types/form.rs @@ -418,7 +418,7 @@ mod tests { use super::*; use crate::{ http::{ - header::{HeaderValue, CONTENT_LENGTH, CONTENT_TYPE}, + header::{HeaderValue, CONTENT_TYPE}, StatusCode, }, test::{assert_body_eq, TestRequest}, diff --git a/actix-web/src/types/payload.rs b/actix-web/src/types/payload.rs index abb4e6b7f..e4db37d0b 100644 --- a/actix-web/src/types/payload.rs +++ b/actix-web/src/types/payload.rs @@ -440,13 +440,11 @@ impl Future for HttpMessageBody { #[cfg(test)] mod tests { - use bytes::Bytes; - use super::*; use crate::{ - http::{header, StatusCode}, + http::StatusCode, test::{call_service, init_service, read_body, TestRequest}, - web, App, Responder, + App, Responder, }; #[actix_rt::test] diff --git a/awc/src/client/connection.rs b/awc/src/client/connection.rs index 5ed965bed..8164e2b59 100644 --- a/awc/src/client/connection.rs +++ b/awc/src/client/connection.rs @@ -380,8 +380,6 @@ mod test { use std::{ future::Future, net, - pin::Pin, - task::{Context, Poll}, time::{Duration, Instant}, }; diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index df6e422f3..49da2015f 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -935,7 +935,6 @@ mod resolver { use std::{cell::RefCell, net::SocketAddr}; use actix_tls::connect::Resolve; - use futures_core::future::LocalBoxFuture; use trust_dns_resolver::{ config::{ResolverConfig, ResolverOpts}, system_conf::read_system_conf, diff --git a/awc/src/client/pool.rs b/awc/src/client/pool.rs index 2cf1f3ace..2938353fd 100644 --- a/awc/src/client/pool.rs +++ b/awc/src/client/pool.rs @@ -374,12 +374,11 @@ impl Acquired { #[cfg(test)] mod test { - use std::{cell::Cell, io}; + use std::cell::Cell; use http::Uri; use super::*; - use crate::client::connection::ConnectionType; /// A stream type that always returns pending on async read. /// diff --git a/awc/src/middleware/redirect.rs b/awc/src/middleware/redirect.rs index c38d6ad92..0ea5f174e 100644 --- a/awc/src/middleware/redirect.rs +++ b/awc/src/middleware/redirect.rs @@ -303,10 +303,7 @@ mod tests { use actix_web::{web, App, Error, HttpRequest, HttpResponse}; use super::*; - use crate::{ - http::{header::HeaderValue, StatusCode}, - ClientBuilder, - }; + use crate::{http::header::HeaderValue, ClientBuilder}; #[actix_rt::test] async fn basic_redirect() { diff --git a/awc/src/responses/json_body.rs b/awc/src/responses/json_body.rs index 3912324b6..e9c03d81a 100644 --- a/awc/src/responses/json_body.rs +++ b/awc/src/responses/json_body.rs @@ -118,7 +118,7 @@ mod tests { use static_assertions::assert_impl_all; use super::*; - use crate::{http::header, test::TestResponse}; + use crate::test::TestResponse; assert_impl_all!(JsonBody: Unpin); diff --git a/awc/src/responses/response_body.rs b/awc/src/responses/response_body.rs index 8d9d1274a..0ff58341f 100644 --- a/awc/src/responses/response_body.rs +++ b/awc/src/responses/response_body.rs @@ -110,7 +110,7 @@ mod tests { use static_assertions::assert_impl_all; use super::*; - use crate::{http::header, test::TestResponse}; + use crate::test::TestResponse; assert_impl_all!(ResponseBody<()>: Unpin); diff --git a/awc/src/test.rs b/awc/src/test.rs index 96ae1f0a1..126583179 100644 --- a/awc/src/test.rs +++ b/awc/src/test.rs @@ -103,7 +103,7 @@ mod tests { use actix_http::header::HttpDate; use super::*; - use crate::{cookie, http::header}; + use crate::http::header; #[test] fn test_basics() { From 7f0504e32bf83adae4a46f9c6ca5d06f5dc93785 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 1 Mar 2024 18:11:30 +0000 Subject: [PATCH 220/314] chore: temp allow #[allow(non_local_definitions)] --- awc/src/client/connector.rs | 5 +++++ awc/src/lib.rs | 1 + 2 files changed, 6 insertions(+) diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 49da2015f..94629b955 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -401,6 +401,7 @@ where use actix_tls::connect::Connection; use actix_utils::future::{ready, Ready}; + #[allow(non_local_definitions)] impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { let io = self.into_parts().0; @@ -451,6 +452,7 @@ where use actix_tls::connect::openssl::{reexports::AsyncSslStream, TlsConnector}; + #[allow(non_local_definitions)] impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { let sock = self.into_parts().0; @@ -488,6 +490,7 @@ where use actix_tls::connect::rustls_0_20::{reexports::AsyncTlsStream, TlsConnector}; + #[allow(non_local_definitions)] impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { let sock = self.into_parts().0; @@ -521,6 +524,7 @@ where use actix_tls::connect::rustls_0_21::{reexports::AsyncTlsStream, TlsConnector}; + #[allow(non_local_definitions)] impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { let sock = self.into_parts().0; @@ -557,6 +561,7 @@ where use actix_tls::connect::rustls_0_22::{reexports::AsyncTlsStream, TlsConnector}; + #[allow(non_local_definitions)] impl IntoConnectionIo for TcpConnection> { fn into_connection_io(self) -> (Box, Protocol) { let sock = self.into_parts().0; diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 253b5161a..460480994 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -102,6 +102,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] +#![allow(unknown_lints)] // temp: #[allow(non_local_definitions)] #![allow( clippy::type_complexity, clippy::borrow_interior_mutable_const, From f8a0f3e1888664f6e05c6bc97d985e62c9d6635d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 18:24:18 +0000 Subject: [PATCH 221/314] build(deps): bump taiki-e/install-action from 2.27.2 to 2.27.9 (#3297) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.27.2 to 2.27.9. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.27.2...v2.27.9) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4d6684159..ad7340ba4 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: cargo-hack,cargo-ci-cache-clean @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b40a9f13e..cd293f5dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 180ba35db..053d8c98d 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 79f53ce10..90c25b3f3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.27.2 + uses: taiki-e/install-action@v2.27.9 with: tool: cargo-public-api From 994ea45d91c2b4a0b020105d57c5d63b5869b037 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 18:40:38 +0000 Subject: [PATCH 222/314] build(deps): bump codecov/codecov-action from 4.0.1 to 4.0.2 (#3296) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.1 to 4.0.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.0.1...v4.0.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 053d8c98d..bdc6f588b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.0.1 + uses: codecov/codecov-action@v4.0.2 with: files: codecov.json fail_ci_if_error: true From c10f05a8672e53ecada8ec2f15bf9d927efade57 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sun, 3 Mar 2024 23:50:16 +0800 Subject: [PATCH 223/314] Add `unicode` feature to switch between `regex` and `regex-lite` crates as a trade-off between full unicode support and binary size (#3291) * - Add `unicode` feature to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. * Update CHANGES.md * Update CHANGES.md * refactor: move regexset code selection to own module * docs: add docs within RegexSet module * chore: restore manifests * test: ensure all actix-router codepaths are tested --------- Co-authored-by: Rob Ede --- .github/workflows/ci.yml | 1 + actix-router/CHANGES.md | 1 + actix-router/Cargo.toml | 9 ++- actix-router/src/lib.rs | 1 + actix-router/src/regex_set.rs | 66 +++++++++++++++++++ actix-router/src/resource.rs | 15 +++-- actix-web/CHANGES.md | 1 + actix-web/Cargo.toml | 10 ++- .../src/http/header/content_disposition.rs | 3 + actix-web/src/middleware/logger.rs | 22 ++++--- actix-web/src/middleware/normalize.rs | 3 + 11 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 actix-router/src/regex_set.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd293f5dc..7a7adb246 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,6 +70,7 @@ jobs: shell: bash run: | set -e + cargo test --lib --tests -p=actix-router --no-default-features cargo test --lib --tests -p=actix-router --all-features cargo test --lib --tests -p=actix-http --all-features cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index a80b15e69..8aa3c8639 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. - Minimum supported Rust version (MSRV) is now 1.72. ## 0.5.2 diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index de39944cc..0b02e84b9 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -17,12 +17,16 @@ name = "actix_router" path = "src/lib.rs" [features] -default = ["http"] +default = ["http", "unicode"] +http = ["dep:http"] +unicode = ["dep:regex"] [dependencies] bytestring = ">=0.1.5, <2" +cfg-if = "1" http = { version = "0.2.7", optional = true } -regex = "1.5" +regex = { version = "1.5", optional = true } +regex-lite = "0.1" serde = "1" tracing = { version = "0.1.30", default-features = false, features = ["log"] } @@ -35,6 +39,7 @@ percent-encoding = "2.1" [[bench]] name = "router" harness = false +required-features = ["unicode"] [[bench]] name = "quoter" diff --git a/actix-router/src/lib.rs b/actix-router/src/lib.rs index f10093436..c4d0d2c87 100644 --- a/actix-router/src/lib.rs +++ b/actix-router/src/lib.rs @@ -10,6 +10,7 @@ mod de; mod path; mod pattern; mod quoter; +mod regex_set; mod resource; mod resource_path; mod router; diff --git a/actix-router/src/regex_set.rs b/actix-router/src/regex_set.rs new file mode 100644 index 000000000..48f38df2c --- /dev/null +++ b/actix-router/src/regex_set.rs @@ -0,0 +1,66 @@ +//! Abstraction over `regex` and `regex-lite` depending on whether we have `unicode` crate feature +//! enabled. + +use cfg_if::cfg_if; +#[cfg(feature = "unicode")] +pub(crate) use regex::{escape, Regex}; +#[cfg(not(feature = "unicode"))] +pub(crate) use regex_lite::{escape, Regex}; + +#[cfg(feature = "unicode")] +#[derive(Debug, Clone)] +pub(crate) struct RegexSet(regex::RegexSet); + +#[cfg(not(feature = "unicode"))] +#[derive(Debug, Clone)] +pub(crate) struct RegexSet(Vec); + +impl RegexSet { + /// Create a new regex set. + /// + /// # Panics + /// + /// Panics if any path patterns are malformed. + pub(crate) fn new(re_set: Vec) -> Self { + cfg_if! { + if #[cfg(feature = "unicode")] { + Self(regex::RegexSet::new(re_set).unwrap()) + } else { + Self(re_set.iter().map(|re| Regex::new(re).unwrap()).collect()) + } + } + } + + /// Create a new empty regex set. + pub(crate) fn empty() -> Self { + cfg_if! { + if #[cfg(feature = "unicode")] { + Self(regex::RegexSet::empty()) + } else { + Self(Vec::new()) + } + } + } + + /// Returns true if regex set matches `path`. + pub(crate) fn is_match(&self, path: &str) -> bool { + cfg_if! { + if #[cfg(feature = "unicode")] { + self.0.is_match(path) + } else { + self.0.iter().any(|re| re.is_match(path)) + } + } + } + + /// Returns index within `path` of first match. + pub(crate) fn first_match_idx(&self, path: &str) -> Option { + cfg_if! { + if #[cfg(feature = "unicode")] { + self.0.matches(path).into_iter().next() + } else { + Some(self.0.iter().enumerate().find(|(_, re)| re.is_match(path))?.0) + } + } + } +} diff --git a/actix-router/src/resource.rs b/actix-router/src/resource.rs index abd132211..3a102945b 100644 --- a/actix-router/src/resource.rs +++ b/actix-router/src/resource.rs @@ -5,10 +5,13 @@ use std::{ mem, }; -use regex::{escape, Regex, RegexSet}; use tracing::error; -use crate::{path::PathItem, IntoPatterns, Patterns, Resource, ResourcePath}; +use crate::{ + path::PathItem, + regex_set::{escape, Regex, RegexSet}, + IntoPatterns, Patterns, Resource, ResourcePath, +}; const MAX_DYNAMIC_SEGMENTS: usize = 16; @@ -233,7 +236,7 @@ enum PatternSegment { Var(String), } -#[derive(Clone, Debug)] +#[derive(Debug, Clone)] #[allow(clippy::large_enum_variant)] enum PatternType { /// Single constant/literal segment. @@ -603,7 +606,7 @@ impl ResourceDef { PatternType::Dynamic(re, _) => Some(re.captures(path)?[1].len()), PatternType::DynamicSet(re, params) => { - let idx = re.matches(path).into_iter().next()?; + let idx = re.first_match_idx(path)?; let (ref pattern, _) = params[idx]; Some(pattern.captures(path)?[1].len()) } @@ -706,7 +709,7 @@ impl ResourceDef { PatternType::DynamicSet(re, params) => { let path = path.unprocessed(); - let (pattern, names) = match re.matches(path).into_iter().next() { + let (pattern, names) = match re.first_match_idx(path) { Some(idx) => ¶ms[idx], _ => return false, }; @@ -870,7 +873,7 @@ impl ResourceDef { } } - let pattern_re_set = RegexSet::new(re_set).unwrap(); + let pattern_re_set = RegexSet::new(re_set); let segments = segments.unwrap_or_default(); ( diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 88215293a..8fa7ae27d 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Changed +- Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. - Minimum supported Rust version (MSRV) is now 1.72. ## 4.5.1 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index b045589bd..aafc3dda8 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -40,7 +40,7 @@ name = "actix_web" path = "src/lib.rs" [features] -default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "http2"] +default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "http2", "unicode"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -72,6 +72,9 @@ rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls # TLS via Rustls v0.22 rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"] +# Full unicode support +unicode = ["dep:regex", "actix-router/unicode"] + # Internal (PRIVATE!) features used to aid testing and checking feature status. # Don't rely on these whatsoever. They may disappear at anytime. __compress = [] @@ -89,7 +92,7 @@ actix-utils = "3" actix-tls = { version = "3.3", default-features = false, optional = true } actix-http = { version = "3.6", features = ["ws"] } -actix-router = "0.5" +actix-router = { version = "0.5", default-features = false, features = ["http"] } actix-web-codegen = { version = "4.2", optional = true } ahash = "0.8" @@ -107,7 +110,8 @@ log = "0.4" mime = "0.3" once_cell = "1.5" pin-project-lite = "0.2.7" -regex = "1.5.5" +regex = { version = "1.5.5", optional = true } +regex-lite = "0.1" serde = "1.0" serde_json = "1.0" serde_urlencoded = "0.7" diff --git a/actix-web/src/http/header/content_disposition.rs b/actix-web/src/http/header/content_disposition.rs index 0606f5aef..9725cd19b 100644 --- a/actix-web/src/http/header/content_disposition.rs +++ b/actix-web/src/http/header/content_disposition.rs @@ -13,7 +13,10 @@ use std::fmt::{self, Write}; use once_cell::sync::Lazy; +#[cfg(feature = "unicode")] use regex::Regex; +#[cfg(not(feature = "unicode"))] +use regex_lite::Regex; use super::{ExtendedValue, Header, TryIntoHeaderValue, Writer}; use crate::http::header; diff --git a/actix-web/src/middleware/logger.rs b/actix-web/src/middleware/logger.rs index ce42c3af1..dc1b02399 100644 --- a/actix-web/src/middleware/logger.rs +++ b/actix-web/src/middleware/logger.rs @@ -18,7 +18,10 @@ use bytes::Bytes; use futures_core::ready; use log::{debug, warn}; use pin_project_lite::pin_project; -use regex::{Regex, RegexSet}; +#[cfg(feature = "unicode")] +use regex::Regex; +#[cfg(not(feature = "unicode"))] +use regex_lite::Regex; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; use crate::{ @@ -87,7 +90,7 @@ pub struct Logger(Rc); struct Inner { format: Format, exclude: HashSet, - exclude_regex: RegexSet, + exclude_regex: Vec, log_target: Cow<'static, str>, } @@ -97,7 +100,7 @@ impl Logger { Logger(Rc::new(Inner { format: Format::new(format), exclude: HashSet::new(), - exclude_regex: RegexSet::empty(), + exclude_regex: Vec::new(), log_target: Cow::Borrowed(module_path!()), })) } @@ -114,10 +117,7 @@ impl Logger { /// Ignore and do not log access info for paths that match regex. pub fn exclude_regex>(mut self, path: T) -> Self { let inner = Rc::get_mut(&mut self.0).unwrap(); - let mut patterns = inner.exclude_regex.patterns().to_vec(); - patterns.push(path.into()); - let regex_set = RegexSet::new(patterns).unwrap(); - inner.exclude_regex = regex_set; + inner.exclude_regex.push(Regex::new(&path.into()).unwrap()); self } @@ -240,7 +240,7 @@ impl Default for Logger { Logger(Rc::new(Inner { format: Format::default(), exclude: HashSet::new(), - exclude_regex: RegexSet::empty(), + exclude_regex: Vec::new(), log_target: Cow::Borrowed(module_path!()), })) } @@ -300,7 +300,11 @@ where fn call(&self, req: ServiceRequest) -> Self::Future { let excluded = self.inner.exclude.contains(req.path()) - || self.inner.exclude_regex.is_match(req.path()); + || self + .inner + .exclude_regex + .iter() + .any(|r| r.is_match(req.path())); if excluded { LoggerResponse { diff --git a/actix-web/src/middleware/normalize.rs b/actix-web/src/middleware/normalize.rs index 3f20431c0..482107ecb 100644 --- a/actix-web/src/middleware/normalize.rs +++ b/actix-web/src/middleware/normalize.rs @@ -4,7 +4,10 @@ use actix_http::uri::{PathAndQuery, Uri}; use actix_service::{Service, Transform}; use actix_utils::future::{ready, Ready}; use bytes::Bytes; +#[cfg(feature = "unicode")] use regex::Regex; +#[cfg(not(feature = "unicode"))] +use regex_lite::Regex; use crate::{ service::{ServiceRequest, ServiceResponse}, From 49020e79ae7b7abc2cd98a0e2ef20aecdf6a975e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 3 Mar 2024 22:18:29 +0000 Subject: [PATCH 224/314] chore: update base64 to v0.22 --- actix-http/Cargo.toml | 2 +- actix-web/CHANGES.md | 5 ++++- awc/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index e8f315cb9..7e1a8c55c 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -106,7 +106,7 @@ h2 = { version = "0.3.24", optional = true } # websockets local-channel = { version = "0.1", optional = true } -base64 = { version = "0.21", optional = true } +base64 = { version = "0.22", optional = true } rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 8fa7ae27d..c6454ed65 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,9 +2,12 @@ ## Unreleased -### Changed +### Added - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. + +### Changed + - Minimum supported Rust version (MSRV) is now 1.72. ## 4.5.1 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 14d93ac30..ab88ca814 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -79,7 +79,7 @@ actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.3", features = ["connect", "uri"] } actix-utils = "3" -base64 = "0.21" +base64 = "0.22" bytes = "1" cfg-if = "1" derive_more = "0.99.5" From a4df623b0c8995e44af2218da884901f0c3cb47a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 3 Mar 2024 23:43:54 +0000 Subject: [PATCH 225/314] chore: bump env_logger to v0.11 --- actix-files/Cargo.toml | 2 +- actix-http/Cargo.toml | 2 +- actix-web-actors/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- actix-web/src/route.rs | 1 + awc/Cargo.toml | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 098d71bd7..3d82f8a76 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -47,5 +47,5 @@ actix-server = { version = "2.2", optional = true } # ensure matching tokio-urin actix-rt = "2.7" actix-test = "0.1" actix-web = "4" -env_logger = "0.10" +env_logger = "0.11" tempfile = "3.2" diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 7e1a8c55c..38969e901 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -127,7 +127,7 @@ actix-web = "4" async-stream = "0.3" criterion = { version = "0.5", features = ["html_reports"] } divan = "0.1.8" -env_logger = "0.10" +env_logger = "0.11" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 0263e9b29..114ec5a87 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -32,6 +32,6 @@ actix-test = "0.1" awc = { version = "3", default-features = false } actix-web = { version = "4", features = ["macros"] } -env_logger = "0.10" +env_logger = "0.11" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } mime = "0.3" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index aafc3dda8..aea8856b1 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -128,7 +128,7 @@ awc = { version = "3", features = ["openssl"] } brotli = "3.3.3" const-str = "0.5" criterion = { version = "0.5", features = ["html_reports"] } -env_logger = "0.10" +env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } rand = "0.8" diff --git a/actix-web/src/route.rs b/actix-web/src/route.rs index a46c1fdd4..261e6b9ae 100644 --- a/actix-web/src/route.rs +++ b/actix-web/src/route.rs @@ -92,6 +92,7 @@ pub struct RouteService { } impl RouteService { + // TODO(breaking): remove pass by ref mut #[allow(clippy::needless_pass_by_ref_mut)] pub fn check(&self, req: &mut ServiceRequest) -> bool { let guard_ctx = req.guard_ctx(); diff --git a/awc/Cargo.toml b/awc/Cargo.toml index ab88ca814..da9e78ae8 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -118,7 +118,7 @@ actix-web = { version = "4", features = ["openssl"] } brotli = "3.3.3" const-str = "0.5" -env_logger = "0.10" +env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" From 58dd00bccfbc353a8459ec3c9d576cbac1c0c13b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 02:18:38 +0000 Subject: [PATCH 226/314] build(deps): bump codecov/codecov-action from 4.0.2 to 4.1.0 (#3302) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.0.2 to 4.1.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.0.2...v4.1.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bdc6f588b..67edc483f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.0.2 + uses: codecov/codecov-action@v4.1.0 with: files: codecov.json fail_ci_if_error: true From d2150a3312d43ac4dcfe9afed1320bb18bcbf680 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 02:18:50 +0000 Subject: [PATCH 227/314] build(deps): bump taiki-e/install-action from 2.27.9 to 2.28.0 (#3301) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.27.9 to 2.28.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.27.9...v2.28.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index ad7340ba4..177384830 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: cargo-hack,cargo-ci-cache-clean @@ -85,7 +85,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: cargo-hack @@ -106,7 +106,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a7adb246..ac76476a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 67edc483f..65fb25cad 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 90c25b3f3..468cc4d0d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.27.9 + uses: taiki-e/install-action@v2.28.0 with: tool: cargo-public-api From ba7bddeadc30a40c1e0a53049c3f726f0f661f4d Mon Sep 17 00:00:00 2001 From: Nelson Dominguez Date: Wed, 6 Mar 2024 01:17:18 +0100 Subject: [PATCH 228/314] docs(actix-web): add missing 'that' to doc comments for Compress middleware (#3304) docs(actix-web): add missing 'that' in doc comments for Compress middleware --- actix-web/src/middleware/compress.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/src/middleware/compress.rs b/actix-web/src/middleware/compress.rs index 8ff518cd3..943868d21 100644 --- a/actix-web/src/middleware/compress.rs +++ b/actix-web/src/middleware/compress.rs @@ -33,7 +33,7 @@ use crate::{ /// considered in this selection process. /// /// # Pre-compressed Payload -/// If you are serving some data is already using a compressed representation (e.g., a gzip +/// If you are serving some data that is already using a compressed representation (e.g., a gzip /// compressed HTML file from disk) you can signal this to `Compress` by setting an appropriate /// `Content-Encoding` header. In addition to preventing double compressing the payload, this header /// is required by the spec when using compressed representations and will inform the client that From 52b0d5fbf90d6aecb25fc8b00aa23ff367486931 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Mon, 11 Mar 2024 23:34:04 +0800 Subject: [PATCH 229/314] CI: Free space before test (#3303) --- .github/workflows/ci-post-merge.yml | 3 ++ scripts/free-disk-space.sh | 53 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 scripts/free-disk-space.sh diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 177384830..3889c2589 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -81,6 +81,9 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Free Disk Space + run: ./scripts/free-disk-space.sh + - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 diff --git a/scripts/free-disk-space.sh b/scripts/free-disk-space.sh new file mode 100755 index 000000000..2946cfcf6 --- /dev/null +++ b/scripts/free-disk-space.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# The Azure provided machines typically have the following disk allocation: +# Total space: 85GB +# Allocated: 67 GB +# Free: 17 GB +# This script frees up 28 GB of disk space by deleting unneeded packages and +# large directories. +# The Flink end to end tests download and generate more than 17 GB of files, +# causing unpredictable behavior and build failures. + +echo "==============================================================================" +echo "Freeing up disk space on CI system" +echo "==============================================================================" + +echo "Listing 100 largest packages" +dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -n | tail -n 100 +df -h + +echo "Removing large packages" +sudo apt-get remove -y '^dotnet-.*' +sudo apt-get remove -y 'php.*' +sudo apt-get remove -y '^mongodb-.*' +sudo apt-get remove -y '^mysql-.*' +sudo apt-get remove -y azure-cli google-cloud-sdk hhvm google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri +sudo apt-get autoremove -y +sudo apt-get clean +df -h + +echo "Removing large directories" +sudo rm -rf /usr/share/dotnet/ +sudo rm -rf /usr/local/graalvm/ +sudo rm -rf /usr/local/.ghcup/ +sudo rm -rf /usr/local/share/powershell +sudo rm -rf /usr/local/share/chromium +sudo rm -rf /usr/local/lib/android +sudo rm -rf /usr/local/lib/node_modules +df -h From 9c3b4c61f73df122ea377ead3d50e688dc5227db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 11:14:22 +0000 Subject: [PATCH 230/314] build(deps): bump taiki-e/install-action from 2.28.0 to 2.28.10 (#3305) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 3889c2589..2b5678f82 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ac76476a6..d22df5e89 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 65fb25cad..f0d3b251b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 468cc4d0d..940d68a5e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.28.0 + uses: taiki-e/install-action@v2.28.10 with: tool: cargo-public-api From 0383f4bdd1210e726143ca1ebcf01169b67a4b6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 02:47:10 +0000 Subject: [PATCH 231/314] build(deps): bump taiki-e/install-action from 2.28.10 to 2.28.16 (#3312) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.28.10 to 2.28.16. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.28.10...v2.28.16) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 2b5678f82..1678bbffa 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d22df5e89..9ce792b3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f0d3b251b..2c394b32b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 940d68a5e..4468708bb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.28.10 + uses: taiki-e/install-action@v2.28.16 with: tool: cargo-public-api From db76ad0f6139160f86411d7107dbbf27954d9d3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:03:40 +0000 Subject: [PATCH 232/314] build(deps): bump taiki-e/install-action from 2.28.16 to 2.29.7 (#3316) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 1678bbffa..cc03fe71c 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ce792b3f..5a97f56da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2c394b32b..ecb01267e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4468708bb..253396789 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.28.16 + uses: taiki-e/install-action@v2.29.7 with: tool: cargo-public-api From 09851f4a548a4c2758685d8811254cf3f4c80f10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:38:30 +0000 Subject: [PATCH 233/314] build(deps): bump taiki-e/install-action from 2.29.7 to 2.32.0 (#3322) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.29.7 to 2.32.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.29.7...v2.32.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index cc03fe71c..63d670dc3 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a97f56da..048145884 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ecb01267e..22522776f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 253396789..188d12168 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.29.7 + uses: taiki-e/install-action@v2.32.0 with: tool: cargo-public-api From ccfa8d3817704b05747f9c3c5839827378d1aab1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:41:43 +0000 Subject: [PATCH 234/314] build(deps): bump codecov/codecov-action from 4.1.0 to 4.1.1 (#3321) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.1.0...v4.1.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 22522776f..1886d9c03 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.1.0 + uses: codecov/codecov-action@v4.1.1 with: files: codecov.json fail_ci_if_error: true From 76b2b2734b5765e3e7878fcabab8073b91ddcb03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 08:17:45 +0100 Subject: [PATCH 235/314] build(deps): bump codecov/codecov-action from 4.1.1 to 4.2.0 (#3326) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.1.1 to 4.2.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.1.1...v4.2.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 1886d9c03..004bc9a6e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.1.1 + uses: codecov/codecov-action@v4.2.0 with: files: codecov.json fail_ci_if_error: true From 5a5486b484d4b9c4e9527b9a00411375d776ed21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 08:19:03 +0100 Subject: [PATCH 236/314] build(deps): bump taiki-e/install-action from 2.32.0 to 2.32.9 (#3325) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.32.0 to 2.32.9. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.32.0...v2.32.9) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 63d670dc3..6b330b4e9 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 048145884..757ceaa85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 004bc9a6e..c9727012b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 188d12168..6af754c49 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.32.0 + uses: taiki-e/install-action@v2.32.9 with: tool: cargo-public-api From d98938b1250293a98913d5c0a53f7a0cc6fe0002 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 02:02:30 +0100 Subject: [PATCH 237/314] build(deps): bump taiki-e/install-action from 2.32.9 to 2.32.17 (#3332) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.32.9 to 2.32.17. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.32.9...v2.32.17) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 6b330b4e9..55202ba6c 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 757ceaa85..2488f7496 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c9727012b..20aeeeb4b 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6af754c49..b0ac537a2 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2023-08-25 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.32.9 + uses: taiki-e/install-action@v2.32.17 with: tool: cargo-public-api From ba7fd048b601e32039ba13d95271f110980ff434 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 02:02:44 +0100 Subject: [PATCH 238/314] build(deps): bump codecov/codecov-action from 4.2.0 to 4.3.0 (#3331) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.2.0...v4.3.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 20aeeeb4b..ac5143d58 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.2.0 + uses: codecov/codecov-action@v4.3.0 with: files: codecov.json fail_ci_if_error: true From 7fc73d58a9de68f0dfcc809d263dc1ffea20da28 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Thu, 2 May 2024 03:22:13 +0100 Subject: [PATCH 239/314] ci: fix public api --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b0ac537a2..a10c2411a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -79,7 +79,7 @@ jobs: - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: - toolchain: nightly-2023-08-25 + toolchain: nightly-2024-04-26 - name: Install cargo-public-api uses: taiki-e/install-action@v2.32.17 From 7f15a95d8e15c3b09f64a301aa33ac89a82863a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 03:22:59 +0100 Subject: [PATCH 240/314] build(deps): bump JamesIves/github-pages-deploy-action from 4.5.0 to 4.6.0 (#3339) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .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 963b7f6b3..6352e44d2 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -35,7 +35,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.5.0 + uses: JamesIves/github-pages-deploy-action@v4.6.0 with: folder: target/doc single-commit: true From babac131d4bf2f9d8e343a77ff75d496a5249d10 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 02:39:28 +0000 Subject: [PATCH 241/314] build(deps): bump taiki-e/install-action from 2.32.17 to 2.33.12 (#3347) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.32.17 to 2.33.12. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.32.17...v2.33.12) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 55202ba6c..10670ab34 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2488f7496..b052cebdf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ac5143d58..5698e271c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a10c2411a..fd0b96c7d 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.32.17 + uses: taiki-e/install-action@v2.33.12 with: tool: cargo-public-api From e4b9d17355d079160416cf8f86a5a87ddbc2e9b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 03:27:31 +0100 Subject: [PATCH 242/314] build(deps): bump codecov/codecov-action from 4.3.0 to 4.3.1 (#3354) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5698e271c..5c228c978 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.3.0 + uses: codecov/codecov-action@v4.3.1 with: files: codecov.json fail_ci_if_error: true From bb65628de5b01bd0a5fa9552b80b72729340a628 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 03:28:35 +0100 Subject: [PATCH 243/314] build(deps): bump taiki-e/install-action from 2.33.12 to 2.33.16 (#3355) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 6 +++--- .github/workflows/ci.yml | 2 +- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 10670ab34..9da5de5fd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack,cargo-ci-cache-clean @@ -88,7 +88,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack @@ -109,7 +109,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install nextest - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: nextest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b052cebdf..85854bdfd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install cargo-hack and cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-hack,cargo-ci-cache-clean diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5c228c978..9ec33ee55 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index fd0b96c7d..9c6846824 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.12 + uses: taiki-e/install-action@v2.33.16 with: tool: cargo-public-api From c1a638861445cf1aee36d5fd7130ea01b16e3eca Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 6 May 2024 06:03:44 +0100 Subject: [PATCH 244/314] refactor: address clippy warnings --- actix-http/src/h1/dispatcher.rs | 2 +- actix-http/src/h2/dispatcher.rs | 2 +- actix-multipart/src/form/mod.rs | 3 ++- actix-router/src/path.rs | 8 ++------ actix-web/src/config.rs | 2 +- actix-web/src/resource.rs | 2 +- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs index a24a6bb07..00b51360e 100644 --- a/actix-http/src/h1/dispatcher.rs +++ b/actix-http/src/h1/dispatcher.rs @@ -706,7 +706,7 @@ where req.head_mut().peer_addr = *this.peer_addr; - req.conn_data = this.conn_data.clone(); + req.conn_data.clone_from(this.conn_data); match this.codec.message_type() { // request has no payload diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 97ceb51e9..400476c88 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -126,7 +126,7 @@ where head.headers = parts.headers.into(); head.peer_addr = this.peer_addr; - req.conn_data = this.conn_data.clone(); + req.conn_data.clone_from(&this.conn_data); let fut = this.flow.service.call(req); let config = this.config.clone(); diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index 67adfd4b2..451b103fd 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -313,7 +313,8 @@ where let entry = field_limits .entry(field.name().to_owned()) .or_insert_with(|| T::limit(field.name())); - limits.field_limit_remaining = entry.to_owned(); + + limits.field_limit_remaining.clone_from(entry); T::handle_field(&req, field, &mut limits, &mut state).await?; diff --git a/actix-router/src/path.rs b/actix-router/src/path.rs index 467420cd3..9031ab763 100644 --- a/actix-router/src/path.rs +++ b/actix-router/src/path.rs @@ -154,15 +154,11 @@ impl Path { None } - /// Get matched parameter by name. + /// Returns matched parameter by name. /// /// If keyed parameter is not available empty string is used as default value. pub fn query(&self, key: &str) -> &str { - if let Some(s) = self.get(key) { - s - } else { - "" - } + self.get(key).unwrap_or_default() } /// Return iterator to items in parameter container. diff --git a/actix-web/src/config.rs b/actix-web/src/config.rs index fba0c2717..5e8b056f1 100644 --- a/actix-web/src/config.rs +++ b/actix-web/src/config.rs @@ -148,7 +148,7 @@ impl AppConfig { #[cfg(test)] pub(crate) fn set_host(&mut self, host: &str) { - self.host = host.to_owned(); + host.clone_into(&mut self.host); } } diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 291d67460..00555b7b2 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -771,7 +771,7 @@ mod tests { data3: web::Data| { assert_eq!(**data1, 10); assert_eq!(**data2, '*'); - let error = std::f64::EPSILON; + let error = f64::EPSILON; assert!((**data3 - 1.0).abs() < error); HttpResponse::Ok() }, From 44f502e0503f15f7f03ec3c1e14668bbd9b60b93 Mon Sep 17 00:00:00 2001 From: asonix Date: Mon, 13 May 2024 23:57:58 -0500 Subject: [PATCH 245/314] awc: gate TlsConnectorService behind any feature that uses it (#3350) --- awc/CHANGES.md | 1 + awc/src/client/connector.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 507c8a080..46939a7ca 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Minimum supported Rust version (MSRV) is now 1.72. +- Fix warning on 1.78 due to unused TlsConnectorService struct ## 3.4.0 diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 94629b955..b66e13ec7 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -649,6 +649,14 @@ where /// service for establish tcp connection and do client tls handshake. /// operation is canceled when timeout limit reached. +#[cfg(any( + feature = "dangerous-h2c", + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", +))] struct TlsConnectorService { /// TCP connection is canceled on `TcpConnectorInnerService`'s timeout setting. tcp_service: Tcp, @@ -659,6 +667,14 @@ struct TlsConnectorService { timeout: Duration, } +#[cfg(any( + feature = "dangerous-h2c", + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22-webpki-roots", + feature = "rustls-0_22-native-roots", +))] impl Service for TlsConnectorService where Tcp: From 3c9a930bd172eba69366c2bf1e5035395c6ebc49 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 14 May 2024 06:30:58 +0100 Subject: [PATCH 246/314] ci: rely more on justfiles (#3365) --- .cargo/config.toml | 4 --- .github/workflows/ci-post-merge.yml | 36 ++------------------ .github/workflows/ci.yml | 38 ++++++++++----------- Cargo.toml | 2 ++ actix-multipart-derive/Cargo.toml | 9 ++--- actix-web-codegen/Cargo.toml | 9 ++--- justfile | 51 ++++++++++++++++++++++++++--- 7 files changed, 79 insertions(+), 70 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 350a924de..6d5a8b810 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -8,7 +8,3 @@ ci-check-default = "hack --workspace check" ci-check-default-tests = "check --workspace --tests" ci-check-all-feature-powerset="hack --workspace --feature-powerset --skip=__compress,experimental-io-uring check" ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --skip=__compress check" - -# testing -ci-doctest-default = "test --workspace --doc --no-fail-fast -- --nocapture" -ci-doctest = "test --workspace --all-features --doc --no-fail-fast -- --nocapture" diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 9da5de5fd..d5cb6e620 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -44,10 +44,10 @@ jobs: with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack and cargo-ci-cache-clean + - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean uses: taiki-e/install-action@v2.33.16 with: - tool: cargo-hack,cargo-ci-cache-clean + tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean - name: check minimal run: cargo ci-check-min @@ -57,19 +57,7 @@ jobs: - name: tests timeout-minutes: 60 - shell: bash - run: | - set -e - cargo test --lib --tests -p=actix-router --all-features - cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls - cargo test --lib --tests -p=actix-web-codegen --all-features - cargo test --lib --tests -p=awc --all-features - cargo test --lib --tests -p=actix-http-test --all-features - cargo test --lib --tests -p=actix-test --all-features - cargo test --lib --tests -p=actix-files - cargo test --lib --tests -p=actix-multipart --all-features - cargo test --lib --tests -p=actix-web-actors --all-features + run: just test - name: CI cache clean run: cargo-ci-cache-clean @@ -97,21 +85,3 @@ jobs: - name: check feature combinations run: cargo ci-check-all-feature-powerset-linux - - nextest: - name: nextest - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - - - name: Install nextest - uses: taiki-e/install-action@v2.33.16 - with: - tool: nextest - - - name: Test with cargo-nextest - run: cargo nextest run diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85854bdfd..d7db0be48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,13 @@ concurrency: cancel-in-progress: true jobs: + read_msrv: + name: Read MSRV + uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@main + build_and_test: + needs: read_msrv + strategy: fail-fast: false matrix: @@ -26,7 +32,7 @@ jobs: - { name: macOS, os: macos-latest, triple: x86_64-apple-darwin } - { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc } version: - - { name: msrv, version: 1.72.0 } + - { name: msrv, version: "${{ needs.read_msrv.outputs.msrv }}" } - { name: stable, version: stable } name: ${{ matrix.target.name }} / ${{ matrix.version.name }} @@ -49,15 +55,14 @@ jobs: with: toolchain: ${{ matrix.version.version }} - - name: Install cargo-hack and cargo-ci-cache-clean + - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean uses: taiki-e/install-action@v2.33.16 with: - tool: cargo-hack,cargo-ci-cache-clean + tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean - name: workaround MSRV issues if: matrix.version.name == 'msrv' - run: | - cargo update -p=clap --precise=4.4.18 + run: just downgrade-for-msrv - name: check minimal run: cargo ci-check-min @@ -67,20 +72,7 @@ jobs: - name: tests timeout-minutes: 60 - shell: bash - run: | - set -e - cargo test --lib --tests -p=actix-router --no-default-features - cargo test --lib --tests -p=actix-router --all-features - cargo test --lib --tests -p=actix-http --all-features - cargo test --lib --tests -p=actix-web --features=rustls-0_20,rustls-0_21,rustls-0_22,openssl -- --skip=test_reading_deflate_encoding_large_random_rustls - cargo test --lib --tests -p=actix-web-codegen --all-features - cargo test --lib --tests -p=awc --all-features - cargo test --lib --tests -p=actix-http-test --all-features - cargo test --lib --tests -p=actix-test --all-features - cargo test --lib --tests -p=actix-files - cargo test --lib --tests -p=actix-multipart --all-features - cargo test --lib --tests -p=actix-web-actors --all-features + run: just test - name: CI cache clean run: cargo-ci-cache-clean @@ -112,6 +104,10 @@ jobs: with: toolchain: nightly + - name: Install just + uses: taiki-e/install-action@v2.33.16 + with: + tool: just + - name: doc tests - run: cargo ci-doctest - timeout-minutes: 60 + run: just test-docs diff --git a/Cargo.toml b/Cargo.toml index 9efeda4d1..19d5dd116 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ members = [ ] [workspace.package] +homepage = "https://actix.rs" +repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.72" diff --git a/actix-multipart-derive/Cargo.toml b/actix-multipart-derive/Cargo.toml index 2f049a3fb..e978864a3 100644 --- a/actix-multipart-derive/Cargo.toml +++ b/actix-multipart-derive/Cargo.toml @@ -4,10 +4,11 @@ version = "0.6.1" authors = ["Jacob Halsey "] description = "Multipart form derive macro for Actix Web" keywords = ["http", "web", "framework", "async", "futures"] -homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web" -license = "MIT OR Apache-2.0" -edition = "2021" +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 7039ea7df..4a45d4fef 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -2,14 +2,15 @@ name = "actix-web-codegen" version = "4.2.2" description = "Routing and runtime macros for Actix Web" -homepage = "https://actix.rs" -repository = "https://github.com/actix/actix-web" authors = [ "Nikolay Kim ", "Rob Ede ", ] -license = "MIT OR Apache-2.0" -edition = "2021" +homepage.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +rust-version.workspace = true [lib] proc-macro = true diff --git a/justfile b/justfile index 42979f18c..d92f4bd3d 100644 --- a/justfile +++ b/justfile @@ -6,14 +6,57 @@ fmt: cargo +nightly fmt npx -y prettier --write $(fd --type=file --hidden --extension=md --extension=yml) +# Downgrade dev-dependencies necessary to run MSRV checks/tests. +[private] +downgrade-for-msrv: + cargo update -p=clap --precise=4.4.18 + +msrv := ``` + cargo metadata --format-version=1 \ + | jq -r 'first(.packages[] | select(.source == null and .rust_version)) | .rust_version' \ + | sed -E 's/^1\.([0-9]{2})$/1\.\1\.0/' +``` +msrv_rustup := "+" + msrv + +non_linux_all_features_list := ``` + cargo metadata --format-version=1 \ + | jq '.packages[] | select(.source == null) | .features | keys' \ + | jq -r --slurp \ + --arg exclusions "tokio-uring,io-uring,experimental-io-uring" \ + 'add | unique | . - ($exclusions | split(",")) | join(",")' +``` + +all_crate_features := if os() == "linux" { + "--all-features" +} else { + "--features='" + non_linux_all_features_list + "'" +} + +# Test workspace using MSRV. +test-msrv: downgrade-for-msrv (test msrv_rustup) + +# Test workspace code. +test toolchain="": + cargo {{ toolchain }} test --lib --tests -p=actix-web-codegen --all-features + cargo {{ toolchain }} test --lib --tests -p=actix-multipart-derive --all-features + cargo {{ toolchain }} nextest run -p=actix-router --no-default-features + cargo {{ toolchain }} nextest run --workspace --exclude=actix-web-codegen --exclude=actix-multipart-derive {{ all_crate_features }} --filter-expr="not test(test_reading_deflate_encoding_large_random_rustls)" + +# Test workspace docs. +test-docs toolchain="": && doc + cargo {{ toolchain }} test --doc --workspace {{ all_crate_features }} --no-fail-fast -- --nocapture + +# Test workspace. +test-all toolchain="": (test toolchain) (test-docs toolchain) + # Document crates in workspace. -doc: - RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl +doc *args: + RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }} # Document crates in workspace and watch for changes. doc-watch: - RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl --open - cargo watch -- RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc --no-deps --workspace --features=rustls,openssl + @just doc --open + cargo watch -- just doc # Update READMEs from crate root documentation. update-readmes: && fmt From 33c47c0ba918e87b35de6ba566ef98341672e21a Mon Sep 17 00:00:00 2001 From: asonix Date: Tue, 14 May 2024 00:45:35 -0500 Subject: [PATCH 247/314] Fix type confusion in some scenarios (#3348) * Fix type confusion in some scenarios When the feature for rustls 0.22 is enabled, and rustls 0.23 is also present in a project, there suddently exist multiple paths for errors when building middleware chains due to the use of two consecutive `?` operators without specifying the intermediate error type. This commit addresses the issue by removing the first `?`, so that the first error type will always be known, and the second `?` always has a well defined implementation. * Add CHANGES entry about type confusion --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/app_service.rs | 5 +++-- actix-web/src/scope.rs | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index c6454ed65..3300a6ffc 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -9,6 +9,7 @@ ### Changed - Minimum supported Rust version (MSRV) is now 1.72. +- Avoid type confusion in rare circumstances ## 4.5.1 diff --git a/actix-web/src/app_service.rs b/actix-web/src/app_service.rs index f2dca954c..65a6ed87b 100644 --- a/actix-web/src/app_service.rs +++ b/actix-web/src/app_service.rs @@ -263,8 +263,9 @@ impl ServiceFactory for AppRoutingFactory { let guards = guards.borrow_mut().take().unwrap_or_default(); let factory_fut = factory.new_service(()); async move { - let service = factory_fut.await?; - Ok((path, guards, service)) + factory_fut + .await + .map(move |service| (path, guards, service)) } })); diff --git a/actix-web/src/scope.rs b/actix-web/src/scope.rs index 27a2827a6..adc9f75d3 100644 --- a/actix-web/src/scope.rs +++ b/actix-web/src/scope.rs @@ -470,8 +470,9 @@ impl ServiceFactory for ScopeFactory { let guards = guards.borrow_mut().take().unwrap_or_default(); let factory_fut = factory.new_service(()); async move { - let service = factory_fut.await?; - Ok((path, guards, service)) + factory_fut + .await + .map(move |service| (path, guards, service)) } })); From c20603fc83ff8d706d9ef3381400e65c17db52e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 05:50:32 +0000 Subject: [PATCH 248/314] build(deps): bump taiki-e/install-action from 2.33.16 to 2.33.22 (#3364) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.16 to 2.33.22. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.16...v2.33.22) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d5cb6e620..40829d8ef 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -45,7 +45,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -76,7 +76,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7db0be48..c1d959fbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -105,7 +105,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 9ec33ee55..943f63223 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9c6846824..03b25ecda 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.16 + uses: taiki-e/install-action@v2.33.22 with: tool: cargo-public-api From fff45b28f4219b3c11f40a839649d60ee4e8750e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 08:58:05 +0000 Subject: [PATCH 249/314] build(deps): update brotli requirement from 3.3.3 to 6.0.0 (#3353) * build(deps): update brotli requirement from 3.3.3 to 6.0.0 Updates the requirements on [brotli](https://github.com/dropbox/rust-brotli) to permit the latest version. - [Release notes](https://github.com/dropbox/rust-brotli/releases) - [Commits](https://github.com/dropbox/rust-brotli/compare/3.3.3...6.0.0) --- updated-dependencies: - dependency-name: brotli dependency-type: direct:production ... Signed-off-by: dependabot[bot] * docs: update changelogs --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-http/CHANGES.md | 1 + actix-http/Cargo.toml | 2 +- actix-web/CHANGES.md | 6 +++++- actix-web/Cargo.toml | 2 +- awc/CHANGES.md | 2 +- awc/Cargo.toml | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index fddd1c2c3..699575068 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,6 +4,7 @@ ### Changed +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. ## 3.6.0 diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 38969e901..05de2cb80 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -114,7 +114,7 @@ sha1 = { version = "0.10", optional = true } actix-tls = { version = "3.3", default-features = false, optional = true } # compress-* -brotli = { version = "3.3.3", optional = true } +brotli = { version = "6", optional = true } flate2 = { version = "1.0.13", optional = true } zstd = { version = "0.13", optional = true } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 3300a6ffc..ea9967693 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -8,8 +8,12 @@ ### Changed +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. -- Avoid type confusion in rare circumstances + +### Fixed + +- Avoid type confusion with `rustls` in some circumstances. ## 4.5.1 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index aea8856b1..b4c713817 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -125,7 +125,7 @@ actix-files = "0.6" actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } awc = { version = "3", features = ["openssl"] } -brotli = "3.3.3" +brotli = "6" const-str = "0.5" criterion = { version = "0.5", features = ["html_reports"] } env_logger = "0.11" diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 46939a7ca..9bb787ab6 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,8 +2,8 @@ ## Unreleased +- Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. -- Fix warning on 1.78 due to unused TlsConnectorService struct ## 3.4.0 diff --git a/awc/Cargo.toml b/awc/Cargo.toml index da9e78ae8..aa77b0241 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -116,7 +116,7 @@ actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } -brotli = "3.3.3" +brotli = "6" const-str = "0.5" env_logger = "0.11" flate2 = "1.0.13" From 2d035c066ea60e9113ce9a710728a59ad03a0066 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 18 May 2024 13:22:53 -0500 Subject: [PATCH 250/314] actix-http: Add rustls 0.23 (#3361) Co-authored-by: Rob Ede --- .github/workflows/ci-post-merge.yml | 4 ++ .github/workflows/ci.yml | 4 ++ actix-http/CHANGES.md | 5 ++ actix-http/Cargo.toml | 12 ++-- actix-http/examples/tls_rustls.rs | 5 +- actix-http/examples/ws.rs | 4 +- actix-http/src/h1/service.rs | 61 ++++++++++++++++++ actix-http/src/h2/service.rs | 51 +++++++++++++++ actix-http/src/lib.rs | 8 ++- actix-http/src/service.rs | 98 +++++++++++++++++++++++++++++ actix-http/tests/test_rustls.rs | 44 ++++++------- 11 files changed, 263 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 40829d8ef..8d509d691 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -30,6 +30,10 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install nasm + if: matrix.target.os == 'windows-latest' + uses: ilammy/setup-nasm@v1.5.1 + - name: Install OpenSSL if: matrix.target.os == 'windows-latest' shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1d959fbf..56333e187 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,10 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Install nasm + if: matrix.target.os == 'windows-latest' + uses: ilammy/setup-nasm@v1.5.1 + - name: Install OpenSSL if: matrix.target.os == 'windows-latest' shell: bash diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 699575068..f7b20dd6a 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,11 @@ ## Unreleased +### Added + +- Add `rustls-0_23` crate feature +- Add `{h1::H1Service, h2::H2Service, HttpService}::rustls_0_23()` and `HttpService::rustls_0_23_with_config()` service constructors. + ### Changed - Update `brotli` dependency to `6`. diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 05de2cb80..efd20905a 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -28,6 +28,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22", + "rustls-0_23", "compress-brotli", "compress-gzip", "compress-zstd", @@ -66,6 +67,9 @@ rustls-0_21 = ["actix-tls/accept", "actix-tls/rustls-0_21"] # TLS via Rustls v0.22 rustls-0_22 = ["actix-tls/accept", "actix-tls/rustls-0_22"] +# TLS via Rustls v0.23 +rustls-0_23 = ["actix-tls/accept", "actix-tls/rustls-0_23"] + # Compression codecs compress-brotli = ["__compress", "brotli"] compress-gzip = ["__compress", "flate2"] @@ -121,7 +125,7 @@ zstd = { version = "0.13", optional = true } [dev-dependencies] actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22-webpki-roots"] } +actix-tls = { version = "3.4", features = ["openssl", "rustls-0_23-webpki-roots"] } actix-web = "4" async-stream = "0.3" @@ -139,16 +143,16 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls_022 = { package = "rustls", version = "0.22" } +tls-rustls_023 = { package = "rustls", version = "0.23" } tokio = { version = "1.24.2", features = ["net", "rt", "macros"] } [[example]] name = "ws" -required-features = ["ws", "rustls-0_22"] +required-features = ["ws", "rustls-0_23"] [[example]] name = "tls_rustls" -required-features = ["http2", "rustls-0_22"] +required-features = ["http2", "rustls-0_23"] [[bench]] name = "response-body-compression" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index 47ff061cd..ebb7b8b38 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -12,12 +12,11 @@ //! Protocol: HTTP/1.1 //! ``` -extern crate tls_rustls_022 as rustls; - use std::io; use actix_http::{Error, HttpService, Request, Response}; use actix_utils::future::ok; +use tls_rustls_023 as rustls; #[actix_rt::main] async fn main() -> io::Result<()> { @@ -36,7 +35,7 @@ async fn main() -> io::Result<()> { ); ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_0_22(rustls_config()) + .rustls_0_23(rustls_config()) })? .run() .await diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index 55085fd73..fac6b136b 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -1,7 +1,7 @@ //! Sets up a WebSocket server over TCP and TLS. //! Sends a heartbeat message every 4 seconds but does not respond to any incoming frames. -extern crate tls_rustls_022 as rustls; +extern crate tls_rustls_023 as rustls; use std::{ io, @@ -30,7 +30,7 @@ async fn main() -> io::Result<()> { .bind("tls", ("127.0.0.1", 8443), || { HttpService::build() .finish(handler) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) })? .run() .await diff --git a/actix-http/src/h1/service.rs b/actix-http/src/h1/service.rs index 64eb39c82..f2f8a0e48 100644 --- a/actix-http/src/h1/service.rs +++ b/actix-http/src/h1/service.rs @@ -335,6 +335,67 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H1Service, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into>, + S::InitError: fmt::Debug, + S::Response: Into>, + + B: MessageBody, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl H1Service where S: ServiceFactory, diff --git a/actix-http/src/h2/service.rs b/actix-http/src/h2/service.rs index d50ffc4e3..636ac3161 100644 --- a/actix-http/src/h2/service.rs +++ b/actix-http/src/h2/service.rs @@ -293,6 +293,57 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl H2Service, S, B> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + mut config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = S::InitError, + > { + let mut protos = vec![b"h2".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + Acceptor::new(config) + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .map(|io: TlsStream| { + let peer_addr = io.get_ref().0.peer_addr().ok(); + (io, peer_addr) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Option)> for H2Service where T: AsyncRead + AsyncWrite + Unpin + 'static, diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index cb82ced00..f9697c4d5 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -6,7 +6,10 @@ //! | ------------------- | ------------------------------------------- | //! | `http2` | HTTP/2 support via [h2]. | //! | `openssl` | TLS support via [OpenSSL]. | -//! | `rustls` | TLS support via [rustls]. | +//! | `rustls` | TLS support via [rustls] 0.20. | +//! | `rustls-0_21` | TLS support via [rustls] 0.21. | +//! | `rustls-0_22` | TLS support via [rustls] 0.22. | +//! | `rustls-0_23` | TLS support via [rustls] 0.23. | //! | `compress-brotli` | Payload compression support: Brotli. | //! | `compress-gzip` | Payload compression support: Deflate, Gzip. | //! | `compress-zstd` | Payload compression support: Zstd. | @@ -28,7 +31,7 @@ #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] -pub use ::http::{uri, uri::Uri, Method, StatusCode, Version}; +pub use http::{uri, uri::Uri, Method, StatusCode, Version}; pub mod body; mod builder; @@ -63,6 +66,7 @@ pub use self::payload::PayloadStream; feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] pub use self::service::TlsAcceptorConfig; pub use self::{ diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs index e24387182..a58be93c7 100644 --- a/actix-http/src/service.rs +++ b/actix-http/src/service.rs @@ -246,6 +246,7 @@ where feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] #[derive(Debug, Default)] pub struct TlsAcceptorConfig { @@ -257,6 +258,7 @@ pub struct TlsAcceptorConfig { feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] impl TlsAcceptorConfig { /// Set TLS handshake timeout duration. @@ -650,6 +652,102 @@ mod rustls_0_22 { } } +#[cfg(feature = "rustls-0_23")] +mod rustls_0_23 { + use std::io; + + use actix_service::ServiceFactoryExt as _; + use actix_tls::accept::{ + rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream}, + TlsError, + }; + + use super::*; + + impl HttpService, S, B, X, U> + where + S: ServiceFactory, + S::Future: 'static, + S::Error: Into> + 'static, + S::InitError: fmt::Debug, + S::Response: Into> + 'static, + >::Future: 'static, + + B: MessageBody + 'static, + + X: ServiceFactory, + X::Future: 'static, + X::Error: Into>, + X::InitError: fmt::Debug, + + U: ServiceFactory< + (Request, Framed, h1::Codec>), + Config = (), + Response = (), + >, + U::Future: 'static, + U::Error: fmt::Display + Into>, + U::InitError: fmt::Debug, + { + /// Create Rustls v0.23 based service. + pub fn rustls_0_23( + self, + config: ServerConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + self.rustls_0_23_with_config(config, TlsAcceptorConfig::default()) + } + + /// Create Rustls v0.23 based service with custom TLS acceptor configuration. + pub fn rustls_0_23_with_config( + self, + mut config: ServerConfig, + tls_acceptor_config: TlsAcceptorConfig, + ) -> impl ServiceFactory< + TcpStream, + Config = (), + Response = (), + Error = TlsError, + InitError = (), + > { + let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; + protos.extend_from_slice(&config.alpn_protocols); + config.alpn_protocols = protos; + + let mut acceptor = Acceptor::new(config); + + if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout { + acceptor.set_handshake_timeout(handshake_timeout); + } + + acceptor + .map_init_err(|_| { + unreachable!("TLS acceptor service factory does not error on init") + }) + .map_err(TlsError::into_service_error) + .and_then(|io: TlsStream| async { + let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() { + if protos.windows(2).any(|window| window == b"h2") { + Protocol::Http2 + } else { + Protocol::Http1 + } + } else { + Protocol::Http1 + }; + let peer_addr = io.get_ref().0.peer_addr().ok(); + Ok((io, proto, peer_addr)) + }) + .and_then(self.map_err(TlsError::Service)) + } + } +} + impl ServiceFactory<(T, Protocol, Option)> for HttpService where diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index 08b3a249b..fd2064d56 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_22")] +#![cfg(feature = "rustls-0_23")] -extern crate tls_rustls_022 as rustls; +extern crate tls_rustls_023 as rustls; use std::{ convert::Infallible, @@ -20,7 +20,7 @@ use actix_http::{ use actix_http_test::test_server; use actix_rt::pin; use actix_service::{fn_factory_with_config, fn_service}; -use actix_tls::connect::rustls_0_22::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_23::webpki_roots_cert_store; use actix_utils::future::{err, ok, poll_fn}; use bytes::{Bytes, BytesMut}; use derive_more::{Display, Error}; @@ -108,7 +108,7 @@ async fn h1() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -122,7 +122,7 @@ async fn h2() -> io::Result<()> { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -140,7 +140,7 @@ async fn h1_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_11); ok::<_, Error>(Response::ok()) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -158,7 +158,7 @@ async fn h2_1() -> io::Result<()> { assert_eq!(req.version(), Version::HTTP_2); ok::<_, Error>(Response::ok()) }) - .rustls_0_22_with_config( + .rustls_0_23_with_config( tls_config(), TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)), ) @@ -179,7 +179,7 @@ async fn h2_body1() -> io::Result<()> { let body = load_body(req.take_payload()).await?; Ok::<_, Error>(Response::ok().set_body(body)) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -205,7 +205,7 @@ async fn h2_content_length() { ]; ok::<_, Infallible>(Response::new(statuses[indx])) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -277,7 +277,7 @@ async fn h2_headers() { } ok::<_, Infallible>(config.body(data.clone())) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -316,7 +316,7 @@ async fn h2_body2() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -333,7 +333,7 @@ async fn h2_head_empty() { let mut srv = test_server(move || { HttpService::build() .finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -359,7 +359,7 @@ async fn h2_head_binary() { let mut srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -384,7 +384,7 @@ async fn h2_head_binary2() { let srv = test_server(move || { HttpService::build() .h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR))) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -410,7 +410,7 @@ async fn h2_body_length() { Response::ok().set_body(SizedStream::new(STR.len() as u64, body)), ) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -434,7 +434,7 @@ async fn h2_body_chunked_explicit() { .body(BodyStream::new(body)), ) }) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -463,7 +463,7 @@ async fn h2_response_http_error_handling() { ) })) })) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -493,7 +493,7 @@ async fn h2_service_error() { let mut srv = test_server(move || { HttpService::build() .h2(|_| err::, _>(BadRequest)) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -510,7 +510,7 @@ async fn h1_service_error() { let mut srv = test_server(move || { HttpService::build() .h1(|_| err::, _>(BadRequest)) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) }) .await; @@ -533,7 +533,7 @@ async fn alpn_h1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h1(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(config) + .rustls_0_23(config) }) .await; @@ -555,7 +555,7 @@ async fn alpn_h2() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .h2(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(config) + .rustls_0_23(config) }) .await; @@ -581,7 +581,7 @@ async fn alpn_h2_1() -> io::Result<()> { config.alpn_protocols.push(CUSTOM_ALPN_PROTOCOL.to_vec()); HttpService::build() .finish(|_| ok::<_, Error>(Response::ok())) - .rustls_0_22(config) + .rustls_0_23(config) }) .await; From 0a2788d6627ed26d3fec560474b1c7f9febd78db Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Sun, 19 May 2024 04:57:35 +1000 Subject: [PATCH 251/314] actix-test: re-export types from awc (#3349) This allows us to pass these types around in functions, without having to add `awc` as a direct (dev-)dependency. Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 1 + actix-test/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 082520447..f465720f1 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Minimum supported Rust version (MSRV) is now 1.72. +- Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. ## 0.1.3 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index b7aeddad2..b90db638b 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -52,7 +52,7 @@ use actix_web::{ rt::{self, System}, web, Error, }; -use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector}; +pub use awc::{error::PayloadError, Client, ClientRequest, ClientResponse, Connector}; use futures_core::Stream; use tokio::sync::mpsc; From 48d7adb7bfee8e373e31e9fe6c78a7da4cec5bec Mon Sep 17 00:00:00 2001 From: Raphael C Date: Sat, 18 May 2024 21:02:00 +0200 Subject: [PATCH 252/314] Documentation for actix multipart (#3344) example for actix-multipart readme & crate docs Co-authored-by: Rob Ede --- actix-multipart/README.md | 62 ++++++++++++++++++++++++++++++++++++++ actix-multipart/src/lib.rs | 35 +++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 56723bd68..83947b0c2 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -14,3 +14,65 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + +## Example + +Dependencies: + +```toml +[dependencies] +actix-multipart = "0.6" +actix-web = "4.5" +serde = { version = "1.0", features = ["derive"] } +``` + +Code: + +```rust +use actix_web::{post, App, HttpServer, Responder}; + +use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm}; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +struct Metadata { + name: String, +} + +#[derive(Debug, MultipartForm)] +struct UploadForm { + #[multipart(limit = "100MB")] + file: TempFile, + json: MPJson, +} + +#[post("/videos")] +pub async fn post_video(MultipartForm(form): MultipartForm) -> impl Responder { + format!( + "Uploaded file {}, with size: {}", + form.json.name, form.file.size + ) +} + +#[actix_web::main] +async fn main() -> std::io::Result<()> { + HttpServer::new(move || App::new().service(post_video)) + .bind(("127.0.0.1", 8080))? + .run() + .await +} +``` + +Curl request : +```bash +curl -v --request POST \ + --url http://localhost:8080/videos \ + -F 'json={"name": "Cargo.lock"};type=application/json' \ + -F file=@./Cargo.lock +``` + + +### Examples + +https://github.com/actix/examples/tree/master/forms/multipart \ No newline at end of file diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index c06a00ca9..d19e951e6 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -1,4 +1,39 @@ //! Multipart form support for Actix Web. +//! # Examples +//! ```no_run +//! use actix_web::{post, App, HttpServer, Responder}; +//! +//! use actix_multipart::form::{json::Json as MPJson, tempfile::TempFile, MultipartForm}; +//! use serde::Deserialize; +//! +//! #[derive(Debug, Deserialize)] +//! struct Metadata { +//! name: String, +//! } +//! +//! #[derive(Debug, MultipartForm)] +//! struct UploadForm { +//! #[multipart(limit = "100MB")] +//! file: TempFile, +//! json: MPJson, +//! } +//! +//! #[post("/videos")] +//! pub async fn post_video(MultipartForm(form): MultipartForm) -> impl Responder { +//! format!( +//! "Uploaded file {}, with size: {}", +//! form.json.name, form.file.size +//! ) +//! } +//! +//! #[actix_web::main] +//! async fn main() -> std::io::Result<()> { +//! HttpServer::new(move || App::new().service(post_video)) +//! .bind(("127.0.0.1", 8080))? +//! .run() +//! .await +//! } +//! ``` #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] From 2e63ff5928abc0704cadf330bcbf630162a37fa8 Mon Sep 17 00:00:00 2001 From: asonix Date: Sat, 18 May 2024 14:05:58 -0500 Subject: [PATCH 253/314] actix-web: Add rustls 0.23 (#3363) * Fix type confusion in some scenarios When the feature for rustls 0.22 is enabled, and rustls 0.23 is also present in a project, there suddently exist multiple paths for errors when building middleware chains due to the use of two consecutive `?` operators without specifying the intermediate error type. This commit addresses the issue by removing the first `?`, so that the first error type will always be known, and the second `?` always has a well defined implementation. * Add CHANGES entry about type confusion * actix-http: add rustls 0.23 support * actix-http: update ws example, tests for rustls 0.23 * actix-http: add rustls 0.23 to changelog * Update comments to mention 0.23 instead of 0.22 * awc: add rustls 0.23 support This also fixes certificate lookup when native-roots is enabled for rustls 0.22. * awc: update changelog for rustls 0.23 * awc: Add base rustls-0_23 feature without roots to better enable custom config * actix-test: add rustls-0.23 * actix-test: add rustls 0.23 to changelog * awc: update changelog with rustls 0.23 tweaks * actix-web: add rustls 0.23 * Add rustls-0_23 to CI * Update tls_rustls.rs * review nits * review nits part 2 * fix doc test --------- Co-authored-by: Rob Ede --- actix-http/examples/tls_rustls.rs | 3 +- actix-test/CHANGES.md | 1 + actix-test/Cargo.toml | 3 + actix-test/src/lib.rs | 53 ++++++++++++++++ actix-web/CHANGES.md | 3 + actix-web/Cargo.toml | 7 +- actix-web/src/lib.rs | 5 +- actix-web/src/server.rs | 102 +++++++++++++++++++++++++++++- actix-web/tests/test_server.rs | 6 +- awc/CHANGES.md | 3 + awc/Cargo.toml | 15 ++++- awc/src/builder.rs | 6 ++ awc/src/client/connector.rs | 97 ++++++++++++++++++++++++++-- awc/tests/test_rustls_client.rs | 12 ++-- 14 files changed, 292 insertions(+), 24 deletions(-) diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index ebb7b8b38..3e273d79c 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -12,11 +12,12 @@ //! Protocol: HTTP/1.1 //! ``` +extern crate tls_rustls_023 as rustls; + use std::io; use actix_http::{Error, HttpService, Request, Response}; use actix_utils::future::ok; -use tls_rustls_023 as rustls; #[actix_rt::main] async fn main() -> io::Result<()> { diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index f465720f1..b55a8305c 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. - Minimum supported Rust version (MSRV) is now 1.72. - Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 7f48fc2cc..69ce080ad 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -29,6 +29,8 @@ rustls-0_20 = ["tls-rustls-0_20", "actix-http/rustls-0_20", "awc/rustls-0_20"] rustls-0_21 = ["tls-rustls-0_21", "actix-http/rustls-0_21", "awc/rustls-0_21"] # TLS via Rustls v0.22 rustls-0_22 = ["tls-rustls-0_22", "actix-http/rustls-0_22", "awc/rustls-0_22-webpki-roots"] +# TLS via Rustls v0.23 +rustls-0_23 = ["tls-rustls-0_23", "actix-http/rustls-0_23", "awc/rustls-0_23-webpki-roots"] # TLS via OpenSSL openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] @@ -53,4 +55,5 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true } tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } +tls-rustls-0_23 = { package = "rustls", version = "0.23", default-features = false, optional = true } tokio = { version = "1.24.2", features = ["sync"] } diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index b90db638b..1c3d8ff11 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -145,6 +145,8 @@ where StreamType::Rustls021(_) => true, #[cfg(feature = "rustls-0_22")] StreamType::Rustls022(_) => true, + #[cfg(feature = "rustls-0_23")] + StreamType::Rustls023(_) => true, }; // run server in separate orphaned thread @@ -371,6 +373,48 @@ where .rustls_0_22(config.clone()) }), }, + #[cfg(feature = "rustls-0_23")] + StreamType::Rustls023(config) => match cfg.tp { + HttpVer::Http1 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h1(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + HttpVer::Http2 => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .h2(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + HttpVer::Both => builder.listen("test", tcp, move || { + let app_cfg = + AppConfig::__priv_test_new(false, local_addr.to_string(), local_addr); + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + HttpService::build() + .client_request_timeout(timeout) + .finish(map_config(fac, move |_| app_cfg.clone())) + .rustls_0_23(config.clone()) + }), + }, } .expect("test server could not be created"); @@ -447,6 +491,8 @@ enum StreamType { Rustls021(tls_rustls_0_21::ServerConfig), #[cfg(feature = "rustls-0_22")] Rustls022(tls_rustls_0_22::ServerConfig), + #[cfg(feature = "rustls-0_23")] + Rustls023(tls_rustls_0_23::ServerConfig), } /// Create default test server config. @@ -537,6 +583,13 @@ impl TestServerConfig { self } + /// Accepts secure connections via Rustls v0.23. + #[cfg(feature = "rustls-0_23")] + pub fn rustls_0_23(mut self, config: tls_rustls_0_23::ServerConfig) -> Self { + self.stream = StreamType::Rustls023(config); + self + } + /// Sets client timeout for first request. pub fn client_request_timeout(mut self, dur: Duration) -> Self { self.client_request_timeout = dur; diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index ea9967693..5b43a51d0 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -5,6 +5,9 @@ ### Added - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. +- Add `rustls-0_23` crate feature. +- Add `HttpServer::{bind_rustls_0_23, listen_rustls_0_23}()` builder methods. +- Add `HttpServer::tls_handshake_timeout()` builder method for `rustls-0_22` and `rustls-0_23`. ### Changed diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index b4c713817..cd09c3054 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -27,6 +27,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22", + "rustls-0_23", "compress-brotli", "compress-gzip", "compress-zstd", @@ -71,6 +72,8 @@ rustls-0_20 = ["http2", "actix-http/rustls-0_20", "actix-tls/accept", "actix-tls rustls-0_21 = ["http2", "actix-http/rustls-0_21", "actix-tls/accept", "actix-tls/rustls-0_21"] # TLS via Rustls v0.22 rustls-0_22 = ["http2", "actix-http/rustls-0_22", "actix-tls/accept", "actix-tls/rustls-0_22"] +# TLS via Rustls v0.23 +rustls-0_23 = ["http2", "actix-http/rustls-0_23", "actix-tls/accept", "actix-tls/rustls-0_23"] # Full unicode support unicode = ["dep:regex", "actix-router/unicode"] @@ -122,7 +125,7 @@ url = "2.1" [dev-dependencies] actix-files = "0.6" -actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } awc = { version = "3", features = ["openssl"] } brotli = "6" @@ -137,7 +140,7 @@ rustls-pemfile = "2" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" tls-openssl = { package = "openssl", version = "0.10.55" } -tls-rustls = { package = "rustls", version = "0.22" } +tls-rustls = { package = "rustls", version = "0.23" } tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index 88f0ae9be..f86a74406 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -64,7 +64,10 @@ //! - `compress-gzip` - gzip and deflate content encoding compression support (enabled by default) //! - `compress-zstd` - zstd content encoding compression support (enabled by default) //! - `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2` -//! - `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2` +//! - `rustls` - HTTPS support via `rustls` 0.20 crate, supports `HTTP/2` +//! - `rustls-0_21` - HTTPS support via `rustls` 0.21 crate, supports `HTTP/2` +//! - `rustls-0_22` - HTTPS support via `rustls` 0.22 crate, supports `HTTP/2` +//! - `rustls-0_23` - HTTPS support via `rustls` 0.23 crate, supports `HTTP/2` //! - `secure-cookies` - secure cookies support #![deny(rust_2018_idioms, nonstandard_style)] diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs index 6592079bf..33b1e1894 100644 --- a/actix-web/src/server.rs +++ b/actix-web/src/server.rs @@ -12,6 +12,7 @@ use std::{ feature = "rustls-0_20", feature = "rustls-0_21", feature = "rustls-0_22", + feature = "rustls-0_23", ))] use actix_http::TlsAcceptorConfig; use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response}; @@ -242,7 +243,13 @@ where /// time, the connection is closed. /// /// By default, the handshake timeout is 3 seconds. - #[cfg(any(feature = "openssl", feature = "rustls-0_20", feature = "rustls-0_21"))] + #[cfg(any( + feature = "openssl", + feature = "rustls-0_20", + feature = "rustls-0_21", + feature = "rustls-0_22", + feature = "rustls-0_23", + ))] pub fn tls_handshake_timeout(self, dur: Duration) -> Self { self.config .lock() @@ -270,6 +277,10 @@ where /// Rustls v0.20. /// - `actix_tls::accept::rustls_0_21::TlsStream` when using /// Rustls v0.21. + /// - `actix_tls::accept::rustls_0_22::TlsStream` when using + /// Rustls v0.22. + /// - `actix_tls::accept::rustls_0_23::TlsStream` when using + /// Rustls v0.23. /// - `actix_web::rt::net::TcpStream` when no encryption is used. /// /// See the `on_connect` example for additional details. @@ -466,6 +477,25 @@ where Ok(self) } + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections + /// using Rustls v0.23. + /// + /// See [`bind()`](Self::bind()) for more details on `addrs` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_23")] + pub fn bind_rustls_0_23( + mut self, + addrs: A, + config: actix_tls::accept::rustls_0_23::reexports::ServerConfig, + ) -> io::Result { + let sockets = bind_addrs(addrs, self.backlog)?; + for lst in sockets { + self = self.listen_rustls_0_23_inner(lst, config.clone())?; + } + Ok(self) + } + /// Resolves socket address(es) and binds server to created listener(s) for TLS connections /// using OpenSSL. /// @@ -595,7 +625,7 @@ where /// Binds to existing listener for accepting incoming TLS connection requests using Rustls /// v0.21. /// - /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// See [`listen()`](Self::listen()) for more details on the `lst` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls-0_21")] @@ -712,7 +742,7 @@ where /// Binds to existing listener for accepting incoming TLS connection requests using Rustls /// v0.22. /// - /// See [`listen()`](Self::listen) for more details on the `lst` argument. + /// See [`listen()`](Self::listen()) for more details on the `lst` argument. /// /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. #[cfg(feature = "rustls-0_22")] @@ -775,6 +805,72 @@ where Ok(self) } + /// Binds to existing listener for accepting incoming TLS connection requests using Rustls + /// v0.23. + /// + /// See [`listen()`](Self::listen()) for more details on the `lst` argument. + /// + /// ALPN protocols "h2" and "http/1.1" are added to any configured ones. + #[cfg(feature = "rustls-0_23")] + pub fn listen_rustls_0_23( + self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_23::reexports::ServerConfig, + ) -> io::Result { + self.listen_rustls_0_23_inner(lst, config) + } + + #[cfg(feature = "rustls-0_23")] + fn listen_rustls_0_23_inner( + mut self, + lst: net::TcpListener, + config: actix_tls::accept::rustls_0_23::reexports::ServerConfig, + ) -> io::Result { + let factory = self.factory.clone(); + let cfg = self.config.clone(); + let addr = lst.local_addr().unwrap(); + self.sockets.push(Socket { + addr, + scheme: "https", + }); + + let on_connect_fn = self.on_connect_fn.clone(); + + self.builder = + self.builder + .listen(format!("actix-web-service-{}", addr), lst, move || { + let c = cfg.lock().unwrap(); + let host = c.host.clone().unwrap_or_else(|| format!("{}", addr)); + + let svc = HttpService::build() + .keep_alive(c.keep_alive) + .client_request_timeout(c.client_request_timeout) + .client_disconnect_timeout(c.client_disconnect_timeout); + + let svc = if let Some(handler) = on_connect_fn.clone() { + svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext)) + } else { + svc + }; + + let fac = factory() + .into_factory() + .map_err(|err| err.into().error_response()); + + let acceptor_config = match c.tls_handshake_timeout { + Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur), + None => TlsAcceptorConfig::default(), + }; + + svc.finish(map_config(fac, move |_| { + AppConfig::new(true, host.clone(), addr) + })) + .rustls_0_23_with_config(config.clone(), acceptor_config) + })?; + + Ok(self) + } + /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL. /// /// See [`listen()`](Self::listen) for more details on the `lst` argument. diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 8fb80216b..60d282351 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -1,6 +1,6 @@ #[cfg(feature = "openssl")] extern crate tls_openssl as openssl; -#[cfg(feature = "rustls-0_22")] +#[cfg(feature = "rustls-0_23")] extern crate tls_rustls as rustls; use std::{ @@ -704,7 +704,7 @@ async fn test_brotli_encoding_large_openssl() { srv.stop().await; } -#[cfg(feature = "rustls-0_22")] +#[cfg(feature = "rustls-0_23")] mod plus_rustls { use std::io::BufReader; @@ -740,7 +740,7 @@ mod plus_rustls { .map(char::from) .collect::(); - let srv = actix_test::start_with(actix_test::config().rustls_0_22(tls_config()), || { + let srv = actix_test::start_with(actix_test::config().rustls_0_23(tls_config()), || { App::new().service(web::resource("/").route(web::to(|bytes: Bytes| async { // echo decompressed request body back in response HttpResponse::Ok() diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 9bb787ab6..4031d2bda 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +- Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features. +- Add `awc::Connector::rustls_0_23()` constructor. +- Fix `rustls-0_22-native-roots` root store lookup - Update `brotli` dependency to `6`. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/awc/Cargo.toml b/awc/Cargo.toml index aa77b0241..2ba8ada31 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -27,6 +27,7 @@ features = [ "rustls-0_20", "rustls-0_21", "rustls-0_22-webpki-roots", + "rustls-0_23-webpki-roots", "compress-brotli", "compress-gzip", "compress-zstd", @@ -48,6 +49,12 @@ rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"] rustls-0_22-webpki-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-webpki-roots"] # TLS via Rustls v0.22 (Native roots) rustls-0_22-native-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-native-roots"] +# TLS via Rustls v0.23 +rustls-0_23 = ["tls-rustls-0_23", "actix-tls/rustls-0_23"] +# TLS via Rustls v0.23 (WebPKI roots) +rustls-0_23-webpki-roots = ["rustls-0_23", "actix-tls/rustls-0_23-webpki-roots"] +# TLS via Rustls v0.23 (Native roots) +rustls-0_23-native-roots = ["rustls-0_23", "actix-tls/rustls-0_23-native-roots"] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -104,6 +111,7 @@ tls-openssl = { package = "openssl", version = "0.10.55", optional = true } tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] } tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true } +tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, default-features = false } trust-dns-resolver = { version = "0.23", optional = true } @@ -111,8 +119,8 @@ trust-dns-resolver = { version = "0.23", optional = true } actix-http = { version = "3.6", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" -actix-test = { version = "0.1", features = ["openssl", "rustls-0_22"] } -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_22"] } +actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } +actix-tls = { version = "3.3", features = ["openssl", "rustls-0_23"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } @@ -126,7 +134,8 @@ rcgen = "0.12" rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" +tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests [[example]] name = "client" -required-features = ["rustls-0_22-webpki-roots"] +required-features = ["rustls-0_23-webpki-roots"] diff --git a/awc/src/builder.rs b/awc/src/builder.rs index a54960382..5aae394f8 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -37,6 +37,12 @@ pub struct ClientBuilder { } impl ClientBuilder { + /// Create a new ClientBuilder with default settings + /// + /// Note: If the `rustls-0_23` feature is enabled and neither `rustls-0_23-native-roots` nor + /// `rustls-0_23-webpki-roots` are enabled, this ClientBuilder will build without TLS. In order + /// to enable TLS in this scenario, a custom `Connector` _must_ be added to the builder before + /// finishing construction. #[allow(clippy::new_ret_no_self)] pub fn new() -> ClientBuilder< impl Service< diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index b66e13ec7..fbe50b65c 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -57,6 +57,10 @@ enum OurTlsConnector { ))] #[allow(dead_code)] // false positive; used in build_tls Rustls022(std::sync::Arc), + + #[cfg(feature = "rustls-0_23")] + #[allow(dead_code)] // false positive; used in build_tls + Rustls023(std::sync::Arc), } /// Manages HTTP client network connectivity. @@ -80,6 +84,14 @@ pub struct Connector { } impl Connector<()> { + /// Create a new connector with default TLS settings + /// + /// # Panics + /// + /// - When the `rustls-0_23-webpki-roots` or `rustls-0_23-native-roots` features are enabled + /// and no default crypto provider has been loaded, this method will panic. + /// - When the `rustls-0_23-native-roots` or `rustls-0_22-native-roots` features are enabled + /// and the runtime system has no native root certificates, this method will panic. #[allow(clippy::new_ret_no_self, clippy::let_unit_value)] pub fn new() -> Connector< impl Service< @@ -96,10 +108,32 @@ impl Connector<()> { } cfg_if::cfg_if! { - if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-webpki-roots"))] { - /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. + if #[cfg(any(feature = "rustls-0_23-webpki-roots", feature = "rustls-0_23-native-roots"))] { + /// Build TLS connector with Rustls v0.23, based on supplied ALPN protocols. /// - /// Note that if other TLS crate features are enabled, Rustls v0.22 will be used. + /// Note that if other TLS crate features are enabled, Rustls v0.23 will be used. + fn build_tls(protocols: Vec>) -> OurTlsConnector { + use actix_tls::connect::rustls_0_23::{self, reexports::ClientConfig}; + + cfg_if::cfg_if! { + if #[cfg(feature = "rustls-0_23-webpki-roots")] { + let certs = rustls_0_23::webpki_roots_cert_store(); + } else if #[cfg(feature = "rustls-0_23-native-roots")] { + let certs = rustls_0_23::native_roots_cert_store().expect("Failed to find native root certificates"); + } + } + + let mut config = ClientConfig::builder() + .with_root_certificates(certs) + .with_no_client_auth(); + + config.alpn_protocols = protocols; + + OurTlsConnector::Rustls023(std::sync::Arc::new(config)) + } + + } else if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots"))] { + /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. fn build_tls(protocols: Vec>) -> OurTlsConnector { use actix_tls::connect::rustls_0_22::{self, reexports::ClientConfig}; @@ -107,7 +141,7 @@ impl Connector<()> { if #[cfg(feature = "rustls-0_22-webpki-roots")] { let certs = rustls_0_22::webpki_roots_cert_store(); } else if #[cfg(feature = "rustls-0_22-native-roots")] { - let certs = rustls_0_22::native_roots_cert_store(); + let certs = rustls_0_22::native_roots_cert_store().expect("Failed to find native root certificates"); } } @@ -167,7 +201,8 @@ impl Connector<()> { OurTlsConnector::OpensslBuilder(ssl) } } else { - /// Provides an empty TLS connector when no TLS feature is enabled. + /// Provides an empty TLS connector when no TLS feature is enabled, or when only the + /// `rustls-0_23` crate feature is enabled. fn build_tls(_: Vec>) -> OurTlsConnector { OurTlsConnector::None } @@ -278,6 +313,24 @@ where self } + /// Sets custom Rustls v0.23 `ClientConfig` instance. + /// + /// In order to enable ALPN, set the `.alpn_protocols` field on the ClientConfig to the + /// following: + /// + /// ```no_run + /// vec![b"h2".to_vec(), b"http/1.1".to_vec()] + /// # ; + /// ``` + #[cfg(feature = "rustls-0_23")] + pub fn rustls_0_23( + mut self, + connector: std::sync::Arc, + ) -> Self { + self.tls = OurTlsConnector::Rustls023(connector); + self + } + /// Sets maximum supported HTTP major version. /// /// Supported versions are HTTP/1.1 and HTTP/2. @@ -588,6 +641,40 @@ where Some(actix_service::boxed::rc_service(tls_service)) } + + #[cfg(feature = "rustls-0_23")] + OurTlsConnector::Rustls023(tls) => { + const H2: &[u8] = b"h2"; + + use actix_tls::connect::rustls_0_23::{reexports::AsyncTlsStream, TlsConnector}; + + #[allow(non_local_definitions)] + impl IntoConnectionIo for TcpConnection> { + fn into_connection_io(self) -> (Box, Protocol) { + let sock = self.into_parts().0; + let h2 = sock + .get_ref() + .1 + .alpn_protocol() + .map_or(false, |protos| protos.windows(2).any(|w| w == H2)); + if h2 { + (Box::new(sock), Protocol::Http2) + } else { + (Box::new(sock), Protocol::Http1) + } + } + } + + let handshake_timeout = self.config.handshake_timeout; + + let tls_service = TlsConnectorService { + tcp_service: tcp_service_inner, + tls_service: TlsConnector::service(tls), + timeout: handshake_timeout, + }; + + Some(actix_service::boxed::rc_service(tls_service)) + } }; let tcp_config = self.config.no_disconnect_timeout(); diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index 1cc3e8c48..719d25119 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -1,6 +1,6 @@ -#![cfg(feature = "rustls-0_22-webpki-roots")] +#![cfg(feature = "rustls-0_23-webpki-roots")] -extern crate tls_rustls_0_22 as rustls; +extern crate tls_rustls_0_23 as rustls; use std::{ io::BufReader, @@ -13,7 +13,7 @@ use std::{ use actix_http::HttpService; use actix_http_test::test_server; use actix_service::{fn_service, map_config, ServiceFactoryExt}; -use actix_tls::connect::rustls_0_22::webpki_roots_cert_store; +use actix_tls::connect::rustls_0_23::webpki_roots_cert_store; use actix_utils::future::ok; use actix_web::{dev::AppConfig, http::Version, web, App, HttpResponse}; use rustls::{ @@ -83,7 +83,7 @@ mod danger { } fn supported_verify_schemes(&self) -> Vec { - rustls::crypto::ring::default_provider() + rustls::crypto::aws_lc_rs::default_provider() .signature_verification_algorithms .supported_schemes() } @@ -107,7 +107,7 @@ async fn test_connection_reuse_h2() { App::new().service(web::resource("/").route(web::to(HttpResponse::Ok))), |_| AppConfig::default(), )) - .rustls_0_22(tls_config()) + .rustls_0_23(tls_config()) .map_err(|_| ()), ) }) @@ -126,7 +126,7 @@ async fn test_connection_reuse_h2() { .set_certificate_verifier(Arc::new(danger::NoCertificateVerification)); let client = awc::Client::builder() - .connector(awc::Connector::new().rustls_0_22(Arc::new(config))) + .connector(awc::Connector::new().rustls_0_23(Arc::new(config))) .finish(); // req 1 From 18e02b83d5e160d3fe7e051104eea700f8eaa3af Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 18 May 2024 20:35:12 +0100 Subject: [PATCH 254/314] docs: fix middleware docs warning --- actix-web/src/middleware/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index ed61556a3..e924de261 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -33,13 +33,13 @@ //! //! # fn main() { //! # // These aren't snake_case, because they are supposed to be unit structs. -//! # let MiddlewareA = middleware::Compress::default(); -//! # let MiddlewareB = middleware::Compress::default(); -//! # let MiddlewareC = middleware::Compress::default(); +//! # type MiddlewareA = middleware::Compress; +//! # type MiddlewareB = middleware::Compress; +//! # type MiddlewareC = middleware::Compress; //! let app = App::new() -//! .wrap(MiddlewareA) -//! .wrap(MiddlewareB) -//! .wrap(MiddlewareC) +//! .wrap(MiddlewareA::default()) +//! .wrap(MiddlewareB::default()) +//! .wrap(MiddlewareC::default()) //! .service(service); //! # } //! ``` From e8262da1381c24a265747ac604e45aee635e00b8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:12:32 +0100 Subject: [PATCH 255/314] chore: update rcgen to 0.13 --- actix-http/Cargo.toml | 2 +- actix-http/examples/tls_rustls.rs | 7 ++++--- actix-http/examples/ws.rs | 7 ++++--- actix-http/tests/test_openssl.rs | 8 +++++--- actix-http/tests/test_rustls.rs | 7 ++++--- actix-web/Cargo.toml | 2 +- actix-web/tests/test_httpserver.rs | 8 +++++--- actix-web/tests/test_server.rs | 15 +++++++++------ awc/Cargo.toml | 2 +- awc/tests/test_connector.rs | 8 +++++--- awc/tests/test_rustls_client.rs | 7 ++++--- awc/tests/test_ssl_client.rs | 8 +++++--- 12 files changed, 48 insertions(+), 33 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index efd20905a..c00c2ee04 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -135,7 +135,7 @@ env_logger = "0.11" futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] } memchr = "2.4" once_cell = "1.9" -rcgen = "0.12" +rcgen = "0.13" regex = "1.3" rustversion = "1" rustls-pemfile = "2" diff --git a/actix-http/examples/tls_rustls.rs b/actix-http/examples/tls_rustls.rs index 3e273d79c..17303c556 100644 --- a/actix-http/examples/tls_rustls.rs +++ b/actix-http/examples/tls_rustls.rs @@ -43,9 +43,10 @@ async fn main() -> io::Result<()> { } fn rustls_config() -> rustls::ServerConfig { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut io::BufReader::new(cert_file.as_bytes()); let key_file = &mut io::BufReader::new(key_file.as_bytes()); diff --git a/actix-http/examples/ws.rs b/actix-http/examples/ws.rs index fac6b136b..fb86bc5ea 100644 --- a/actix-http/examples/ws.rs +++ b/actix-http/examples/ws.rs @@ -87,9 +87,10 @@ fn tls_config() -> rustls::ServerConfig { use rustls_pemfile::{certs, pkcs8_private_keys}; - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs index cb16a4fec..4dd22b585 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -42,9 +42,11 @@ where } fn tls_config() -> SslAcceptor { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index fd2064d56..3ca0d94c2 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -52,9 +52,10 @@ where } fn tls_config() -> RustlsServerConfig { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index cd09c3054..bd24ea35f 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -135,7 +135,7 @@ env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } rand = "0.8" -rcgen = "0.12" +rcgen = "0.13" rustls-pemfile = "2" serde = { version = "1.0", features = ["derive"] } static_assertions = "1" diff --git a/actix-web/tests/test_httpserver.rs b/actix-web/tests/test_httpserver.rs index 86e0575f3..039c0ffbc 100644 --- a/actix-web/tests/test_httpserver.rs +++ b/actix-web/tests/test_httpserver.rs @@ -64,9 +64,11 @@ fn ssl_acceptor() -> openssl::ssl::SslAcceptorBuilder { x509::X509, }; - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/actix-web/tests/test_server.rs b/actix-web/tests/test_server.rs index 60d282351..960cf1e2b 100644 --- a/actix-web/tests/test_server.rs +++ b/actix-web/tests/test_server.rs @@ -34,9 +34,11 @@ const STR: &str = const_str::repeat!(S, 100); #[cfg(feature = "openssl")] fn openssl_config() -> SslAcceptor { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); @@ -714,9 +716,10 @@ mod plus_rustls { use super::*; fn tls_config() -> RustlsServerConfig { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 2ba8ada31..b1ee62361 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -130,7 +130,7 @@ env_logger = "0.11" flate2 = "1.0.13" futures-util = { version = "0.3.17", default-features = false } static_assertions = "1.1" -rcgen = "0.12" +rcgen = "0.13" rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" diff --git a/awc/tests/test_connector.rs b/awc/tests/test_connector.rs index b3eb97367..a8b7e98c1 100644 --- a/awc/tests/test_connector.rs +++ b/awc/tests/test_connector.rs @@ -13,9 +13,11 @@ use openssl::{ }; fn tls_config() -> SslAcceptor { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs index 719d25119..7e832f67d 100644 --- a/awc/tests/test_rustls_client.rs +++ b/awc/tests/test_rustls_client.rs @@ -23,9 +23,10 @@ use rustls::{ use rustls_pemfile::{certs, pkcs8_private_keys}; fn tls_config() -> ServerConfig { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); let cert_file = &mut BufReader::new(cert_file.as_bytes()); let key_file = &mut BufReader::new(key_file.as_bytes()); diff --git a/awc/tests/test_ssl_client.rs b/awc/tests/test_ssl_client.rs index 5273c3fff..95d4c15f1 100644 --- a/awc/tests/test_ssl_client.rs +++ b/awc/tests/test_ssl_client.rs @@ -19,9 +19,11 @@ use openssl::{ }; fn tls_config() -> SslAcceptor { - let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap(); - let cert_file = cert.serialize_pem().unwrap(); - let key_file = cert.serialize_private_key_pem(); + let rcgen::CertifiedKey { cert, key_pair } = + rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap(); + let cert_file = cert.pem(); + let key_file = key_pair.serialize_pem(); + let cert = X509::from_pem(cert_file.as_bytes()).unwrap(); let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap(); From fe7268487aa89fe92fac92a547c9fd23dd37508e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:14:30 +0100 Subject: [PATCH 256/314] chore(actix-http): prepare release 3.7.0 --- actix-http/CHANGES.md | 2 ++ actix-http/Cargo.toml | 2 +- actix-http/README.md | 4 ++-- actix-test/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index f7b20dd6a..61eeb4beb 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.7.0 + ### Added - Add `rustls-0_23` crate feature diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index c00c2ee04..57509defc 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-http" -version = "3.6.0" +version = "3.7.0" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-http/README.md b/actix-http/README.md index 3881b805d..0ba3fdcac 100644 --- a/actix-http/README.md +++ b/actix-http/README.md @@ -5,11 +5,11 @@ [![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=3.6.0)](https://docs.rs/actix-http/3.6.0) +[![Documentation](https://docs.rs/actix-http/badge.svg?version=3.7.0)](https://docs.rs/actix-http/3.7.0) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-http.svg)
-[![dependency status](https://deps.rs/crate/actix-http/3.6.0/status.svg)](https://deps.rs/crate/actix-http/3.6.0) +[![dependency status](https://deps.rs/crate/actix-http/3.7.0/status.svg)](https://deps.rs/crate/actix-http/3.7.0) [![Download](https://img.shields.io/crates/d/actix-http.svg)](https://crates.io/crates/actix-http) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 69ce080ad..23dde9cf0 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -37,7 +37,7 @@ openssl = ["tls-openssl", "actix-http/openssl", "awc/openssl"] [dependencies] actix-codec = "0.5" -actix-http = "3.6" +actix-http = "3.7" actix-http-test = "3" actix-rt = "2.1" actix-service = "2" diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index bd24ea35f..1faee7a42 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -94,7 +94,7 @@ actix-service = "2" actix-utils = "3" actix-tls = { version = "3.3", default-features = false, optional = true } -actix-http = { version = "3.6", features = ["ws"] } +actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5", default-features = false, features = ["http"] } actix-web-codegen = { version = "4.2", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index b1ee62361..f844db210 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -81,7 +81,7 @@ dangerous-h2c = [] [dependencies] actix-codec = "0.5" actix-service = "2" -actix-http = { version = "3.6", features = ["http2", "ws"] } +actix-http = { version = "3.7", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } actix-tls = { version = "3.3", features = ["connect", "uri"] } actix-utils = "3" @@ -116,7 +116,7 @@ tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, defau trust-dns-resolver = { version = "0.23", optional = true } [dev-dependencies] -actix-http = { version = "3.6", features = ["openssl"] } +actix-http = { version = "3.7", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } From 59115bca49bbbb539c6774d613165f424df29a49 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:15:48 +0100 Subject: [PATCH 257/314] chore(actix-web): prepare release 4.6.0 --- actix-test/Cargo.toml | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 23dde9cf0..3e96f06e5 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -42,7 +42,7 @@ actix-http-test = "3" actix-rt = "2.1" actix-service = "2" actix-utils = "3" -actix-web = { version = "4.5", default-features = false, features = ["cookies"] } +actix-web = { version = "4.6", default-features = false, features = ["cookies"] } awc = { version = "3.4", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 5b43a51d0..993c7c596 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.6.0 + ### Added - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 1faee7a42..cf4da74f0 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.5.1" +version = "4.6.0" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index 35e07fc0b..4e7e785a5 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.5.1)](https://docs.rs/actix-web/4.5.1) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.6.0)](https://docs.rs/actix-web/4.6.0) ![MSRV](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.5.1/status.svg)](https://deps.rs/crate/actix-web/4.5.1) +[![Dependency Status](https://deps.rs/crate/actix-web/4.6.0/status.svg)](https://deps.rs/crate/actix-web/4.6.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 9a437fe8357a74d4ab04e6df1c431d499a334413 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 10:16:16 +0100 Subject: [PATCH 258/314] chore(awc): prepare release 3.5.0 --- actix-test/Cargo.toml | 2 +- awc/CHANGES.md | 2 ++ awc/Cargo.toml | 2 +- awc/README.md | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 3e96f06e5..dddcabec9 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -43,7 +43,7 @@ actix-rt = "2.1" actix-service = "2" actix-utils = "3" actix-web = { version = "4.6", default-features = false, features = ["cookies"] } -awc = { version = "3.4", default-features = false, features = ["cookies"] } +awc = { version = "3.5", default-features = false, features = ["cookies"] } futures-core = { version = "0.3.17", default-features = false, features = ["std"] } futures-util = { version = "0.3.17", default-features = false, features = [] } diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 4031d2bda..54c5e9869 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 3.5.0 + - Add `rustls-0_23`, `rustls-0_23-webpki-roots`, and `rustls-0_23-native-roots` crate features. - Add `awc::Connector::rustls_0_23()` constructor. - Fix `rustls-0_22-native-roots` root store lookup diff --git a/awc/Cargo.toml b/awc/Cargo.toml index f844db210..58986f3e5 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "awc" -version = "3.4.0" +version = "3.5.0" authors = ["Nikolay Kim "] description = "Async HTTP and WebSocket client library" keywords = ["actix", "http", "framework", "async", "web"] diff --git a/awc/README.md b/awc/README.md index 19236b85a..8e7b42812 100644 --- a/awc/README.md +++ b/awc/README.md @@ -5,9 +5,9 @@ [![crates.io](https://img.shields.io/crates/v/awc?label=latest)](https://crates.io/crates/awc) -[![Documentation](https://docs.rs/awc/badge.svg?version=3.4.0)](https://docs.rs/awc/3.4.0) +[![Documentation](https://docs.rs/awc/badge.svg?version=3.5.0)](https://docs.rs/awc/3.5.0) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/awc) -[![Dependency Status](https://deps.rs/crate/awc/3.4.0/status.svg)](https://deps.rs/crate/awc/3.4.0) +[![Dependency Status](https://deps.rs/crate/awc/3.5.0/status.svg)](https://deps.rs/crate/awc/3.5.0) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From acb740584c759499000cc19d322d4f0293389631 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 11:55:12 +0100 Subject: [PATCH 259/314] fix: correct aws rustls v0.23 feature gating --- actix-http/Cargo.toml | 2 +- actix-web/Cargo.toml | 2 +- awc/Cargo.toml | 4 ++-- awc/src/client/connector.rs | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 57509defc..a999e73c8 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -115,7 +115,7 @@ rand = { version = "0.8", optional = true } sha1 = { version = "0.10", optional = true } # openssl/rustls -actix-tls = { version = "3.3", default-features = false, optional = true } +actix-tls = { version = "3.4", default-features = false, optional = true } # compress-* brotli = { version = "6", optional = true } diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index cf4da74f0..32fcc0609 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -92,7 +92,7 @@ actix-rt = { version = "2.6", default-features = false } actix-server = "2" actix-service = "2" actix-utils = "3" -actix-tls = { version = "3.3", default-features = false, optional = true } +actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5", default-features = false, features = ["http"] } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 58986f3e5..f51b3904b 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -83,7 +83,7 @@ actix-codec = "0.5" actix-service = "2" actix-http = { version = "3.7", features = ["http2", "ws"] } actix-rt = { version = "2.1", default-features = false } -actix-tls = { version = "3.3", features = ["connect", "uri"] } +actix-tls = { version = "3.4", features = ["connect", "uri"] } actix-utils = "3" base64 = "0.22" @@ -120,7 +120,7 @@ actix-http = { version = "3.7", features = ["openssl"] } actix-http-test = { version = "3", features = ["openssl"] } actix-server = "2" actix-test = { version = "0.1", features = ["openssl", "rustls-0_23"] } -actix-tls = { version = "3.3", features = ["openssl", "rustls-0_23"] } +actix-tls = { version = "3.4", features = ["openssl", "rustls-0_23"] } actix-utils = "3" actix-web = { version = "4", features = ["openssl"] } diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index fbe50b65c..5d0b655a4 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -131,7 +131,6 @@ impl Connector<()> { OurTlsConnector::Rustls023(std::sync::Arc::new(config)) } - } else if #[cfg(any(feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots"))] { /// Build TLS connector with Rustls v0.22, based on supplied ALPN protocols. fn build_tls(protocols: Vec>) -> OurTlsConnector { @@ -743,6 +742,9 @@ where feature = "rustls-0_21", feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots", + feature = "rustls-0_23", + feature = "rustls-0_23-webpki-roots", + feature = "rustls-0_23-native-roots" ))] struct TlsConnectorService { /// TCP connection is canceled on `TcpConnectorInnerService`'s timeout setting. @@ -761,6 +763,7 @@ struct TlsConnectorService { feature = "rustls-0_21", feature = "rustls-0_22-webpki-roots", feature = "rustls-0_22-native-roots", + feature = "rustls-0_23", ))] impl Service for TlsConnectorService where From 804a3445658cc946e52632457b2807cac660f2d5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 12:06:20 +0100 Subject: [PATCH 260/314] ci: limit cargo hack concurrency --- .cargo/config.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 6d5a8b810..a2345e184 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -6,5 +6,5 @@ lint-all = "clippy --workspace --all-features --all-targets -- -Dclippy::todo" ci-check-min = "hack --workspace check --no-default-features" ci-check-default = "hack --workspace check" ci-check-default-tests = "check --workspace --tests" -ci-check-all-feature-powerset="hack --workspace --feature-powerset --skip=__compress,experimental-io-uring check" -ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --skip=__compress check" +ci-check-all-feature-powerset="hack --workspace --feature-powerset --depth=4 --skip=__compress,experimental-io-uring check" +ci-check-all-feature-powerset-linux="hack --workspace --feature-powerset --depth=4 --skip=__compress check" From b342b8fc82317365dd9e43659601345d86ba065d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 12:09:46 +0100 Subject: [PATCH 261/314] chore(actix-router): prepare release 0.5.3 --- actix-router/CHANGES.md | 2 ++ actix-router/Cargo.toml | 2 +- actix-router/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-router/CHANGES.md b/actix-router/CHANGES.md index 8aa3c8639..6305b45c3 100644 --- a/actix-router/CHANGES.md +++ b/actix-router/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.5.3 + - Add `unicode` crate feature (on-by-default) to switch between `regex` and `regex-lite` as a trade-off between full unicode support and binary size. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index 0b02e84b9..56e4bed2f 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-router" -version = "0.5.2" +version = "0.5.3" authors = [ "Nikolay Kim ", "Ali MJ Al-Nasrawy ", diff --git a/actix-router/README.md b/actix-router/README.md index 751c307b1..12d1b0146 100644 --- a/actix-router/README.md +++ b/actix-router/README.md @@ -3,11 +3,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-router?label=latest)](https://crates.io/crates/actix-router) -[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.2)](https://docs.rs/actix-router/0.5.2) +[![Documentation](https://docs.rs/actix-router/badge.svg?version=0.5.3)](https://docs.rs/actix-router/0.5.3) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-router.svg)
-[![dependency status](https://deps.rs/crate/actix-router/0.5.2/status.svg)](https://deps.rs/crate/actix-router/0.5.2) +[![dependency status](https://deps.rs/crate/actix-router/0.5.3/status.svg)](https://deps.rs/crate/actix-router/0.5.3) [![Download](https://img.shields.io/crates/d/actix-router.svg)](https://crates.io/crates/actix-router) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 32fcc0609..9f3ab6e5e 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -95,7 +95,7 @@ actix-utils = "3" actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } -actix-router = { version = "0.5", default-features = false, features = ["http"] } +actix-router = { version = "0.5.3", default-features = false, features = ["http"] } actix-web-codegen = { version = "4.2", optional = true } ahash = "0.8" From fdff3775a8625588d7a55a8ec0ad471308f4ae6f Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 19 May 2024 20:24:33 +0100 Subject: [PATCH 262/314] ci: use mold linker (#3370) --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56333e187..a81f0e8ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,10 @@ jobs: echo 'OPENSSL_DIR=C:\Program Files\OpenSSL' >> $GITHUB_ENV echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV + - name: Setup mold linker + if: matrix.target.os == 'ubuntu-latest' + uses: rui314/setup-mold@v1 + - name: Install Rust (${{ matrix.version.name }}) uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: From 4f7b334d8054041296b94cdcedd162017e2869dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:27:44 +0100 Subject: [PATCH 263/314] build(deps): bump taiki-e/install-action from 2.33.22 to 2.33.26 (#3376) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.22 to 2.33.26. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.22...v2.33.26) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 8d509d691..dfb0ca56d 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a81f0e8ed..153ab78f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 943f63223..5eaaae8bf 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 03b25ecda..39392fabb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.22 + uses: taiki-e/install-action@v2.33.26 with: tool: cargo-public-api From d4bcdf28f24728edadaa584dfc31eabcb8ca1bdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:30:27 +0100 Subject: [PATCH 264/314] build(deps): bump JamesIves/github-pages-deploy-action from 4.6.0 to 4.6.1 (#3375) build(deps): bump JamesIves/github-pages-deploy-action Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/v4.6.0...v4.6.1) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .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 6352e44d2..b38a80e5b 100644 --- a/.github/workflows/upload-doc.yml +++ b/.github/workflows/upload-doc.yml @@ -35,7 +35,7 @@ jobs: run: echo '' > target/doc/index.html - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.6.0 + uses: JamesIves/github-pages-deploy-action@v4.6.1 with: folder: target/doc single-commit: true From 1b214bc5f5160f8754f1e3fc77039156d7347793 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 10:30:48 +0100 Subject: [PATCH 265/314] build(deps): bump codecov/codecov-action from 4.3.1 to 4.4.0 (#3374) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.3.1 to 4.4.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.3.1...v4.4.0) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5eaaae8bf..ce370b105 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.3.1 + uses: codecov/codecov-action@v4.4.0 with: files: codecov.json fail_ci_if_error: true From cc06fd6a5e6881885961156fc112e31f1ddcb5f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:57:59 +0000 Subject: [PATCH 266/314] build(deps): bump codecov/codecov-action from 4.4.0 to 4.4.1 (#3381) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4.4.0 to 4.4.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4.4.0...v4.4.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ce370b105..8d9494e3e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -31,7 +31,7 @@ jobs: run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4.4.0 + uses: codecov/codecov-action@v4.4.1 with: files: codecov.json fail_ci_if_error: true From 26efa64278ccb0ec2a0d49f0364c9d7930bb57f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 00:58:18 +0000 Subject: [PATCH 267/314] build(deps): bump taiki-e/install-action from 2.33.26 to 2.33.34 (#3380) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.26 to 2.33.34. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.26...v2.33.34) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index dfb0ca56d..4e4f266b6 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 153ab78f7..1f7a5d812 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 8d9494e3e..ff1767fb3 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install cargo-llvm-cov - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 39392fabb..630f0604c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.26 + uses: taiki-e/install-action@v2.33.34 with: tool: cargo-public-api From 3ce97effa22e4e9ad4dc719d7791b665abf2c9eb Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 28 May 2024 01:21:23 +0100 Subject: [PATCH 268/314] ci: delete upload doc workflow --- .github/workflows/coverage.yml | 4 ++-- .github/workflows/upload-doc.yml | 41 -------------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 .github/workflows/upload-doc.yml diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ff1767fb3..d3467c698 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -22,10 +22,10 @@ jobs: with: components: llvm-tools-preview - - name: Install cargo-llvm-cov + - name: Install just,cargo-llvm-cov uses: taiki-e/install-action@v2.33.34 with: - tool: cargo-llvm-cov + tool: just,cargo-llvm-cov - name: Generate code coverage run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml deleted file mode 100644 index b38a80e5b..000000000 --- a/.github/workflows/upload-doc.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Upload Documentation - -on: - push: - branches: [master] - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - build: - permissions: - contents: write - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - with: - toolchain: nightly - - - name: Build Docs - run: cargo +nightly doc --no-deps --workspace --all-features - env: - RUSTDOCFLAGS: --cfg=docsrs - - - name: Tweak HTML - run: echo '' > target/doc/index.html - - - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@v4.6.1 - with: - folder: target/doc - single-commit: true From dd84bcb6095aba3b95939a30b7209390ce90f9db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 02:24:09 +0100 Subject: [PATCH 269/314] build(deps): bump taiki-e/install-action from 2.33.34 to 2.34.0 (#3386) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.33.34 to 2.34.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.33.34...v2.34.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4e4f266b6..4231b4dc2 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f7a5d812..ed2930bc6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index d3467c698..da892bd7a 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install just,cargo-llvm-cov - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: just,cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 630f0604c..629396986 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-04-26 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.33.34 + uses: taiki-e/install-action@v2.34.0 with: tool: cargo-public-api From 5c18569b7896f0816b72efa172600a898e596281 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:17:10 +0100 Subject: [PATCH 270/314] docs: align App:app_data arg name --- actix-web/src/app.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-web/src/app.rs b/actix-web/src/app.rs index 1a3b79086..3d86d1f9b 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -112,8 +112,8 @@ where /// }) /// ``` #[doc(alias = "manage")] - pub fn app_data(mut self, ext: U) -> Self { - self.extensions.insert(ext); + pub fn app_data(mut self, data: U) -> Self { + self.extensions.insert(data); self } From ebd8bb266d07828d3556ee10ee8a4c3d9bd0d98e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:31:17 +0100 Subject: [PATCH 271/314] ci: fix cargo-public-api --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 629396986..d7a16ccb4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -79,7 +79,7 @@ jobs: - name: Install Rust uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 with: - toolchain: nightly-2024-04-26 + toolchain: nightly-2024-06-07 - name: Install cargo-public-api uses: taiki-e/install-action@v2.34.0 From 85655f731d9d23f9b472b0a2ace817031c8c5e8d Mon Sep 17 00:00:00 2001 From: Abedi Date: Fri, 7 Jun 2024 17:25:29 +0330 Subject: [PATCH 272/314] From Boxed ResponseError impl added (#3388) * From Boxed ResponseError impl added * docs: update changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/error/error.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 993c7c596..e0390563c 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Implement `From>` for `Error`. + ## 4.6.0 ### Added diff --git a/actix-web/src/error/error.rs b/actix-web/src/error/error.rs index 3a5a128f6..670a58a00 100644 --- a/actix-web/src/error/error.rs +++ b/actix-web/src/error/error.rs @@ -60,6 +60,12 @@ impl From for Error { } } +impl From> for Error { + fn from(value: Box) -> Self { + Error { cause: value } + } +} + impl From for Response { fn from(err: Error) -> Response { err.error_response().into() From b2d0196f342f0f90a9e9e32584f0826bebed4891 Mon Sep 17 00:00:00 2001 From: Dylan Anthony <43723790+dbanty@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:08:13 -0600 Subject: [PATCH 273/314] Do not require actix-router default features from actix-web-codegen (#3372) * fix: Do not require actix-router default features from actix-web-codegen * docs: update changelog * test: update trybuild stderr --------- Co-authored-by: Dylan Anthony Co-authored-by: Rob Ede --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/Cargo.toml | 2 +- .../tests/trybuild/route-malformed-path-fail.stderr | 5 +---- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index a5acdd21c..875c4021e 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. ## 4.2.2 diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 4a45d4fef..31c470694 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -16,7 +16,7 @@ rust-version.workspace = true proc-macro = true [dependencies] -actix-router = "0.5" +actix-router = { version = "0.5", default-features = false } proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full", "extra-traits"] } diff --git a/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr b/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr index 93c510109..c1100c784 100644 --- a/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr +++ b/actix-web-codegen/tests/trybuild/route-malformed-path-fail.stderr @@ -20,10 +20,7 @@ error: custom attribute panicked 13 | #[get("/{}")] | ^^^^^^^^^^^^^ | - = help: message: Wrong path pattern: "/{}" regex parse error: - ((?s-m)^/(?P<>[^/]+))$ - ^ - error: empty capture group name + = help: message: Wrong path pattern: "/{}" empty capture group names are not allowed error: custom attribute panicked --> $DIR/route-malformed-path-fail.rs:23:1 From 8fdf35895478b2ed5f08651e123922c012ae2937 Mon Sep 17 00:00:00 2001 From: Raphael C Date: Fri, 7 Jun 2024 16:31:53 +0200 Subject: [PATCH 274/314] Add app_data method to GuardContext (#3341) * changes: guard * fix(guard): docs link to app_data * docs: fix changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/guard/mod.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index e0390563c..757fdce68 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. ## 4.6.0 diff --git a/actix-web/src/guard/mod.rs b/actix-web/src/guard/mod.rs index 9451a60f9..41609953a 100644 --- a/actix-web/src/guard/mod.rs +++ b/actix-web/src/guard/mod.rs @@ -110,6 +110,12 @@ impl<'a> GuardContext<'a> { pub fn header(&self) -> Option { H::parse(self.req).ok() } + + /// Counterpart to [HttpRequest::app_data](crate::HttpRequest::app_data). + #[inline] + pub fn app_data(&self) -> Option<&T> { + self.req.app_data() + } } /// Interface for routing guards. @@ -512,4 +518,18 @@ mod tests { .to_srv_request(); assert!(guard.check(&req.guard_ctx())); } + + #[test] + fn app_data() { + const TEST_VALUE: u32 = 42; + let guard = fn_guard(|ctx| dbg!(ctx.app_data::()) == Some(&TEST_VALUE)); + + let req = TestRequest::default().app_data(TEST_VALUE).to_srv_request(); + assert!(guard.check(&req.guard_ctx())); + + let req = TestRequest::default() + .app_data(TEST_VALUE * 2) + .to_srv_request(); + assert!(!guard.check(&req.guard_ctx())); + } } From 8b4d23a69a0cdf5ac9a32d59ab2b3cbb21b71ffa Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Sat, 8 Jun 2024 00:40:55 +1000 Subject: [PATCH 275/314] Allow disabling redirect following in actix-test (#3356) If you're testing that redirects are being properly generated, then it's useful to not have the client go off on a wild goose chase of its own. Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 3 ++- actix-test/src/lib.rs | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index b55a8305c..940b595c0 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -3,8 +3,9 @@ ## Unreleased - Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. -- Minimum supported Rust version (MSRV) is now 1.72. +- Add `TestServerConfig::disable_redirects()` method. - Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. +- Minimum supported Rust version (MSRV) is now 1.72. ## 0.1.3 diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 1c3d8ff11..433f14571 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -149,6 +149,8 @@ where StreamType::Rustls023(_) => true, }; + let client_cfg = cfg.clone(); + // run server in separate orphaned thread thread::spawn(move || { rt::System::new().block_on(async move { @@ -460,7 +462,13 @@ where } }; - Client::builder().connector(connector).finish() + let mut client_builder = Client::builder().connector(connector); + + if client_cfg.disable_redirects { + client_builder = client_builder.disable_redirects(); + } + + client_builder.finish() }; TestServer { @@ -507,6 +515,7 @@ pub struct TestServerConfig { client_request_timeout: Duration, port: u16, workers: usize, + disable_redirects: bool, } impl Default for TestServerConfig { @@ -524,6 +533,7 @@ impl TestServerConfig { client_request_timeout: Duration::from_secs(5), port: 0, workers: 1, + disable_redirects: false, } } @@ -611,6 +621,15 @@ impl TestServerConfig { self.workers = workers; self } + + /// Instruct the client to not follow redirects. + /// + /// By default, the client will follow up to 10 consecutive redirects + /// before giving up. + pub fn disable_redirects(mut self) -> Self { + self.disable_redirects = true; + self + } } /// A basic HTTP server controller that simplifies the process of writing integration tests for From 4493aa35d006c8a479db2b1410802461655eba25 Mon Sep 17 00:00:00 2001 From: asonix Date: Fri, 7 Jun 2024 09:41:32 -0500 Subject: [PATCH 276/314] actix-http::ws: Remove redundant + 4 byte reservation when masked (#3371) * actix-http::ws: Remove redundant + 4 byte reservation when masked * actix-http: Update CHANGES wrt byte fix * docs: remove changelog entry --------- Co-authored-by: Rob Ede --- actix-http/src/ws/frame.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs index c9fb0cde9..35b3f8e66 100644 --- a/actix-http/src/ws/frame.rs +++ b/actix-http/src/ws/frame.rs @@ -178,14 +178,14 @@ impl Parser { }; if payload_len < 126 { - dst.reserve(p_len + 2 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 2); dst.put_slice(&[one, two | payload_len as u8]); } else if payload_len <= 65_535 { - dst.reserve(p_len + 4 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 4); dst.put_slice(&[one, two | 126]); dst.put_u16(payload_len as u16); } else { - dst.reserve(p_len + 10 + if mask { 4 } else { 0 }); + dst.reserve(p_len + 10); dst.put_slice(&[one, two | 127]); dst.put_u64(payload_len as u64); }; From 5221c1b19452cd98fa03882374295b56fa9af327 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 14:51:05 +0100 Subject: [PATCH 277/314] ci: pin msrv lookup job --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed2930bc6..ab611fc0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: read_msrv: name: Read MSRV - uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@main + uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@v0.1.0 build_and_test: needs: read_msrv From b9305ff59db29f6ce20740ef2ad5db3e4b60ffe5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:04:04 +0100 Subject: [PATCH 278/314] chore: fmt --- actix-multipart/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 83947b0c2..35c7f9a1f 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -15,7 +15,6 @@ - ## Example Dependencies: @@ -65,6 +64,7 @@ async fn main() -> std::io::Result<()> { ``` Curl request : + ```bash curl -v --request POST \ --url http://localhost:8080/videos \ @@ -72,7 +72,6 @@ curl -v --request POST \ -F file=@./Cargo.lock ``` - ### Examples -https://github.com/actix/examples/tree/master/forms/multipart \ No newline at end of file +https://github.com/actix/examples/tree/master/forms/multipart From cff958e5187b4980d8a87c2a886a284ccbd3d9b2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:10:25 +0100 Subject: [PATCH 279/314] chore: address clippy lint --- actix-test/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 433f14571..48d5079a7 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -488,6 +488,7 @@ enum HttpVer { Both, } +#[allow(clippy::large_enum_variant)] #[derive(Clone)] enum StreamType { Tcp, From 534cfe1fda1d65b9cea7d75a0a8c55f46439bb4e Mon Sep 17 00:00:00 2001 From: Sebastian Detert Date: Fri, 7 Jun 2024 17:22:48 +0200 Subject: [PATCH 280/314] feat: add .customize().add_cookie() (#3215) * feat: add .customize().add_cookie() * docs: added cookie hint * fix: added unwrap to test of add_cookie() * docs: added changelog entry for .customize().add_cookie() * chore: make append_header infallible * docs: update changelog --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/response/customize_responder.rs | 42 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 757fdce68..75f3631c9 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. diff --git a/actix-web/src/response/customize_responder.rs b/actix-web/src/response/customize_responder.rs index 4cbd96e20..6a43ac5e6 100644 --- a/actix-web/src/response/customize_responder.rs +++ b/actix-web/src/response/customize_responder.rs @@ -7,7 +7,7 @@ use actix_http::{ use crate::{HttpRequest, HttpResponse, Responder}; -/// Allows overriding status code and headers for a [`Responder`]. +/// Allows overriding status code and headers (including cookies) for a [`Responder`]. /// /// Created by calling the [`customize`](Responder::customize) method on a [`Responder`] type. pub struct CustomizeResponder { @@ -137,6 +137,29 @@ impl CustomizeResponder { Some(&mut self.inner) } } + + /// Appends a `cookie` to the final response. + /// + /// # Errors + /// + /// Final response will be an error if `cookie` cannot be converted into a valid header value. + #[cfg(feature = "cookies")] + pub fn add_cookie(mut self, cookie: &crate::cookie::Cookie<'_>) -> Self { + use actix_http::header::{TryIntoHeaderValue as _, SET_COOKIE}; + + if let Some(inner) = self.inner() { + match cookie.to_string().try_into_value() { + Ok(val) => { + inner.append_headers.append(SET_COOKIE, val); + } + Err(err) => { + self.error = Some(err.into()); + } + } + } + + self + } } impl Responder for CustomizeResponder @@ -175,6 +198,7 @@ mod tests { use super::*; use crate::{ + cookie::Cookie, http::header::{HeaderValue, CONTENT_TYPE}, test::TestRequest, }; @@ -209,6 +233,22 @@ mod tests { to_bytes(res.into_body()).await.unwrap(), Bytes::from_static(b"test"), ); + + let res = "test" + .to_string() + .customize() + .add_cookie(&Cookie::new("name", "value")) + .respond_to(&req); + + assert!(res.status().is_success()); + assert_eq!( + res.cookies().collect::>>(), + vec![Cookie::new("name", "value")], + ); + assert_eq!( + to_bytes(res.into_body()).await.unwrap(), + Bytes::from_static(b"test"), + ); } #[actix_rt::test] From c366649516dcd1d780ca8b7938397dac61338c15 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Fri, 7 Jun 2024 16:57:03 +0100 Subject: [PATCH 281/314] docs: example of CPU core pinning --- actix-web/Cargo.toml | 2 +- actix-web/examples/worker-cpu-pin.rs | 41 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 actix-web/examples/worker-cpu-pin.rs diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 9f3ab6e5e..a666f14be 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -35,7 +35,6 @@ features = [ "secure-cookies", ] - [lib] name = "actix_web" path = "src/lib.rs" @@ -130,6 +129,7 @@ awc = { version = "3", features = ["openssl"] } brotli = "6" const-str = "0.5" +core_affinity = "0.8" criterion = { version = "0.5", features = ["html_reports"] } env_logger = "0.11" flate2 = "1.0.13" diff --git a/actix-web/examples/worker-cpu-pin.rs b/actix-web/examples/worker-cpu-pin.rs new file mode 100644 index 000000000..58e060821 --- /dev/null +++ b/actix-web/examples/worker-cpu-pin.rs @@ -0,0 +1,41 @@ +use std::{ + io, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, + thread, +}; + +use actix_web::{middleware, web, App, HttpServer}; + +async fn hello() -> &'static str { + "Hello world!" +} + +#[actix_web::main] +async fn main() -> io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let core_ids = core_affinity::get_core_ids().unwrap(); + let n_core_ids = core_ids.len(); + let next_core_id = Arc::new(AtomicUsize::new(0)); + + HttpServer::new(move || { + let pin = Arc::clone(&next_core_id).fetch_add(1, Ordering::AcqRel); + log::info!( + "setting CPU affinity for worker {}: pinning to core {}", + thread::current().name().unwrap(), + pin, + ); + core_affinity::set_for_current(core_ids[pin]); + + App::new() + .wrap(middleware::Logger::default()) + .service(web::resource("/").get(hello)) + }) + .bind(("127.0.0.1", 8080))? + .workers(n_core_ids) + .run() + .await +} From 3db7891303093d5992cfd3483405b80b495b8f8e Mon Sep 17 00:00:00 2001 From: Jonathan Lim Date: Fri, 7 Jun 2024 15:10:48 -0700 Subject: [PATCH 282/314] Scope macro (#3136) * add scope proc macro * Update scope macro code to work with current HttpServiceFactory * started some test code * add some unit tests * code formatting cleanup * add another test for combining and calling 2 scopes * format code with formatter * Update actix-web-codegen/src/lib.rs with comment documentation fix Co-authored-by: oliver <151407407+kwfn@users.noreply.github.com> * work in progress. revised procedural macro to change othe macro call * add tests again. refactor nested code. * clean up code. fix bugs with route and method attributes with parameters * clean up for rust fmt * clean up for rust fmt * fix out of date comment for scope macro * sync to master branch by adding test_wrap * needed to format code * test: split out scope tests * test: add negative tests * chore: move imports back inside (?) * docs: tweak scope docs * fix: prevent trailing slashes in scope prefixes * chore: address clippy lints --------- Co-authored-by: oliver <151407407+kwfn@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/src/lib.rs | 50 +++++ actix-web-codegen/src/route.rs | 20 +- actix-web-codegen/src/scope.rs | 103 +++++++++ .../tests/{test_macro.rs => routes.rs} | 0 actix-web-codegen/tests/scopes.rs | 200 ++++++++++++++++++ actix-web-codegen/tests/trybuild.rs | 5 + .../tests/trybuild/scope-invalid-args.rs | 14 ++ .../tests/trybuild/scope-invalid-args.stderr | 17 ++ .../tests/trybuild/scope-missing-args.rs | 6 + .../tests/trybuild/scope-missing-args.stderr | 7 + .../tests/trybuild/scope-on-handler.rs | 8 + .../tests/trybuild/scope-on-handler.stderr | 5 + .../tests/trybuild/scope-trailing-slash.rs | 6 + .../trybuild/scope-trailing-slash.stderr | 5 + actix-web/src/lib.rs | 1 + awc/src/client/connector.rs | 2 +- justfile | 6 +- 18 files changed, 439 insertions(+), 17 deletions(-) create mode 100644 actix-web-codegen/src/scope.rs rename actix-web-codegen/tests/{test_macro.rs => routes.rs} (100%) create mode 100644 actix-web-codegen/tests/scopes.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-invalid-args.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-invalid-args.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-missing-args.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-missing-args.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-on-handler.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-on-handler.stderr create mode 100644 actix-web-codegen/tests/trybuild/scope-trailing-slash.rs create mode 100644 actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 875c4021e..792f6aa4f 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Add `#[scope]` macro. - Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 6d6c9ab5c..c518007a0 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -83,6 +83,7 @@ use proc_macro::TokenStream; use quote::quote; mod route; +mod scope; /// Creates resource handler, allowing multiple HTTP method guards. /// @@ -197,6 +198,43 @@ method_macro!(Options, options); method_macro!(Trace, trace); method_macro!(Patch, patch); +/// Prepends a path prefix to all handlers using routing macros inside the attached module. +/// +/// # Syntax +/// +/// ``` +/// # use actix_web_codegen::scope; +/// #[scope("/prefix")] +/// mod api { +/// // ... +/// } +/// ``` +/// +/// # Arguments +/// +/// - `"/prefix"` - Raw literal string to be prefixed onto contained handlers' paths. +/// +/// # Example +/// +/// ``` +/// # use actix_web_codegen::{scope, get}; +/// # use actix_web::Responder; +/// #[scope("/api")] +/// mod api { +/// # use super::*; +/// #[get("/hello")] +/// pub async fn hello() -> impl Responder { +/// // this has path /api/hello +/// "Hello, world!" +/// } +/// } +/// # fn main() {} +/// ``` +#[proc_macro_attribute] +pub fn scope(args: TokenStream, input: TokenStream) -> TokenStream { + scope::with_scope(args, input) +} + /// Marks async main function as the Actix Web system entry-point. /// /// Note that Actix Web also works under `#[tokio::main]` since version 4.0. However, this macro is @@ -240,3 +278,15 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream { output.extend(item); output } + +/// Converts the error to a token stream and appends it to the original input. +/// +/// Returning the original input in addition to the error is good for IDEs which can gracefully +/// recover and show more precise errors within the macro body. +/// +/// See for more info. +fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream { + let compile_err = TokenStream::from(err.to_compile_error()); + item.extend(compile_err); + item +} diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 7a2dfc051..d0605fc04 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -6,10 +6,12 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token}; +use crate::input_and_compile_error; + #[derive(Debug)] pub struct RouteArgs { - path: syn::LitStr, - options: Punctuated, + pub(crate) path: syn::LitStr, + pub(crate) options: Punctuated, } impl syn::parse::Parse for RouteArgs { @@ -78,7 +80,7 @@ macro_rules! standard_method_type { } } - fn from_path(method: &Path) -> Result { + pub(crate) fn from_path(method: &Path) -> Result { match () { $(_ if method.is_ident(stringify!($lower)) => Ok(Self::$variant),)+ _ => Err(()), @@ -542,15 +544,3 @@ pub(crate) fn with_methods(input: TokenStream) -> TokenStream { Err(err) => input_and_compile_error(input, err), } } - -/// Converts the error to a token stream and appends it to the original input. -/// -/// Returning the original input in addition to the error is good for IDEs which can gracefully -/// recover and show more precise errors within the macro body. -/// -/// See for more info. -fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStream { - let compile_err = TokenStream::from(err.to_compile_error()); - item.extend(compile_err); - item -} diff --git a/actix-web-codegen/src/scope.rs b/actix-web-codegen/src/scope.rs new file mode 100644 index 000000000..067d95a60 --- /dev/null +++ b/actix-web-codegen/src/scope.rs @@ -0,0 +1,103 @@ +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::{quote, ToTokens as _}; + +use crate::{ + input_and_compile_error, + route::{MethodType, RouteArgs}, +}; + +pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream { + match with_scope_inner(args, input.clone()) { + Ok(stream) => stream, + Err(err) => input_and_compile_error(input, err), + } +} + +fn with_scope_inner(args: TokenStream, input: TokenStream) -> syn::Result { + if args.is_empty() { + return Err(syn::Error::new( + Span::call_site(), + "missing arguments for scope macro, expected: #[scope(\"/prefix\")]", + )); + } + + let scope_prefix = syn::parse::(args.clone()).map_err(|err| { + syn::Error::new( + err.span(), + "argument to scope macro is not a string literal, expected: #[scope(\"/prefix\")]", + ) + })?; + + let scope_prefix_value = scope_prefix.value(); + + if scope_prefix_value.ends_with('/') { + // trailing slashes cause non-obvious problems + // it's better to point them out to developers rather than + + return Err(syn::Error::new( + scope_prefix.span(), + "scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes", + )); + } + + let mut module = syn::parse::(input).map_err(|err| { + syn::Error::new(err.span(), "#[scope] macro must be attached to a module") + })?; + + // modify any routing macros (method or route[s]) attached to + // functions by prefixing them with this scope macro's argument + if let Some((_, items)) = &mut module.content { + for item in items { + if let syn::Item::Fn(fun) = item { + fun.attrs = fun + .attrs + .iter() + .map(|attr| modify_attribute_with_scope(attr, &scope_prefix_value)) + .collect(); + } + } + } + + Ok(module.to_token_stream().into()) +} + +/// Checks if the attribute is a method type and has a route path, then modifies it. +fn modify_attribute_with_scope(attr: &syn::Attribute, scope_path: &str) -> syn::Attribute { + match (attr.parse_args::(), attr.clone().meta) { + (Ok(route_args), syn::Meta::List(meta_list)) if has_allowed_methods_in_scope(attr) => { + let modified_path = format!("{}{}", scope_path, route_args.path.value()); + + let options_tokens: Vec = route_args + .options + .iter() + .map(|option| { + quote! { ,#option } + }) + .collect(); + + let combined_options_tokens: TokenStream2 = + options_tokens + .into_iter() + .fold(TokenStream2::new(), |mut acc, ts| { + acc.extend(std::iter::once(ts)); + acc + }); + + syn::Attribute { + meta: syn::Meta::List(syn::MetaList { + tokens: quote! { #modified_path #combined_options_tokens }, + ..meta_list.clone() + }), + ..attr.clone() + } + } + _ => attr.clone(), + } +} + +fn has_allowed_methods_in_scope(attr: &syn::Attribute) -> bool { + MethodType::from_path(attr.path()).is_ok() + || attr.path().is_ident("route") + || attr.path().is_ident("ROUTE") +} diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/routes.rs similarity index 100% rename from actix-web-codegen/tests/test_macro.rs rename to actix-web-codegen/tests/routes.rs diff --git a/actix-web-codegen/tests/scopes.rs b/actix-web-codegen/tests/scopes.rs new file mode 100644 index 000000000..6a370a2e2 --- /dev/null +++ b/actix-web-codegen/tests/scopes.rs @@ -0,0 +1,200 @@ +use actix_web::{guard::GuardContext, http, http::header, web, App, HttpResponse, Responder}; +use actix_web_codegen::{delete, get, post, route, routes, scope}; + +pub fn image_guard(ctx: &GuardContext) -> bool { + ctx.header::() + .map(|h| h.preference() == "image/*") + .unwrap_or(false) +} + +#[scope("/test")] +mod scope_module { + // ensure that imports can be brought into the scope + use super::*; + + #[get("/test/guard", guard = "image_guard")] + pub async fn guard() -> impl Responder { + HttpResponse::Ok() + } + + #[get("/test")] + pub async fn test() -> impl Responder { + HttpResponse::Ok().finish() + } + + #[get("/twice-test/{value}")] + pub async fn twice(value: web::Path) -> impl actix_web::Responder { + let int_value: i32 = value.parse().unwrap_or(0); + let doubled = int_value * 2; + HttpResponse::Ok().body(format!("Twice value: {}", doubled)) + } + + #[post("/test")] + pub async fn post() -> impl Responder { + HttpResponse::Ok().body("post works") + } + + #[delete("/test")] + pub async fn delete() -> impl Responder { + "delete works" + } + + #[route("/test", method = "PUT", method = "PATCH", method = "CUSTOM")] + pub async fn multiple_shared_path() -> impl Responder { + HttpResponse::Ok().finish() + } + + #[routes] + #[head("/test1")] + #[connect("/test2")] + #[options("/test3")] + #[trace("/test4")] + async fn multiple_separate_paths() -> impl Responder { + HttpResponse::Ok().finish() + } + + // test calling this from other mod scope with scope attribute... + pub fn mod_common(message: String) -> impl actix_web::Responder { + HttpResponse::Ok().body(message) + } +} + +/// Scope doc string to check in cargo expand. +#[scope("/v1")] +mod mod_scope_v1 { + use super::*; + + /// Route doc string to check in cargo expand. + #[get("/test")] + pub async fn test() -> impl Responder { + scope_module::mod_common("version1 works".to_string()) + } +} + +#[scope("/v2")] +mod mod_scope_v2 { + use super::*; + + // check to make sure non-function tokens in the scope block are preserved... + enum TestEnum { + Works, + } + + #[get("/test")] + pub async fn test() -> impl Responder { + // make sure this type still exists... + let test_enum = TestEnum::Works; + + match test_enum { + TestEnum::Works => scope_module::mod_common("version2 works".to_string()), + } + } +} + +#[actix_rt::test] +async fn scope_get_async() { + let srv = actix_test::start(|| App::new().service(scope_module::test)); + + let request = srv.request(http::Method::GET, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_get_param_async() { + let srv = actix_test::start(|| App::new().service(scope_module::twice)); + + let request = srv.request(http::Method::GET, srv.url("/test/twice-test/4")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "Twice value: 8"); +} + +#[actix_rt::test] +async fn scope_post_async() { + let srv = actix_test::start(|| App::new().service(scope_module::post)); + + let request = srv.request(http::Method::POST, srv.url("/test/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "post works"); +} + +#[actix_rt::test] +async fn multiple_shared_path_async() { + let srv = actix_test::start(|| App::new().service(scope_module::multiple_shared_path)); + + let request = srv.request(http::Method::PUT, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::PATCH, srv.url("/test/test")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn multiple_multi_path_async() { + let srv = actix_test::start(|| App::new().service(scope_module::multiple_separate_paths)); + + let request = srv.request(http::Method::HEAD, srv.url("/test/test1")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::CONNECT, srv.url("/test/test2")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::OPTIONS, srv.url("/test/test3")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::TRACE, srv.url("/test/test4")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_delete_async() { + let srv = actix_test::start(|| App::new().service(scope_module::delete)); + + let request = srv.request(http::Method::DELETE, srv.url("/test/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "delete works"); +} + +#[actix_rt::test] +async fn scope_get_with_guard_async() { + let srv = actix_test::start(|| App::new().service(scope_module::guard)); + + let request = srv + .request(http::Method::GET, srv.url("/test/test/guard")) + .insert_header(("Accept", "image/*")); + let response = request.send().await.unwrap(); + assert!(response.status().is_success()); +} + +#[actix_rt::test] +async fn scope_v1_v2_async() { + let srv = actix_test::start(|| { + App::new() + .service(mod_scope_v1::test) + .service(mod_scope_v2::test) + }); + + let request = srv.request(http::Method::GET, srv.url("/v1/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "version1 works"); + + let request = srv.request(http::Method::GET, srv.url("/v2/test")); + let mut response = request.send().await.unwrap(); + let body = response.body().await.unwrap(); + let body_str = String::from_utf8(body.to_vec()).unwrap(); + assert_eq!(body_str, "version2 works"); +} diff --git a/actix-web-codegen/tests/trybuild.rs b/actix-web-codegen/tests/trybuild.rs index 88f77548b..91073cf3b 100644 --- a/actix-web-codegen/tests/trybuild.rs +++ b/actix-web-codegen/tests/trybuild.rs @@ -18,6 +18,11 @@ fn compile_macros() { t.compile_fail("tests/trybuild/routes-missing-method-fail.rs"); t.compile_fail("tests/trybuild/routes-missing-args-fail.rs"); + t.compile_fail("tests/trybuild/scope-on-handler.rs"); + t.compile_fail("tests/trybuild/scope-missing-args.rs"); + t.compile_fail("tests/trybuild/scope-invalid-args.rs"); + t.compile_fail("tests/trybuild/scope-trailing-slash.rs"); + t.pass("tests/trybuild/docstring-ok.rs"); t.pass("tests/trybuild/test-runtime.rs"); diff --git a/actix-web-codegen/tests/trybuild/scope-invalid-args.rs b/actix-web-codegen/tests/trybuild/scope-invalid-args.rs new file mode 100644 index 000000000..ec021d5eb --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-invalid-args.rs @@ -0,0 +1,14 @@ +use actix_web_codegen::scope; + +const PATH: &str = "/api"; + +#[scope(PATH)] +mod api_const {} + +#[scope(true)] +mod api_bool {} + +#[scope(123)] +mod api_num {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr b/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr new file mode 100644 index 000000000..0ab335966 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-invalid-args.stderr @@ -0,0 +1,17 @@ +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:5:9 + | +5 | #[scope(PATH)] + | ^^^^ + +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:8:9 + | +8 | #[scope(true)] + | ^^^^ + +error: argument to scope macro is not a string literal, expected: #[scope("/prefix")] + --> tests/trybuild/scope-invalid-args.rs:11:9 + | +11 | #[scope(123)] + | ^^^ diff --git a/actix-web-codegen/tests/trybuild/scope-missing-args.rs b/actix-web-codegen/tests/trybuild/scope-missing-args.rs new file mode 100644 index 000000000..39bcb9d1a --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-missing-args.rs @@ -0,0 +1,6 @@ +use actix_web_codegen::scope; + +#[scope] +mod api {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-missing-args.stderr b/actix-web-codegen/tests/trybuild/scope-missing-args.stderr new file mode 100644 index 000000000..d59842e39 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-missing-args.stderr @@ -0,0 +1,7 @@ +error: missing arguments for scope macro, expected: #[scope("/prefix")] + --> tests/trybuild/scope-missing-args.rs:3:1 + | +3 | #[scope] + | ^^^^^^^^ + | + = note: this error originates in the attribute macro `scope` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/actix-web-codegen/tests/trybuild/scope-on-handler.rs b/actix-web-codegen/tests/trybuild/scope-on-handler.rs new file mode 100644 index 000000000..e5d478981 --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-on-handler.rs @@ -0,0 +1,8 @@ +use actix_web_codegen::scope; + +#[scope("/api")] +async fn index() -> &'static str { + "Hello World!" +} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-on-handler.stderr b/actix-web-codegen/tests/trybuild/scope-on-handler.stderr new file mode 100644 index 000000000..4491f42dd --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-on-handler.stderr @@ -0,0 +1,5 @@ +error: #[scope] macro must be attached to a module + --> tests/trybuild/scope-on-handler.rs:4:1 + | +4 | async fn index() -> &'static str { + | ^^^^^ diff --git a/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs b/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs new file mode 100644 index 000000000..84632b59f --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-trailing-slash.rs @@ -0,0 +1,6 @@ +use actix_web_codegen::scope; + +#[scope("/api/")] +mod api {} + +fn main() {} diff --git a/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr b/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr new file mode 100644 index 000000000..66933432e --- /dev/null +++ b/actix-web-codegen/tests/trybuild/scope-trailing-slash.stderr @@ -0,0 +1,5 @@ +error: scopes should not have trailing slashes; see https://docs.rs/actix-web/4/actix_web/struct.Scope.html#avoid-trailing-slashes + --> tests/trybuild/scope-trailing-slash.rs:3:9 + | +3 | #[scope("/api/")] + | ^^^^^^^ diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index f86a74406..205391388 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -145,5 +145,6 @@ codegen_reexport!(delete); codegen_reexport!(trace); codegen_reexport!(connect); codegen_reexport!(options); +codegen_reexport!(scope); pub(crate) type BoxError = Box; diff --git a/awc/src/client/connector.rs b/awc/src/client/connector.rs index 5d0b655a4..f3d443070 100644 --- a/awc/src/client/connector.rs +++ b/awc/src/client/connector.rs @@ -1080,7 +1080,7 @@ mod resolver { // resolver struct is cached in thread local so new clients can reuse the existing instance thread_local! { - static TRUST_DNS_RESOLVER: RefCell> = RefCell::new(None); + static TRUST_DNS_RESOLVER: RefCell> = const { RefCell::new(None) }; } // get from thread local or construct a new trust-dns resolver. diff --git a/justfile b/justfile index d92f4bd3d..4e106ef11 100644 --- a/justfile +++ b/justfile @@ -4,7 +4,7 @@ _list: # Format workspace. fmt: cargo +nightly fmt - npx -y prettier --write $(fd --type=file --hidden --extension=md --extension=yml) + fd --hidden --type=file --extension=md --extension=yml --exec-batch npx -y prettier --write # Downgrade dev-dependencies necessary to run MSRV checks/tests. [private] @@ -32,6 +32,10 @@ all_crate_features := if os() == "linux" { "--features='" + non_linux_all_features_list + "'" } +# Run Clippy over workspace. +clippy toolchain="": + cargo {{ toolchain }} clippy --workspace --all-targets {{ all_crate_features }} + # Test workspace using MSRV. test-msrv: downgrade-for-msrv (test msrv_rustup) From 7c4c26d2df5d344ae524a72f733fd3af0c13a3a2 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sat, 8 Jun 2024 05:26:26 +0100 Subject: [PATCH 283/314] feat: expose Identity middleware (#3390) --- .github/workflows/lint.yml | 2 +- actix-web/CHANGES.md | 1 + actix-web/src/middleware/compat.rs | 13 ++---------- actix-web/src/middleware/condition.rs | 4 ++-- .../src/middleware/{noop.rs => identity.rs} | 20 +++++++++++-------- actix-web/src/middleware/mod.rs | 16 ++++++--------- 6 files changed, 24 insertions(+), 32 deletions(-) rename actix-web/src/middleware/{noop.rs => identity.rs} (57%) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d7a16ccb4..dd44d4cb3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -89,5 +89,5 @@ jobs: - name: Generate API diff run: | for f in $(find -mindepth 2 -maxdepth 2 -name Cargo.toml); do - cargo public-api --manifest-path "$f" diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} + cargo public-api --manifest-path "$f" --simplified diff ${{ github.event.pull_request.base.sha }}..${{ github.sha }} done diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 75f3631c9..93fbbf465 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. - Implement `From>` for `Error`. diff --git a/actix-web/src/middleware/compat.rs b/actix-web/src/middleware/compat.rs index 7df510a5c..963dfdabb 100644 --- a/actix-web/src/middleware/compat.rs +++ b/actix-web/src/middleware/compat.rs @@ -38,15 +38,6 @@ pub struct Compat { transform: T, } -#[cfg(test)] -impl Compat { - pub(crate) fn noop() -> Self { - Self { - transform: super::Noop, - } - } -} - impl Compat { /// Wrap a middleware to give it broader compatibility. pub fn new(middleware: T) -> Self { @@ -152,7 +143,7 @@ mod tests { use crate::{ dev::ServiceRequest, http::StatusCode, - middleware::{self, Condition, Logger}, + middleware::{self, Condition, Identity, Logger}, test::{self, call_service, init_service, TestRequest}, web, App, HttpResponse, }; @@ -225,7 +216,7 @@ mod tests { async fn compat_noop_is_noop() { let srv = test::ok_service(); - let mw = Compat::noop() + let mw = Compat::new(Identity) .new_transform(srv.into_service()) .await .unwrap(); diff --git a/actix-web/src/middleware/condition.rs b/actix-web/src/middleware/condition.rs index 55c56d494..5ee4467d9 100644 --- a/actix-web/src/middleware/condition.rs +++ b/actix-web/src/middleware/condition.rs @@ -141,7 +141,7 @@ mod tests { header::{HeaderValue, CONTENT_TYPE}, StatusCode, }, - middleware::{self, ErrorHandlerResponse, ErrorHandlers}, + middleware::{self, ErrorHandlerResponse, ErrorHandlers, Identity}, test::{self, TestRequest}, web::Bytes, HttpResponse, @@ -158,7 +158,7 @@ mod tests { #[test] fn compat_with_builtin_middleware() { - let _ = Condition::new(true, middleware::Compat::noop()); + let _ = Condition::new(true, middleware::Compat::new(Identity)); let _ = Condition::new(true, middleware::Logger::default()); let _ = Condition::new(true, middleware::Compress::default()); let _ = Condition::new(true, middleware::NormalizePath::trim()); diff --git a/actix-web/src/middleware/noop.rs b/actix-web/src/middleware/identity.rs similarity index 57% rename from actix-web/src/middleware/noop.rs rename to actix-web/src/middleware/identity.rs index ae7da1d81..de374a57b 100644 --- a/actix-web/src/middleware/noop.rs +++ b/actix-web/src/middleware/identity.rs @@ -2,35 +2,39 @@ use actix_utils::future::{ready, Ready}; -use crate::dev::{Service, Transform}; +use crate::dev::{forward_ready, Service, Transform}; /// A no-op middleware that passes through request and response untouched. -pub(crate) struct Noop; +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct Identity; -impl, Req> Transform for Noop { +impl, Req> Transform for Identity { type Response = S::Response; type Error = S::Error; - type Transform = NoopService; + type Transform = IdentityMiddleware; type InitError = (); type Future = Ready>; + #[inline] fn new_transform(&self, service: S) -> Self::Future { - ready(Ok(NoopService { service })) + ready(Ok(IdentityMiddleware { service })) } } #[doc(hidden)] -pub(crate) struct NoopService { +pub struct IdentityMiddleware { service: S, } -impl, Req> Service for NoopService { +impl, Req> Service for IdentityMiddleware { type Response = S::Response; type Error = S::Error; type Future = S::Future; - crate::dev::forward_ready!(service); + forward_ready!(service); + #[inline] fn call(&self, req: Req) -> Self::Future { self.service.call(req) } diff --git a/actix-web/src/middleware/mod.rs b/actix-web/src/middleware/mod.rs index e924de261..1c27b1110 100644 --- a/actix-web/src/middleware/mod.rs +++ b/actix-web/src/middleware/mod.rs @@ -218,31 +218,27 @@ //! [lab_from_fn]: https://docs.rs/actix-web-lab/latest/actix_web_lab/middleware/fn.from_fn.html mod compat; +#[cfg(feature = "__compress")] +mod compress; mod condition; mod default_headers; mod err_handlers; +mod identity; mod logger; -#[cfg(test)] -mod noop; mod normalize; -#[cfg(test)] -pub(crate) use self::noop::Noop; +#[cfg(feature = "__compress")] +pub use self::compress::Compress; pub use self::{ compat::Compat, condition::Condition, default_headers::DefaultHeaders, err_handlers::{ErrorHandlerResponse, ErrorHandlers}, + identity::Identity, logger::Logger, normalize::{NormalizePath, TrailingSlash}, }; -#[cfg(feature = "__compress")] -mod compress; - -#[cfg(feature = "__compress")] -pub use self::compress::Compress; - #[cfg(test)] mod tests { use super::*; From ebc43dcf1b52ddf083090402b28392469ffa1997 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:10:15 +0100 Subject: [PATCH 284/314] feat: forwards-compatibility for handler visibility inheritance fix (#3391) --- actix-web-codegen/CHANGES.md | 1 + actix-web-codegen/Cargo.toml | 4 ++++ actix-web-codegen/src/route.rs | 9 ++++++++- actix-web-codegen/tests/scopes.rs | 2 +- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 26 ++++++++++++++++++++++---- awc/Cargo.toml | 2 +- 7 files changed, 39 insertions(+), 7 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 792f6aa4f..0a240680e 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -3,6 +3,7 @@ ## Unreleased - Add `#[scope]` macro. +- Add `compat-routing-macros-force-pub` crate feature which, on-by-default, which when disabled causes handlers to inherit their attached function's visibility. - Prevent inclusion of default `actix-router` features. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 31c470694..7eb995039 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -15,6 +15,10 @@ rust-version.workspace = true [lib] proc-macro = true +[features] +default = ["compat-routing-macros-force-pub"] +compat-routing-macros-force-pub = [] + [dependencies] actix-router = { version = "0.5", default-features = false } proc-macro2 = "1" diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index d0605fc04..e24903e3a 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -413,6 +413,13 @@ impl ToTokens for Route { doc_attributes, } = self; + #[allow(unused_variables)] // used when force-pub feature is disabled + let vis = &ast.vis; + + // TODO(breaking): remove this force-pub forwards-compatibility feature + #[cfg(feature = "compat-routing-macros-force-pub")] + let vis = syn::Visibility::Public(::default()); + let registrations: TokenStream2 = args .iter() .map(|args| { @@ -460,7 +467,7 @@ impl ToTokens for Route { let stream = quote! { #(#doc_attributes)* #[allow(non_camel_case_types, missing_docs)] - pub struct #name; + #vis struct #name; impl ::actix_web::dev::HttpServiceFactory for #name { fn register(self, __config: &mut actix_web::dev::AppService) { diff --git a/actix-web-codegen/tests/scopes.rs b/actix-web-codegen/tests/scopes.rs index 6a370a2e2..4ee6db16f 100644 --- a/actix-web-codegen/tests/scopes.rs +++ b/actix-web-codegen/tests/scopes.rs @@ -49,7 +49,7 @@ mod scope_module { #[connect("/test2")] #[options("/test3")] #[trace("/test4")] - async fn multiple_separate_paths() -> impl Responder { + pub async fn multiple_separate_paths() -> impl Responder { HttpResponse::Ok().finish() } diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 93fbbf465..97bdf29c2 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -7,6 +7,8 @@ - Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. +- Add `compat-routing-macros-force-pub` crate feature which (on-by-default) which, when disabled, causes handlers to inherit their attached function's visibility. +- Add `compat` crate feature group (on-by-default) which, when disabled, helps with transitioning to some planned v5.0 breaking changes, starting only with `compat-routing-macros-force-pub`. - Implement `From>` for `Error`. ## 4.6.0 diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index a666f14be..c36f317ce 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -40,7 +40,16 @@ name = "actix_web" path = "src/lib.rs" [features] -default = ["macros", "compress-brotli", "compress-gzip", "compress-zstd", "cookies", "http2", "unicode"] +default = [ + "macros", + "compress-brotli", + "compress-gzip", + "compress-zstd", + "cookies", + "http2", + "unicode", + "compat", +] # Brotli algorithm content-encoding support compress-brotli = ["actix-http/compress-brotli", "__compress"] @@ -50,14 +59,15 @@ compress-gzip = ["actix-http/compress-gzip", "__compress"] compress-zstd = ["actix-http/compress-zstd", "__compress"] # Routing and runtime proc macros -macros = ["actix-macros", "actix-web-codegen"] +macros = ["dep:actix-macros", "dep:actix-web-codegen"] # Cookies support -cookies = ["cookie"] +cookies = ["dep:cookie"] # Secure & signed cookies secure-cookies = ["cookies", "cookie/secure"] +# HTTP/2 support (including h2c). http2 = ["actix-http/http2"] # TLS via OpenSSL @@ -84,6 +94,14 @@ __compress = [] # io-uring feature only available for Linux OSes. experimental-io-uring = ["actix-server/io-uring"] +# Feature group which, when disabled, helps migrate code to v5.0. +compat = [ + "compat-routing-macros-force-pub", +] + +# Opt-out forwards-compatibility for handler visibility inheritance fix. +compat-routing-macros-force-pub = ["actix-web-codegen?/compat-routing-macros-force-pub"] + [dependencies] actix-codec = "0.5" actix-macros = { version = "0.2.3", optional = true } @@ -95,7 +113,7 @@ actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5.3", default-features = false, features = ["http"] } -actix-web-codegen = { version = "4.2", optional = true } +actix-web-codegen = { version = "4.2", optional = true, default-features = false } ahash = "0.8" bytes = "1" diff --git a/awc/Cargo.toml b/awc/Cargo.toml index f51b3904b..09f580aff 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -64,7 +64,7 @@ compress-gzip = ["actix-http/compress-gzip", "__compress"] compress-zstd = ["actix-http/compress-zstd", "__compress"] # Cookie parsing and cookie jar -cookies = ["cookie"] +cookies = ["dep:cookie"] # Use `trust-dns-resolver` crate as DNS resolver trust-dns = ["trust-dns-resolver"] From d6f885127d5d72096b9129085508b9af29c5cfee Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:16:36 +0100 Subject: [PATCH 285/314] chore(actix-test): prepare release 0.1.4 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 940b595c0..8088c2504 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.4 + - Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. - Add `TestServerConfig::disable_redirects()` method. - Various types from `awc`, such as `ClientRequest` and `ClientResponse`, are now re-exported. diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index dddcabec9..1ae619145 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.3" +version = "0.1.4" authors = [ "Nikolay Kim ", "Rob Ede ", From b4faf8820cb14a3648bb03385e0ceca844de8d9d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:19:09 +0100 Subject: [PATCH 286/314] chore(actix-web-codegen): prepare release 4.3.0 --- actix-web-codegen/CHANGES.md | 2 ++ actix-web-codegen/Cargo.toml | 2 +- actix-web-codegen/README.md | 4 ++-- actix-web/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/actix-web-codegen/CHANGES.md b/actix-web-codegen/CHANGES.md index 0a240680e..d143723f4 100644 --- a/actix-web-codegen/CHANGES.md +++ b/actix-web-codegen/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.3.0 + - Add `#[scope]` macro. - Add `compat-routing-macros-force-pub` crate feature which, on-by-default, which when disabled causes handlers to inherit their attached function's visibility. - Prevent inclusion of default `actix-router` features. diff --git a/actix-web-codegen/Cargo.toml b/actix-web-codegen/Cargo.toml index 7eb995039..7500807d2 100644 --- a/actix-web-codegen/Cargo.toml +++ b/actix-web-codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web-codegen" -version = "4.2.2" +version = "4.3.0" description = "Routing and runtime macros for Actix Web" authors = [ "Nikolay Kim ", diff --git a/actix-web-codegen/README.md b/actix-web-codegen/README.md index 9229f8f16..e61bf5c74 100644 --- a/actix-web-codegen/README.md +++ b/actix-web-codegen/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-web-codegen?label=latest)](https://crates.io/crates/actix-web-codegen) -[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.2.2)](https://docs.rs/actix-web-codegen/4.2.2) +[![Documentation](https://docs.rs/actix-web-codegen/badge.svg?version=4.3.0)](https://docs.rs/actix-web-codegen/4.3.0) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-web-codegen.svg)
-[![dependency status](https://deps.rs/crate/actix-web-codegen/4.2.2/status.svg)](https://deps.rs/crate/actix-web-codegen/4.2.2) +[![dependency status](https://deps.rs/crate/actix-web-codegen/4.3.0/status.svg)](https://deps.rs/crate/actix-web-codegen/4.3.0) [![Download](https://img.shields.io/crates/d/actix-web-codegen.svg)](https://crates.io/crates/actix-web-codegen) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index c36f317ce..243b91d29 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -113,7 +113,7 @@ actix-tls = { version = "3.4", default-features = false, optional = true } actix-http = { version = "3.7", features = ["ws"] } actix-router = { version = "0.5.3", default-features = false, features = ["http"] } -actix-web-codegen = { version = "4.2", optional = true, default-features = false } +actix-web-codegen = { version = "4.3", optional = true, default-features = false } ahash = "0.8" bytes = "1" From 12a0521ef88d13120363edeca484e75c98af8934 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:20:36 +0100 Subject: [PATCH 287/314] chore(actix-multipart): prepare release 0.6.2 --- actix-multipart/CHANGES.md | 2 ++ actix-multipart/Cargo.toml | 2 +- actix-multipart/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-multipart/CHANGES.md b/actix-multipart/CHANGES.md index 196d2ca93..a91edf9c8 100644 --- a/actix-multipart/CHANGES.md +++ b/actix-multipart/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.6.2 + - Add testing utilities under new module `test`. - Minimum supported Rust version (MSRV) is now 1.72. diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index 6e36c3391..f1289d3a2 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-multipart" -version = "0.6.1" +version = "0.6.2" authors = [ "Nikolay Kim ", "Jacob Halsey ", diff --git a/actix-multipart/README.md b/actix-multipart/README.md index 35c7f9a1f..c7697785a 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -5,11 +5,11 @@ [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) -[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.1)](https://docs.rs/actix-multipart/0.6.1) +[![Documentation](https://docs.rs/actix-multipart/badge.svg?version=0.6.2)](https://docs.rs/actix-multipart/0.6.2) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-multipart.svg)
-[![dependency status](https://deps.rs/crate/actix-multipart/0.6.1/status.svg)](https://deps.rs/crate/actix-multipart/0.6.1) +[![dependency status](https://deps.rs/crate/actix-multipart/0.6.2/status.svg)](https://deps.rs/crate/actix-multipart/0.6.2) [![Download](https://img.shields.io/crates/d/actix-multipart.svg)](https://crates.io/crates/actix-multipart) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From a5c78483f9d83d3f916d75c8a5ce46909faf32bc Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:22:03 +0100 Subject: [PATCH 288/314] chore(actix-web): prepare release 4.7.0 --- actix-web/CHANGES.md | 2 ++ actix-web/Cargo.toml | 2 +- actix-web/README.md | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 97bdf29c2..27259dc5c 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 4.7.0 + ### Added - Add `middleware::Identity` type. diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 243b91d29..10a507680 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-web" -version = "4.6.0" +version = "4.7.0" description = "Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust" authors = [ "Nikolay Kim ", diff --git a/actix-web/README.md b/actix-web/README.md index 4e7e785a5..8b4375bdd 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -8,10 +8,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=4.6.0)](https://docs.rs/actix-web/4.6.0) +[![Documentation](https://docs.rs/actix-web/badge.svg?version=4.7.0)](https://docs.rs/actix-web/4.7.0) ![MSRV](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-web.svg) -[![Dependency Status](https://deps.rs/crate/actix-web/4.6.0/status.svg)](https://deps.rs/crate/actix-web/4.6.0) +[![Dependency Status](https://deps.rs/crate/actix-web/4.7.0/status.svg)](https://deps.rs/crate/actix-web/4.7.0)
[![CI](https://github.com/actix/actix-web/actions/workflows/ci.yml/badge.svg)](https://github.com/actix/actix-web/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/actix/actix-web/branch/master/graph/badge.svg)](https://codecov.io/gh/actix/actix-web) From 40e1034566febd583ea7669e4fa76908e9bfe3ad Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 00:38:49 +0100 Subject: [PATCH 289/314] docs: update changelog --- actix-web/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 27259dc5c..4e74e0902 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -6,6 +6,7 @@ ### Added +- Add `#[scope]` macro. - Add `middleware::Identity` type. - Add `CustomizeResponder::add_cookie()` method. - Add `guard::GuardContext::app_data()` method. From 266834cf7c0e7b243b671b0b2ac41a20f8100286 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 04:51:53 +0100 Subject: [PATCH 290/314] chore: narrow h2 version --- actix-http/Cargo.toml | 2 +- awc/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index a999e73c8..87e2b391d 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -106,7 +106,7 @@ tokio-util = { version = "0.7", features = ["io", "codec"] } tracing = { version = "0.1.30", default-features = false, features = ["log"] } # http2 -h2 = { version = "0.3.24", optional = true } +h2 = { version = "0.3.26", optional = true } # websockets local-channel = { version = "0.1", optional = true } diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 09f580aff..6ab408ea6 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -92,7 +92,7 @@ cfg-if = "1" derive_more = "0.99.5" futures-core = { version = "0.3.17", default-features = false, features = ["alloc"] } futures-util = { version = "0.3.17", default-features = false, features = ["alloc", "sink"] } -h2 = "0.3.24" +h2 = "0.3.26" http = "0.2.7" itoa = "1" log =" 0.4" From 8018983a68742570d86bd8f5a0ba0b8ed389e75d Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 06:08:21 +0100 Subject: [PATCH 291/314] docs: update changelog for #3393 --- actix-http/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 61eeb4beb..85ba03100 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Add `error::InvalidStatusCode` re-export. + ## 3.7.0 ### Added From f7646bcc485f43ff4ba987cd613891883a081a07 Mon Sep 17 00:00:00 2001 From: asonix Date: Sun, 9 Jun 2024 00:04:42 -0500 Subject: [PATCH 292/314] actix-web-actors: take the internal buffer when yielding (#3369) * actix-web-actors: take the internal buffer when yielding * actix-web-actors: Add CHANGES entry re: taking buffer --- actix-web-actors/CHANGES.md | 1 + actix-web-actors/src/ws.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/actix-web-actors/CHANGES.md b/actix-web-actors/CHANGES.md index 9a622d8da..3e854c0b8 100644 --- a/actix-web-actors/CHANGES.md +++ b/actix-web-actors/CHANGES.md @@ -2,6 +2,7 @@ ## Unreleased +- Take the encoded buffer when yielding bytes in the response stream rather than splitting the buffer, reducing memory use - Minimum supported Rust version (MSRV) is now 1.72. ## 4.3.0 diff --git a/actix-web-actors/src/ws.rs b/actix-web-actors/src/ws.rs index 1fb903225..7f7607fa9 100644 --- a/actix-web-actors/src/ws.rs +++ b/actix-web-actors/src/ws.rs @@ -710,7 +710,7 @@ where } if !this.buf.is_empty() { - Poll::Ready(Some(Ok(this.buf.split().freeze()))) + Poll::Ready(Some(Ok(std::mem::take(&mut this.buf).freeze()))) } else if this.fut.alive() && !this.closed { Poll::Pending } else { From 22593a1532be29374100de0d256b493f2557bcd3 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 9 Jun 2024 01:07:56 -0400 Subject: [PATCH 293/314] Re-export `http::status::InvalidStatusCode` (#3393) * [actix-http/src/lib.rs] Expose/re-export `http::status::InvalidStatusCode` * [actix-http/src/error.rs] Re-export `http::status::InvalidStatusCode` ; [actix-http/src/lib.rs] Revert --- actix-http/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs index 69e2f14a1..6f332118e 100644 --- a/actix-http/src/error.rs +++ b/actix-http/src/error.rs @@ -3,7 +3,7 @@ use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; use derive_more::{Display, Error, From}; -pub use http::Error as HttpError; +pub use http::{status::InvalidStatusCode, Error as HttpError}; use http::{uri::InvalidUri, StatusCode}; use crate::{body::BoxBody, Response}; From 8b8eb4eae1212796216a53aa9ca445108206d7fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Jun 2024 18:37:42 +0100 Subject: [PATCH 294/314] build(deps): update tokio-uring requirement from 0.4 to 0.5 (#3385) * build(deps): update tokio-uring requirement from 0.4 to 0.5 Updates the requirements on [tokio-uring](https://github.com/tokio-rs/tokio-uring) to permit the latest version. - [Release notes](https://github.com/tokio-rs/tokio-uring/releases) - [Changelog](https://github.com/tokio-rs/tokio-uring/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/tokio-uring/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: tokio-uring dependency-type: direct:production ... Signed-off-by: dependabot[bot] * chore: narrow actix-server requirement --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob Ede --- actix-files/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 3d82f8a76..a69af3020 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -40,8 +40,8 @@ v_htmlescape = "0.15.5" # experimental-io-uring [target.'cfg(target_os = "linux")'.dependencies] -tokio-uring = { version = "0.4", optional = true, features = ["bytes"] } -actix-server = { version = "2.2", optional = true } # ensure matching tokio-uring versions +tokio-uring = { version = "0.5", optional = true, features = ["bytes"] } +actix-server = { version = "2.4", optional = true } # ensure matching tokio-uring versions [dev-dependencies] actix-rt = "2.7" From 37577dcb89c01834820e95d2361eed32732447a5 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 9 Jun 2024 19:45:14 +0100 Subject: [PATCH 295/314] chore(actix-files): prepare release 0.6.6 --- actix-files/CHANGES.md | 3 +++ actix-files/Cargo.toml | 2 +- actix-files/README.md | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md index 393e7b61a..e94f43907 100644 --- a/actix-files/CHANGES.md +++ b/actix-files/CHANGES.md @@ -2,6 +2,9 @@ ## Unreleased +## 0.6.6 + +- Update `tokio-uring` dependency to `0.4`. - Minimum supported Rust version (MSRV) is now 1.72. ## 0.6.5 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index a69af3020..7adb8eaf5 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-files" -version = "0.6.5" +version = "0.6.6" authors = [ "Nikolay Kim ", "Rob Ede ", diff --git a/actix-files/README.md b/actix-files/README.md index a6b3f63c6..f6d5143f5 100644 --- a/actix-files/README.md +++ b/actix-files/README.md @@ -3,11 +3,11 @@ [![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.6.5)](https://docs.rs/actix-files/0.6.5) +[![Documentation](https://docs.rs/actix-files/badge.svg?version=0.6.6)](https://docs.rs/actix-files/0.6.6) ![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) ![License](https://img.shields.io/crates/l/actix-files.svg)
-[![dependency status](https://deps.rs/crate/actix-files/0.6.5/status.svg)](https://deps.rs/crate/actix-files/0.6.5) +[![dependency status](https://deps.rs/crate/actix-files/0.6.6/status.svg)](https://deps.rs/crate/actix-files/0.6.6) [![Download](https://img.shields.io/crates/d/actix-files.svg)](https://crates.io/crates/actix-files) [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) From 758ae1dac1c5cc574698f058b30bd075bac8b681 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 10 Jun 2024 05:07:08 +1000 Subject: [PATCH 296/314] actix-test: allow the configuration of the TestServer address (#3351) * actix-test: allow the configuration of the TestServer address This is useful if you're running (say) Selenium tests against a running TestServer, and the Selenium workers are Docker containers elsewhere in the network. Not a *particularly* common use case, perhaps, but one that I can attest happens every now and then. * Update CHANGES.md * Adjust default listen address to avoid test failures --------- Co-authored-by: Rob Ede --- actix-test/CHANGES.md | 2 ++ actix-test/src/lib.rs | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index 8088c2504..dd409c917 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +- Add `TestServerConfig::listen_address()` method. + ## 0.1.4 - Add `TestServerConfig::rustls_0_23()` method for Rustls v0.23 support behind new `rustls-0_23` crate feature. diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 48d5079a7..803320607 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -154,7 +154,7 @@ where // run server in separate orphaned thread thread::spawn(move || { rt::System::new().block_on(async move { - let tcp = net::TcpListener::bind(("127.0.0.1", cfg.port)).unwrap(); + let tcp = net::TcpListener::bind((cfg.listen_address.clone(), cfg.port)).unwrap(); let local_addr = tcp.local_addr().unwrap(); let factory = factory.clone(); let srv_cfg = cfg.clone(); @@ -514,6 +514,7 @@ pub struct TestServerConfig { tp: HttpVer, stream: StreamType, client_request_timeout: Duration, + listen_address: String, port: u16, workers: usize, disable_redirects: bool, @@ -532,6 +533,7 @@ impl TestServerConfig { tp: HttpVer::Both, stream: StreamType::Tcp, client_request_timeout: Duration::from_secs(5), + listen_address: "127.0.0.1".to_string(), port: 0, workers: 1, disable_redirects: false, @@ -607,6 +609,14 @@ impl TestServerConfig { self } + /// Sets the address the server will listen on. + /// + /// By default, only listens on `127.0.0.1`. + pub fn listen_address(mut self, addr: impl Into) -> Self { + self.listen_address = addr.into(); + self + } + /// Sets test server port. /// /// By default, a random free port is determined by the OS. @@ -657,9 +667,9 @@ impl TestServer { let scheme = if self.tls { "https" } else { "http" }; if uri.starts_with('/') { - format!("{}://localhost:{}{}", scheme, self.addr.port(), uri) + format!("{}://{}{}", scheme, self.addr, uri) } else { - format!("{}://localhost:{}/{}", scheme, self.addr.port(), uri) + format!("{}://{}/{}", scheme, self.addr, uri) } } From da56de45564640dba4461d5c5f8b5d1f23f25533 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 00:01:17 +0100 Subject: [PATCH 297/314] chore(actix-test): prepare release 0.1.5 --- actix-test/CHANGES.md | 2 ++ actix-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-test/CHANGES.md b/actix-test/CHANGES.md index dd409c917..ec2dd6776 100644 --- a/actix-test/CHANGES.md +++ b/actix-test/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.1.5 + - Add `TestServerConfig::listen_address()` method. ## 0.1.4 diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 1ae619145..41267c969 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-test" -version = "0.1.4" +version = "0.1.5" authors = [ "Nikolay Kim ", "Rob Ede ", From a2b9823d9d428b2abec75e98afb8dfd412098886 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 10 Jun 2024 09:40:09 +1000 Subject: [PATCH 298/314] Strip non-address characters from Forwarded for= (#3343) * Strip non-address characters from Forwarded for= This is something of a followup to #2528, which asked for port information to not be included in when it was taken from the local socket. The header's element may optionally contain port information (https://datatracker.ietf.org/doc/html/rfc7239#section-6). However, as I understand it, is *supposed* to only contain an IP address, without port (per #2528). This PR corrects that discrepancy, making it easier to parse the result of this method in application code. There should not be any compatibility concerns, as anyone parsing the output of would already need to handle both port and portless cases anyway. * Update CHANGES.md --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/info.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 4e74e0902..3d9176dee 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- `ConnectionInfo::realip_remote_addr()` now handles IPv6 addresses from `Forwarded` header correctly. Previously, it sometimes returned the forwarded port as well. + ## 4.7.0 ### Added diff --git a/actix-web/src/info.rs b/actix-web/src/info.rs index c5d9638f4..aee936ba9 100644 --- a/actix-web/src/info.rs +++ b/actix-web/src/info.rs @@ -21,6 +21,19 @@ fn unquote(val: &str) -> &str { val.trim().trim_start_matches('"').trim_end_matches('"') } +/// Remove port and IPv6 square brackets from a peer specification. +fn bare_address(val: &str) -> &str { + if val.starts_with('[') { + val.split("]:") + .next() + .map(|s| s.trim_start_matches('[').trim_end_matches(']')) + // This shouldn't *actually* ever happen + .unwrap_or(val) + } else { + val.split(':').next().unwrap_or(val) + } +} + /// Extracts and trims first value for given header name. fn first_header_value<'a>(req: &'a RequestHead, name: &'_ HeaderName) -> Option<&'a str> { let hdr = req.headers.get(name)?.to_str().ok()?; @@ -100,7 +113,7 @@ impl ConnectionInfo { // --- https://datatracker.ietf.org/doc/html/rfc7239#section-5.2 match name.trim().to_lowercase().as_str() { - "for" => realip_remote_addr.get_or_insert_with(|| unquote(val)), + "for" => realip_remote_addr.get_or_insert_with(|| bare_address(unquote(val))), "proto" => scheme.get_or_insert_with(|| unquote(val)), "host" => host.get_or_insert_with(|| unquote(val)), "by" => { @@ -368,16 +381,25 @@ mod tests { .insert_header((header::FORWARDED, r#"for="192.0.2.60:8080""#)) .to_http_request(); let info = req.connection_info(); - assert_eq!(info.realip_remote_addr(), Some("192.0.2.60:8080")); + assert_eq!(info.realip_remote_addr(), Some("192.0.2.60")); } #[test] fn forwarded_for_ipv6() { + let req = TestRequest::default() + .insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]""#)) + .to_http_request(); + let info = req.connection_info(); + assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17")); + } + + #[test] + fn forwarded_for_ipv6_with_port() { let req = TestRequest::default() .insert_header((header::FORWARDED, r#"for="[2001:db8:cafe::17]:4711""#)) .to_http_request(); let info = req.connection_info(); - assert_eq!(info.realip_remote_addr(), Some("[2001:db8:cafe::17]:4711")); + assert_eq!(info.realip_remote_addr(), Some("2001:db8:cafe::17")); } #[test] From 4908fd7dea00a361cf6b37f9d66f1ac3c4805543 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:44:58 +0100 Subject: [PATCH 299/314] build(deps): bump taiki-e/install-action from 2.34.0 to 2.38.0 (#3396) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.34.0 to 2.38.0. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.34.0...v2.38.0) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 4 ++-- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index 4231b4dc2..d0eb3f8fd 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -49,7 +49,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -80,7 +80,7 @@ jobs: uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 - name: Install cargo-hack - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: cargo-hack diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab611fc0a..cc51b89f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: toolchain: ${{ matrix.version.version }} - name: Install just, cargo-hack, cargo-nextest, cargo-ci-cache-clean - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-hack,cargo-nextest,cargo-ci-cache-clean @@ -113,7 +113,7 @@ jobs: toolchain: nightly - name: Install just - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index da892bd7a..5c944bece 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -23,7 +23,7 @@ jobs: components: llvm-tools-preview - name: Install just,cargo-llvm-cov - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: just,cargo-llvm-cov diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index dd44d4cb3..d5c667f99 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -82,7 +82,7 @@ jobs: toolchain: nightly-2024-06-07 - name: Install cargo-public-api - uses: taiki-e/install-action@v2.34.0 + uses: taiki-e/install-action@v2.38.0 with: tool: cargo-public-api From 7f529e35b296c8359bdf22e7480722a5844e3ce2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 01:45:11 +0100 Subject: [PATCH 300/314] build(deps): bump actions-rust-lang/setup-rust-toolchain from 1.8.0 to 1.9.0 (#3395) build(deps): bump actions-rust-lang/setup-rust-toolchain Bumps [actions-rust-lang/setup-rust-toolchain](https://github.com/actions-rust-lang/setup-rust-toolchain) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/actions-rust-lang/setup-rust-toolchain/releases) - [Changelog](https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions-rust-lang/setup-rust-toolchain/compare/v1.8.0...v1.9.0) --- updated-dependencies: - dependency-name: actions-rust-lang/setup-rust-toolchain dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-post-merge.yml | 4 ++-- .github/workflows/ci.yml | 6 +++--- .github/workflows/coverage.yml | 2 +- .github/workflows/lint.yml | 8 ++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-post-merge.yml b/.github/workflows/ci-post-merge.yml index d0eb3f8fd..1729d9a07 100644 --- a/.github/workflows/ci-post-merge.yml +++ b/.github/workflows/ci-post-merge.yml @@ -44,7 +44,7 @@ jobs: echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: ${{ matrix.version.version }} @@ -77,7 +77,7 @@ jobs: run: ./scripts/free-disk-space.sh - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 - name: Install cargo-hack uses: taiki-e/install-action@v2.38.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc51b89f6..1b6f7b460 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,7 +59,7 @@ jobs: uses: rui314/setup-mold@v1 - name: Install Rust (${{ matrix.version.name }}) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: ${{ matrix.version.version }} @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly @@ -108,7 +108,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 5c944bece..de7fd7031 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: components: llvm-tools-preview diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d5c667f99..8fe8f59d3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly components: rustfmt @@ -36,7 +36,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: components: clippy @@ -55,7 +55,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Rust (nightly) - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly components: rust-docs @@ -77,7 +77,7 @@ jobs: uses: actions/checkout@v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.8.0 + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly-2024-06-07 From 53086a90a679e609ae6afe43d0eb94cdb270f3c0 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 01:58:13 +0100 Subject: [PATCH 301/314] build: add coverage recipes to justfile --- actix-web/src/info.rs | 3 ++- justfile | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/actix-web/src/info.rs b/actix-web/src/info.rs index aee936ba9..1b2e554f9 100644 --- a/actix-web/src/info.rs +++ b/actix-web/src/info.rs @@ -27,7 +27,8 @@ fn bare_address(val: &str) -> &str { val.split("]:") .next() .map(|s| s.trim_start_matches('[').trim_end_matches(']')) - // This shouldn't *actually* ever happen + // this indicates that the IPv6 address is malformed so shouldn't + // usually happen, but if it does, just return the original input .unwrap_or(val) } else { val.split(':').next().unwrap_or(val) diff --git a/justfile b/justfile index 4e106ef11..7f6dbb61e 100644 --- a/justfile +++ b/justfile @@ -53,6 +53,14 @@ test-docs toolchain="": && doc # Test workspace. test-all toolchain="": (test toolchain) (test-docs toolchain) +# Test workspace and generate Codecov coverage file. +test-coverage-codecov toolchain="": + cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --codecov --output-path codecov.json + +# Test workspace and generate LCOV coverage file. +test-coverage-lcov toolchain="": + cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --lcov --output-path lcov.info + # Document crates in workspace. doc *args: RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }} From 59e42c1446c7524f8c72a89cd8682e58f81d0376 Mon Sep 17 00:00:00 2001 From: Matt Palmer Date: Mon, 10 Jun 2024 11:19:35 +1000 Subject: [PATCH 302/314] Return 415 rather than 400 on Urlencoded Content-Type mismatch (#3334) Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 1 + actix-web/src/error/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 3d9176dee..28dd25fb5 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -5,6 +5,7 @@ ### Fixed - `ConnectionInfo::realip_remote_addr()` now handles IPv6 addresses from `Forwarded` header correctly. Previously, it sometimes returned the forwarded port as well. +- The `UrlencodedError::ContentType` variant (relevant to the `Form` extractor) now uses the 415 (Media Type Unsupported) status code in it's `ResponseError` implementation. ## 4.7.0 diff --git a/actix-web/src/error/mod.rs b/actix-web/src/error/mod.rs index 91a6bcc3f..25535332c 100644 --- a/actix-web/src/error/mod.rs +++ b/actix-web/src/error/mod.rs @@ -100,6 +100,7 @@ impl ResponseError for UrlencodedError { match self { Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE, Self::UnknownLength => StatusCode::LENGTH_REQUIRED, + Self::ContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE, Self::Payload(err) => err.status_code(), _ => StatusCode::BAD_REQUEST, } @@ -232,7 +233,7 @@ mod tests { let resp = UrlencodedError::UnknownLength.error_response(); assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED); let resp = UrlencodedError::ContentType.error_response(); - assert_eq!(resp.status(), StatusCode::BAD_REQUEST); + assert_eq!(resp.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE); } #[test] From 2ee92d778ec82b3a879967dd5bb690b8eed26f7c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 03:39:06 +0100 Subject: [PATCH 303/314] ci: external types checking (#3175) --- .github/workflows/lint.yml | 25 ++++++++++++++++++++++++- actix-files/Cargo.toml | 11 ++++++++--- actix-http-test/Cargo.toml | 14 +++++++++++--- actix-http/Cargo.toml | 23 ++++++++++++++++++++--- actix-multipart/Cargo.toml | 15 +++++++++++++++ actix-router/Cargo.toml | 8 +++++--- actix-test/Cargo.toml | 16 ++++++++++++++++ actix-web-actors/Cargo.toml | 12 +++++++++--- actix-web/Cargo.toml | 28 +++++++++++++++++++++++++--- awc/Cargo.toml | 27 ++++++++++++++++++++++----- justfile | 26 ++++++++++++++++++++++++++ 11 files changed, 181 insertions(+), 24 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8fe8f59d3..ca9d2bbeb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -65,6 +65,29 @@ jobs: RUSTDOCFLAGS: -D warnings run: cargo +nightly doc --no-deps --workspace --all-features + check-external-types: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust (nightly-2024-05-01) + uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 + with: + toolchain: nightly-2024-05-01 + + - name: Install just + uses: taiki-e/install-action@v2.38.0 + with: + tool: just + + - name: Install cargo-check-external-types + uses: taiki-e/cache-cargo-install-action@v1.2.2 + with: + tool: cargo-check-external-types + + - name: check external types + run: just check-external-types-all +nightly-2024-05-01 + public-api-diff: runs-on: ubuntu-latest steps: @@ -76,7 +99,7 @@ jobs: - name: Checkout PR branch uses: actions/checkout@v4 - - name: Install Rust + - name: Install Rust (nightly-2024-06-07) uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: toolchain: nightly-2024-06-07 diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml index 7adb8eaf5..57cd4e913 100644 --- a/actix-files/Cargo.toml +++ b/actix-files/Cargo.toml @@ -13,9 +13,14 @@ categories = ["asynchronous", "web-programming::http-server"] license = "MIT OR Apache-2.0" edition = "2021" -[lib] -name = "actix_files" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_http::*", + "actix_service::*", + "actix_web::*", + "http::*", + "mime::*", +] [features] experimental-io-uring = ["actix-web/experimental-io-uring", "tokio-uring"] diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml index bfb0a3539..0947579a5 100644 --- a/actix-http-test/Cargo.toml +++ b/actix-http-test/Cargo.toml @@ -18,9 +18,17 @@ edition = "2021" [package.metadata.docs.rs] features = [] -[lib] -name = "actix_http_test" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_codec::*", + "actix_http::*", + "actix_server::*", + "awc::*", + "bytes::*", + "futures_core::*", + "http::*", + "tokio::*", +] [features] default = [] diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml index 87e2b391d..4dc0f0bd8 100644 --- a/actix-http/Cargo.toml +++ b/actix-http/Cargo.toml @@ -34,9 +34,26 @@ features = [ "compress-zstd", ] -[lib] -name = "actix_http" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_codec::*", + "actix_service::*", + "actix_tls::*", + "actix_utils::*", + "bytes::*", + "bytestring::*", + "encoding_rs::*", + "futures_core::*", + "h2::*", + "http::*", + "httparse::*", + "language_tags::*", + "mime::*", + "openssl::*", + "rustls::*", + "tokio_util::*", + "tokio::*", +] [features] default = [] diff --git a/actix-multipart/Cargo.toml b/actix-multipart/Cargo.toml index f1289d3a2..5e9b78d84 100644 --- a/actix-multipart/Cargo.toml +++ b/actix-multipart/Cargo.toml @@ -16,6 +16,21 @@ edition = "2021" rustdoc-args = ["--cfg", "docsrs"] all-features = true +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_http::*", + "actix_multipart_derive::*", + "actix_utils::*", + "actix_web::*", + "bytes::*", + "futures_core::*", + "mime::*", + "serde_json::*", + "serde_plain::*", + "serde::*", + "tempfile::*", +] + [features] default = ["tempfile", "derive"] derive = ["actix-multipart-derive"] diff --git a/actix-router/Cargo.toml b/actix-router/Cargo.toml index 56e4bed2f..7e7e3beb8 100644 --- a/actix-router/Cargo.toml +++ b/actix-router/Cargo.toml @@ -12,9 +12,11 @@ repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" -[lib] -name = "actix_router" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "http::*", + "serde::*", +] [features] default = ["http", "unicode"] diff --git a/actix-test/Cargo.toml b/actix-test/Cargo.toml index 41267c969..e810ae80b 100644 --- a/actix-test/Cargo.toml +++ b/actix-test/Cargo.toml @@ -18,6 +18,22 @@ categories = [ license = "MIT OR Apache-2.0" edition = "2021" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_codec::*", + "actix_http_test::*", + "actix_http::*", + "actix_service::*", + "actix_web::*", + "awc::*", + "bytes::*", + "futures_core::*", + "http::*", + "openssl::*", + "rustls::*", + "tokio::*", +] + [features] default = [] diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml index 114ec5a87..3c74a4f47 100644 --- a/actix-web-actors/Cargo.toml +++ b/actix-web-actors/Cargo.toml @@ -9,9 +9,15 @@ repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" -[lib] -name = "actix_web_actors" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix::*", + "actix_http::*", + "actix_web::*", + "bytes::*", + "bytestring::*", + "futures_core::*", +] [dependencies] actix = { version = ">=0.12, <0.14", default-features = false } diff --git a/actix-web/Cargo.toml b/actix-web/Cargo.toml index 10a507680..3827d4400 100644 --- a/actix-web/Cargo.toml +++ b/actix-web/Cargo.toml @@ -35,9 +35,31 @@ features = [ "secure-cookies", ] -[lib] -name = "actix_web" -path = "src/lib.rs" +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_http::*", + "actix_router::*", + "actix_rt::*", + "actix_server::*", + "actix_service::*", + "actix_utils::*", + "actix_web_codegen::*", + "bytes::*", + "cookie::*", + "cookie", + "futures_core::*", + "http::*", + "language_tags::*", + "mime::*", + "openssl::*", + "rustls::*", + "serde_json::*", + "serde_urlencoded::*", + "serde::*", + "serde::*", + "tokio::*", + "url::*", +] [features] default = [ diff --git a/awc/Cargo.toml b/awc/Cargo.toml index 6ab408ea6..4fc2057f6 100644 --- a/awc/Cargo.toml +++ b/awc/Cargo.toml @@ -15,10 +15,6 @@ repository = "https://github.com/actix/actix-web" license = "MIT OR Apache-2.0" edition = "2021" -[lib] -name = "awc" -path = "src/lib.rs" - [package.metadata.docs.rs] rustdoc-args = ["--cfg", "docsrs"] features = [ @@ -33,6 +29,27 @@ features = [ "compress-zstd", ] +[package.metadata.cargo_check_external_types] +allowed_external_types = [ + "actix_codec::*", + "actix_http::*", + "actix_rt::*", + "actix_service::*", + "actix_tls::*", + "bytes::*", + "cookie::*", + "cookie", + "futures_core::*", + "h2::*", + "http::*", + "openssl::*", + "rustls::*", + "serde_json::*", + "serde_urlencoded::*", + "serde::*", + "tokio::*", +] + [features] default = ["compress-brotli", "compress-gzip", "compress-zstd", "cookies"] @@ -134,7 +151,7 @@ rcgen = "0.13" rustls-pemfile = "2" tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] } zstd = "0.13" -tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests +tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests [[example]] name = "client" diff --git a/justfile b/justfile index 7f6dbb61e..28b4dfd0a 100644 --- a/justfile +++ b/justfile @@ -74,3 +74,29 @@ doc-watch: update-readmes: && fmt cd ./actix-files && cargo rdme --force cd ./actix-router && cargo rdme --force + +# Check for unintentional external type exposure on all crates in workspace. +check-external-types-all toolchain="+nightly": + #!/usr/bin/env bash + set -euo pipefail + exit=0 + for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do + if ! just check-external-types-manifest "$f" {{toolchain}}; then exit=1; fi + echo + echo + done + exit $exit + +# Check for unintentional external type exposure on all crates in workspace. +check-external-types-all-table toolchain="+nightly": + #!/usr/bin/env bash + set -euo pipefail + for f in $(find . -mindepth 2 -maxdepth 2 -name Cargo.toml | grep -vE "\-codegen/|\-derive/|\-macros/"); do + echo + echo "Checking for $f" + just check-external-types-manifest "$f" {{toolchain}} --output-format=markdown-table + done + +# Check for unintentional external type exposure on a crate. +check-external-types-manifest manifest_path toolchain="+nightly" *extra_args="": + cargo {{toolchain}} check-external-types --manifest-path "{{manifest_path}}" {{extra_args}} From 7a2313cc4b6a9ff613903c7684162e3129ef7b72 Mon Sep 17 00:00:00 2001 From: Timo Caktu <74780331+TimoCak@users.noreply.github.com> Date: Mon, 10 Jun 2024 04:49:50 +0200 Subject: [PATCH 304/314] web: add `HttpRequest::full_url()` (#3096) * implemented function which returns full uir * changes added into the changelog * added test funtion for full_uri method * refactor: rename to full_url --------- Co-authored-by: Rob Ede --- actix-web/CHANGES.md | 4 ++++ actix-web/src/request.rs | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 28dd25fb5..bb0844e05 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +### Added + +- Add `HttpRequest::full_url()` method to get the complete URL of the request. + ### Fixed - `ConnectionInfo::realip_remote_addr()` now handles IPv6 addresses from `Forwarded` header correctly. Previously, it sometimes returned the forwarded port as well. diff --git a/actix-web/src/request.rs b/actix-web/src/request.rs index 08a222c86..47b3e3d88 100644 --- a/actix-web/src/request.rs +++ b/actix-web/src/request.rs @@ -91,6 +91,35 @@ impl HttpRequest { &self.head().uri } + /// Returns request's original full URL. + /// + /// Reconstructed URL is best-effort, using [`connection_info`](HttpRequest::connection_info()) + /// to get forwarded scheme & host. + /// + /// ``` + /// use actix_web::test::TestRequest; + /// let req = TestRequest::with_uri("http://10.1.2.3:8443/api?id=4&name=foo") + /// .insert_header(("host", "example.com")) + /// .to_http_request(); + /// + /// assert_eq!( + /// req.full_url().as_str(), + /// "http://example.com/api?id=4&name=foo", + /// ); + /// ``` + pub fn full_url(&self) -> url::Url { + let info = self.connection_info(); + let scheme = info.scheme(); + let host = info.host(); + let path_and_query = self + .uri() + .path_and_query() + .map(|paq| paq.as_str()) + .unwrap_or("/"); + + url::Url::parse(&format!("{scheme}://{host}{path_and_query}")).unwrap() + } + /// Read the Request method. #[inline] pub fn method(&self) -> &Method { @@ -963,4 +992,27 @@ mod tests { assert!(format!("{:?}", req).contains(location_header)); } + + #[test] + fn check_full_url() { + let req = TestRequest::with_uri("/api?id=4&name=foo").to_http_request(); + assert_eq!( + req.full_url().as_str(), + "http://localhost:8080/api?id=4&name=foo", + ); + + let req = TestRequest::with_uri("https://example.com/api?id=4&name=foo").to_http_request(); + assert_eq!( + req.full_url().as_str(), + "https://example.com/api?id=4&name=foo", + ); + + let req = TestRequest::with_uri("http://10.1.2.3:8443/api?id=4&name=foo") + .insert_header(("host", "example.com")) + .to_http_request(); + assert_eq!( + req.full_url().as_str(), + "http://example.com/api?id=4&name=foo", + ); + } } From d9579cf58af2230b651d476945639c17b31ef84a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 04:05:21 +0100 Subject: [PATCH 305/314] test: coverage for doctests --- .github/workflows/coverage.yml | 2 +- justfile | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index de7fd7031..f1d787767 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -28,7 +28,7 @@ jobs: tool: just,cargo-llvm-cov - name: Generate code coverage - run: cargo llvm-cov --workspace --all-features --codecov --output-path codecov.json + run: just test-coverage-codecov - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.4.1 diff --git a/justfile b/justfile index 28b4dfd0a..530bf5f64 100644 --- a/justfile +++ b/justfile @@ -53,13 +53,19 @@ test-docs toolchain="": && doc # Test workspace. test-all toolchain="": (test toolchain) (test-docs toolchain) -# Test workspace and generate Codecov coverage file. -test-coverage-codecov toolchain="": - cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --codecov --output-path codecov.json +# Test workspace and collect coverage info. +[private] +test-coverage toolchain="": + cargo {{ toolchain }} llvm-cov nextest --no-report {{ all_crate_features }} + cargo {{ toolchain }} llvm-cov --doc --no-report {{ all_crate_features }} -# Test workspace and generate LCOV coverage file. -test-coverage-lcov toolchain="": - cargo {{ toolchain }} llvm-cov --workspace {{ all_crate_features }} --lcov --output-path lcov.info +# Test workspace and generate Codecov report. +test-coverage-codecov toolchain="": (test-coverage toolchain) + cargo {{ toolchain }} llvm-cov report --doctests --codecov --output-path=codecov.json + +# Test workspace and generate LCOV report. +test-coverage-lcov toolchain="": (test-coverage toolchain) + cargo {{ toolchain }} llvm-cov report --doctests --lcov --output-path=lcov.info # Document crates in workspace. doc *args: From 9553e7afff8661dd8805f77a24a1d178e1665d3a Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 04:08:10 +0100 Subject: [PATCH 306/314] ci: fix coverage --- .github/workflows/coverage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index f1d787767..7aeea6291 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -22,10 +22,10 @@ jobs: with: components: llvm-tools-preview - - name: Install just,cargo-llvm-cov + - name: Install just, cargo-llvm-cov, cargo-nextest uses: taiki-e/install-action@v2.38.0 with: - tool: just,cargo-llvm-cov + tool: just,cargo-llvm-cov,cargo-nextest - name: Generate code coverage run: just test-coverage-codecov From 9b3de1f1fe59bd6d3ebc645590eb49f77260a20b Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 04:15:58 +0100 Subject: [PATCH 307/314] ci: fix doctest coverage --- .github/workflows/coverage.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 7aeea6291..ca3115713 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -17,10 +17,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install Rust + - name: Install Rust (nightly) uses: actions-rust-lang/setup-rust-toolchain@v1.9.0 with: - components: llvm-tools-preview + toolchain: nightly + components: llvm-tools - name: Install just, cargo-llvm-cov, cargo-nextest uses: taiki-e/install-action@v2.38.0 From 0fd85bae2a8fa5f804c88f01aacb2202f44baed7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 21:51:53 +0100 Subject: [PATCH 308/314] test: demonstrate panic in multipart forms (#3397) --- actix-multipart/src/form/mod.rs | 66 ++++++++++++++++++++++++++++++++- actix-multipart/src/server.rs | 19 ++++++++-- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index 451b103fd..6fbdfa1a1 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -33,6 +33,14 @@ pub trait FieldReader<'t>: Sized + Any { type Future: Future>; /// The form will call this function to handle the field. + /// + /// # Panics + /// + /// When reading the `field` payload using its `Stream` implementation, polling (manually or via + /// `next()`/`try_next()`) may panic after the payload is exhausted. If this is a problem for + /// your implementation of this method, you should [`fuse()`] the `Field` first. + /// + /// [`fuse()`]: https://docs.rs/futures-util/0.3/futures_util/stream/trait.StreamExt.html#method.fuse fn read_field(req: &'t HttpRequest, field: Field, limits: &'t mut Limits) -> Self::Future; } @@ -396,11 +404,20 @@ mod tests { use actix_http::encoding::Decoder; use actix_multipart_rfc7578::client::multipart; use actix_test::TestServer; - use actix_web::{dev::Payload, http::StatusCode, web, App, HttpResponse, Responder}; + use actix_web::{ + dev::Payload, http::StatusCode, web, App, HttpRequest, HttpResponse, Resource, Responder, + }; use awc::{Client, ClientResponse}; + use futures_core::future::LocalBoxFuture; + use futures_util::TryStreamExt as _; use super::MultipartForm; - use crate::form::{bytes::Bytes, tempfile::TempFile, text::Text, MultipartFormConfig}; + use crate::{ + form::{ + bytes::Bytes, tempfile::TempFile, text::Text, FieldReader, Limits, MultipartFormConfig, + }, + Field, MultipartError, + }; pub async fn send_form( srv: &TestServer, @@ -734,4 +751,49 @@ mod tests { let response = send_form(&srv, form, "/").await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); } + + #[should_panic(expected = "called `Result::unwrap()` on an `Err` value: Connect(Disconnected)")] + #[actix_web::test] + async fn field_try_next_panic() { + #[derive(Debug)] + struct NullSink; + + impl<'t> FieldReader<'t> for NullSink { + type Future = LocalBoxFuture<'t, Result>; + + fn read_field( + _: &'t HttpRequest, + mut field: Field, + _limits: &'t mut Limits, + ) -> Self::Future { + Box::pin(async move { + // exhaust field stream + while let Some(_chunk) = field.try_next().await? {} + + // poll again, crash + let _post = field.try_next().await; + + Ok(Self) + }) + } + } + + #[allow(dead_code)] + #[derive(MultipartForm)] + struct NullSinkForm { + foo: NullSink, + } + + async fn null_sink(_form: MultipartForm) -> impl Responder { + "unreachable" + } + + let srv = actix_test::start(|| App::new().service(Resource::new("/").post(null_sink))); + + let mut form = multipart::Form::default(); + form.add_text("foo", "data is not important to this test"); + + // panics with Err(Connect(Disconnected)) due to form NullSink panic + let _res = send_form(&srv, form, "/").await; + } } diff --git a/actix-multipart/src/server.rs b/actix-multipart/src/server.rs index d0f833318..0256aa7bf 100644 --- a/actix-multipart/src/server.rs +++ b/actix-multipart/src/server.rs @@ -465,7 +465,12 @@ impl Stream for Field { fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.get_mut(); let mut inner = this.inner.borrow_mut(); - if let Some(mut buffer) = inner.payload.as_ref().unwrap().get_mut(&this.safety) { + if let Some(mut buffer) = inner + .payload + .as_ref() + .expect("Field should not be polled after completion") + .get_mut(&this.safety) + { // check safety and poll read payload to buffer. buffer.poll_stream(cx)?; } else if !this.safety.is_clean() { @@ -496,6 +501,7 @@ impl fmt::Debug for Field { } struct InnerField { + /// Payload is initialized as Some and is `take`n when the field stream finishes. payload: Option, boundary: String, eof: bool, @@ -643,7 +649,12 @@ impl InnerField { return Poll::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() + .expect("Field should not be polled after completion") + .get_mut(s) + { if !self.eof { let res = if let Some(ref mut len) = self.length { InnerField::read_len(&mut payload, len) @@ -674,8 +685,10 @@ impl InnerField { }; if let Poll::Ready(None) = result { - self.payload.take(); + // drop payload buffer and make future un-poll-able + let _ = self.payload.take(); } + result } } From 4c4c27993864249d58d9e3a04c9c80cf4f7d678c Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 23:23:38 +0100 Subject: [PATCH 309/314] docs(test): intrgrate cargo-rdme --- actix-multipart/src/form/mod.rs | 2 +- actix-test/README.md | 45 +++++++++++++++++++++++++++++++++ actix-test/src/lib.rs | 1 + justfile | 1 + 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 actix-test/README.md diff --git a/actix-multipart/src/form/mod.rs b/actix-multipart/src/form/mod.rs index 6fbdfa1a1..68cdefec5 100644 --- a/actix-multipart/src/form/mod.rs +++ b/actix-multipart/src/form/mod.rs @@ -40,7 +40,7 @@ pub trait FieldReader<'t>: Sized + Any { /// `next()`/`try_next()`) may panic after the payload is exhausted. If this is a problem for /// your implementation of this method, you should [`fuse()`] the `Field` first. /// - /// [`fuse()`]: https://docs.rs/futures-util/0.3/futures_util/stream/trait.StreamExt.html#method.fuse + /// [`fuse()`]: futures_util::stream::StreamExt::fuse() fn read_field(req: &'t HttpRequest, field: Field, limits: &'t mut Limits) -> Self::Future; } diff --git a/actix-test/README.md b/actix-test/README.md new file mode 100644 index 000000000..1a9b6f22a --- /dev/null +++ b/actix-test/README.md @@ -0,0 +1,45 @@ +# `actix-test` + + + +[![crates.io](https://img.shields.io/crates/v/actix-test?label=latest)](https://crates.io/crates/actix-test) +[![Documentation](https://docs.rs/actix-test/badge.svg?version=0.1.5)](https://docs.rs/actix-test/0.1.5) +![Version](https://img.shields.io/badge/rustc-1.72+-ab6000.svg) +![MIT or Apache 2.0 licensed](https://img.shields.io/crates/l/actix-test.svg) +
+[![dependency status](https://deps.rs/crate/actix-test/0.1.5/status.svg)](https://deps.rs/crate/actix-test/0.1.5) +[![Download](https://img.shields.io/crates/d/actix-test.svg)](https://crates.io/crates/actix-test) +[![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + + + + +Integration testing tools for Actix Web applications. + +The main integration testing tool is [`TestServer`]. It spawns a real HTTP server on an unused port and provides methods that use a real HTTP client. Therefore, it is much closer to real-world cases than using `init_service`, which skips HTTP encoding and decoding. + +## Examples + +```rust +use actix_web::{get, web, test, App, HttpResponse, Error, Responder}; + +#[get("/")] +async fn my_handler() -> Result { + Ok(HttpResponse::Ok()) +} + +#[actix_rt::test] +async fn test_example() { + let srv = actix_test::start(|| + App::new().service(my_handler) + ); + + let req = srv.get("/"); + let res = req.send().await.unwrap(); + + assert!(res.status().is_success()); +} +``` + + diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 803320607..9be99978d 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -5,6 +5,7 @@ //! real-world cases than using `init_service`, which skips HTTP encoding and decoding. //! //! # Examples +//! //! ``` //! use actix_web::{get, web, test, App, HttpResponse, Error, Responder}; //! diff --git a/justfile b/justfile index 530bf5f64..2ea6031f8 100644 --- a/justfile +++ b/justfile @@ -80,6 +80,7 @@ doc-watch: update-readmes: && fmt cd ./actix-files && cargo rdme --force cd ./actix-router && cargo rdme --force + cd ./actix-test && cargo rdme --force # Check for unintentional external type exposure on all crates in workspace. check-external-types-all toolchain="+nightly": From cd301a6932e274229ced4904d87600500a692229 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 23:30:51 +0100 Subject: [PATCH 310/314] docs: local docs doc everything but only list workspace crates --- justfile | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/justfile b/justfile index 2ea6031f8..f44236ece 100644 --- a/justfile +++ b/justfile @@ -68,8 +68,17 @@ test-coverage-lcov toolchain="": (test-coverage toolchain) cargo {{ toolchain }} llvm-cov report --doctests --lcov --output-path=lcov.info # Document crates in workspace. -doc *args: - RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --no-deps --workspace {{ all_crate_features }} {{ args }} +doc *args: && doc-set-workspace-crates + RUSTDOCFLAGS="--cfg=docsrs -Dwarnings" cargo +nightly doc --workspace {{ all_crate_features }} {{ args }} + +[private] +doc-set-workspace-crates: + #!/usr/bin/env bash + ( + echo "window.ALL_CRATES =" + cargo metadata --format-version=1 | jq '[.packages[] | select(.source == null) | .name]' + echo ";" + ) > "$CARGO_TARGET_DIR/doc/crates.js" # Document crates in workspace and watch for changes. doc-watch: From cc5030c542084fefee87cce743286b79b6a58fb8 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 23:31:45 +0100 Subject: [PATCH 311/314] docs(http-test): use cargo-rdme --- actix-http-test/README.md | 8 ++++++-- justfile | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/actix-http-test/README.md b/actix-http-test/README.md index ee242d1d5..939028121 100644 --- a/actix-http-test/README.md +++ b/actix-http-test/README.md @@ -1,7 +1,5 @@ # `actix-http-test` -> Various helpers for Actix applications to use during testing. - [![crates.io](https://img.shields.io/crates/v/actix-http-test?label=latest)](https://crates.io/crates/actix-http-test) @@ -14,3 +12,9 @@ [![Chat on Discord](https://img.shields.io/discord/771444961383153695?label=chat&logo=discord)](https://discord.gg/NWpN5mmg3x) + + + +Various helpers for Actix applications to use during testing. + + diff --git a/justfile b/justfile index f44236ece..9f909bfac 100644 --- a/justfile +++ b/justfile @@ -88,6 +88,7 @@ doc-watch: # Update READMEs from crate root documentation. update-readmes: && fmt cd ./actix-files && cargo rdme --force + cd ./actix-http-test && cargo rdme --force cd ./actix-router && cargo rdme --force cd ./actix-test && cargo rdme --force From 132b84d3b1f0f01a8a4923c442039ba46f845977 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 23:35:26 +0100 Subject: [PATCH 312/314] docs(multipart): use cargo-rdme --- actix-multipart/README.md | 21 ++++++--------------- actix-multipart/src/lib.rs | 2 ++ justfile | 1 + 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/actix-multipart/README.md b/actix-multipart/README.md index c7697785a..ef7630637 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -1,7 +1,5 @@ # `actix-multipart` -> Multipart form support for Actix Web. - [![crates.io](https://img.shields.io/crates/v/actix-multipart?label=latest)](https://crates.io/crates/actix-multipart) @@ -15,18 +13,13 @@ -## Example + -Dependencies: +Multipart form support for Actix Web. -```toml -[dependencies] -actix-multipart = "0.6" -actix-web = "4.5" -serde = { version = "1.0", features = ["derive"] } -``` +## Examples -Code: +[More available in the examples repo →](https://github.com/actix/examples/tree/master/forms/multipart) ```rust use actix_web::{post, App, HttpServer, Responder}; @@ -63,6 +56,8 @@ async fn main() -> std::io::Result<()> { } ``` + + Curl request : ```bash @@ -71,7 +66,3 @@ curl -v --request POST \ -F 'json={"name": "Cargo.lock"};type=application/json' \ -F file=@./Cargo.lock ``` - -### Examples - -https://github.com/actix/examples/tree/master/forms/multipart diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index d19e951e6..51b06db38 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -1,5 +1,7 @@ //! Multipart form support for Actix Web. +//! //! # Examples +//! //! ```no_run //! use actix_web::{post, App, HttpServer, Responder}; //! diff --git a/justfile b/justfile index 9f909bfac..d15ffcf67 100644 --- a/justfile +++ b/justfile @@ -90,6 +90,7 @@ update-readmes: && fmt cd ./actix-files && cargo rdme --force cd ./actix-http-test && cargo rdme --force cd ./actix-router && cargo rdme --force + cd ./actix-multipart && cargo rdme --force cd ./actix-test && cargo rdme --force # Check for unintentional external type exposure on all crates in workspace. From 0ce488e57a06f8971f9dd8b51b16766c682bd9cc Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 10 Jun 2024 23:54:16 +0100 Subject: [PATCH 313/314] docs: fix build --- justfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/justfile b/justfile index d15ffcf67..646c6b44d 100644 --- a/justfile +++ b/justfile @@ -78,7 +78,7 @@ doc-set-workspace-crates: echo "window.ALL_CRATES =" cargo metadata --format-version=1 | jq '[.packages[] | select(.source == null) | .name]' echo ";" - ) > "$CARGO_TARGET_DIR/doc/crates.js" + ) > "$(cargo metadata --format-version=1 | jq -r '.target_directory')/doc/crates.js" # Document crates in workspace and watch for changes. doc-watch: From 188206a90382111e2d8337febf4f6965c0730b6e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Tue, 11 Jun 2024 00:36:46 +0100 Subject: [PATCH 314/314] feat: Html responder (#3399) --- actix-multipart/README.md | 4 +-- actix-web/CHANGES.md | 1 + actix-web/README.md | 2 +- actix-web/src/types/html.rs | 66 +++++++++++++++++++++++++++++++++++++ actix-web/src/types/mod.rs | 2 ++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 actix-web/src/types/html.rs diff --git a/actix-multipart/README.md b/actix-multipart/README.md index ef7630637..d61347f32 100644 --- a/actix-multipart/README.md +++ b/actix-multipart/README.md @@ -19,8 +19,6 @@ Multipart form support for Actix Web. ## Examples -[More available in the examples repo →](https://github.com/actix/examples/tree/master/forms/multipart) - ```rust use actix_web::{post, App, HttpServer, Responder}; @@ -58,6 +56,8 @@ async fn main() -> std::io::Result<()> { +[More available in the examples repo →](https://github.com/actix/examples/tree/master/forms/multipart) + Curl request : ```bash diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index bb0844e05..54c7045ae 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -4,6 +4,7 @@ ### Added +- Add `web::Html` responder. - Add `HttpRequest::full_url()` method to get the complete URL of the request. ### Fixed diff --git a/actix-web/README.md b/actix-web/README.md index 8b4375bdd..3f9d3e0d5 100644 --- a/actix-web/README.md +++ b/actix-web/README.md @@ -109,4 +109,4 @@ This project is licensed under either of the following licenses, at your option: ## Code of Conduct -Contribution to the actix-web repo is organized under the terms of the Contributor Covenant. The Actix team promises to intervene to uphold that code of conduct. +Contribution to the `actix/actix-web` repo is organized under the terms of the Contributor Covenant. The Actix team promises to intervene to uphold that code of conduct. diff --git a/actix-web/src/types/html.rs b/actix-web/src/types/html.rs new file mode 100644 index 000000000..c370ee07b --- /dev/null +++ b/actix-web/src/types/html.rs @@ -0,0 +1,66 @@ +//! Semantic HTML responder. See [`Html`]. + +use crate::{ + http::{ + header::{self, ContentType, TryIntoHeaderValue}, + StatusCode, + }, + HttpRequest, HttpResponse, Responder, +}; + +/// Semantic HTML responder. +/// +/// When used as a responder, creates a 200 OK response, sets the correct HTML content type, and +/// uses the string passed to [`Html::new()`] as the body. +/// +/// ``` +/// # use actix_web::web::Html; +/// Html::new("

Hello, World!

") +/// # ; +/// ``` +#[derive(Debug, Clone, PartialEq, Hash)] +pub struct Html(String); + +impl Html { + /// Constructs a new `Html` responder. + pub fn new(html: impl Into) -> Self { + Self(html.into()) + } +} + +impl Responder for Html { + type Body = String; + + fn respond_to(self, _req: &HttpRequest) -> HttpResponse { + let mut res = HttpResponse::with_body(StatusCode::OK, self.0); + res.headers_mut().insert( + header::CONTENT_TYPE, + ContentType::html().try_into_value().unwrap(), + ); + res + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::TestRequest; + + #[test] + fn responder() { + let req = TestRequest::default().to_http_request(); + + let res = Html::new("

Hello, World!

"); + let res = res.respond_to(&req); + + assert!(res.status().is_success()); + assert!(res + .headers() + .get(header::CONTENT_TYPE) + .unwrap() + .to_str() + .unwrap() + .starts_with("text/html")); + assert!(res.body().starts_with("

")); + } +} diff --git a/actix-web/src/types/mod.rs b/actix-web/src/types/mod.rs index 792edd650..cabe53d6a 100644 --- a/actix-web/src/types/mod.rs +++ b/actix-web/src/types/mod.rs @@ -3,6 +3,7 @@ mod either; mod form; mod header; +mod html; mod json; mod path; mod payload; @@ -13,6 +14,7 @@ pub use self::{ either::Either, form::{Form, FormConfig, UrlEncoded}, header::Header, + html::Html, json::{Json, JsonBody, JsonConfig}, path::{Path, PathConfig}, payload::{Payload, PayloadConfig},