mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into doc/actix-web-actors
This commit is contained in:
commit
f88ef5a026
|
@ -1,8 +1,14 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2022-xx-xx
|
## Unreleased - 2022-xx-xx
|
||||||
|
### Fixed
|
||||||
|
- Websocket parser no longer throws endless overflow errors after receiving an oversized frame. [#2790]
|
||||||
|
|
||||||
|
### Changed
|
||||||
- Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
|
- Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
|
||||||
|
|
||||||
|
[#2790]: https://github.com/actix/actix-web/pull/2790
|
||||||
|
|
||||||
|
|
||||||
## 3.1.0 - 2022-06-11
|
## 3.1.0 - 2022-06-11
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -17,7 +17,6 @@ impl Parser {
|
||||||
fn parse_metadata(
|
fn parse_metadata(
|
||||||
src: &[u8],
|
src: &[u8],
|
||||||
server: bool,
|
server: bool,
|
||||||
max_size: usize,
|
|
||||||
) -> Result<Option<(usize, bool, OpCode, usize, Option<[u8; 4]>)>, ProtocolError> {
|
) -> Result<Option<(usize, bool, OpCode, usize, Option<[u8; 4]>)>, ProtocolError> {
|
||||||
let chunk_len = src.len();
|
let chunk_len = src.len();
|
||||||
|
|
||||||
|
@ -60,20 +59,12 @@ impl Parser {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap());
|
let len = u64::from_be_bytes(TryFrom::try_from(&src[idx..idx + 8]).unwrap());
|
||||||
if len > max_size as u64 {
|
|
||||||
return Err(ProtocolError::Overflow);
|
|
||||||
}
|
|
||||||
idx += 8;
|
idx += 8;
|
||||||
len as usize
|
len as usize
|
||||||
} else {
|
} else {
|
||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
// check for max allowed size
|
|
||||||
if length > max_size {
|
|
||||||
return Err(ProtocolError::Overflow);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mask = if server {
|
let mask = if server {
|
||||||
if chunk_len < idx + 4 {
|
if chunk_len < idx + 4 {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
@ -98,8 +89,7 @@ impl Parser {
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
|
) -> Result<Option<(bool, OpCode, Option<BytesMut>)>, ProtocolError> {
|
||||||
// try to parse ws frame metadata
|
// try to parse ws frame metadata
|
||||||
let (idx, finished, opcode, length, mask) =
|
let (idx, finished, opcode, length, mask) = match Parser::parse_metadata(src, server)? {
|
||||||
match Parser::parse_metadata(src, server, max_size)? {
|
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(res) => res,
|
Some(res) => res,
|
||||||
};
|
};
|
||||||
|
@ -112,6 +102,13 @@ impl Parser {
|
||||||
// remove prefix
|
// remove prefix
|
||||||
src.advance(idx);
|
src.advance(idx);
|
||||||
|
|
||||||
|
// check for max allowed size
|
||||||
|
if length > max_size {
|
||||||
|
// drop the payload
|
||||||
|
src.advance(length);
|
||||||
|
return Err(ProtocolError::Overflow);
|
||||||
|
}
|
||||||
|
|
||||||
// no need for body
|
// no need for body
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return Ok(Some((finished, opcode, None)));
|
return Ok(Some((finished, opcode, None)));
|
||||||
|
@ -339,6 +336,30 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_frame_max_size_recoverability() {
|
||||||
|
let mut buf = BytesMut::new();
|
||||||
|
// The first text frame with length == 2, payload doesn't matter.
|
||||||
|
buf.extend(&[0b0000_0001u8, 0b0000_0010u8, 0b0000_0000u8, 0b0000_0000u8]);
|
||||||
|
// Next binary frame with length == 2 and payload == `[0x1111_1111u8, 0x1111_1111u8]`.
|
||||||
|
buf.extend(&[0b0000_0010u8, 0b0000_0010u8, 0b1111_1111u8, 0b1111_1111u8]);
|
||||||
|
|
||||||
|
assert_eq!(buf.len(), 8);
|
||||||
|
assert!(matches!(
|
||||||
|
Parser::parse(&mut buf, false, 1),
|
||||||
|
Err(ProtocolError::Overflow)
|
||||||
|
));
|
||||||
|
assert_eq!(buf.len(), 4);
|
||||||
|
let frame = extract(Parser::parse(&mut buf, false, 2));
|
||||||
|
assert!(!frame.finished);
|
||||||
|
assert_eq!(frame.opcode, OpCode::Binary);
|
||||||
|
assert_eq!(
|
||||||
|
frame.payload,
|
||||||
|
Bytes::from(vec![0b1111_1111u8, 0b1111_1111u8])
|
||||||
|
);
|
||||||
|
assert_eq!(buf.len(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ping_frame() {
|
fn test_ping_frame() {
|
||||||
let mut buf = BytesMut::new();
|
let mut buf = BytesMut::new();
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
## Unreleased - 2022-xx-xx
|
## Unreleased - 2022-xx-xx
|
||||||
- Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
|
- Minimum supported Rust version (MSRV) is now 1.57 due to transitive `time` dependency.
|
||||||
|
### Added
|
||||||
|
- Add `ServiceRequest::{parts, request}()` getter methods. [#2786]
|
||||||
|
|
||||||
|
[#2786]: https://github.com/actix/actix-web/pull/2786
|
||||||
|
|
||||||
## 4.1.0 - 2022-06-11
|
## 4.1.0 - 2022-06-11
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -60,7 +60,7 @@ where
|
||||||
/// [`HttpRequest::app_data`](crate::HttpRequest::app_data) method at runtime.
|
/// [`HttpRequest::app_data`](crate::HttpRequest::app_data) method at runtime.
|
||||||
///
|
///
|
||||||
/// # [`Data<T>`]
|
/// # [`Data<T>`]
|
||||||
/// Any [`Data<T>`] type added here can utilize it's extractor implementation in handlers.
|
/// Any [`Data<T>`] type added here can utilize its extractor implementation in handlers.
|
||||||
/// Types not wrapped in `Data<T>` cannot use this extractor. See [its docs](Data<T>) for more
|
/// Types not wrapped in `Data<T>` cannot use this extractor. See [its docs](Data<T>) for more
|
||||||
/// about its usage and patterns.
|
/// about its usage and patterns.
|
||||||
///
|
///
|
||||||
|
|
|
@ -257,7 +257,7 @@ impl ServiceFactory<ServiceRequest> for AppRoutingFactory {
|
||||||
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
|
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
|
||||||
|
|
||||||
fn new_service(&self, _: ()) -> Self::Future {
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
// construct all services factory future with it's resource def and guards.
|
// construct all services factory future with its resource def and guards.
|
||||||
let factory_fut = join_all(self.services.iter().map(|(path, factory, guards)| {
|
let factory_fut = join_all(self.services.iter().map(|(path, factory, guards)| {
|
||||||
let path = path.clone();
|
let path = path.clone();
|
||||||
let guards = guards.borrow_mut().take().unwrap_or_default();
|
let guards = guards.borrow_mut().take().unwrap_or_default();
|
||||||
|
|
|
@ -153,6 +153,16 @@ impl AppConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AppConfig {
|
impl Default for AppConfig {
|
||||||
|
/// Returns the default AppConfig.
|
||||||
|
/// Note: The included socket address is "127.0.0.1".
|
||||||
|
///
|
||||||
|
/// 127.0.0.1: non-routable meta address that denotes an unknown, invalid or non-applicable target.
|
||||||
|
/// If you need a service only accessed by itself, use a loopback address.
|
||||||
|
/// A loopback address for IPv4 is any loopback address that begins with "127".
|
||||||
|
/// Loopback addresses should be only used to test your application locally.
|
||||||
|
/// The default configuration provides a loopback address.
|
||||||
|
///
|
||||||
|
/// 0.0.0.0: if configured to use this special address, the application will listen to any IP address configured on the machine.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
AppConfig::new(
|
AppConfig::new(
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -254,7 +254,7 @@ impl Guard for AllGuard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a guard and inverts the outcome of it's `Guard` implementation.
|
/// Wraps a guard and inverts the outcome of its `Guard` implementation.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// The handler below will be called for any request method apart from `GET`.
|
/// The handler below will be called for any request method apart from `GET`.
|
||||||
|
@ -459,7 +459,7 @@ impl Guard for HostGuard {
|
||||||
return scheme == req_host_uri_scheme;
|
return scheme == req_host_uri_scheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is the the correct behavior?
|
// TODO: is this the correct behavior?
|
||||||
// falls through if scheme cannot be determined
|
// falls through if scheme cannot be determined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ use crate::{
|
||||||
/// Thanks to Rust's type system, Actix Web can infer the function parameter types. During the
|
/// Thanks to Rust's type system, Actix Web can infer the function parameter types. During the
|
||||||
/// extraction step, the parameter types are described as a tuple type, [`from_request`] is run on
|
/// extraction step, the parameter types are described as a tuple type, [`from_request`] is run on
|
||||||
/// that tuple, and the `Handler::call` implementation for that particular function arity
|
/// that tuple, and the `Handler::call` implementation for that particular function arity
|
||||||
/// destructures the tuple into it's component types and calls your handler function with them.
|
/// destructures the tuple into its component types and calls your handler function with them.
|
||||||
///
|
///
|
||||||
/// In pseudo-code the process looks something like this:
|
/// In pseudo-code the process looks something like this:
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
|
|
|
@ -343,7 +343,7 @@ mod response_fut_impl {
|
||||||
|
|
||||||
// Future is only implemented for BoxBody payload type because it's the most useful for making
|
// Future is only implemented for BoxBody payload type because it's the most useful for making
|
||||||
// simple handlers without async blocks. Making it generic over all MessageBody types requires a
|
// simple handlers without async blocks. Making it generic over all MessageBody types requires a
|
||||||
// future impl on Response which would cause it's body field to be, undesirably, Option<B>.
|
// future impl on Response which would cause its body field to be, undesirably, Option<B>.
|
||||||
//
|
//
|
||||||
// This impl is not particularly efficient due to the Response construction and should probably
|
// This impl is not particularly efficient due to the Response construction and should probably
|
||||||
// not be invoked if performance is important. Prefer an async fn/block in such cases.
|
// not be invoked if performance is important. Prefer an async fn/block in such cases.
|
||||||
|
|
|
@ -95,6 +95,18 @@ impl ServiceRequest {
|
||||||
(&mut self.req, &mut self.payload)
|
(&mut self.req, &mut self.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns immutable accessors to inner parts.
|
||||||
|
#[inline]
|
||||||
|
pub fn parts(&self) -> (&HttpRequest, &Payload) {
|
||||||
|
(&self.req, &self.payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns immutable accessor to inner [`HttpRequest`].
|
||||||
|
#[inline]
|
||||||
|
pub fn request(&self) -> &HttpRequest {
|
||||||
|
&self.req
|
||||||
|
}
|
||||||
|
|
||||||
/// Derives a type from this request using an [extractor](crate::FromRequest).
|
/// Derives a type from this request using an [extractor](crate::FromRequest).
|
||||||
///
|
///
|
||||||
/// Returns the `T` extractor's `Future` type which can be `await`ed. This is particularly handy
|
/// Returns the `T` extractor's `Future` type which can be `await`ed. This is particularly handy
|
||||||
|
|
Loading…
Reference in New Issue