1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-26 11:31:09 +00:00

remove direct dep on pin-project in -http (#2524)

This commit is contained in:
Rob Ede 2021-12-17 14:13:54 +00:00 committed by GitHub
parent 5359fa56c2
commit 2cf27863cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 158 additions and 123 deletions

View file

@ -45,7 +45,7 @@ __compress = []
actix-service = "2.0.0" actix-service = "2.0.0"
actix-codec = "0.4.1" actix-codec = "0.4.1"
actix-utils = "3.0.0" actix-utils = "3.0.0"
actix-rt = "2.2" actix-rt = { version = "2.2", default-features = false }
ahash = "0.7" ahash = "0.7"
base64 = "0.13" base64 = "0.13"
@ -66,7 +66,6 @@ local-channel = "0.1"
log = "0.4" log = "0.4"
mime = "0.3" mime = "0.3"
percent-encoding = "2.1" percent-encoding = "2.1"
pin-project = "1.0.0"
pin-project-lite = "0.2" pin-project-lite = "0.2"
rand = "0.8" rand = "0.8"
sha-1 = "0.9" sha-1 = "0.9"

View file

@ -15,7 +15,7 @@ use bitflags::bitflags;
use bytes::{Buf, BytesMut}; use bytes::{Buf, BytesMut};
use futures_core::ready; use futures_core::ready;
use log::{error, trace}; use log::{error, trace};
use pin_project::pin_project; use pin_project_lite::pin_project;
use crate::{ use crate::{
body::{BodySize, BoxBody, MessageBody}, body::{BodySize, BoxBody, MessageBody},
@ -46,10 +46,16 @@ bitflags! {
} }
} }
#[pin_project] // there's 2 versions of Dispatcher state because of:
/// Dispatcher for HTTP/1.1 protocol // https://github.com/taiki-e/pin-project-lite/issues/3
pub struct Dispatcher<T, S, B, X, U> //
where // tl;dr: pin-project-lite doesn't play well with other attribute macros
#[cfg(not(test))]
pin_project! {
/// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S, B, X, U>
where
S: Service<Request>, S: Service<Request>,
S::Error: Into<Response<BoxBody>>, S::Error: Into<Response<BoxBody>>,
@ -60,17 +66,40 @@ where
U: Service<(Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
#[pin]
inner: DispatcherState<T, S, B, X, U>,
}
}
#[cfg(test)]
pin_project! {
/// Dispatcher for HTTP/1.1 protocol
pub struct Dispatcher<T, S, B, X, U>
where
S: Service<Request>,
S::Error: Into<Response<BoxBody>>,
B: MessageBody,
X: Service<Request, Response = Request>,
X::Error: Into<Response<BoxBody>>,
U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display,
{
#[pin] #[pin]
inner: DispatcherState<T, S, B, X, U>, inner: DispatcherState<T, S, B, X, U>,
#[cfg(test)] // used in tests
poll_count: u64, poll_count: u64,
}
} }
#[pin_project(project = DispatcherStateProj)] pin_project! {
enum DispatcherState<T, S, B, X, U> #[project = DispatcherStateProj]
where enum DispatcherState<T, S, B, X, U>
where
S: Service<Request>, S: Service<Request>,
S::Error: Into<Response<BoxBody>>, S::Error: Into<Response<BoxBody>>,
@ -81,14 +110,16 @@ where
U: Service<(Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
Normal(#[pin] InnerDispatcher<T, S, B, X, U>), Normal { #[pin] inner: InnerDispatcher<T, S, B, X, U> },
Upgrade(#[pin] U::Future), Upgrade { #[pin] fut: U::Future },
}
} }
#[pin_project(project = InnerDispatcherProj)] pin_project! {
struct InnerDispatcher<T, S, B, X, U> #[project = InnerDispatcherProj]
where struct InnerDispatcher<T, S, B, X, U>
where
S: Service<Request>, S: Service<Request>,
S::Error: Into<Response<BoxBody>>, S::Error: Into<Response<BoxBody>>,
@ -99,7 +130,7 @@ where
U: Service<(Request, Framed<T, Codec>), Response = ()>, U: Service<(Request, Framed<T, Codec>), Response = ()>,
U::Error: fmt::Display, U::Error: fmt::Display,
{ {
flow: Rc<HttpFlow<S, X, U>>, flow: Rc<HttpFlow<S, X, U>>,
flags: Flags, flags: Flags,
peer_addr: Option<net::SocketAddr>, peer_addr: Option<net::SocketAddr>,
@ -119,6 +150,7 @@ where
read_buf: BytesMut, read_buf: BytesMut,
write_buf: BytesMut, write_buf: BytesMut,
codec: Codec, codec: Codec,
}
} }
enum DispatcherMessage { enum DispatcherMessage {
@ -127,19 +159,21 @@ enum DispatcherMessage {
Error(Response<()>), Error(Response<()>),
} }
#[pin_project(project = StateProj)] pin_project! {
enum State<S, B, X> #[project = StateProj]
where enum State<S, B, X>
where
S: Service<Request>, S: Service<Request>,
X: Service<Request, Response = Request>, X: Service<Request, Response = Request>,
B: MessageBody, B: MessageBody,
{ {
None, None,
ExpectCall(#[pin] X::Future), ExpectCall { #[pin] fut: X::Future },
ServiceCall(#[pin] S::Future), ServiceCall { #[pin] fut: S::Future },
SendPayload(#[pin] B), SendPayload { #[pin] body: B },
SendErrorPayload(#[pin] BoxBody), SendErrorPayload { #[pin] body: BoxBody },
}
} }
impl<S, B, X> State<S, B, X> impl<S, B, X> State<S, B, X>
@ -198,7 +232,8 @@ where
}; };
Dispatcher { Dispatcher {
inner: DispatcherState::Normal(InnerDispatcher { inner: DispatcherState::Normal {
inner: InnerDispatcher {
flow, flow,
flags, flags,
peer_addr, peer_addr,
@ -216,7 +251,8 @@ where
read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE), read_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE), write_buf: BytesMut::with_capacity(HW_BUFFER_SIZE),
codec: Codec::new(config), codec: Codec::new(config),
}), },
},
#[cfg(test)] #[cfg(test)]
poll_count: 0, poll_count: 0,
@ -316,7 +352,7 @@ where
let size = self.as_mut().send_response_inner(message, &body)?; let size = self.as_mut().send_response_inner(message, &body)?;
let state = match size { let state = match size {
BodySize::None | BodySize::Sized(0) => State::None, BodySize::None | BodySize::Sized(0) => State::None,
_ => State::SendPayload(body), _ => State::SendPayload { body },
}; };
self.project().state.set(state); self.project().state.set(state);
Ok(()) Ok(())
@ -330,7 +366,7 @@ where
let size = self.as_mut().send_response_inner(message, &body)?; let size = self.as_mut().send_response_inner(message, &body)?;
let state = match size { let state = match size {
BodySize::None | BodySize::Sized(0) => State::None, BodySize::None | BodySize::Sized(0) => State::None,
_ => State::SendErrorPayload(body), _ => State::SendErrorPayload { body },
}; };
self.project().state.set(state); self.project().state.set(state);
Ok(()) Ok(())
@ -356,12 +392,12 @@ where
// Handle `EXPECT: 100-Continue` header // Handle `EXPECT: 100-Continue` header
if req.head().expect() { if req.head().expect() {
// set InnerDispatcher state and continue loop to poll it. // set InnerDispatcher state and continue loop to poll it.
let task = this.flow.expect.call(req); let fut = this.flow.expect.call(req);
this.state.set(State::ExpectCall(task)); this.state.set(State::ExpectCall { fut });
} else { } else {
// the same as expect call. // the same as expect call.
let task = this.flow.service.call(req); let fut = this.flow.service.call(req);
this.state.set(State::ServiceCall(task)); this.state.set(State::ServiceCall { fut });
}; };
} }
@ -381,7 +417,7 @@ where
// all messages are dealt with. // all messages are dealt with.
None => return Ok(PollResponse::DoNothing), None => return Ok(PollResponse::DoNothing),
}, },
StateProj::ServiceCall(fut) => match fut.poll(cx) { StateProj::ServiceCall { fut } => match fut.poll(cx) {
// service call resolved. send response. // service call resolved. send response.
Poll::Ready(Ok(res)) => { Poll::Ready(Ok(res)) => {
let (res, body) = res.into().replace_body(()); let (res, body) = res.into().replace_body(());
@ -407,11 +443,11 @@ where
} }
}, },
StateProj::SendPayload(mut stream) => { StateProj::SendPayload { mut body } => {
// keep populate writer buffer until buffer size limit hit, // keep populate writer buffer until buffer size limit hit,
// get blocked or finished. // get blocked or finished.
while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE { while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE {
match stream.as_mut().poll_next(cx) { match body.as_mut().poll_next(cx) {
Poll::Ready(Some(Ok(item))) => { Poll::Ready(Some(Ok(item))) => {
this.codec this.codec
.encode(Message::Chunk(Some(item)), this.write_buf)?; .encode(Message::Chunk(Some(item)), this.write_buf)?;
@ -437,13 +473,13 @@ where
return Ok(PollResponse::DrainWriteBuf); return Ok(PollResponse::DrainWriteBuf);
} }
StateProj::SendErrorPayload(mut stream) => { StateProj::SendErrorPayload { mut body } => {
// TODO: de-dupe impl with SendPayload // TODO: de-dupe impl with SendPayload
// keep populate writer buffer until buffer size limit hit, // keep populate writer buffer until buffer size limit hit,
// get blocked or finished. // get blocked or finished.
while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE { while this.write_buf.len() < super::payload::MAX_BUFFER_SIZE {
match stream.as_mut().poll_next(cx) { match body.as_mut().poll_next(cx) {
Poll::Ready(Some(Ok(item))) => { Poll::Ready(Some(Ok(item))) => {
this.codec this.codec
.encode(Message::Chunk(Some(item)), this.write_buf)?; .encode(Message::Chunk(Some(item)), this.write_buf)?;
@ -469,14 +505,14 @@ where
return Ok(PollResponse::DrainWriteBuf); return Ok(PollResponse::DrainWriteBuf);
} }
StateProj::ExpectCall(fut) => match fut.poll(cx) { StateProj::ExpectCall { fut } => match fut.poll(cx) {
// expect resolved. write continue to buffer and set InnerDispatcher state // expect resolved. write continue to buffer and set InnerDispatcher state
// to service call. // to service call.
Poll::Ready(Ok(req)) => { Poll::Ready(Ok(req)) => {
this.write_buf this.write_buf
.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n"); .extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
let fut = this.flow.service.call(req); let fut = this.flow.service.call(req);
this.state.set(State::ServiceCall(fut)); this.state.set(State::ServiceCall { fut });
} }
// send expect error as response // send expect error as response
@ -502,25 +538,25 @@ where
let mut this = self.as_mut().project(); let mut this = self.as_mut().project();
if req.head().expect() { if req.head().expect() {
// set dispatcher state so the future is pinned. // set dispatcher state so the future is pinned.
let task = this.flow.expect.call(req); let fut = this.flow.expect.call(req);
this.state.set(State::ExpectCall(task)); this.state.set(State::ExpectCall { fut });
} else { } else {
// the same as above. // the same as above.
let task = this.flow.service.call(req); let fut = this.flow.service.call(req);
this.state.set(State::ServiceCall(task)); this.state.set(State::ServiceCall { fut });
}; };
// eagerly poll the future for once(or twice if expect is resolved immediately). // eagerly poll the future for once(or twice if expect is resolved immediately).
loop { loop {
match self.as_mut().project().state.project() { match self.as_mut().project().state.project() {
StateProj::ExpectCall(fut) => { StateProj::ExpectCall { fut } => {
match fut.poll(cx) { match fut.poll(cx) {
// expect is resolved. continue loop and poll the service call branch. // expect is resolved. continue loop and poll the service call branch.
Poll::Ready(Ok(req)) => { Poll::Ready(Ok(req)) => {
self.as_mut().send_continue(); self.as_mut().send_continue();
let mut this = self.as_mut().project(); let mut this = self.as_mut().project();
let task = this.flow.service.call(req); let fut = this.flow.service.call(req);
this.state.set(State::ServiceCall(task)); this.state.set(State::ServiceCall { fut });
continue; continue;
} }
// future is pending. return Ok(()) to notify that a new state is // future is pending. return Ok(()) to notify that a new state is
@ -536,7 +572,7 @@ where
} }
} }
} }
StateProj::ServiceCall(fut) => { StateProj::ServiceCall { fut } => {
// return no matter the service call future's result. // return no matter the service call future's result.
return match fut.poll(cx) { return match fut.poll(cx) {
// future is resolved. send response and return a result. On success // future is resolved. send response and return a result. On success
@ -901,7 +937,7 @@ where
} }
match this.inner.project() { match this.inner.project() {
DispatcherStateProj::Normal(mut inner) => { DispatcherStateProj::Normal { mut inner } => {
inner.as_mut().poll_keepalive(cx)?; inner.as_mut().poll_keepalive(cx)?;
if inner.flags.contains(Flags::SHUTDOWN) { if inner.flags.contains(Flags::SHUTDOWN) {
@ -941,7 +977,7 @@ where
self.as_mut() self.as_mut()
.project() .project()
.inner .inner
.set(DispatcherState::Upgrade(upgrade)); .set(DispatcherState::Upgrade { fut: upgrade });
return self.poll(cx); return self.poll(cx);
} }
}; };
@ -993,8 +1029,8 @@ where
} }
} }
} }
DispatcherStateProj::Upgrade(fut) => fut.poll(cx).map_err(|e| { DispatcherStateProj::Upgrade { fut: upgrade } => upgrade.poll(cx).map_err(|err| {
error!("Upgrade handler error: {}", e); error!("Upgrade handler error: {}", err);
DispatchError::Upgrade DispatchError::Upgrade
}), }),
} }
@ -1088,7 +1124,7 @@ mod tests {
Poll::Ready(res) => assert!(res.is_err()), Poll::Ready(res) => assert!(res.is_err()),
} }
if let DispatcherStateProj::Normal(inner) = h1.project().inner.project() { if let DispatcherStateProj::Normal { inner } = h1.project().inner.project() {
assert!(inner.flags.contains(Flags::READ_DISCONNECT)); assert!(inner.flags.contains(Flags::READ_DISCONNECT));
assert_eq!( assert_eq!(
&inner.project().io.take().unwrap().write_buf[..26], &inner.project().io.take().unwrap().write_buf[..26],
@ -1123,7 +1159,7 @@ mod tests {
actix_rt::pin!(h1); actix_rt::pin!(h1);
assert!(matches!(&h1.inner, DispatcherState::Normal(_))); assert!(matches!(&h1.inner, DispatcherState::Normal { .. }));
match h1.as_mut().poll(cx) { match h1.as_mut().poll(cx) {
Poll::Pending => panic!("first poll should not be pending"), Poll::Pending => panic!("first poll should not be pending"),
@ -1133,7 +1169,7 @@ mod tests {
// polls: initial => shutdown // polls: initial => shutdown
assert_eq!(h1.poll_count, 2); assert_eq!(h1.poll_count, 2);
if let DispatcherStateProj::Normal(inner) = h1.project().inner.project() { if let DispatcherStateProj::Normal { inner } = h1.project().inner.project() {
let res = &mut inner.project().io.take().unwrap().write_buf[..]; let res = &mut inner.project().io.take().unwrap().write_buf[..];
stabilize_date_header(res); stabilize_date_header(res);
@ -1177,7 +1213,7 @@ mod tests {
actix_rt::pin!(h1); actix_rt::pin!(h1);
assert!(matches!(&h1.inner, DispatcherState::Normal(_))); assert!(matches!(&h1.inner, DispatcherState::Normal { .. }));
match h1.as_mut().poll(cx) { match h1.as_mut().poll(cx) {
Poll::Pending => panic!("first poll should not be pending"), Poll::Pending => panic!("first poll should not be pending"),
@ -1187,7 +1223,7 @@ mod tests {
// polls: initial => shutdown // polls: initial => shutdown
assert_eq!(h1.poll_count, 1); assert_eq!(h1.poll_count, 1);
if let DispatcherStateProj::Normal(inner) = h1.project().inner.project() { if let DispatcherStateProj::Normal { inner } = h1.project().inner.project() {
let res = &mut inner.project().io.take().unwrap().write_buf[..]; let res = &mut inner.project().io.take().unwrap().write_buf[..];
stabilize_date_header(res); stabilize_date_header(res);
@ -1237,13 +1273,13 @@ mod tests {
actix_rt::pin!(h1); actix_rt::pin!(h1);
assert!(h1.as_mut().poll(cx).is_pending()); assert!(h1.as_mut().poll(cx).is_pending());
assert!(matches!(&h1.inner, DispatcherState::Normal(_))); assert!(matches!(&h1.inner, DispatcherState::Normal { .. }));
// polls: manual // polls: manual
assert_eq!(h1.poll_count, 1); assert_eq!(h1.poll_count, 1);
eprintln!("poll count: {}", h1.poll_count); eprintln!("poll count: {}", h1.poll_count);
if let DispatcherState::Normal(ref inner) = h1.inner { if let DispatcherState::Normal { ref inner } = h1.inner {
let io = inner.io.as_ref().unwrap(); let io = inner.io.as_ref().unwrap();
let res = &io.write_buf()[..]; let res = &io.write_buf()[..];
assert_eq!( assert_eq!(
@ -1258,7 +1294,7 @@ mod tests {
// polls: manual manual shutdown // polls: manual manual shutdown
assert_eq!(h1.poll_count, 3); assert_eq!(h1.poll_count, 3);
if let DispatcherState::Normal(ref inner) = h1.inner { if let DispatcherState::Normal { ref inner } = h1.inner {
let io = inner.io.as_ref().unwrap(); let io = inner.io.as_ref().unwrap();
let mut res = (&io.write_buf()[..]).to_owned(); let mut res = (&io.write_buf()[..]).to_owned();
stabilize_date_header(&mut res); stabilize_date_header(&mut res);
@ -1309,12 +1345,12 @@ mod tests {
actix_rt::pin!(h1); actix_rt::pin!(h1);
assert!(h1.as_mut().poll(cx).is_ready()); assert!(h1.as_mut().poll(cx).is_ready());
assert!(matches!(&h1.inner, DispatcherState::Normal(_))); assert!(matches!(&h1.inner, DispatcherState::Normal { .. }));
// polls: manual shutdown // polls: manual shutdown
assert_eq!(h1.poll_count, 2); assert_eq!(h1.poll_count, 2);
if let DispatcherState::Normal(ref inner) = h1.inner { if let DispatcherState::Normal { ref inner } = h1.inner {
let io = inner.io.as_ref().unwrap(); let io = inner.io.as_ref().unwrap();
let mut res = (&io.write_buf()[..]).to_owned(); let mut res = (&io.write_buf()[..]).to_owned();
stabilize_date_header(&mut res); stabilize_date_header(&mut res);
@ -1386,7 +1422,7 @@ mod tests {
actix_rt::pin!(h1); actix_rt::pin!(h1);
assert!(h1.as_mut().poll(cx).is_ready()); assert!(h1.as_mut().poll(cx).is_ready());
assert!(matches!(&h1.inner, DispatcherState::Upgrade(_))); assert!(matches!(&h1.inner, DispatcherState::Upgrade { .. }));
// polls: manual shutdown // polls: manual shutdown
assert_eq!(h1.poll_count, 2); assert_eq!(h1.poll_count, 2);