From 51e54dac8b18ea0ac0b1d55f6a9d8af903e0e811 Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Wed, 27 Jan 2021 02:49:57 -0800
Subject: [PATCH 01/14] fix limit not working on HttpMessageBody::limit (#1938)
---
src/types/payload.rs | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/types/payload.rs b/src/types/payload.rs
index ce4a9cb1b..e8fba0632 100644
--- a/src/types/payload.rs
+++ b/src/types/payload.rs
@@ -289,10 +289,12 @@ impl HttpMessageBody {
if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) {
match l.to_str() {
Ok(s) => match s.parse::() {
- Ok(l) if l > DEFAULT_CONFIG_LIMIT => {
- err = Some(PayloadError::Overflow)
+ Ok(l) => {
+ if l > DEFAULT_CONFIG_LIMIT {
+ err = Some(PayloadError::Overflow);
+ }
+ length = Some(l)
}
- Ok(l) => length = Some(l),
Err(_) => err = Some(PayloadError::UnknownLength),
},
Err(_) => err = Some(PayloadError::UnknownLength),
@@ -316,9 +318,11 @@ impl HttpMessageBody {
/// Change max size of payload. By default max size is 256kB
pub fn limit(mut self, limit: usize) -> Self {
if let Some(l) = self.length {
- if l > limit {
- self.err = Some(PayloadError::Overflow);
- }
+ self.err = if l > limit {
+ Some(PayloadError::Overflow)
+ } else {
+ None
+ };
}
self.limit = limit;
self
From 83fb4978ad9c7758449d9fb71dc9eab5af442eb7 Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Sat, 6 Feb 2021 08:05:33 -0800
Subject: [PATCH 02/14] fix awc test_client test (#1960)
---
awc/tests/test_client.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs
index 88987e639..8ca94ec91 100644
--- a/awc/tests/test_client.rs
+++ b/awc/tests/test_client.rs
@@ -722,9 +722,9 @@ async fn test_client_cookie_handling() {
async fn client_unread_response() {
let addr = test::unused_addr();
- std::thread::spawn(move || {
- let lst = std::net::TcpListener::bind(addr).unwrap();
+ let lst = std::net::TcpListener::bind(addr).unwrap();
+ std::thread::spawn(move || {
for stream in lst.incoming() {
let mut stream = stream.unwrap();
let mut b = [0; 1000];
From 20cf0094e591f53c31aa87987c0875bcf3595a05 Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Sat, 6 Feb 2021 08:23:59 -0800
Subject: [PATCH 03/14] fix master branch build. change web::block output type.
(#1957)
---
CHANGES.md | 2 +
Cargo.toml | 6 +-
actix-files/Cargo.toml | 2 +-
actix-files/src/chunked.rs | 106 +++++++++++++++++------------
actix-files/src/named.rs | 16 +----
actix-http-test/Cargo.toml | 2 +-
actix-http/CHANGES.md | 2 +
actix-http/Cargo.toml | 2 +-
actix-http/src/encoding/decoder.rs | 11 +--
actix-http/src/encoding/encoder.rs | 13 +---
actix-http/src/error.rs | 27 +++-----
actix-multipart/Cargo.toml | 2 +-
actix-web-actors/Cargo.toml | 2 +-
actix-web-codegen/Cargo.toml | 2 +-
awc/Cargo.toml | 2 +-
src/test.rs | 2 +-
src/web.rs | 13 ++--
17 files changed, 98 insertions(+), 114 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index a6bcd56cc..3f6b09d7a 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -11,6 +11,7 @@
* `ServiceRequest::into_parts` and `ServiceRequest::from_parts` would not fail.
`ServiceRequest::from_request` would not fail and no payload would be generated [#1893]
* Our `Either` type now uses `Left`/`Right` variants (instead of `A`/`B`) [#1894]
+* `web::block` accept any closure that has an output bound to `Send` and `'static`. [#1957]
### Fixed
* Multiple calls `App::data` with the same type now keeps the latest call's data. [#1906]
@@ -28,6 +29,7 @@
[#1894]: https://github.com/actix/actix-web/pull/1894
[#1869]: https://github.com/actix/actix-web/pull/1869
[#1906]: https://github.com/actix/actix-web/pull/1906
+[#1957]: https://github.com/actix/actix-web/pull/1957
## 4.0.0-beta.1 - 2021-01-07
diff --git a/Cargo.toml b/Cargo.toml
index bae6cb6cb..28cee0dad 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -74,11 +74,11 @@ required-features = ["rustls"]
[dependencies]
actix-codec = "0.4.0-beta.1"
-actix-macros = "0.1.0"
+actix-macros = "=0.2.0-beta.1"
actix-router = "0.2.4"
-actix-rt = "2.0.0-beta.2"
+actix-rt = "=2.0.0-beta.2"
actix-server = "2.0.0-beta.2"
-actix-service = "2.0.0-beta.3"
+actix-service = "=2.0.0-beta.3"
actix-utils = "3.0.0-beta.1"
actix-tls = { version = "3.0.0-beta.2", default-features = false, optional = true }
diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml
index bde2cb717..b72631eb1 100644
--- a/actix-files/Cargo.toml
+++ b/actix-files/Cargo.toml
@@ -31,5 +31,5 @@ percent-encoding = "2.1"
v_htmlescape = "0.12"
[dev-dependencies]
-actix-rt = "2.0.0-beta.2"
+actix-rt = "=2.0.0-beta.2"
actix-web = "4.0.0-beta.1"
diff --git a/actix-files/src/chunked.rs b/actix-files/src/chunked.rs
index 5b7b17dc4..2a62b1d26 100644
--- a/actix-files/src/chunked.rs
+++ b/actix-files/src/chunked.rs
@@ -8,7 +8,7 @@ use std::{
};
use actix_web::{
- error::{Error, ErrorInternalServerError},
+ error::{BlockingError, Error},
rt::task::{spawn_blocking, JoinHandle},
};
use bytes::Bytes;
@@ -18,11 +18,26 @@ use futures_core::{ready, Stream};
/// A helper created from a `std::fs::File` which reads the file
/// chunk-by-chunk on a `ThreadPool`.
pub struct ChunkedReadFile {
- pub(crate) size: u64,
- pub(crate) offset: u64,
- pub(crate) file: Option,
- pub(crate) fut: Option>>,
- pub(crate) counter: u64,
+ size: u64,
+ offset: u64,
+ state: ChunkedReadFileState,
+ counter: u64,
+}
+
+enum ChunkedReadFileState {
+ File(Option),
+ Future(JoinHandle>),
+}
+
+impl ChunkedReadFile {
+ pub(crate) fn new(size: u64, offset: u64, file: File) -> Self {
+ Self {
+ size,
+ offset,
+ state: ChunkedReadFileState::File(Some(file)),
+ counter: 0,
+ }
+ }
}
impl fmt::Debug for ChunkedReadFile {
@@ -38,49 +53,52 @@ impl Stream for ChunkedReadFile {
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll
@@ -99,9 +98,9 @@ One of the fastest web frameworks available according to the
This project is licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
- [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
+ [http://www.apache.org/licenses/LICENSE-2.0])
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
- [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
+ [http://opensource.org/licenses/MIT])
at your option.
diff --git a/actix-http-test/Cargo.toml b/actix-http-test/Cargo.toml
index 0a804e109..25fd74a10 100644
--- a/actix-http-test/Cargo.toml
+++ b/actix-http-test/Cargo.toml
@@ -26,7 +26,7 @@ path = "src/lib.rs"
default = []
# openssl
-openssl = ["open-ssl", "awc/openssl"]
+openssl = ["tls-openssl", "awc/openssl"]
[dependencies]
actix-service = "2.0.0-beta.4"
@@ -47,8 +47,8 @@ serde = "1.0"
serde_json = "1.0"
slab = "0.4"
serde_urlencoded = "0.7"
-time = { version = "0.2.7", default-features = false, features = ["std"] }
-open-ssl = { version = "0.10", package = "openssl", optional = true }
+time = { version = "0.2.23", default-features = false, features = ["std"] }
+tls-openssl = { version = "0.10.9", package = "openssl", optional = true }
[dev-dependencies]
actix-web = "4.0.0-beta.1"
diff --git a/actix-http-test/src/lib.rs b/actix-http-test/src/lib.rs
index 2958b7f59..fcf8b3476 100644
--- a/actix-http-test/src/lib.rs
+++ b/actix-http-test/src/lib.rs
@@ -4,6 +4,9 @@
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+#[cfg(feature = "openssl")]
+extern crate tls_openssl as openssl;
+
use std::sync::mpsc;
use std::{net, thread, time};
@@ -82,7 +85,7 @@ pub async fn test_server_with_addr>(
let connector = {
#[cfg(feature = "openssl")]
{
- use open_ssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
+ use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
diff --git a/actix-http/Cargo.toml b/actix-http/Cargo.toml
index f55dc3b69..22a54f569 100644
--- a/actix-http/Cargo.toml
+++ b/actix-http/Cargo.toml
@@ -58,7 +58,7 @@ encoding_rs = "0.8"
futures-channel = { version = "0.3.7", default-features = false, features = ["alloc"] }
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
futures-util = { version = "0.3.7", default-features = false, features = ["alloc", "sink"] }
-ahash = "0.6"
+ahash = "0.7"
h2 = "0.3.0"
http = "0.2.2"
httparse = "1.3"
@@ -78,7 +78,7 @@ sha-1 = "0.9"
smallvec = "1.6"
slab = "0.4"
serde_urlencoded = "0.7"
-time = { version = "0.2.7", default-features = false, features = ["std"] }
+time = { version = "0.2.23", default-features = false, features = ["std"] }
# compression
brotli2 = { version="0.3.2", optional = true }
@@ -89,10 +89,10 @@ actix-server = "2.0.0-beta.3"
actix-http-test = { version = "3.0.0-beta.1", features = ["openssl"] }
actix-tls = { version = "3.0.0-beta.2", features = ["openssl"] }
criterion = "0.3"
-env_logger = "0.7"
+env_logger = "0.8"
serde_derive = "1.0"
-open-ssl = { version="0.10", package = "openssl" }
-rust-tls = { version="0.19", package = "rustls" }
+tls-openssl = { version = "0.10", package = "openssl" }
+tls-rustls = { version = "0.19", package = "rustls" }
[[bench]]
name = "write-camel-case"
diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs
index f20cfd70c..73bbe6208 100644
--- a/actix-http/tests/test_openssl.rs
+++ b/actix-http/tests/test_openssl.rs
@@ -1,4 +1,7 @@
#![cfg(feature = "openssl")]
+
+extern crate tls_openssl as openssl;
+
use std::io;
use actix_http::error::{ErrorBadRequest, PayloadError};
@@ -11,7 +14,7 @@ use actix_service::{fn_service, ServiceFactoryExt};
use bytes::{Bytes, BytesMut};
use futures_util::future::{err, ok, ready};
use futures_util::stream::{once, Stream, StreamExt};
-use open_ssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
+use openssl::ssl::{AlpnError, SslAcceptor, SslFiletype, SslMethod};
async fn load_body(stream: S) -> Result
where
diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs
index 2f6b31f49..59ffcfeb0 100644
--- a/actix-http/tests/test_rustls.rs
+++ b/actix-http/tests/test_rustls.rs
@@ -1,4 +1,7 @@
#![cfg(feature = "rustls")]
+
+extern crate tls_rustls as rustls;
+
use actix_http::error::PayloadError;
use actix_http::http::header::{self, HeaderName, HeaderValue};
use actix_http::http::{Method, StatusCode, Version};
@@ -9,7 +12,7 @@ use actix_service::{fn_factory_with_config, fn_service};
use bytes::{Bytes, BytesMut};
use futures_util::future::{self, err, ok};
use futures_util::stream::{once, Stream, StreamExt};
-use rust_tls::{
+use rustls::{
internal::pemfile::{certs, pkcs8_private_keys},
NoClientAuth, ServerConfig as RustlsServerConfig,
};
diff --git a/actix-web-actors/Cargo.toml b/actix-web-actors/Cargo.toml
index c6fd1c233..522279fd0 100644
--- a/actix-web-actors/Cargo.toml
+++ b/actix-web-actors/Cargo.toml
@@ -29,5 +29,5 @@ tokio = { version = "1", features = ["sync"] }
[dev-dependencies]
actix-rt = "2"
-env_logger = "0.7"
+env_logger = "0.8"
futures-util = { version = "0.3.7", default-features = false }
diff --git a/awc/Cargo.toml b/awc/Cargo.toml
index 24275b6f5..7a9130780 100644
--- a/awc/Cargo.toml
+++ b/awc/Cargo.toml
@@ -28,10 +28,10 @@ features = ["openssl", "rustls", "compress"]
default = ["compress"]
# openssl
-openssl = ["open-ssl", "actix-http/openssl"]
+openssl = ["tls-openssl", "actix-http/openssl"]
# rustls
-rustls = ["rust-tls", "actix-http/rustls"]
+rustls = ["tls-rustls", "actix-http/rustls"]
# content-encoding support
compress = ["actix-http/compress"]
@@ -54,8 +54,8 @@ rand = "0.8"
serde = "1.0"
serde_json = "1.0"
serde_urlencoded = "0.7"
-open-ssl = { version = "0.10", package = "openssl", optional = true }
-rust-tls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
+tls-openssl = { version = "0.10.9", package = "openssl", optional = true }
+tls-rustls = { version = "0.19.0", package = "rustls", optional = true, features = ["dangerous_configuration"] }
[dev-dependencies]
actix-web = { version = "4.0.0-beta.1", features = ["openssl"] }
@@ -68,6 +68,6 @@ actix-tls = { version = "3.0.0-beta.3", features = ["openssl", "rustls"] }
brotli2 = "0.3.2"
flate2 = "1.0.13"
futures-util = { version = "0.3.7", default-features = false }
-env_logger = "0.7"
+env_logger = "0.8"
rcgen = "0.8"
webpki = "0.21"
diff --git a/awc/tests/test_connector.rs b/awc/tests/test_connector.rs
index e500801c4..4e4fa5833 100644
--- a/awc/tests/test_connector.rs
+++ b/awc/tests/test_connector.rs
@@ -1,10 +1,13 @@
#![cfg(feature = "openssl")]
+
+extern crate tls_openssl as openssl;
+
use actix_http::HttpService;
use actix_http_test::test_server;
use actix_service::{map_config, ServiceFactoryExt};
use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse};
-use open_ssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode};
+use openssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode};
fn ssl_acceptor() -> SslAcceptor {
// load ssl keys
@@ -20,7 +23,7 @@ fn ssl_acceptor() -> SslAcceptor {
if protos.windows(3).any(|window| window == H2) {
Ok(b"h2")
} else {
- Err(open_ssl::ssl::AlpnError::NOACK)
+ Err(openssl::ssl::AlpnError::NOACK)
}
});
builder.set_alpn_protos(b"\x02h2").unwrap();
diff --git a/awc/tests/test_rustls_client.rs b/awc/tests/test_rustls_client.rs
index 2da3d9696..b0f3b71be 100644
--- a/awc/tests/test_rustls_client.rs
+++ b/awc/tests/test_rustls_client.rs
@@ -1,6 +1,6 @@
#![cfg(feature = "rustls")]
-extern crate rust_tls as rustls;
+extern crate tls_rustls as rustls;
use std::{
io::BufReader,
diff --git a/awc/tests/test_ssl_client.rs b/awc/tests/test_ssl_client.rs
index de1514042..064824d59 100644
--- a/awc/tests/test_ssl_client.rs
+++ b/awc/tests/test_ssl_client.rs
@@ -1,4 +1,7 @@
#![cfg(feature = "openssl")]
+
+extern crate tls_openssl as openssl;
+
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
@@ -8,7 +11,7 @@ use actix_service::{map_config, pipeline_factory, ServiceFactoryExt};
use actix_web::http::Version;
use actix_web::{dev::AppConfig, web, App, HttpResponse};
use futures_util::future::ok;
-use open_ssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode};
+use openssl::ssl::{SslAcceptor, SslConnector, SslFiletype, SslMethod, SslVerifyMode};
fn ssl_acceptor() -> SslAcceptor {
// load ssl keys
@@ -24,7 +27,7 @@ fn ssl_acceptor() -> SslAcceptor {
if protos.windows(3).any(|window| window == H2) {
Ok(b"h2")
} else {
- Err(open_ssl::ssl::AlpnError::NOACK)
+ Err(openssl::ssl::AlpnError::NOACK)
}
});
builder.set_alpn_protos(b"\x02h2").unwrap();
diff --git a/src/lib.rs b/src/lib.rs
index 52471f4b3..46fbc2937 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -71,6 +71,11 @@
#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
+#[cfg(feature = "openssl")]
+extern crate tls_openssl as openssl;
+#[cfg(feature = "rustls")]
+extern crate tls_rustls as rustls;
+
mod app;
mod app_service;
mod config;
diff --git a/src/test.rs b/src/test.rs
index 3acb520ff..62c329c91 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -773,7 +773,7 @@ where
let connector = {
#[cfg(feature = "openssl")]
{
- use open_ssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
+ use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
@@ -825,9 +825,9 @@ enum HttpVer {
enum StreamType {
Tcp,
#[cfg(feature = "openssl")]
- Openssl(open_ssl::ssl::SslAcceptor),
+ Openssl(openssl::ssl::SslAcceptor),
#[cfg(feature = "rustls")]
- Rustls(rust_tls::ServerConfig),
+ Rustls(rustls::ServerConfig),
}
impl Default for TestServerConfig {
@@ -865,14 +865,14 @@ impl TestServerConfig {
/// Start openssl server
#[cfg(feature = "openssl")]
- pub fn openssl(mut self, acceptor: open_ssl::ssl::SslAcceptor) -> Self {
+ pub fn openssl(mut self, acceptor: openssl::ssl::SslAcceptor) -> Self {
self.stream = StreamType::Openssl(acceptor);
self
}
/// Start rustls server
#[cfg(feature = "rustls")]
- pub fn rustls(mut self, config: rust_tls::ServerConfig) -> Self {
+ pub fn rustls(mut self, config: rustls::ServerConfig) -> Self {
self.stream = StreamType::Rustls(config);
self
}
diff --git a/tests/test_httpserver.rs b/tests/test_httpserver.rs
index 78d4ef685..cd5a75d49 100644
--- a/tests/test_httpserver.rs
+++ b/tests/test_httpserver.rs
@@ -2,7 +2,12 @@ use std::sync::mpsc;
use std::{thread, time::Duration};
#[cfg(feature = "openssl")]
-use open_ssl::ssl::SslAcceptorBuilder;
+extern crate tls_openssl as openssl;
+#[cfg(feature = "rustls")]
+extern crate tls_rustls as rustls;
+
+#[cfg(feature = "openssl")]
+use openssl::ssl::SslAcceptorBuilder;
use actix_web::{test, web, App, HttpResponse, HttpServer};
@@ -70,7 +75,7 @@ async fn test_start() {
#[allow(clippy::unnecessary_wraps)]
#[cfg(feature = "openssl")]
fn ssl_acceptor() -> std::io::Result {
- use open_ssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
+ use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
// load ssl keys
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder
@@ -116,7 +121,7 @@ async fn test_start_ssl() {
});
let (srv, sys) = rx.recv().unwrap();
- use open_ssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
+ use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
let mut builder = SslConnector::builder(SslMethod::tls()).unwrap();
builder.set_verify(SslVerifyMode::NONE);
let _ = builder
diff --git a/tests/test_server.rs b/tests/test_server.rs
index 0f51a2fdb..c626474cf 100644
--- a/tests/test_server.rs
+++ b/tests/test_server.rs
@@ -1,3 +1,8 @@
+#[cfg(feature = "openssl")]
+extern crate tls_openssl as openssl;
+#[cfg(feature = "rustls")]
+extern crate tls_rustls as rustls;
+
use std::{
future::Future,
io::{Read, Write},
@@ -713,7 +718,7 @@ async fn test_brotli_encoding_large() {
#[actix_rt::test]
async fn test_brotli_encoding_large_openssl() {
// load ssl keys
- use open_ssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
+ use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder
.set_private_key_file("tests/key.pem", SslFiletype::PEM)
@@ -753,8 +758,8 @@ async fn test_brotli_encoding_large_openssl() {
#[cfg(all(feature = "rustls", feature = "openssl"))]
#[actix_rt::test]
async fn test_reading_deflate_encoding_large_random_rustls() {
- use rust_tls::internal::pemfile::{certs, pkcs8_private_keys};
- use rust_tls::{NoClientAuth, ServerConfig};
+ use rustls::internal::pemfile::{certs, pkcs8_private_keys};
+ use rustls::{NoClientAuth, ServerConfig};
use std::fs::File;
use std::io::BufReader;
From 50309aa295ba38eb74998092850734b8c8bfa981 Mon Sep 17 00:00:00 2001
From: Jens Reidel
Date: Sun, 7 Feb 2021 05:50:23 +0100
Subject: [PATCH 08/14] Use askama-escape for html escaping (#1953)
---
actix-files/CHANGES.md | 2 ++
actix-files/Cargo.toml | 3 ++-
actix-files/src/directory.rs | 4 ++--
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/actix-files/CHANGES.md b/actix-files/CHANGES.md
index 9f606dfcd..8e5566b61 100644
--- a/actix-files/CHANGES.md
+++ b/actix-files/CHANGES.md
@@ -2,8 +2,10 @@
## Unreleased - 2021-xx-xx
* Fix If-Modified-Since and If-Unmodified-Since to not compare using sub-second timestamps. [#1887]
+* Replace `v_htmlescape` with `askama_escape`. [#1953]
[#1887]: https://github.com/actix/actix-web/pull/1887
+[#1953]: https://github.com/actix/actix-web/pull/1953
## 0.6.0-beta.1 - 2021-01-07
* `HttpRange::parse` now has its own error type.
diff --git a/actix-files/Cargo.toml b/actix-files/Cargo.toml
index 3371ab060..b4317596c 100644
--- a/actix-files/Cargo.toml
+++ b/actix-files/Cargo.toml
@@ -19,6 +19,8 @@ path = "src/lib.rs"
[dependencies]
actix-web = { version = "4.0.0-beta.1", default-features = false }
actix-service = "2.0.0-beta.4"
+
+askama_escape = "0.10"
bitflags = "1"
bytes = "1"
futures-core = { version = "0.3.7", default-features = false }
@@ -28,7 +30,6 @@ log = "0.4"
mime = "0.3"
mime_guess = "2.0.1"
percent-encoding = "2.1"
-v_htmlescape = "0.12"
[dev-dependencies]
actix-rt = "2"
diff --git a/actix-files/src/directory.rs b/actix-files/src/directory.rs
index 3717985d3..1103dd6a7 100644
--- a/actix-files/src/directory.rs
+++ b/actix-files/src/directory.rs
@@ -1,8 +1,8 @@
use std::{fmt::Write, fs::DirEntry, io, path::Path, path::PathBuf};
use actix_web::{dev::ServiceResponse, HttpRequest, HttpResponse};
+use askama_escape::{escape as escape_html_entity, Html};
use percent_encoding::{utf8_percent_encode, CONTROLS};
-use v_htmlescape::escape as escape_html_entity;
/// A directory; responds with the generated directory listing.
#[derive(Debug)]
@@ -50,7 +50,7 @@ macro_rules! encode_file_url {
// " -- " & -- & ' -- ' < -- < > -- > / -- /
macro_rules! encode_file_name {
($entry:ident) => {
- escape_html_entity(&$entry.file_name().to_string_lossy())
+ escape_html_entity(&$entry.file_name().to_string_lossy(), Html)
};
}
From deafb7c8b8038b3ab4bb80cf9b465a30453c7d44 Mon Sep 17 00:00:00 2001
From: Alexander Jackson
Date: Sun, 7 Feb 2021 04:54:41 +0000
Subject: [PATCH 09/14] Improve `impl ResponseError` documentation (#1939)
Co-authored-by: Rob Ede
---
actix-http/src/error.rs | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/actix-http/src/error.rs b/actix-http/src/error.rs
index 28697cbbf..7beedc3ba 100644
--- a/actix-http/src/error.rs
+++ b/actix-http/src/error.rs
@@ -147,7 +147,10 @@ impl From for Error {
}
}
-/// Return `GATEWAY_TIMEOUT` for `TimeoutError`
+/// Inspects the underlying enum and returns an appropriate status code.
+///
+/// If the variant is [`TimeoutError::Service`], the error code of the service is returned.
+/// Otherwise, [`StatusCode::GATEWAY_TIMEOUT`] is returned.
impl ResponseError for TimeoutError {
fn status_code(&self) -> StatusCode {
match self {
@@ -161,41 +164,44 @@ impl ResponseError for TimeoutError {
#[display(fmt = "UnknownError")]
struct UnitError;
-/// `InternalServerError` for `UnitError`
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`UnitError`].
impl ResponseError for UnitError {}
-/// `InternalServerError` for `JsonError`
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`JsonError`].
impl ResponseError for JsonError {}
-/// `InternalServerError` for `FormError`
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`FormError`].
impl ResponseError for FormError {}
#[cfg(feature = "openssl")]
-/// `InternalServerError` for `openssl::ssl::Error`
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`actix_tls::accept::openssl::SslError`].
impl ResponseError for actix_tls::accept::openssl::SslError {}
-/// Return `BAD_REQUEST` for `de::value::Error`
+/// Returns [`StatusCode::BAD_REQUEST`] for [`DeError`].
impl ResponseError for DeError {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
}
-/// `InternalServerError` for `Canceled`
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`Canceled`].
impl ResponseError for Canceled {}
-/// Return `BAD_REQUEST` for `Utf8Error`
+/// Returns [`StatusCode::BAD_REQUEST`] for [`Utf8Error`].
impl ResponseError for Utf8Error {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
}
-/// Return `InternalServerError` for `HttpError`,
-/// Response generation can return `HttpError`, so it is internal error
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`HttpError`].
impl ResponseError for HttpError {}
-/// Return `InternalServerError` for `io::Error`
+/// Inspects the underlying [`io::ErrorKind`] and returns an appropriate status code.
+///
+/// If the error is [`io::ErrorKind::NotFound`], [`StatusCode::NOT_FOUND`] is returned. If the
+/// error is [`io::ErrorKind::PermissionDenied`], [`StatusCode::FORBIDDEN`] is returned. Otherwise,
+/// [`StatusCode::INTERNAL_SERVER_ERROR`] is returned.
impl ResponseError for io::Error {
fn status_code(&self) -> StatusCode {
match self.kind() {
@@ -206,7 +212,7 @@ impl ResponseError for io::Error {
}
}
-/// `BadRequest` for `InvalidHeaderValue`
+/// Returns [`StatusCode::BAD_REQUEST`] for [`header::InvalidHeaderValue`].
impl ResponseError for header::InvalidHeaderValue {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
@@ -963,8 +969,9 @@ where
}
#[cfg(feature = "actors")]
-/// `InternalServerError` for `actix::MailboxError`
-/// This is supported on feature=`actors` only
+/// Returns [`StatusCode::INTERNAL_SERVER_ERROR`] for [`actix::MailboxError`].
+///
+/// This is only supported when the feature `actors` is enabled.
impl ResponseError for actix::MailboxError {}
#[cfg(test)]
From 4c243cbf89e680772ed8ec7dcdde143e026e2a6c Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Sun, 7 Feb 2021 10:56:39 -0800
Subject: [PATCH 10/14] simplify methods of awc::connect::Connect trait (#1941)
---
actix-http/src/h1/client.rs | 12 ---
actix-http/src/h1/encoder.rs | 16 +---
awc/src/connect.rs | 143 +++++------------------------------
awc/src/sender.rs | 43 ++++++-----
4 files changed, 49 insertions(+), 165 deletions(-)
diff --git a/actix-http/src/h1/client.rs b/actix-http/src/h1/client.rs
index 2e0103409..4a6104688 100644
--- a/actix-http/src/h1/client.rs
+++ b/actix-http/src/h1/client.rs
@@ -223,15 +223,3 @@ impl Encoder> for ClientCodec {
Ok(())
}
}
-
-pub struct Writer<'a>(pub &'a mut BytesMut);
-
-impl<'a> io::Write for Writer<'a> {
- fn write(&mut self, buf: &[u8]) -> io::Result {
- self.0.extend_from_slice(buf);
- Ok(buf.len())
- }
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
-}
diff --git a/actix-http/src/h1/encoder.rs b/actix-http/src/h1/encoder.rs
index bb89905fb..bd8287b26 100644
--- a/actix-http/src/h1/encoder.rs
+++ b/actix-http/src/h1/encoder.rs
@@ -337,7 +337,7 @@ impl MessageType for RequestHeadType {
let head = self.as_ref();
dst.reserve(256 + head.headers.len() * AVERAGE_HEADER_SIZE);
write!(
- Writer(dst),
+ helpers::Writer(dst),
"{} {} {}",
head.method,
head.uri.path_and_query().map(|u| u.as_str()).unwrap_or("/"),
@@ -470,7 +470,7 @@ impl TransferEncoding {
*eof = true;
buf.extend_from_slice(b"0\r\n\r\n");
} else {
- writeln!(Writer(buf), "{:X}\r", msg.len())
+ writeln!(helpers::Writer(buf), "{:X}\r", msg.len())
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
buf.reserve(msg.len() + 2);
@@ -520,18 +520,6 @@ impl TransferEncoding {
}
}
-struct Writer<'a>(pub &'a mut BytesMut);
-
-impl<'a> io::Write for Writer<'a> {
- fn write(&mut self, buf: &[u8]) -> io::Result {
- self.0.extend_from_slice(buf);
- Ok(buf.len())
- }
- fn flush(&mut self) -> io::Result<()> {
- Ok(())
- }
-}
-
/// # Safety
/// Callers must ensure that the given length matches given value length.
unsafe fn write_data(value: &[u8], buf: *mut u8, len: usize) {
diff --git a/awc/src/connect.rs b/awc/src/connect.rs
index 2ffb8ec37..5450550a7 100644
--- a/awc/src/connect.rs
+++ b/awc/src/connect.rs
@@ -1,71 +1,39 @@
-use std::future::Future;
-use std::pin::Pin;
-use std::rc::Rc;
-use std::task::{Context, Poll};
-use std::{fmt, io, net};
+use std::{
+ fmt, io, net,
+ pin::Pin,
+ task::{Context, Poll},
+};
use actix_codec::{AsyncRead, AsyncWrite, Framed, ReadBuf};
-use actix_http::body::Body;
-use actix_http::client::{
- Connect as ClientConnect, ConnectError, Connection, SendRequestError,
+use actix_http::{
+ body::Body,
+ client::{Connect as ClientConnect, ConnectError, Connection, SendRequestError},
+ h1::ClientCodec,
+ RequestHead, RequestHeadType, ResponseHead,
};
-use actix_http::h1::ClientCodec;
-use actix_http::http::HeaderMap;
-use actix_http::{RequestHead, RequestHeadType, ResponseHead};
use actix_service::Service;
+use futures_core::future::LocalBoxFuture;
use crate::response::ClientResponse;
pub(crate) struct ConnectorWrapper(pub T);
+type TunnelResponse = (ResponseHead, Framed);
+
pub(crate) trait Connect {
fn send_request(
&self,
- head: RequestHead,
+ head: RequestHeadType,
body: Body,
addr: Option,
- ) -> Pin>>>;
-
- fn send_request_extra(
- &self,
- head: Rc,
- extra_headers: Option,
- body: Body,
- addr: Option,
- ) -> Pin>>>;
+ ) -> LocalBoxFuture<'static, Result>;
/// Send request, returns Response and Framed
fn open_tunnel(
&self,
head: RequestHead,
addr: Option,
- ) -> Pin<
- Box<
- dyn Future<
- Output = Result<
- (ResponseHead, Framed),
- SendRequestError,
- >,
- >,
- >,
- >;
-
- /// Send request and extra headers, returns Response and Framed
- fn open_tunnel_extra(
- &self,
- head: Rc,
- extra_headers: Option,
- addr: Option,
- ) -> Pin<
- Box<
- dyn Future<
- Output = Result<
- (ResponseHead, Framed),
- SendRequestError,
- >,
- >,
- >,
- >;
+ ) -> LocalBoxFuture<'static, Result>;
}
impl Connect for ConnectorWrapper
@@ -79,13 +47,13 @@ where
{
fn send_request(
&self,
- head: RequestHead,
+ head: RequestHeadType,
body: Body,
addr: Option,
- ) -> Pin>>> {
+ ) -> LocalBoxFuture<'static, Result> {
// connect to the host
let fut = self.0.call(ClientConnect {
- uri: head.uri.clone(),
+ uri: head.as_ref().uri.clone(),
addr,
});
@@ -93,33 +61,7 @@ where
let connection = fut.await?;
// send request
- connection
- .send_request(RequestHeadType::from(head), body)
- .await
- .map(|(head, payload)| ClientResponse::new(head, payload))
- })
- }
-
- fn send_request_extra(
- &self,
- head: Rc,
- extra_headers: Option,
- body: Body,
- addr: Option,
- ) -> Pin>>> {
- // connect to the host
- let fut = self.0.call(ClientConnect {
- uri: head.uri.clone(),
- addr,
- });
-
- Box::pin(async move {
- let connection = fut.await?;
-
- // send request
- let (head, payload) = connection
- .send_request(RequestHeadType::Rc(head, extra_headers), body)
- .await?;
+ let (head, payload) = connection.send_request(head, body).await?;
Ok(ClientResponse::new(head, payload))
})
@@ -129,16 +71,7 @@ where
&self,
head: RequestHead,
addr: Option,
- ) -> Pin<
- Box<
- dyn Future<
- Output = Result<
- (ResponseHead, Framed),
- SendRequestError,
- >,
- >,
- >,
- > {
+ ) -> LocalBoxFuture<'static, Result> {
// connect to the host
let fut = self.0.call(ClientConnect {
uri: head.uri.clone(),
@@ -156,40 +89,6 @@ where
Ok((head, framed))
})
}
-
- fn open_tunnel_extra(
- &self,
- head: Rc,
- extra_headers: Option,
- addr: Option,
- ) -> Pin<
- Box<
- dyn Future<
- Output = Result<
- (ResponseHead, Framed),
- SendRequestError,
- >,
- >,
- >,
- > {
- // connect to the host
- let fut = self.0.call(ClientConnect {
- uri: head.uri.clone(),
- addr,
- });
-
- Box::pin(async move {
- let connection = fut.await?;
-
- // send request
- let (head, framed) = connection
- .open_tunnel(RequestHeadType::Rc(head, extra_headers))
- .await?;
-
- let framed = framed.into_map_io(|io| BoxedSocket(Box::new(Socket(io))));
- Ok((head, framed))
- })
- }
}
trait AsyncSocket {
diff --git a/awc/src/sender.rs b/awc/src/sender.rs
index 5f790a038..1cf863d96 100644
--- a/awc/src/sender.rs
+++ b/awc/src/sender.rs
@@ -1,21 +1,26 @@
-use std::future::Future;
-use std::net;
-use std::pin::Pin;
-use std::rc::Rc;
-use std::task::{Context, Poll};
-use std::time::Duration;
+use std::{
+ future::Future,
+ net,
+ pin::Pin,
+ rc::Rc,
+ task::{Context, Poll},
+ time::Duration,
+};
+use actix_http::{
+ body::{Body, BodyStream},
+ http::{
+ header::{self, HeaderMap, HeaderName, IntoHeaderValue},
+ Error as HttpError,
+ },
+ Error, RequestHead, RequestHeadType,
+};
use actix_rt::time::{sleep, Sleep};
use bytes::Bytes;
use derive_more::From;
use futures_core::Stream;
use serde::Serialize;
-use actix_http::body::{Body, BodyStream};
-use actix_http::http::header::{self, IntoHeaderValue};
-use actix_http::http::{Error as HttpError, HeaderMap, HeaderName};
-use actix_http::{Error, RequestHead};
-
#[cfg(feature = "compress")]
use actix_http::encoding::Decoder;
#[cfg(feature = "compress")]
@@ -184,12 +189,16 @@ impl RequestSender {
B: Into,
{
let fut = match self {
- RequestSender::Owned(head) => {
- config.connector.send_request(head, body.into(), addr)
- }
- RequestSender::Rc(head, extra_headers) => config
- .connector
- .send_request_extra(head, extra_headers, body.into(), addr),
+ RequestSender::Owned(head) => config.connector.send_request(
+ RequestHeadType::Owned(head),
+ body.into(),
+ addr,
+ ),
+ RequestSender::Rc(head, extra_headers) => config.connector.send_request(
+ RequestHeadType::Rc(head, extra_headers),
+ body.into(),
+ addr,
+ ),
};
SendClientRequest::new(fut, response_decompress, timeout.or(config.timeout))
From dbc47c9122b5731a11a5e1dc388efd0a13d65754 Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Sun, 7 Feb 2021 12:19:10 -0800
Subject: [PATCH 11/14] optimize actix-http messages (#1914)
---
actix-http/src/message.rs | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/actix-http/src/message.rs b/actix-http/src/message.rs
index bccb4d53e..736f35ee1 100644
--- a/actix-http/src/message.rs
+++ b/actix-http/src/message.rs
@@ -343,6 +343,8 @@ impl ResponseHead {
}
pub struct Message {
+ // Rc here should not be cloned by anyone.
+ // It's used to reuse allocation of T and no shared ownership is allowed.
head: Rc,
}
@@ -353,14 +355,6 @@ impl Message {
}
}
-impl Clone for Message {
- fn clone(&self) -> Self {
- Message {
- head: self.head.clone(),
- }
- }
-}
-
impl std::ops::Deref for Message {
type Target = T;
@@ -377,9 +371,7 @@ impl std::ops::DerefMut for Message {
impl Drop for Message {
fn drop(&mut self) {
- if Rc::strong_count(&self.head) == 1 {
- T::with_pool(|p| p.release(self.head.clone()))
- }
+ T::with_pool(|p| p.release(self.head.clone()))
}
}
From 9604e249c9c840decd22ac6d66252063690e987c Mon Sep 17 00:00:00 2001
From: Rob Ede
Date: Sun, 7 Feb 2021 20:33:53 +0000
Subject: [PATCH 12/14] use stable clippy (#1963)
---
.github/workflows/bench.yml | 2 +-
.github/workflows/clippy-fmt.yml | 21 ++++++++++++++-------
.github/workflows/upload-doc.yml | 2 +-
src/middleware/condition.rs | 1 -
src/middleware/err_handlers.rs | 2 --
tests/test_httpserver.rs | 1 -
6 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml
index d19471a16..828d62561 100644
--- a/.github/workflows/bench.yml
+++ b/.github/workflows/bench.yml
@@ -1,4 +1,4 @@
-name: Benchmark (Linux)
+name: Benchmark
on:
pull_request:
diff --git a/.github/workflows/clippy-fmt.yml b/.github/workflows/clippy-fmt.yml
index fb1ed7f32..e966fa4ab 100644
--- a/.github/workflows/clippy-fmt.yml
+++ b/.github/workflows/clippy-fmt.yml
@@ -1,32 +1,39 @@
+name: Lint
+
on:
pull_request:
types: [opened, synchronize, reopened]
-name: Clippy and rustfmt Check
jobs:
- clippy_check:
+ fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - uses: actions-rs/toolchain@v1
+ - name: Install Rust
+ uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt
- override: true
- name: Check with rustfmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- - uses: actions-rs/toolchain@v1
+ clippy:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Rust
+ uses: actions-rs/toolchain@v1
with:
- toolchain: nightly
+ toolchain: stable
components: clippy
override: true
- name: Check with Clippy
uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- args: --all-features --all --tests
+ args: --workspace --tests --all-features
diff --git a/.github/workflows/upload-doc.yml b/.github/workflows/upload-doc.yml
index ba87a5637..c080dd8c3 100644
--- a/.github/workflows/upload-doc.yml
+++ b/.github/workflows/upload-doc.yml
@@ -24,7 +24,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: doc
- args: --no-deps --workspace --all-features
+ args: --workspace --all-features --no-deps
- name: Tweak HTML
run: echo "" > target/doc/index.html
diff --git a/src/middleware/condition.rs b/src/middleware/condition.rs
index 85eba3fb8..9263292b9 100644
--- a/src/middleware/condition.rs
+++ b/src/middleware/condition.rs
@@ -106,7 +106,6 @@ mod tests {
HttpResponse,
};
- #[allow(clippy::unnecessary_wraps)]
fn render_500(mut res: ServiceResponse) -> Result> {
res.response_mut()
.headers_mut()
diff --git a/src/middleware/err_handlers.rs b/src/middleware/err_handlers.rs
index 70933241d..b55959460 100644
--- a/src/middleware/err_handlers.rs
+++ b/src/middleware/err_handlers.rs
@@ -182,7 +182,6 @@ mod tests {
use crate::test::{self, TestRequest};
use crate::HttpResponse;
- #[allow(clippy::unnecessary_wraps)]
fn render_500(mut res: ServiceResponse) -> Result> {
res.response_mut()
.headers_mut()
@@ -207,7 +206,6 @@ mod tests {
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
}
- #[allow(clippy::unnecessary_wraps)]
fn render_500_async(
mut res: ServiceResponse,
) -> Result> {
diff --git a/tests/test_httpserver.rs b/tests/test_httpserver.rs
index cd5a75d49..07c171674 100644
--- a/tests/test_httpserver.rs
+++ b/tests/test_httpserver.rs
@@ -72,7 +72,6 @@ async fn test_start() {
let _ = sys.stop();
}
-#[allow(clippy::unnecessary_wraps)]
#[cfg(feature = "openssl")]
fn ssl_acceptor() -> std::io::Result {
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
From 266cf0622c18fe569f6af3f0de19f0a226c98bc0 Mon Sep 17 00:00:00 2001
From: fakeshadow <24548779@qq.com>
Date: Sun, 7 Feb 2021 14:48:27 -0800
Subject: [PATCH 13/14] reduce branch.remove deadcode for h1 dispatcher (#1962)
---
actix-http/src/h1/dispatcher.rs | 202 +++++++++++++++-----------------
1 file changed, 95 insertions(+), 107 deletions(-)
diff --git a/actix-http/src/h1/dispatcher.rs b/actix-http/src/h1/dispatcher.rs
index e65a1bd56..f8fc95921 100644
--- a/actix-http/src/h1/dispatcher.rs
+++ b/actix-http/src/h1/dispatcher.rs
@@ -734,6 +734,78 @@ where
}
Ok(())
}
+
+ /// Returns true when io stream can be disconnected after write to it.
+ ///
+ /// It covers these conditions:
+ ///
+ /// - `std::io::ErrorKind::ConnectionReset` after partial read.
+ /// - all data read done.
+ #[inline(always)]
+ fn read_available(
+ self: Pin<&mut Self>,
+ cx: &mut Context<'_>,
+ ) -> Result {
+ let this = self.project();
+
+ if this.flags.contains(Flags::READ_DISCONNECT) {
+ return Ok(false);
+ };
+
+ let mut io = Pin::new(this.io.as_mut().unwrap());
+
+ let mut read_some = false;
+
+ loop {
+ // grow buffer if necessary.
+ let remaining = this.read_buf.capacity() - this.read_buf.len();
+ if remaining < LW_BUFFER_SIZE {
+ this.read_buf.reserve(HW_BUFFER_SIZE - remaining);
+ }
+
+ match actix_codec::poll_read_buf(io.as_mut(), cx, this.read_buf) {
+ Poll::Pending => return Ok(false),
+ Poll::Ready(Ok(n)) => {
+ if n == 0 {
+ return Ok(true);
+ } else {
+ // Return early when read buf exceed decoder's max buffer size.
+ if this.read_buf.len() >= super::decoder::MAX_BUFFER_SIZE {
+ // at this point it's not known io is still scheduled to
+ // be waked up. so force wake up dispatcher just in case.
+ // TODO: figure out the overhead.
+ cx.waker().wake_by_ref();
+ return Ok(false);
+ }
+
+ read_some = true;
+ }
+ }
+ Poll::Ready(Err(err)) => {
+ return if err.kind() == io::ErrorKind::WouldBlock {
+ Ok(false)
+ } else if err.kind() == io::ErrorKind::ConnectionReset && read_some {
+ Ok(true)
+ } else {
+ Err(DispatchError::Io(err))
+ }
+ }
+ }
+ }
+ }
+
+ /// call upgrade service with request.
+ fn upgrade(self: Pin<&mut Self>, req: Request) -> U::Future {
+ let this = self.project();
+ let mut parts = FramedParts::with_read_buf(
+ this.io.take().unwrap(),
+ mem::take(this.codec),
+ mem::take(this.read_buf),
+ );
+ parts.write_buf = mem::take(this.write_buf);
+ let framed = Framed::from_parts(parts);
+ this.flow.upgrade.as_ref().unwrap().call((req, framed))
+ }
}
impl Future for Dispatcher
@@ -778,60 +850,36 @@ where
}
}
} else {
- // read socket into a buf
- let should_disconnect =
- if !inner.flags.contains(Flags::READ_DISCONNECT) {
- let mut inner_p = inner.as_mut().project();
- read_available(
- cx,
- inner_p.io.as_mut().unwrap(),
- &mut inner_p.read_buf,
- )?
- } else {
- None
- };
+ // read from io stream and fill read buffer.
+ let should_disconnect = inner.as_mut().read_available(cx)?;
inner.as_mut().poll_request(cx)?;
- if let Some(true) = should_disconnect {
- let inner_p = inner.as_mut().project();
- inner_p.flags.insert(Flags::READ_DISCONNECT);
- if let Some(mut payload) = inner_p.payload.take() {
+
+ // io stream should to be closed.
+ if should_disconnect {
+ let inner = inner.as_mut().project();
+ inner.flags.insert(Flags::READ_DISCONNECT);
+ if let Some(mut payload) = inner.payload.take() {
payload.feed_eof();
}
};
loop {
- let inner_p = inner.as_mut().project();
- let remaining =
- inner_p.write_buf.capacity() - inner_p.write_buf.len();
- if remaining < LW_BUFFER_SIZE {
- inner_p.write_buf.reserve(HW_BUFFER_SIZE - remaining);
- }
- let result = inner.as_mut().poll_response(cx)?;
- let drain = result == PollResponse::DrainWriteBuf;
-
- // switch to upgrade handler
- if let PollResponse::Upgrade(req) = result {
- let inner_p = inner.as_mut().project();
- let mut parts = FramedParts::with_read_buf(
- inner_p.io.take().unwrap(),
- mem::take(inner_p.codec),
- mem::take(inner_p.read_buf),
- );
- parts.write_buf = mem::take(inner_p.write_buf);
- let framed = Framed::from_parts(parts);
- let upgrade = inner_p
- .flow
- .upgrade
- .as_ref()
- .unwrap()
- .call((req, framed));
- self.as_mut()
- .project()
- .inner
- .set(DispatcherState::Upgrade(upgrade));
- return self.poll(cx);
- }
+ // poll_response and populate write buffer.
+ // drain indicate if write buffer should be emptied before next run.
+ let drain = match inner.as_mut().poll_response(cx)? {
+ PollResponse::DrainWriteBuf => true,
+ PollResponse::DoNothing => false,
+ // upgrade request and goes Upgrade variant of DispatcherState.
+ PollResponse::Upgrade(req) => {
+ let upgrade = inner.upgrade(req);
+ self.as_mut()
+ .project()
+ .inner
+ .set(DispatcherState::Upgrade(upgrade));
+ return self.poll(cx);
+ }
+ };
// we didn't get WouldBlock from write operation,
// so data get written to kernel completely (macOS)
@@ -888,66 +936,6 @@ where
}
}
-/// Returns either:
-/// - `Ok(Some(true))` - data was read and done reading all data.
-/// - `Ok(Some(false))` - data was read but there should be more to read.
-/// - `Ok(None)` - no data was read but there should be more to read later.
-/// - Unhandled Errors
-fn read_available(
- cx: &mut Context<'_>,
- io: &mut T,
- buf: &mut BytesMut,
-) -> Result