mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-09 12:26:16 +02:00
Compare commits
8 Commits
codegen-v4
...
test-v0.1.
Author | SHA1 | Date | |
---|---|---|---|
129b78f9c7 | |||
ad27150c5f | |||
8d5d6a2598 | |||
e97329eb2a | |||
fbfff3e751 | |||
fdfb3d45db | |||
4e05629368 | |||
e35ec28cd2 |
@ -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"] }
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
## 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.
|
||||
|
||||
## 0.1.0 - 2022-07-24
|
||||
|
@ -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"] }
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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]]
|
||||
|
@ -5,7 +5,7 @@
|
||||
</p>
|
||||
<p>
|
||||
|
||||
[](https://crates.io/crates/actix-web) [](https://docs.rs/actix-web/4.3.0)   [](https://deps.rs/crate/actix-web/4.3.0) <br /> [](https://github.com/actix/actix-web/actions/workflows/ci.yml) [](https://codecov.io/gh/actix/actix-web)  [](https://discord.gg/NWpN5mmg3x)
|
||||
[](https://crates.io/crates/actix-web) [](https://docs.rs/actix-web/4.3.1)   [](https://deps.rs/crate/actix-web/4.3.1) <br /> [](https://github.com/actix/actix-web/actions/workflows/ci.yml) [](https://codecov.io/gh/actix/actix-web)  [](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
@ -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"),
|
||||
|
@ -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]]
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user