From 6f0a6bd1bb7ffdd98fa5ce825b24a73c4d71d9a7 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Sun, 1 Jan 2023 20:56:27 +0000 Subject: [PATCH 01/44] address clippy lints For intrepid commit message readers: The choice to add allows for the inlined format args lint instead of actually inlining them is not very clear because our actual real world MSRV is not clear. We currently claim 1.60 is our MSRV but this is mainly due to dependencies. I'm fairly sure that we could support < 1.58 if those deps are outdated in a users lockfile. We'll remove these allows again at some point soon. --- actix-files/src/lib.rs | 1 + actix-http-test/src/lib.rs | 3 +++ actix-http/benches/quality-value.rs | 2 ++ actix-http/src/body/sized_stream.rs | 2 +- actix-http/src/h1/chunked.rs | 2 +- actix-http/src/h1/encoder.rs | 2 +- actix-http/src/lib.rs | 3 ++- actix-http/tests/test_openssl.rs | 1 + actix-http/tests/test_rustls.rs | 1 + actix-http/tests/test_server.rs | 2 ++ 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-test/src/lib.rs | 2 ++ actix-web-actors/src/lib.rs | 1 + actix-web-codegen/src/route.rs | 2 +- actix-web/benches/server.rs | 2 ++ actix-web/examples/basic.rs | 2 ++ actix-web/examples/macroless.rs | 2 ++ actix-web/examples/on-connect.rs | 2 ++ actix-web/examples/uds.rs | 2 ++ actix-web/src/app.rs | 1 + actix-web/src/lib.rs | 1 + actix-web/tests/test_httpserver.rs | 2 ++ awc/examples/client.rs | 2 ++ awc/src/builder.rs | 2 +- awc/src/lib.rs | 3 ++- awc/src/request.rs | 4 +++- awc/src/ws.rs | 4 +++- awc/tests/test_client.rs | 2 ++ 31 files changed, 52 insertions(+), 10 deletions(-) diff --git a/actix-files/src/lib.rs b/actix-files/src/lib.rs index 40327e5e8..0fbe39a8e 100644 --- a/actix-files/src/lib.rs +++ b/actix-files/src/lib.rs @@ -13,6 +13,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible, missing_docs, missing_debug_implementations)] +#![allow(clippy::uninlined_format_args)] 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 8636ef9c4..a66f7b486 100644 --- a/actix-http-test/src/lib.rs +++ b/actix-http-test/src/lib.rs @@ -2,6 +2,7 @@ #![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")] @@ -87,6 +88,7 @@ pub async fn test_server_with_addr>( // notify TestServer that server and system have shut down // all thread managed resources should be dropped at this point + #[allow(clippy::let_underscore_future)] let _ = thread_stop_tx.send(()); }); @@ -294,6 +296,7 @@ impl Drop for TestServer { // without needing to await anything // signal server to stop + #[allow(clippy::let_underscore_future)] let _ = self.server.stop(true); // signal system to stop diff --git a/actix-http/benches/quality-value.rs b/actix-http/benches/quality-value.rs index 33ba9c4c8..0ed274ded 100644 --- a/actix-http/benches/quality-value.rs +++ b/actix-http/benches/quality-value.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; const CODES: &[u16] = &[0, 1000, 201, 800, 550]; diff --git a/actix-http/src/body/sized_stream.rs b/actix-http/src/body/sized_stream.rs index e5e27b287..08cd81a0d 100644 --- a/actix-http/src/body/sized_stream.rs +++ b/actix-http/src/body/sized_stream.rs @@ -44,7 +44,7 @@ where #[inline] fn size(&self) -> BodySize { - BodySize::Sized(self.size as u64) + BodySize::Sized(self.size) } /// Attempts to pull out the next value of the underlying [`Stream`]. diff --git a/actix-http/src/h1/chunked.rs b/actix-http/src/h1/chunked.rs index 4005ed892..fc9081b81 100644 --- a/actix-http/src/h1/chunked.rs +++ b/actix-http/src/h1/chunked.rs @@ -71,7 +71,7 @@ impl ChunkedState { match size.checked_mul(radix) { Some(n) => { - *size = n as u64; + *size = n; *size += rem as u64; Poll::Ready(Ok(ChunkedState::Size)) diff --git a/actix-http/src/h1/encoder.rs b/actix-http/src/h1/encoder.rs index 21cfd75c4..abe396ce2 100644 --- a/actix-http/src/h1/encoder.rs +++ b/actix-http/src/h1/encoder.rs @@ -450,7 +450,7 @@ impl TransferEncoding { buf.extend_from_slice(&msg[..len as usize]); - *remaining -= len as u64; + *remaining -= len; Ok(*remaining == 0) } else { Ok(true) diff --git a/actix-http/src/lib.rs b/actix-http/src/lib.rs index 864db4986..05f80eba4 100644 --- a/actix-http/src/lib.rs +++ b/actix-http/src/lib.rs @@ -21,7 +21,8 @@ #![allow( clippy::type_complexity, clippy::too_many_arguments, - clippy::borrow_interior_mutable_const + clippy::borrow_interior_mutable_const, + clippy::uninlined_format_args )] #![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 40dbb6ba4..7464bee4e 100644 --- a/actix-http/tests/test_openssl.rs +++ b/actix-http/tests/test_openssl.rs @@ -1,4 +1,5 @@ #![cfg(feature = "openssl")] +#![allow(clippy::uninlined_format_args)] extern crate tls_openssl as openssl; diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs index d9ff42b7d..0b8197a69 100644 --- a/actix-http/tests/test_rustls.rs +++ b/actix-http/tests/test_rustls.rs @@ -1,4 +1,5 @@ #![cfg(feature = "rustls")] +#![allow(clippy::uninlined_format_args)] extern crate tls_rustls as rustls; diff --git a/actix-http/tests/test_server.rs b/actix-http/tests/test_server.rs index e70089b1d..0816ab221 100644 --- a/actix-http/tests/test_server.rs +++ b/actix-http/tests/test_server.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use std::{ convert::Infallible, io::{Read, Write}, diff --git a/actix-http/tests/test_ws.rs b/actix-http/tests/test_ws.rs index 8b3ab8e1b..a9c1acd33 100644 --- a/actix-http/tests/test_ws.rs +++ b/actix-http/tests/test_ws.rs @@ -1,3 +1,5 @@ +#![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 3d536e08d..37d03db49 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)] +#![allow(clippy::borrow_interior_mutable_const, clippy::uninlined_format_args)] mod error; mod extractor; diff --git a/actix-router/benches/quoter.rs b/actix-router/benches/quoter.rs index c18f1620e..9ca06da39 100644 --- a/actix-router/benches/quoter.rs +++ b/actix-router/benches/quoter.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use criterion::{black_box, criterion_group, criterion_main, Criterion}; use std::borrow::Cow; diff --git a/actix-router/src/lib.rs b/actix-router/src/lib.rs index 0febcf1ac..418dd432b 100644 --- a/actix-router/src/lib.rs +++ b/actix-router/src/lib.rs @@ -2,6 +2,7 @@ #![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")] diff --git a/actix-test/src/lib.rs b/actix-test/src/lib.rs index 5efd9758e..1aff2dc83 100644 --- a/actix-test/src/lib.rs +++ b/actix-test/src/lib.rs @@ -321,6 +321,7 @@ where // all thread managed resources should be dropped at this point }); + #[allow(clippy::let_underscore_future)] let _ = thread_stop_tx.send(()); }); @@ -567,6 +568,7 @@ impl Drop for TestServer { // without needing to await anything // signal server to stop + #[allow(clippy::let_underscore_future)] let _ = self.server.stop(true); // signal system to stop diff --git a/actix-web-actors/src/lib.rs b/actix-web-actors/src/lib.rs index 106bc5202..7a34048da 100644 --- a/actix-web-actors/src/lib.rs +++ b/actix-web-actors/src/lib.rs @@ -57,6 +57,7 @@ #![deny(rust_2018_idioms, nonstandard_style)] #![warn(future_incompatible)] +#![allow(clippy::uninlined_format_args)] mod context; pub mod ws; diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 7a0658468..e5493702d 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -155,7 +155,7 @@ impl Args { if !methods.insert(method) { return Err(syn::Error::new_spanned( &nv.lit, - &format!( + format!( "HTTP method defined more than once: `{}`", lit.value() ), diff --git a/actix-web/benches/server.rs b/actix-web/benches/server.rs index 0d45c9403..2c9f71dc5 100644 --- a/actix-web/benches/server.rs +++ b/actix-web/benches/server.rs @@ -1,3 +1,5 @@ +#![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/basic.rs b/actix-web/examples/basic.rs index 36b1cdd8f..60715f477 100644 --- a/actix-web/examples/basic.rs +++ b/actix-web/examples/basic.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use actix_web::{get, middleware, web, App, HttpRequest, HttpResponse, HttpServer}; #[get("/resource1/{name}/index.html")] diff --git a/actix-web/examples/macroless.rs b/actix-web/examples/macroless.rs index 78ffd45c1..d3589da21 100644 --- a/actix-web/examples/macroless.rs +++ b/actix-web/examples/macroless.rs @@ -1,3 +1,5 @@ +#![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/on-connect.rs b/actix-web/examples/on-connect.rs index 24c6f8418..57017fcd6 100644 --- a/actix-web/examples/on-connect.rs +++ b/actix-web/examples/on-connect.rs @@ -4,6 +4,8 @@ //! 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::{ diff --git a/actix-web/examples/uds.rs b/actix-web/examples/uds.rs index cf0ffebde..ba4b25a29 100644 --- a/actix-web/examples/uds.rs +++ b/actix-web/examples/uds.rs @@ -1,3 +1,5 @@ +#![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/app.rs b/actix-web/src/app.rs index e53ab8080..353b82b19 100644 --- a/actix-web/src/app.rs +++ b/actix-web/src/app.rs @@ -712,6 +712,7 @@ mod tests { .route("/", web::to(|| async { "hello" })) } + #[allow(clippy::let_underscore_future)] let _ = init_service(my_app()); } } diff --git a/actix-web/src/lib.rs b/actix-web/src/lib.rs index 338541208..6a94976c5 100644 --- a/actix-web/src/lib.rs +++ b/actix-web/src/lib.rs @@ -69,6 +69,7 @@ #![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_cfg))] diff --git a/actix-web/tests/test_httpserver.rs b/actix-web/tests/test_httpserver.rs index 86e0575f3..861d76d93 100644 --- a/actix-web/tests/test_httpserver.rs +++ b/actix-web/tests/test_httpserver.rs @@ -1,3 +1,5 @@ +#![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 16ad330b8..26edcfd62 100644 --- a/awc/examples/client.rs +++ b/awc/examples/client.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use std::error::Error as StdError; #[tokio::main] diff --git a/awc/src/builder.rs b/awc/src/builder.rs index c101d18f0..34a5f8505 100644 --- a/awc/src/builder.rs +++ b/awc/src/builder.rs @@ -210,7 +210,7 @@ where }; self.add_default_header(( header::AUTHORIZATION, - format!("Basic {}", base64::encode(&auth)), + format!("Basic {}", base64::encode(auth)), )) } diff --git a/awc/src/lib.rs b/awc/src/lib.rs index 412ccbe61..bb7f06c93 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -105,7 +105,8 @@ #![allow( clippy::type_complexity, clippy::borrow_interior_mutable_const, - clippy::needless_doctest_main + clippy::needless_doctest_main, + clippy::uninlined_format_args )] #![doc(html_logo_url = "https://actix.rs/img/logo.png")] #![doc(html_favicon_url = "https://actix.rs/favicon.ico")] diff --git a/awc/src/request.rs b/awc/src/request.rs index 102db3c16..331c80af7 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -238,7 +238,7 @@ impl ClientRequest { self.insert_header(( header::AUTHORIZATION, - format!("Basic {}", base64::encode(&auth)), + format!("Basic {}", base64::encode(auth)), )) } @@ -565,6 +565,8 @@ mod tests { assert_eq!(req.head.version, Version::HTTP_2); let _ = req.headers_mut(); + + #[allow(clippy::let_underscore_future)] let _ = req.send_body(""); } diff --git a/awc/src/ws.rs b/awc/src/ws.rs index 4ef2e2b36..f905b8ef2 100644 --- a/awc/src/ws.rs +++ b/awc/src/ws.rs @@ -236,7 +236,7 @@ impl WebsocketsRequest { Some(password) => format!("{}:{}", username, password), None => format!("{}:", username), }; - self.header(AUTHORIZATION, format!("Basic {}", base64::encode(&auth))) + self.header(AUTHORIZATION, format!("Basic {}", base64::encode(auth))) } /// Set HTTP bearer authentication header @@ -503,6 +503,8 @@ mod tests { .unwrap(), "Bearer someS3cr3tAutht0k3n" ); + + #[allow(clippy::let_underscore_future)] let _ = req.connect(); } diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index db987fdfa..0949595cb 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -1,3 +1,5 @@ +#![allow(clippy::uninlined_format_args)] + use std::{ collections::HashMap, convert::Infallible, From 77459ec415a44ab90ed5b11ec6165f0dd0fe5e37 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 2 Jan 2023 00:14:25 +0000 Subject: [PATCH 02/44] add h2c example --- actix-http/examples/h2c-detect.rs | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 actix-http/examples/h2c-detect.rs diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs new file mode 100644 index 000000000..e1491324b --- /dev/null +++ b/actix-http/examples/h2c-detect.rs @@ -0,0 +1,54 @@ +//! An example that supports automatic selection of plaintext h1/h2c connections. +//! +//! Notably, both the following commands will work. +//! ```console +//! $ curl --http1.1 'http://localhost:8080/' +//! $ curl --http2-prior-knowledge 'http://localhost:8080/' +//! ``` + +use std::{convert::Infallible, io}; + +use actix_http::{HttpService, Protocol, Request, Response, StatusCode}; +use actix_rt::net::TcpStream; +use actix_server::Server; +use actix_service::{fn_service, ServiceFactoryExt}; + +const H2_PREFACE: &[u8] = b"PRI * HTTP/2"; + +#[actix_rt::main] +async fn main() -> io::Result<()> { + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + Server::build() + .bind("h2c-detect", ("127.0.0.1", 8080), || { + fn_service(move |io: TcpStream| async move { + let mut buf = [0; 12]; + + io.peek(&mut buf).await?; + + let proto = if buf == H2_PREFACE { + tracing::info!("selecting h2c"); + Protocol::Http2 + } else { + tracing::info!("selecting h1"); + Protocol::Http1 + }; + + let peer_addr = io.peer_addr().ok(); + Ok::<_, io::Error>((io, proto, peer_addr)) + }) + .and_then( + HttpService::build() + .finish(|_req: Request| async move { + Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) + }) + .map_err(|err| { + tracing::error!("{}", err); + io::Error::new(io::ErrorKind::Other, "http service dispatch error") + }), + ) + })? + .workers(2) + .run() + .await +} From d2364c80c4311d70f32a6a50e26a2a3ef43a9206 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 2 Jan 2023 00:16:59 +0000 Subject: [PATCH 03/44] improve error handling on new new example --- actix-http/examples/h2c-detect.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/actix-http/examples/h2c-detect.rs b/actix-http/examples/h2c-detect.rs index e1491324b..550a03d2a 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, Protocol, Request, Response, StatusCode}; +use actix_http::{error::DispatchError, HttpService, Protocol, Request, Response, StatusCode}; use actix_rt::net::TcpStream; use actix_server::Server; use actix_service::{fn_service, ServiceFactoryExt}; @@ -24,7 +24,7 @@ async fn main() -> io::Result<()> { fn_service(move |io: TcpStream| async move { let mut buf = [0; 12]; - io.peek(&mut buf).await?; + io.peek(&mut buf).await.map_err(DispatchError::Io)?; let proto = if buf == H2_PREFACE { tracing::info!("selecting h2c"); @@ -35,18 +35,11 @@ async fn main() -> io::Result<()> { }; let peer_addr = io.peer_addr().ok(); - Ok::<_, io::Error>((io, proto, peer_addr)) + Ok((io, proto, peer_addr)) }) - .and_then( - HttpService::build() - .finish(|_req: Request| async move { - Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) - }) - .map_err(|err| { - tracing::error!("{}", err); - io::Error::new(io::ErrorKind::Other, "http service dispatch error") - }), - ) + .and_then(HttpService::build().finish(|_req: Request| async move { + Ok::<_, Infallible>(Response::build(StatusCode::OK).body("Hello!")) + })) })? .workers(2) .run() From 7b936bc443d22fca679a1fca72b488adfecee3e6 Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 2 Jan 2023 13:33:31 +0000 Subject: [PATCH 04/44] add some useful header name constants (#2956) --- actix-http/CHANGES.md | 8 +++++++ actix-http/src/header/common.rs | 39 +++++++++++++++++++++++++++++++++ actix-http/src/header/mod.rs | 35 +++++++++++++++++++---------- 3 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 actix-http/src/header/common.rs diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 045ae461f..3c820ccf8 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -4,12 +4,20 @@ ### Added - Implement `MessageBody` for `&mut B` where `B: MessageBody + Unpin`. [#2868] - Implement `MessageBody` for `Pin` where `B::Target: MessageBody`. [#2868] +- Header name constants in `header` module. [#2956] + - `CROSS_ORIGIN_EMBEDDER_POLICY` + - `CROSS_ORIGIN_OPENER_POLICY` + - `PERMISSIONS_POLICY` + - `X_FORWARDED_FOR` + - `X_FORWARDED_HOST` + - `X_FORWARDED_PROTO` ### Performance - Improve overall performance of operations on `Extensions`. [#2890] [#2868]: https://github.com/actix/actix-web/pull/2868 [#2890]: https://github.com/actix/actix-web/pull/2890 +[#2956]: https://github.com/actix/actix-web/pull/2956 ## 3.2.2 - 2022-09-11 diff --git a/actix-http/src/header/common.rs b/actix-http/src/header/common.rs new file mode 100644 index 000000000..52909099a --- /dev/null +++ b/actix-http/src/header/common.rs @@ -0,0 +1,39 @@ +//! Common header names not defined in [`http`]. +//! +//! Any headers added to this file will need to be re-exported from the list at `crate::headers`. + +use http::header::HeaderName; + +/// Response header that prevents a document from loading any cross-origin resources that don't +/// explicitly grant the document permission (using [CORP] or [CORS]). +/// +/// [CORP]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP) +/// [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +pub const CROSS_ORIGIN_EMBEDDER_POLICY: HeaderName = + HeaderName::from_static("cross-origin-embedder-policy"); + +/// Response header that allows you to ensure a top-level document does not share a browsing context +/// group with cross-origin documents. +pub const CROSS_ORIGIN_OPENER_POLICY: HeaderName = + HeaderName::from_static("cross-origin-opener-policy"); + +/// Response header that conveys a desire that the browser blocks no-cors cross-origin/cross-site +/// requests to the given resource. +pub const CROSS_ORIGIN_RESOURCE_POLICY: HeaderName = + HeaderName::from_static("cross-origin-resource-policy"); + +/// Response header that provides a mechanism to allow and deny the use of browser features in a +/// document or within any `