,
+
flags: Flags,
}
diff --git a/actix-http/src/requests/mod.rs b/actix-http/src/requests/mod.rs
index fc35da65a..4a27818a5 100644
--- a/actix-http/src/requests/mod.rs
+++ b/actix-http/src/requests/mod.rs
@@ -3,5 +3,7 @@
mod head;
mod request;
-pub use self::head::{RequestHead, RequestHeadType};
-pub use self::request::Request;
+pub use self::{
+ head::{RequestHead, RequestHeadType},
+ request::Request,
+};
diff --git a/actix-http/src/requests/request.rs b/actix-http/src/requests/request.rs
index ac358e8df..6a267a7a6 100644
--- a/actix-http/src/requests/request.rs
+++ b/actix-http/src/requests/request.rs
@@ -10,8 +10,7 @@ use std::{
use http::{header, Method, Uri, Version};
use crate::{
- header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload,
- RequestHead,
+ header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload, RequestHead,
};
/// An HTTP request.
@@ -174,7 +173,7 @@ impl Request
{
/// Peer address is the directly connected peer's socket address. If a proxy is used in front of
/// the Actix Web server, then it would be address of this proxy.
///
- /// Will only return None when called in unit tests.
+ /// Will only return None when called in unit tests unless set manually.
#[inline]
pub fn peer_addr(&self) -> Option {
self.head().peer_addr
@@ -234,7 +233,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/responses/builder.rs b/actix-http/src/responses/builder.rs
index 063af92da..bb7d0f712 100644
--- a/actix-http/src/responses/builder.rs
+++ b/actix-http/src/responses/builder.rs
@@ -93,7 +93,7 @@ impl ResponseBuilder {
Ok((key, value)) => {
parts.headers.insert(key, value);
}
- Err(e) => self.err = Some(e.into()),
+ Err(err) => self.err = Some(err.into()),
};
}
@@ -119,7 +119,7 @@ impl ResponseBuilder {
if let Some(parts) = self.inner() {
match header.try_into_pair() {
Ok((key, value)) => parts.headers.append(key, value),
- Err(e) => self.err = Some(e.into()),
+ Err(err) => self.err = Some(err.into()),
};
}
@@ -193,7 +193,7 @@ impl ResponseBuilder {
Ok(value) => {
parts.headers.insert(header::CONTENT_TYPE, value);
}
- Err(e) => self.err = Some(e.into()),
+ Err(err) => self.err = Some(err.into()),
};
}
self
@@ -351,12 +351,9 @@ mod tests {
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain");
let resp = Response::build(StatusCode::OK)
- .content_type(mime::APPLICATION_JAVASCRIPT_UTF_8)
+ .content_type(mime::TEXT_JAVASCRIPT)
.body(Bytes::new());
- assert_eq!(
- resp.headers().get(CONTENT_TYPE).unwrap(),
- "application/javascript; charset=utf-8"
- );
+ assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/javascript");
}
#[test]
diff --git a/actix-http/src/responses/mod.rs b/actix-http/src/responses/mod.rs
index 899232b9f..d99628232 100644
--- a/actix-http/src/responses/mod.rs
+++ b/actix-http/src/responses/mod.rs
@@ -5,7 +5,5 @@ mod head;
#[allow(clippy::module_inception)]
mod response;
-pub use self::builder::ResponseBuilder;
pub(crate) use self::head::BoxedResponseHead;
-pub use self::head::ResponseHead;
-pub use self::response::Response;
+pub use self::{builder::ResponseBuilder, head::ResponseHead, response::Response};
diff --git a/actix-http/src/service.rs b/actix-http/src/service.rs
index 22177b849..3be099d9f 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.
@@ -200,13 +200,8 @@ where
/// The resulting service only supports HTTP/1.x.
pub fn tcp(
self,
- ) -> impl ServiceFactory<
- TcpStream,
- Config = (),
- Response = (),
- Error = DispatchError,
- InitError = (),
- > {
+ ) -> impl ServiceFactory
+ {
fn_service(|io: TcpStream| async {
let peer_addr = io.peer_addr().ok();
Ok((io, Protocol::Http1, peer_addr))
@@ -219,13 +214,8 @@ where
#[cfg(feature = "http2")]
pub fn tcp_auto_h2c(
self,
- ) -> impl ServiceFactory<
- TcpStream,
- Config = (),
- Response = (),
- Error = DispatchError,
- InitError = (),
- > {
+ ) -> impl ServiceFactory
+ {
fn_service(move |io: TcpStream| async move {
// subset of HTTP/2 preface defined by RFC 9113 §3.4
// this subset was chosen to maximize likelihood that peeking only once will allow us to
@@ -251,13 +241,13 @@ where
}
/// Configuration options used when accepting TLS connection.
-#[cfg(any(feature = "openssl", feature = "rustls"))]
+#[cfg(feature = "__tls")]
#[derive(Debug, Default)]
pub struct TlsAcceptorConfig {
pub(crate) handshake_timeout: Option,
}
-#[cfg(any(feature = "openssl", feature = "rustls"))]
+#[cfg(feature = "__tls")]
impl TlsAcceptorConfig {
/// Set TLS handshake timeout duration.
pub fn handshake_timeout(self, dur: std::time::Duration) -> Self {
@@ -362,13 +352,13 @@ mod openssl {
}
}
-#[cfg(feature = "rustls")]
-mod rustls {
+#[cfg(feature = "rustls-0_20")]
+mod rustls_0_20 {
use std::io;
use actix_service::ServiceFactoryExt as _;
use actix_tls::accept::{
- rustls::{reexports::ServerConfig, Acceptor, TlsStream},
+ rustls_0_20::{reexports::ServerConfig, Acceptor, TlsStream},
TlsError,
};
@@ -399,7 +389,7 @@ mod rustls {
U::Error: fmt::Display + Into>,
U::InitError: fmt::Debug,
{
- /// Create Rustls based service.
+ /// Create Rustls v0.20 based service.
pub fn rustls(
self,
config: ServerConfig,
@@ -413,7 +403,7 @@ mod rustls {
self.rustls_with_config(config, TlsAcceptorConfig::default())
}
- /// Create Rustls based service with custom TLS acceptor configuration.
+ /// Create Rustls v0.20 based service with custom TLS acceptor configuration.
pub fn rustls_with_config(
self,
mut config: ServerConfig,
@@ -458,6 +448,294 @@ mod rustls {
}
}
+#[cfg(feature = "rustls-0_21")]
+mod rustls_0_21 {
+ use std::io;
+
+ use actix_service::ServiceFactoryExt as _;
+ use actix_tls::accept::{
+ rustls_0_21::{reexports::ServerConfig, Acceptor, TlsStream},
+ TlsError,
+ };
+
+ use super::*;
+
+ impl HttpService, S, B, X, U>
+ where
+ S: ServiceFactory,
+ S::Future: 'static,
+ S::Error: Into> + 'static,
+ S::InitError: fmt::Debug,
+ S::Response: Into> + 'static,
+ >::Future: 'static,
+
+ B: MessageBody + 'static,
+
+ X: ServiceFactory,
+ X::Future: 'static,
+ X::Error: Into>,
+ X::InitError: fmt::Debug,
+
+ U: ServiceFactory<
+ (Request, Framed, h1::Codec>),
+ Config = (),
+ Response = (),
+ >,
+ U::Future: 'static,
+ U::Error: fmt::Display + Into>,
+ U::InitError: fmt::Debug,
+ {
+ /// Create Rustls v0.21 based service.
+ pub fn rustls_021(
+ self,
+ config: ServerConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ self.rustls_021_with_config(config, TlsAcceptorConfig::default())
+ }
+
+ /// Create Rustls v0.21 based service with custom TLS acceptor configuration.
+ pub fn rustls_021_with_config(
+ self,
+ mut config: ServerConfig,
+ tls_acceptor_config: TlsAcceptorConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
+ protos.extend_from_slice(&config.alpn_protocols);
+ config.alpn_protocols = protos;
+
+ let mut acceptor = Acceptor::new(config);
+
+ if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
+ acceptor.set_handshake_timeout(handshake_timeout);
+ }
+
+ acceptor
+ .map_init_err(|_| {
+ unreachable!("TLS acceptor service factory does not error on init")
+ })
+ .map_err(TlsError::into_service_error)
+ .and_then(|io: TlsStream| async {
+ let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() {
+ if protos.windows(2).any(|window| window == b"h2") {
+ Protocol::Http2
+ } else {
+ Protocol::Http1
+ }
+ } else {
+ Protocol::Http1
+ };
+ let peer_addr = io.get_ref().0.peer_addr().ok();
+ Ok((io, proto, peer_addr))
+ })
+ .and_then(self.map_err(TlsError::Service))
+ }
+ }
+}
+
+#[cfg(feature = "rustls-0_22")]
+mod rustls_0_22 {
+ use std::io;
+
+ use actix_service::ServiceFactoryExt as _;
+ use actix_tls::accept::{
+ rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream},
+ TlsError,
+ };
+
+ use super::*;
+
+ impl HttpService, S, B, X, U>
+ where
+ S: ServiceFactory,
+ S::Future: 'static,
+ S::Error: Into> + 'static,
+ S::InitError: fmt::Debug,
+ S::Response: Into> + 'static,
+ >::Future: 'static,
+
+ B: MessageBody + 'static,
+
+ X: ServiceFactory,
+ X::Future: 'static,
+ X::Error: Into>,
+ X::InitError: fmt::Debug,
+
+ U: ServiceFactory<
+ (Request, Framed, h1::Codec>),
+ Config = (),
+ Response = (),
+ >,
+ U::Future: 'static,
+ U::Error: fmt::Display + Into>,
+ U::InitError: fmt::Debug,
+ {
+ /// Create Rustls v0.22 based service.
+ pub fn rustls_0_22(
+ self,
+ config: ServerConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ self.rustls_0_22_with_config(config, TlsAcceptorConfig::default())
+ }
+
+ /// Create Rustls v0.22 based service with custom TLS acceptor configuration.
+ pub fn rustls_0_22_with_config(
+ self,
+ mut config: ServerConfig,
+ tls_acceptor_config: TlsAcceptorConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
+ protos.extend_from_slice(&config.alpn_protocols);
+ config.alpn_protocols = protos;
+
+ let mut acceptor = Acceptor::new(config);
+
+ if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
+ acceptor.set_handshake_timeout(handshake_timeout);
+ }
+
+ acceptor
+ .map_init_err(|_| {
+ unreachable!("TLS acceptor service factory does not error on init")
+ })
+ .map_err(TlsError::into_service_error)
+ .and_then(|io: TlsStream| async {
+ let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() {
+ if protos.windows(2).any(|window| window == b"h2") {
+ Protocol::Http2
+ } else {
+ Protocol::Http1
+ }
+ } else {
+ Protocol::Http1
+ };
+ let peer_addr = io.get_ref().0.peer_addr().ok();
+ Ok((io, proto, peer_addr))
+ })
+ .and_then(self.map_err(TlsError::Service))
+ }
+ }
+}
+
+#[cfg(feature = "rustls-0_23")]
+mod rustls_0_23 {
+ use std::io;
+
+ use actix_service::ServiceFactoryExt as _;
+ use actix_tls::accept::{
+ rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream},
+ TlsError,
+ };
+
+ use super::*;
+
+ impl HttpService, S, B, X, U>
+ where
+ S: ServiceFactory,
+ S::Future: 'static,
+ S::Error: Into> + 'static,
+ S::InitError: fmt::Debug,
+ S::Response: Into> + 'static,
+ >::Future: 'static,
+
+ B: MessageBody + 'static,
+
+ X: ServiceFactory,
+ X::Future: 'static,
+ X::Error: Into>,
+ X::InitError: fmt::Debug,
+
+ U: ServiceFactory<
+ (Request, Framed, h1::Codec>),
+ Config = (),
+ Response = (),
+ >,
+ U::Future: 'static,
+ U::Error: fmt::Display + Into>,
+ U::InitError: fmt::Debug,
+ {
+ /// Create Rustls v0.23 based service.
+ pub fn rustls_0_23(
+ self,
+ config: ServerConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ self.rustls_0_23_with_config(config, TlsAcceptorConfig::default())
+ }
+
+ /// Create Rustls v0.23 based service with custom TLS acceptor configuration.
+ pub fn rustls_0_23_with_config(
+ self,
+ mut config: ServerConfig,
+ tls_acceptor_config: TlsAcceptorConfig,
+ ) -> impl ServiceFactory<
+ TcpStream,
+ Config = (),
+ Response = (),
+ Error = TlsError,
+ InitError = (),
+ > {
+ let mut protos = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
+ protos.extend_from_slice(&config.alpn_protocols);
+ config.alpn_protocols = protos;
+
+ let mut acceptor = Acceptor::new(config);
+
+ if let Some(handshake_timeout) = tls_acceptor_config.handshake_timeout {
+ acceptor.set_handshake_timeout(handshake_timeout);
+ }
+
+ acceptor
+ .map_init_err(|_| {
+ unreachable!("TLS acceptor service factory does not error on init")
+ })
+ .map_err(TlsError::into_service_error)
+ .and_then(|io: TlsStream| async {
+ let proto = if let Some(protos) = io.get_ref().1.alpn_protocol() {
+ if protos.windows(2).any(|window| window == b"h2") {
+ Protocol::Http2
+ } else {
+ Protocol::Http1
+ }
+ } else {
+ Protocol::Http1
+ };
+ let peer_addr = io.get_ref().0.peer_addr().ok();
+ Ok((io, proto, peer_addr))
+ })
+ .and_then(self.map_err(TlsError::Service))
+ }
+ }
+}
+
impl ServiceFactory<(T, Protocol, Option)>
for HttpService
where
@@ -497,23 +775,23 @@ where
let cfg = self.cfg.clone();
Box::pin(async move {
- let expect = expect
- .await
- .map_err(|e| error!("Init http expect service error: {:?}", e))?;
+ let expect = expect.await.map_err(|err| {
+ tracing::error!("Initialization of HTTP expect service error: {err:?}");
+ })?;
let upgrade = match upgrade {
Some(upgrade) => {
- let upgrade = upgrade
- .await
- .map_err(|e| error!("Init http upgrade service error: {:?}", e))?;
+ let upgrade = upgrade.await.map_err(|err| {
+ tracing::error!("Initialization of HTTP upgrade service error: {err:?}");
+ })?;
Some(upgrade)
}
None => None,
};
- let service = service
- .await
- .map_err(|e| error!("Init http service error: {:?}", e))?;
+ let service = service.await.map_err(|err| {
+ tracing::error!("Initialization of HTTP service error: {err:?}");
+ })?;
Ok(HttpServiceHandler::new(
cfg,
@@ -563,10 +841,7 @@ where
}
}
- pub(super) fn _poll_ready(
- &self,
- cx: &mut Context<'_>,
- ) -> Poll>> {
+ pub(super) fn _poll_ready(&self, cx: &mut Context<'_>) -> Poll>> {
ready!(self.flow.expect.poll_ready(cx).map_err(Into::into))?;
ready!(self.flow.service.poll_ready(cx).map_err(Into::into))?;
@@ -625,10 +900,7 @@ where
})
}
- fn call(
- &self,
- (io, proto, peer_addr): (T, Protocol, Option),
- ) -> Self::Future {
+ fn call(&self, (io, proto, peer_addr): (T, Protocol, Option)) -> Self::Future {
let conn_data = OnConnectData::from_io(&io, self.on_connect_ext.as_deref());
match proto {
@@ -638,7 +910,7 @@ where
handshake: Some((
crate::h2::handshake_with_timeout(io, &self.cfg),
self.cfg.clone(),
- self.flow.clone(),
+ Rc::clone(&self.flow),
conn_data,
peer_addr,
)),
@@ -654,7 +926,7 @@ where
state: State::H1 {
dispatcher: h1::Dispatcher::new(
io,
- self.flow.clone(),
+ Rc::clone(&self.flow),
self.cfg.clone(),
peer_addr,
conn_data,
diff --git a/actix-http/src/test.rs b/actix-http/src/test.rs
index 3815e64c6..dfa9a86c9 100644
--- a/actix-http/src/test.rs
+++ b/actix-http/src/test.rs
@@ -159,8 +159,8 @@ impl TestBuffer {
#[allow(dead_code)]
pub(crate) fn clone(&self) -> Self {
Self {
- read_buf: self.read_buf.clone(),
- write_buf: self.write_buf.clone(),
+ read_buf: Rc::clone(&self.read_buf),
+ write_buf: Rc::clone(&self.write_buf),
err: self.err.clone(),
}
}
diff --git a/actix-http/src/ws/codec.rs b/actix-http/src/ws/codec.rs
index 6a149f9a4..ad487e400 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;
@@ -295,7 +296,7 @@ impl Decoder for Codec {
}
}
Ok(None) => Ok(None),
- Err(e) => Err(e),
+ Err(err) => Err(err),
}
}
}
diff --git a/actix-http/src/ws/dispatcher.rs b/actix-http/src/ws/dispatcher.rs
index 396f1e86c..7d0a300b7 100644
--- a/actix-http/src/ws/dispatcher.rs
+++ b/actix-http/src/ws/dispatcher.rs
@@ -70,15 +70,14 @@ mod inner {
task::{Context, Poll},
};
+ use actix_codec::Framed;
use actix_service::{IntoService, Service};
use futures_core::stream::Stream;
use local_channel::mpsc;
use pin_project_lite::pin_project;
- use tracing::debug;
-
- use actix_codec::Framed;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_util::codec::{Decoder, Encoder};
+ use tracing::debug;
use crate::{body::BoxBody, Response};
@@ -115,14 +114,14 @@ mod inner {
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- DispatcherError::Service(ref e) => {
- write!(fmt, "DispatcherError::Service({:?})", e)
+ DispatcherError::Service(ref err) => {
+ write!(fmt, "DispatcherError::Service({err:?})")
}
- DispatcherError::Encoder(ref e) => {
- write!(fmt, "DispatcherError::Encoder({:?})", e)
+ DispatcherError::Encoder(ref err) => {
+ write!(fmt, "DispatcherError::Encoder({err:?})")
}
- DispatcherError::Decoder(ref e) => {
- write!(fmt, "DispatcherError::Decoder({:?})", e)
+ DispatcherError::Decoder(ref err) => {
+ write!(fmt, "DispatcherError::Decoder({err:?})")
}
}
}
@@ -137,9 +136,9 @@ mod inner {
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
- DispatcherError::Service(ref e) => write!(fmt, "{}", e),
- DispatcherError::Encoder(ref e) => write!(fmt, "{:?}", e),
- DispatcherError::Decoder(ref e) => write!(fmt, "{:?}", e),
+ DispatcherError::Service(ref err) => write!(fmt, "{err}"),
+ DispatcherError::Encoder(ref err) => write!(fmt, "{err:?}"),
+ DispatcherError::Decoder(ref err) => write!(fmt, "{err:?}"),
}
}
}
@@ -413,9 +412,7 @@ mod inner {
}
State::Error(_) => {
// flush write buffer
- if !this.framed.is_write_buf_empty()
- && this.framed.flush(cx).is_pending()
- {
+ if !this.framed.is_write_buf_empty() && this.framed.flush(cx).is_pending() {
return Poll::Pending;
}
Poll::Ready(Err(this.state.take_error()))
diff --git a/actix-http/src/ws/frame.rs b/actix-http/src/ws/frame.rs
index c7e0427ea..7147cc92a 100644
--- a/actix-http/src/ws/frame.rs
+++ b/actix-http/src/ws/frame.rs
@@ -1,4 +1,4 @@
-use std::convert::TryFrom;
+use std::cmp::min;
use bytes::{Buf, BufMut, BytesMut};
use tracing::debug;
@@ -94,8 +94,22 @@ impl Parser {
Some(res) => res,
};
+ let frame_len = match idx.checked_add(length) {
+ Some(len) => len,
+ None => return Err(ProtocolError::Overflow),
+ };
+
// not enough data
- if src.len() < idx + length {
+ if src.len() < frame_len {
+ let min_length = min(length, max_size);
+ let required_cap = match idx.checked_add(min_length) {
+ Some(cap) => cap,
+ None => return Err(ProtocolError::Overflow),
+ };
+
+ if src.capacity() < required_cap {
+ src.reserve(required_cap - src.capacity());
+ }
return Ok(None);
}
@@ -174,14 +188,14 @@ impl Parser {
};
if payload_len < 126 {
- dst.reserve(p_len + 2 + if mask { 4 } else { 0 });
+ dst.reserve(p_len + 2);
dst.put_slice(&[one, two | payload_len as u8]);
} else if payload_len <= 65_535 {
- dst.reserve(p_len + 4 + if mask { 4 } else { 0 });
+ dst.reserve(p_len + 4);
dst.put_slice(&[one, two | 126]);
dst.put_u16(payload_len as u16);
} else {
- dst.reserve(p_len + 10 + if mask { 4 } else { 0 });
+ dst.reserve(p_len + 10);
dst.put_slice(&[one, two | 127]);
dst.put_u64(payload_len as u64);
};
@@ -217,9 +231,10 @@ impl Parser {
#[cfg(test)]
mod tests {
- use super::*;
use bytes::Bytes;
+ use super::*;
+
struct F {
finished: bool,
opcode: OpCode,
@@ -397,4 +412,14 @@ mod tests {
Parser::write_close(&mut buf, None, false);
assert_eq!(&buf[..], &vec![0x88, 0x00][..]);
}
+
+ #[test]
+ fn test_parse_length_overflow() {
+ let buf: [u8; 14] = [
+ 0x0a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x0e, 0x8f,
+ ];
+ let mut buf = BytesMut::from(&buf[..]);
+ let result = Parser::parse(&mut buf, true, 65536);
+ assert!(matches!(result, Err(ProtocolError::Overflow)));
+ }
}
diff --git a/actix-http/src/ws/mask.rs b/actix-http/src/ws/mask.rs
index be72e5631..115a8cf9b 100644
--- a/actix-http/src/ws/mask.rs
+++ b/actix-http/src/ws/mask.rs
@@ -50,7 +50,7 @@ mod tests {
#[test]
fn test_apply_mask() {
let mask = [0x6d, 0xb6, 0xb2, 0x80];
- let unmasked = vec![
+ let unmasked = [
0xf3, 0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x82, 0xff, 0xfe, 0x00, 0x17, 0x74, 0xf9,
0x12, 0x03,
];
diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs
index 2a0b0a99c..c2ae010c2 100644
--- a/actix-http/src/ws/mod.rs
+++ b/actix-http/src/ws/mod.rs
@@ -8,8 +8,7 @@ use std::io;
use derive_more::{Display, Error, From};
use http::{header, Method, StatusCode};
-use crate::body::BoxBody;
-use crate::{header::HeaderValue, RequestHead, Response, ResponseBuilder};
+use crate::{body::BoxBody, header::HeaderValue, RequestHead, Response, ResponseBuilder};
mod codec;
mod dispatcher;
@@ -17,52 +16,54 @@ mod frame;
mod mask;
mod proto;
-pub use self::codec::{Codec, Frame, Item, Message};
-pub use self::dispatcher::Dispatcher;
-pub use self::frame::Parser;
-pub use self::proto::{hash_key, CloseCode, CloseReason, OpCode};
+pub use self::{
+ codec::{Codec, Frame, Item, Message},
+ dispatcher::Dispatcher,
+ frame::Parser,
+ proto::{hash_key, CloseCode, CloseReason, OpCode},
+};
/// WebSocket protocol errors.
#[derive(Debug, Display, Error, From)]
pub enum ProtocolError {
/// Received an unmasked frame from client.
- #[display(fmt = "received an unmasked frame from client")]
+ #[display("received an unmasked frame from client")]
UnmaskedFrame,
/// Received a masked frame from server.
- #[display(fmt = "received a masked frame from server")]
+ #[display("received a masked frame from server")]
MaskedFrame,
/// Encountered invalid opcode.
- #[display(fmt = "invalid opcode ({})", _0)]
+ #[display("invalid opcode ({})", _0)]
InvalidOpcode(#[error(not(source))] u8),
/// Invalid control frame length
- #[display(fmt = "invalid control frame length ({})", _0)]
+ #[display("invalid control frame length ({})", _0)]
InvalidLength(#[error(not(source))] usize),
/// Bad opcode.
- #[display(fmt = "bad opcode")]
+ #[display("bad opcode")]
BadOpCode,
/// A payload reached size limit.
- #[display(fmt = "payload reached size limit")]
+ #[display("payload reached size limit")]
Overflow,
/// Continuation has not started.
- #[display(fmt = "continuation has not started")]
+ #[display("continuation has not started")]
ContinuationNotStarted,
/// Received new continuation but it is already started.
- #[display(fmt = "received new continuation but it has already started")]
+ #[display("received new continuation but it has already started")]
ContinuationStarted,
/// Unknown continuation fragment.
- #[display(fmt = "unknown continuation fragment: {}", _0)]
+ #[display("unknown continuation fragment: {}", _0)]
ContinuationFragment(#[error(not(source))] OpCode),
/// I/O error.
- #[display(fmt = "I/O error: {}", _0)]
+ #[display("I/O error: {}", _0)]
Io(io::Error),
}
@@ -70,27 +71,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("method not allowed")]
GetMethodRequired,
/// Upgrade header if not set to WebSocket.
- #[display(fmt = "WebSocket upgrade is expected")]
+ #[display("WebSocket upgrade is expected")]
NoWebsocketUpgrade,
/// Connection header is not set to upgrade.
- #[display(fmt = "connection upgrade is expected")]
+ #[display("connection upgrade is expected")]
NoConnectionUpgrade,
/// WebSocket version header is not set.
- #[display(fmt = "WebSocket version header is required")]
+ #[display("WebSocket version header is required")]
NoVersionHeader,
/// Unsupported WebSocket version.
- #[display(fmt = "unsupported WebSocket version")]
+ #[display("unsupported WebSocket version")]
UnsupportedVersion,
/// WebSocket key is not set or wrong.
- #[display(fmt = "unknown WebSocket key")]
+ #[display("unknown WebSocket key")]
BadWebsocketKey,
}
@@ -219,10 +220,8 @@ pub fn handshake_response(req: &RequestHead) -> ResponseBuilder {
#[cfg(test)]
mod tests {
- use crate::{header, Method};
-
use super::*;
- use crate::test::TestRequest;
+ use crate::{header, test::TestRequest};
#[test]
fn test_handshake() {
diff --git a/actix-http/src/ws/proto.rs b/actix-http/src/ws/proto.rs
index 0653c00b0..27815eaf2 100644
--- a/actix-http/src/ws/proto.rs
+++ b/actix-http/src/ws/proto.rs
@@ -1,7 +1,4 @@
-use std::{
- convert::{From, Into},
- fmt,
-};
+use std::fmt;
use base64::prelude::*;
use tracing::error;
diff --git a/actix-http/tests/test_client.rs b/actix-http/tests/test_client.rs
index 5888527f1..2d940984d 100644
--- a/actix-http/tests/test_client.rs
+++ b/actix-http/tests/test_client.rs
@@ -94,7 +94,7 @@ async fn with_query_parameter() {
}
#[derive(Debug, Display, Error)]
-#[display(fmt = "expect failed")]
+#[display("expect failed")]
struct ExpectFailed;
impl From for Response {
diff --git a/actix-http/tests/test_openssl.rs b/actix-http/tests/test_openssl.rs
index 7464bee4e..83456b0cb 100644
--- a/actix-http/tests/test_openssl.rs
+++ b/actix-http/tests/test_openssl.rs
@@ -1,5 +1,4 @@
#![cfg(feature = "openssl")]
-#![allow(clippy::uninlined_format_args)]
extern crate tls_openssl as openssl;
@@ -43,9 +42,11 @@ where
}
fn tls_config() -> SslAcceptor {
- let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
- let cert_file = cert.serialize_pem().unwrap();
- let key_file = cert.serialize_private_key_pem();
+ let rcgen::CertifiedKey { cert, key_pair } =
+ rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
+ let cert_file = cert.pem();
+ let key_file = key_pair.serialize_pem();
+
let cert = X509::from_pem(cert_file.as_bytes()).unwrap();
let key = PKey::private_key_from_pem(key_file.as_bytes()).unwrap();
@@ -321,8 +322,7 @@ async fn h2_body_length() {
let mut srv = test_server(move || {
HttpService::build()
.h2(|_| async {
- let body =
- once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) });
+ let body = once(async { Ok::<_, Infallible>(Bytes::from_static(STR.as_ref())) });
Ok::<_, Infallible>(
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
@@ -398,7 +398,7 @@ async fn h2_response_http_error_handling() {
}
#[derive(Debug, Display, Error)]
-#[display(fmt = "error")]
+#[display("error")]
struct BadRequest;
impl From for Response {
diff --git a/actix-http/tests/test_rustls.rs b/actix-http/tests/test_rustls.rs
index 0b8197a69..43e47c0a4 100644
--- a/actix-http/tests/test_rustls.rs
+++ b/actix-http/tests/test_rustls.rs
@@ -1,10 +1,9 @@
-#![cfg(feature = "rustls")]
-#![allow(clippy::uninlined_format_args)]
+#![cfg(feature = "rustls-0_23")]
-extern crate tls_rustls as rustls;
+extern crate tls_rustls_023 as rustls;
use std::{
- convert::{Infallible, TryFrom},
+ convert::Infallible,
io::{self, BufReader, Write},
net::{SocketAddr, TcpStream as StdTcpStream},
sync::Arc,
@@ -21,13 +20,13 @@ use actix_http::{
use actix_http_test::test_server;
use actix_rt::pin;
use actix_service::{fn_factory_with_config, fn_service};
-use actix_tls::connect::rustls::webpki_roots_cert_store;
+use actix_tls::connect::rustls_0_23::webpki_roots_cert_store;
use actix_utils::future::{err, ok, poll_fn};
use bytes::{Bytes, BytesMut};
use derive_more::{Display, Error};
use futures_core::{ready, Stream};
use futures_util::stream::once;
-use rustls::{Certificate, PrivateKey, ServerConfig as RustlsServerConfig, ServerName};
+use rustls::{pki_types::ServerName, ServerConfig as RustlsServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
async fn load_body(stream: S) -> Result
@@ -53,24 +52,25 @@ where
}
fn tls_config() -> RustlsServerConfig {
- let cert = rcgen::generate_simple_self_signed(vec!["localhost".to_owned()]).unwrap();
- let cert_file = cert.serialize_pem().unwrap();
- let key_file = cert.serialize_private_key_pem();
+ let rcgen::CertifiedKey { cert, key_pair } =
+ rcgen::generate_simple_self_signed(["localhost".to_owned()]).unwrap();
+ let cert_file = cert.pem();
+ let key_file = key_pair.serialize_pem();
let cert_file = &mut BufReader::new(cert_file.as_bytes());
let key_file = &mut BufReader::new(key_file.as_bytes());
- let cert_chain = certs(cert_file)
- .unwrap()
- .into_iter()
- .map(Certificate)
- .collect();
- let mut keys = pkcs8_private_keys(key_file).unwrap();
+ let cert_chain = certs(cert_file).collect::, _>>().unwrap();
+ let mut keys = pkcs8_private_keys(key_file)
+ .collect::, _>>()
+ .unwrap();
let mut config = RustlsServerConfig::builder()
- .with_safe_defaults()
.with_no_client_auth()
- .with_single_cert(cert_chain, PrivateKey(keys.remove(0)))
+ .with_single_cert(
+ cert_chain,
+ rustls::pki_types::PrivateKeyDer::Pkcs8(keys.remove(0)),
+ )
.unwrap();
config.alpn_protocols.push(HTTP1_1_ALPN_PROTOCOL.to_vec());
@@ -84,17 +84,14 @@ pub fn get_negotiated_alpn_protocol(
client_alpn_protocol: &[u8],
) -> Option> {
let mut config = rustls::ClientConfig::builder()
- .with_safe_defaults()
.with_root_certificates(webpki_roots_cert_store())
.with_no_client_auth();
config.alpn_protocols.push(client_alpn_protocol.to_vec());
- let mut sess = rustls::ClientConnection::new(
- Arc::new(config),
- ServerName::try_from("localhost").unwrap(),
- )
- .unwrap();
+ let mut sess =
+ rustls::ClientConnection::new(Arc::new(config), ServerName::try_from("localhost").unwrap())
+ .unwrap();
let mut sock = StdTcpStream::connect(addr).unwrap();
let mut stream = rustls::Stream::new(&mut sess, &mut sock);
@@ -112,7 +109,7 @@ async fn h1() -> io::Result<()> {
let srv = test_server(move || {
HttpService::build()
.h1(|_| ok::<_, Error>(Response::ok()))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -126,7 +123,7 @@ async fn h2() -> io::Result<()> {
let srv = test_server(move || {
HttpService::build()
.h2(|_| ok::<_, Error>(Response::ok()))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -144,7 +141,7 @@ async fn h1_1() -> io::Result<()> {
assert_eq!(req.version(), Version::HTTP_11);
ok::<_, Error>(Response::ok())
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -162,7 +159,7 @@ async fn h2_1() -> io::Result<()> {
assert_eq!(req.version(), Version::HTTP_2);
ok::<_, Error>(Response::ok())
})
- .rustls_with_config(
+ .rustls_0_23_with_config(
tls_config(),
TlsAcceptorConfig::default().handshake_timeout(Duration::from_secs(5)),
)
@@ -183,7 +180,7 @@ async fn h2_body1() -> io::Result<()> {
let body = load_body(req.take_payload()).await?;
Ok::<_, Error>(Response::ok().set_body(body))
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -209,7 +206,7 @@ async fn h2_content_length() {
];
ok::<_, Infallible>(Response::new(statuses[indx]))
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -281,7 +278,7 @@ async fn h2_headers() {
}
ok::<_, Infallible>(config.body(data.clone()))
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -320,7 +317,7 @@ async fn h2_body2() {
let mut srv = test_server(move || {
HttpService::build()
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -337,7 +334,7 @@ async fn h2_head_empty() {
let mut srv = test_server(move || {
HttpService::build()
.finish(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -363,7 +360,7 @@ async fn h2_head_binary() {
let mut srv = test_server(move || {
HttpService::build()
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -388,7 +385,7 @@ async fn h2_head_binary2() {
let srv = test_server(move || {
HttpService::build()
.h2(|_| ok::<_, Infallible>(Response::ok().set_body(STR)))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -414,7 +411,7 @@ async fn h2_body_length() {
Response::ok().set_body(SizedStream::new(STR.len() as u64, body)),
)
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -438,7 +435,7 @@ async fn h2_body_chunked_explicit() {
.body(BodyStream::new(body)),
)
})
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -467,7 +464,7 @@ async fn h2_response_http_error_handling() {
)
}))
}))
- .rustls(tls_config())
+ .rustls_0_23(tls_config())
})
.await;
@@ -483,7 +480,7 @@ async fn h2_response_http_error_handling() {
}
#[derive(Debug, Display, Error)]
-#[display(fmt = "error")]
+#[display("error")]
struct BadRequest;
impl From