From 42193bee295ce131f18fbc0d49b7206214717330 Mon Sep 17 00:00:00 2001
From: Lioness100
Date: Mon, 20 Feb 2023 03:11:16 -0500
Subject: [PATCH 001/278] 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 002/278] 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 003/278] 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
-[![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 005/278] 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 006/278] 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 007/278] 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 008/278] 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 009/278] 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 010/278] 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 011/278] 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 012/278] 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 013/278] 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 014/278] 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 015/278] 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 016/278] 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 017/278] 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 018/278] 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 019/278] 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 020/278] 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 021/278] 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 022/278] 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 023/278] 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 024/278] 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 025/278] 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 026/278] 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 027/278] 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 028/278] 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 029/278] 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 030/278] 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 031/278] 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 032/278] 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 033/278] 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 034/278] 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 035/278] 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 036/278] 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 037/278] 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 038/278] 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 039/278] 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 040/278] 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 041/278] 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 042/278] 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 043/278] 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 044/278] 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 045/278] 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 046/278] 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 047/278] 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
-[![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 048/278] 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 049/278] 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 050/278] 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 051/278] 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 052/278] 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 053/278] 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 054/278] 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