mirror of https://github.com/fafhrd91/actix-web
fix(http): fix sending responses for upgraded ones on WS (#4117)
This commit is contained in:
parent
a928601f31
commit
a945e09da8
|
|
@ -49,7 +49,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.13.0"
|
version = "3.13.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-codec",
|
"actix-codec",
|
||||||
"actix-http-test",
|
"actix-http-test",
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,12 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
## 3.13.1
|
||||||
|
|
||||||
|
- Fix HTTP/1 WebSocket upgrade responses being overwritten with `Connection: close` when the upgraded request payload remains open. [#4115]
|
||||||
|
|
||||||
|
[#4115]: https://github.com/actix/actix-web/issues/4115
|
||||||
|
|
||||||
## 3.13.0
|
## 3.13.0
|
||||||
|
|
||||||
- When configured, gracefully close HTTP/1 connections after early responses to unread request bodies. [#3967]
|
- When configured, gracefully close HTTP/1 connections after early responses to unread request bodies. [#3967]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.13.0"
|
version = "3.13.1"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||||
description = "HTTP types and services for the Actix ecosystem"
|
description = "HTTP types and services for the Actix ecosystem"
|
||||||
keywords = ["actix", "http", "framework", "async", "futures"]
|
keywords = ["actix", "http", "framework", "async", "futures"]
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@
|
||||||
<!-- prettier-ignore-start -->
|
<!-- prettier-ignore-start -->
|
||||||
|
|
||||||
[](https://crates.io/crates/actix-http)
|
[](https://crates.io/crates/actix-http)
|
||||||
[](https://docs.rs/actix-http/3.12.0)
|
[](https://docs.rs/actix-http/3.13.1)
|
||||||

|

|
||||||

|

|
||||||
<br />
|
<br />
|
||||||
[](https://deps.rs/crate/actix-http/3.12.0)
|
[](https://deps.rs/crate/actix-http/3.13.1)
|
||||||
[](https://crates.io/crates/actix-http)
|
[](https://crates.io/crates/actix-http)
|
||||||
[](https://discord.gg/NWpN5mmg3x)
|
[](https://discord.gg/NWpN5mmg3x)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -451,7 +451,7 @@ where
|
||||||
mut res: Response<()>,
|
mut res: Response<()>,
|
||||||
body: B,
|
body: B,
|
||||||
) -> Result<(), DispatchError> {
|
) -> Result<(), DispatchError> {
|
||||||
let close_after_response = {
|
let close_after_response = !res.upgrade() && {
|
||||||
let this = self.as_mut().project();
|
let this = self.as_mut().project();
|
||||||
should_close_after_response(this.payload.as_ref(), *this.payload_drainable)
|
should_close_after_response(this.payload.as_ref(), *this.payload_drainable)
|
||||||
};
|
};
|
||||||
|
|
@ -492,7 +492,7 @@ where
|
||||||
mut res: Response<()>,
|
mut res: Response<()>,
|
||||||
body: BoxBody,
|
body: BoxBody,
|
||||||
) -> Result<(), DispatchError> {
|
) -> Result<(), DispatchError> {
|
||||||
let close_after_response = {
|
let close_after_response = !res.upgrade() && {
|
||||||
let this = self.as_mut().project();
|
let this = self.as_mut().project();
|
||||||
should_close_after_response(this.payload.as_ref(), *this.payload_drainable)
|
should_close_after_response(this.payload.as_ref(), *this.payload_drainable)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,17 @@ fn ready_chunk_body_service(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn upgrade_response_service(
|
||||||
|
) -> impl Service<Request, Response = Response<impl MessageBody>, Error = Error> {
|
||||||
|
fn_service(|_req: Request| {
|
||||||
|
ready(Ok::<_, Error>(
|
||||||
|
Response::build(StatusCode::SWITCHING_PROTOCOLS)
|
||||||
|
.upgrade("websocket")
|
||||||
|
.finish(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn late_request() {
|
async fn late_request() {
|
||||||
let mut buf = TestBuffer::empty();
|
let mut buf = TestBuffer::empty();
|
||||||
|
|
@ -1133,6 +1144,64 @@ async fn upgrade_handling() {
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn upgrade_response_does_not_close_unfinished_payload() {
|
||||||
|
let buf = TestSeqBuffer::new(http_msg(
|
||||||
|
r"
|
||||||
|
GET /ws HTTP/1.1
|
||||||
|
Connection: Upgrade
|
||||||
|
Upgrade: websocket
|
||||||
|
Sec-WebSocket-Version: 13
|
||||||
|
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
|
||||||
|
|
||||||
|
",
|
||||||
|
));
|
||||||
|
|
||||||
|
let services = HttpFlow::new(
|
||||||
|
upgrade_response_service(),
|
||||||
|
ExpectHandler,
|
||||||
|
None::<UpgradeHandler>,
|
||||||
|
);
|
||||||
|
|
||||||
|
let h1 = Dispatcher::new(
|
||||||
|
buf.clone(),
|
||||||
|
services,
|
||||||
|
ServiceConfig::default(),
|
||||||
|
None,
|
||||||
|
OnConnectData::default(),
|
||||||
|
);
|
||||||
|
pin!(h1);
|
||||||
|
|
||||||
|
lazy(|cx| {
|
||||||
|
assert!(h1.as_mut().poll(cx).is_pending());
|
||||||
|
|
||||||
|
let mut res = BytesMut::from(buf.take_write_buf().as_ref());
|
||||||
|
stabilize_date_header(&mut res);
|
||||||
|
let res = &res[..];
|
||||||
|
|
||||||
|
let exp = http_msg(
|
||||||
|
r"
|
||||||
|
HTTP/1.1 101 Switching Protocols
|
||||||
|
connection: upgrade
|
||||||
|
upgrade: websocket
|
||||||
|
date: Thu, 01 Jan 1970 12:34:56 UTC
|
||||||
|
|
||||||
|
",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
exp,
|
||||||
|
"\nexpected response not in write buffer:\n\
|
||||||
|
response: {:?}\n\
|
||||||
|
expected: {:?}",
|
||||||
|
String::from_utf8_lossy(res),
|
||||||
|
String::from_utf8_lossy(&exp)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
// fix in #2624 reverted temporarily
|
// fix in #2624 reverted temporarily
|
||||||
// complete fix tracked in #2745
|
// complete fix tracked in #2745
|
||||||
#[ignore]
|
#[ignore]
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ actix-service = "2"
|
||||||
actix-tls = { version = "3.4", default-features = false, optional = true }
|
actix-tls = { version = "3.4", default-features = false, optional = true }
|
||||||
actix-utils = "3"
|
actix-utils = "3"
|
||||||
|
|
||||||
actix-http = "3.13.0"
|
actix-http = "3.13.1"
|
||||||
actix-router = { version = "0.5.4", default-features = false, features = ["http"] }
|
actix-router = { version = "0.5.4", default-features = false, features = ["http"] }
|
||||||
actix-web-codegen = { version = "4.3", optional = true, default-features = false }
|
actix-web-codegen = { version = "4.3", optional = true, default-features = false }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ dangerous-h2c = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-codec = "0.5"
|
actix-codec = "0.5"
|
||||||
actix-http = { version = "3.13.0", features = ["http2", "ws"] }
|
actix-http = { version = "3.13.1", features = ["http2", "ws"] }
|
||||||
actix-rt = { version = "2.1", default-features = false }
|
actix-rt = { version = "2.1", default-features = false }
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-tls = { version = "3.4", features = ["connect", "uri"] }
|
actix-tls = { version = "3.4", features = ["connect", "uri"] }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue