1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-07-03 01:34:32 +02:00

Compare commits

...

12 Commits

25 changed files with 141 additions and 78 deletions

View File

@ -1,6 +1,6 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 0.6.3 - 2023-01-21

View File

@ -1,6 +1,6 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 3.1.0 - 2023-01-21

View File

@ -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"] }

View File

@ -1,6 +1,6 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 3.3.0 - 2023-01-21

View File

@ -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"
@ -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"

View File

@ -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

View File

@ -0,0 +1,5 @@
# Changes
## 0.6.0 - 2023-02-26
- Add `MultipartForm` derive macro.

View File

@ -1,6 +1,6 @@
[package]
name = "actix-multipart-derive"
version = "0.5.0"
version = "0.6.0"
authors = ["Jacob Halsey <jacob@jhalsey.com>"]
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
@ -20,7 +24,7 @@ quote = "1"
syn = "1"
[dev-dependencies]
actix-multipart = "0.5"
actix-multipart = "0.6"
actix-web = "4"
rustversion = "1"
trybuild = "1"

View File

@ -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)
<br />
[![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

View File

@ -1,6 +1,8 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 0.6.0 - 2023-02-26
- Added `MultipartForm` typed data extractor. [#2883]

View File

@ -1,6 +1,6 @@
[package]
name = "actix-multipart"
version = "0.5.0"
version = "0.6.0"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Jacob Halsey <jacob@jhalsey.com>",
@ -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 }
@ -44,7 +40,7 @@ serde_json = "1"
serde_plain = "1"
# TODO(MSRV 1.60): replace with dep: prefix
tempfile-dep = { package = "tempfile", version = "3.4", optional = true }
tokio = { version = "1.18.5", features = ["sync"] }
tokio = { version = "1.24.2", features = ["sync"] }
[dev-dependencies]
actix-http = "3"
@ -53,5 +49,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"

View File

@ -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)
<br />
[![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)

View File

@ -1,6 +1,6 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 0.5.1 - 2022-09-19

View File

@ -1,7 +1,10 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-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.
## 0.1.0 - 2022-07-24

View File

@ -1,6 +1,6 @@
[package]
name = "actix-test"
version = "0.1.0"
version = "0.1.1"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@ -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"] }

View File

@ -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

View File

@ -1,6 +1,6 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 4.2.0 - 2023-01-21

View File

@ -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]

View File

@ -1,10 +1,10 @@
# Changes
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 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

View File

@ -1,6 +1,8 @@
# Changelog
## Unreleased - 2022-xx-xx
## Unreleased - 2023-xx-xx
## 4.3.1 - 2023-02-26
- Add support for custom methods with the `#[route]` macro. [#2969]

View File

@ -1,6 +1,6 @@
[package]
name = "actix-web"
version = "4.3.0"
version = "4.3.1"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
"Rob Ede <robjtede@icloud.com>",
@ -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"
@ -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.4"
time = { version = "0.3", default-features = false, features = ["formatting"] }
url = "2.1"
@ -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]]

View File

@ -5,7 +5,7 @@
</p>
<p>
[![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) <br /> [![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) <br /> [![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)
</p>
</div>

View File

@ -50,18 +50,24 @@ type DefaultHandler<B> = Option<Rc<ErrorHandler<B>>>;
/// will pass by unchanged by this middleware.
///
/// # Examples
/// ## Handler Response
/// Header
/// ```
/// use actix_web::http::{header, StatusCode};
/// use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers};
/// use actix_web::{dev, web, App, HttpResponse, Result};
///
/// fn add_error_header<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// Adding a header:
///
/// ```
/// use actix_web::{
/// dev::ServiceResponse,
/// http::{header, StatusCode},
/// middleware::{ErrorHandlerResponse, ErrorHandlers},
/// web, App, HttpResponse, Result,
/// };
///
/// fn add_error_header<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// 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,45 +76,62 @@ type DefaultHandler<B> = Option<Rc<ErrorHandler<B>>>;
/// .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<B>(res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// // 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<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// // 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};
/// fn add_error_header<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// # use actix_web::{
/// # dev::ServiceResponse,
/// # http::{header, StatusCode},
/// # middleware::{ErrorHandlerResponse, ErrorHandlers},
/// # web, App, HttpResponse, Result,
/// # };
/// fn add_error_header<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// 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()))
/// }
///
/// fn handle_bad_request<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// fn handle_bad_request<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// res.response_mut().headers_mut().insert(
/// 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,20 +145,24 @@ type DefaultHandler<B> = Option<Rc<ErrorHandler<B>>>;
/// )
/// .service(web::resource("/").route(web::get().to(HttpResponse::InternalServerError)));
/// ```
/// Alternatively, you can set default handlers for only client or only server errors:
///
/// ```rust
/// # use actix_web::http::{header, StatusCode};
/// # use actix_web::middleware::{ErrorHandlerResponse, ErrorHandlers};
/// # use actix_web::{dev, web, App, HttpResponse, Result};
/// # fn add_error_header<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// You can set default handlers for all client (4xx) or all server (5xx) errors:
///
/// ```
/// # use actix_web::{
/// # dev::ServiceResponse,
/// # http::{header, StatusCode},
/// # middleware::{ErrorHandlerResponse, ErrorHandlers},
/// # web, App, HttpResponse, Result,
/// # };
/// # fn add_error_header<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// # 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<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// # fn handle_bad_request<B>(mut res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
/// # res.response_mut().headers_mut().insert(
/// # header::CONTENT_TYPE,
/// # header::HeaderValue::from_static("Bad Request Error"),

View File

@ -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"
@ -80,7 +79,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 +105,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]]

View File

@ -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<AHashMap<Key, VecDeque<PooledConnection<Io>>>>,
available: RefCell<HashMap<Key, VecDeque<PooledConnection<Io>>>>,
permits: Arc<Semaphore>,
}