mirror of https://github.com/fafhrd91/actix-web
Compare commits
3 Commits
fde7934243
...
25963dbdf1
| Author | SHA1 | Date |
|---|---|---|
|
|
25963dbdf1 | |
|
|
4df9953c86 | |
|
|
016841137e |
|
|
@ -71,7 +71,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "actix-http"
|
||||
version = "3.11.1"
|
||||
version = "3.11.2"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http-test",
|
||||
|
|
@ -620,7 +620,7 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
|||
|
||||
[[package]]
|
||||
name = "awc"
|
||||
version = "3.8.0"
|
||||
version = "3.8.1"
|
||||
dependencies = [
|
||||
"actix-codec",
|
||||
"actix-http",
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
## 3.11.2
|
||||
|
||||
- Properly wake Payload receivers when feeding errors or EOF.
|
||||
- Add `ServiceConfigBuilder` type to facilitate future configuration extensions.
|
||||
- Add a configuration option to allow/disallow half closed connections in HTTP/1. This defaults to allow, reverting the change made in 3.11.1.
|
||||
- Shutdown connections when HTTP Responses are written without reading full Requests.
|
||||
|
||||
## 3.11.1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "actix-http"
|
||||
version = "3.11.1"
|
||||
version = "3.11.2"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>", "Rob Ede <robjtede@icloud.com>"]
|
||||
description = "HTTP types and services for the Actix ecosystem"
|
||||
keywords = ["actix", "http", "framework", "async", "futures"]
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
<!-- prettier-ignore-start -->
|
||||
|
||||
[](https://crates.io/crates/actix-http)
|
||||
[](https://docs.rs/actix-http/3.11.1)
|
||||
[](https://docs.rs/actix-http/3.11.2)
|
||||

|
||||

|
||||
<br />
|
||||
[](https://deps.rs/crate/actix-http/3.11.1)
|
||||
[](https://deps.rs/crate/actix-http/3.11.2)
|
||||
[](https://crates.io/crates/actix-http)
|
||||
[](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
|
|
|
|||
|
|
@ -386,7 +386,14 @@ where
|
|||
let mut this = self.project();
|
||||
this.state.set(match size {
|
||||
BodySize::None | BodySize::Sized(0) => {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
let payload_unfinished = this.payload.is_some();
|
||||
|
||||
if payload_unfinished {
|
||||
this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
|
||||
} else {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
}
|
||||
|
||||
State::None
|
||||
}
|
||||
_ => State::SendPayload { body },
|
||||
|
|
@ -404,7 +411,14 @@ where
|
|||
let mut this = self.project();
|
||||
this.state.set(match size {
|
||||
BodySize::None | BodySize::Sized(0) => {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
let payload_unfinished = this.payload.is_some();
|
||||
|
||||
if payload_unfinished {
|
||||
this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
|
||||
} else {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
}
|
||||
|
||||
State::None
|
||||
}
|
||||
_ => State::SendErrorPayload { body },
|
||||
|
|
@ -503,10 +517,22 @@ where
|
|||
Poll::Ready(None) => {
|
||||
this.codec.encode(Message::Chunk(None), this.write_buf)?;
|
||||
|
||||
// if we have not yet pipelined to the next request, then
|
||||
// this.payload was the payload for the request we just finished
|
||||
// responding to. We can check to see if we finished reading it
|
||||
// yet, and if not, shutdown the connection.
|
||||
let payload_unfinished = this.payload.is_some();
|
||||
let not_pipelined = this.messages.is_empty();
|
||||
|
||||
// payload stream finished.
|
||||
// set state to None and handle next message
|
||||
this.state.set(State::None);
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
|
||||
if not_pipelined && payload_unfinished {
|
||||
this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
|
||||
} else {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
}
|
||||
|
||||
continue 'res;
|
||||
}
|
||||
|
|
@ -542,10 +568,22 @@ where
|
|||
Poll::Ready(None) => {
|
||||
this.codec.encode(Message::Chunk(None), this.write_buf)?;
|
||||
|
||||
// payload stream finished
|
||||
// if we have not yet pipelined to the next request, then
|
||||
// this.payload was the payload for the request we just finished
|
||||
// responding to. We can check to see if we finished reading it
|
||||
// yet, and if not, shutdown the connection.
|
||||
let payload_unfinished = this.payload.is_some();
|
||||
let not_pipelined = this.messages.is_empty();
|
||||
|
||||
// payload stream finished.
|
||||
// set state to None and handle next message
|
||||
this.state.set(State::None);
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
|
||||
if not_pipelined && payload_unfinished {
|
||||
this.flags.insert(Flags::SHUTDOWN | Flags::FINISHED);
|
||||
} else {
|
||||
this.flags.insert(Flags::FINISHED);
|
||||
}
|
||||
|
||||
continue 'res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,6 +535,73 @@ async fn pipelining_ok_then_ok() {
|
|||
.await;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn early_response_with_payload_closes_connection() {
|
||||
lazy(|cx| {
|
||||
let buf = TestBuffer::new(
|
||||
"\
|
||||
GET /unfinished HTTP/1.1\r\n\
|
||||
Content-Length: 2\r\n\
|
||||
\r\n\
|
||||
",
|
||||
);
|
||||
|
||||
let cfg = ServiceConfig::new(
|
||||
KeepAlive::Os,
|
||||
Duration::from_millis(1),
|
||||
Duration::from_millis(1),
|
||||
false,
|
||||
None,
|
||||
);
|
||||
|
||||
let services = HttpFlow::new(echo_path_service(), ExpectHandler, None);
|
||||
|
||||
let h1 = Dispatcher::<_, _, _, _, UpgradeHandler>::new(
|
||||
buf.clone(),
|
||||
services,
|
||||
cfg,
|
||||
None,
|
||||
OnConnectData::default(),
|
||||
);
|
||||
|
||||
pin!(h1);
|
||||
|
||||
assert!(matches!(&h1.inner, DispatcherState::Normal { .. }));
|
||||
|
||||
match h1.as_mut().poll(cx) {
|
||||
Poll::Pending => panic!("Should have shut down"),
|
||||
Poll::Ready(res) => assert!(res.is_ok()),
|
||||
}
|
||||
|
||||
// polls: initial => shutdown
|
||||
assert_eq!(h1.poll_count, 2);
|
||||
|
||||
{
|
||||
let mut res = buf.write_buf_slice_mut();
|
||||
stabilize_date_header(&mut res);
|
||||
let res = &res[..];
|
||||
|
||||
let exp = b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
content-length: 11\r\n\
|
||||
date: Thu, 01 Jan 1970 12:34:56 UTC\r\n\r\n\
|
||||
/unfinished\
|
||||
";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn pipelining_ok_then_bad() {
|
||||
lazy(|cx| {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
## 3.8.1
|
||||
|
||||
- Fix a bug where `GO_AWAY` errors did not stop connections from returning to the pool.
|
||||
|
||||
## 3.8.0
|
||||
|
||||
- Add `hickory-dns` crate feature (off-by-default).
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "awc"
|
||||
version = "3.8.0"
|
||||
version = "3.8.1"
|
||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||
description = "Async HTTP and WebSocket client library"
|
||||
keywords = ["actix", "http", "framework", "async", "web"]
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
<!-- prettier-ignore-start -->
|
||||
|
||||
[](https://crates.io/crates/awc)
|
||||
[](https://docs.rs/awc/3.8.0)
|
||||
[](https://docs.rs/awc/3.8.1)
|
||||

|
||||
[](https://deps.rs/crate/awc/3.8.0)
|
||||
[](https://deps.rs/crate/awc/3.8.1)
|
||||
[](https://discord.gg/NWpN5mmg3x)
|
||||
|
||||
<!-- prettier-ignore-end -->
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ where
|
|||
|
||||
let res = poll_fn(|cx| io.poll_ready(cx)).await;
|
||||
if let Err(err) = res {
|
||||
io.on_release(err.is_io());
|
||||
io.on_release(err.is_io() || err.is_go_away());
|
||||
return Err(SendRequestError::from(err));
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ where
|
|||
fut.await.map_err(SendRequestError::from)?
|
||||
}
|
||||
Err(err) => {
|
||||
io.on_release(err.is_io());
|
||||
io.on_release(err.is_io() || err.is_go_away());
|
||||
return Err(err.into());
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue