mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-25 22:49:21 +02:00
make actix-http compile with std::future
This commit is contained in:
@ -1,10 +1,12 @@
|
||||
use std::future::Future;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::Decoder;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::{Async, Poll};
|
||||
use http::header::{HeaderName, HeaderValue};
|
||||
use http::{header, HttpTryFrom, Method, StatusCode, Uri, Version};
|
||||
use httparse;
|
||||
@ -442,9 +444,10 @@ impl Decoder for PayloadDecoder {
|
||||
loop {
|
||||
let mut buf = None;
|
||||
// advances the chunked state
|
||||
*state = match state.step(src, size, &mut buf)? {
|
||||
Async::NotReady => return Ok(None),
|
||||
Async::Ready(state) => state,
|
||||
*state = match state.step(src, size, &mut buf) {
|
||||
Poll::Pending => return Ok(None),
|
||||
Poll::Ready(Ok(state)) => state,
|
||||
Poll::Ready(Err(e)) => return Err(e),
|
||||
};
|
||||
if *state == ChunkedState::End {
|
||||
trace!("End of chunked stream");
|
||||
@ -476,7 +479,7 @@ macro_rules! byte (
|
||||
$rdr.split_to(1);
|
||||
b
|
||||
} else {
|
||||
return Ok(Async::NotReady)
|
||||
return Poll::Pending
|
||||
}
|
||||
})
|
||||
);
|
||||
@ -487,7 +490,7 @@ impl ChunkedState {
|
||||
body: &mut BytesMut,
|
||||
size: &mut u64,
|
||||
buf: &mut Option<Bytes>,
|
||||
) -> Poll<ChunkedState, io::Error> {
|
||||
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
use self::ChunkedState::*;
|
||||
match *self {
|
||||
Size => ChunkedState::read_size(body, size),
|
||||
@ -499,10 +502,14 @@ impl ChunkedState {
|
||||
BodyLf => ChunkedState::read_body_lf(body),
|
||||
EndCr => ChunkedState::read_end_cr(body),
|
||||
EndLf => ChunkedState::read_end_lf(body),
|
||||
End => Ok(Async::Ready(ChunkedState::End)),
|
||||
End => Poll::Ready(Ok(ChunkedState::End)),
|
||||
}
|
||||
}
|
||||
fn read_size(rdr: &mut BytesMut, size: &mut u64) -> Poll<ChunkedState, io::Error> {
|
||||
|
||||
fn read_size(
|
||||
rdr: &mut BytesMut,
|
||||
size: &mut u64,
|
||||
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
let radix = 16;
|
||||
match byte!(rdr) {
|
||||
b @ b'0'..=b'9' => {
|
||||
@ -517,48 +524,49 @@ impl ChunkedState {
|
||||
*size *= radix;
|
||||
*size += u64::from(b + 10 - b'A');
|
||||
}
|
||||
b'\t' | b' ' => return Ok(Async::Ready(ChunkedState::SizeLws)),
|
||||
b';' => return Ok(Async::Ready(ChunkedState::Extension)),
|
||||
b'\r' => return Ok(Async::Ready(ChunkedState::SizeLf)),
|
||||
b'\t' | b' ' => return Poll::Ready(Ok(ChunkedState::SizeLws)),
|
||||
b';' => return Poll::Ready(Ok(ChunkedState::Extension)),
|
||||
b'\r' => return Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||
_ => {
|
||||
return Err(io::Error::new(
|
||||
return Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk size line: Invalid Size",
|
||||
));
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(Async::Ready(ChunkedState::Size))
|
||||
Poll::Ready(Ok(ChunkedState::Size))
|
||||
}
|
||||
fn read_size_lws(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
|
||||
fn read_size_lws(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
trace!("read_size_lws");
|
||||
match byte!(rdr) {
|
||||
// LWS can follow the chunk size, but no more digits can come
|
||||
b'\t' | b' ' => Ok(Async::Ready(ChunkedState::SizeLws)),
|
||||
b';' => Ok(Async::Ready(ChunkedState::Extension)),
|
||||
b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\t' | b' ' => Poll::Ready(Ok(ChunkedState::SizeLws)),
|
||||
b';' => Poll::Ready(Ok(ChunkedState::Extension)),
|
||||
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk size linear white space",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
fn read_extension(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
fn read_extension(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\r' => Ok(Async::Ready(ChunkedState::SizeLf)),
|
||||
_ => Ok(Async::Ready(ChunkedState::Extension)), // no supported extensions
|
||||
b'\r' => Poll::Ready(Ok(ChunkedState::SizeLf)),
|
||||
_ => Poll::Ready(Ok(ChunkedState::Extension)), // no supported extensions
|
||||
}
|
||||
}
|
||||
fn read_size_lf(
|
||||
rdr: &mut BytesMut,
|
||||
size: &mut u64,
|
||||
) -> Poll<ChunkedState, io::Error> {
|
||||
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\n' if *size > 0 => Ok(Async::Ready(ChunkedState::Body)),
|
||||
b'\n' if *size == 0 => Ok(Async::Ready(ChunkedState::EndCr)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\n' if *size > 0 => Poll::Ready(Ok(ChunkedState::Body)),
|
||||
b'\n' if *size == 0 => Poll::Ready(Ok(ChunkedState::EndCr)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk size LF",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -566,12 +574,12 @@ impl ChunkedState {
|
||||
rdr: &mut BytesMut,
|
||||
rem: &mut u64,
|
||||
buf: &mut Option<Bytes>,
|
||||
) -> Poll<ChunkedState, io::Error> {
|
||||
) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
trace!("Chunked read, remaining={:?}", rem);
|
||||
|
||||
let len = rdr.len() as u64;
|
||||
if len == 0 {
|
||||
Ok(Async::Ready(ChunkedState::Body))
|
||||
Poll::Ready(Ok(ChunkedState::Body))
|
||||
} else {
|
||||
let slice;
|
||||
if *rem > len {
|
||||
@ -583,47 +591,47 @@ impl ChunkedState {
|
||||
}
|
||||
*buf = Some(slice);
|
||||
if *rem > 0 {
|
||||
Ok(Async::Ready(ChunkedState::Body))
|
||||
Poll::Ready(Ok(ChunkedState::Body))
|
||||
} else {
|
||||
Ok(Async::Ready(ChunkedState::BodyCr))
|
||||
Poll::Ready(Ok(ChunkedState::BodyCr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_body_cr(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
fn read_body_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\r' => Ok(Async::Ready(ChunkedState::BodyLf)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\r' => Poll::Ready(Ok(ChunkedState::BodyLf)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk body CR",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
fn read_body_lf(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
fn read_body_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\n' => Ok(Async::Ready(ChunkedState::Size)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\n' => Poll::Ready(Ok(ChunkedState::Size)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk body LF",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
fn read_end_cr(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
fn read_end_cr(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\r' => Ok(Async::Ready(ChunkedState::EndLf)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\r' => Poll::Ready(Ok(ChunkedState::EndLf)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk end CR",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
fn read_end_lf(rdr: &mut BytesMut) -> Poll<ChunkedState, io::Error> {
|
||||
fn read_end_lf(rdr: &mut BytesMut) -> Poll<Result<ChunkedState, io::Error>> {
|
||||
match byte!(rdr) {
|
||||
b'\n' => Ok(Async::Ready(ChunkedState::End)),
|
||||
_ => Err(io::Error::new(
|
||||
b'\n' => Poll::Ready(Ok(ChunkedState::End)),
|
||||
_ => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid chunk end LF",
|
||||
)),
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
use std::collections::VecDeque;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::Instant;
|
||||
use std::{fmt, io, net};
|
||||
use std::{fmt, io, io::Write, net};
|
||||
|
||||
use actix_codec::{Decoder, Encoder, Framed, FramedParts};
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder, Framed, FramedParts};
|
||||
use actix_server_config::IoStream;
|
||||
use actix_service::Service;
|
||||
use bitflags::bitflags;
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use futures::{Async, Future, Poll};
|
||||
use log::{error, trace};
|
||||
use tokio_timer::Delay;
|
||||
use tokio_timer::{delay, Delay};
|
||||
|
||||
use crate::body::{Body, BodySize, MessageBody, ResponseBody};
|
||||
use crate::cloneable::CloneableService;
|
||||
@ -46,11 +48,14 @@ pub struct Dispatcher<T, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
inner: DispatcherState<T, S, B, X, U>,
|
||||
}
|
||||
@ -59,11 +64,14 @@ enum DispatcherState<T, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
Normal(InnerDispatcher<T, S, B, X, U>),
|
||||
Upgrade(U::Future),
|
||||
@ -74,11 +82,14 @@ struct InnerDispatcher<T, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
service: CloneableService<S>,
|
||||
expect: CloneableService<X>,
|
||||
@ -170,11 +181,14 @@ where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
/// Create http/1 dispatcher.
|
||||
pub(crate) fn new(
|
||||
@ -255,20 +269,23 @@ where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
fn can_read(&self) -> bool {
|
||||
fn can_read(&self, cx: &mut Context) -> bool {
|
||||
if self
|
||||
.flags
|
||||
.intersects(Flags::READ_DISCONNECT | Flags::UPGRADE)
|
||||
{
|
||||
false
|
||||
} else if let Some(ref info) = self.payload {
|
||||
info.need_read() == PayloadStatus::Read
|
||||
info.need_read(cx) == PayloadStatus::Read
|
||||
} else {
|
||||
true
|
||||
}
|
||||
@ -287,7 +304,7 @@ where
|
||||
///
|
||||
/// true - got whouldblock
|
||||
/// false - didnt get whouldblock
|
||||
fn poll_flush(&mut self) -> Result<bool, DispatchError> {
|
||||
fn poll_flush(&mut self, cx: &mut Context) -> Result<bool, DispatchError> {
|
||||
if self.write_buf.is_empty() {
|
||||
return Ok(false);
|
||||
}
|
||||
@ -295,23 +312,23 @@ where
|
||||
let len = self.write_buf.len();
|
||||
let mut written = 0;
|
||||
while written < len {
|
||||
match self.io.write(&self.write_buf[written..]) {
|
||||
Ok(0) => {
|
||||
match Pin::new(&mut self.io).poll_write(cx, &self.write_buf[written..]) {
|
||||
Poll::Ready(Ok(0)) => {
|
||||
return Err(DispatchError::Io(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
"",
|
||||
)));
|
||||
}
|
||||
Ok(n) => {
|
||||
Poll::Ready(Ok(n)) => {
|
||||
written += n;
|
||||
}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
||||
Poll::Pending => {
|
||||
if written > 0 {
|
||||
let _ = self.write_buf.split_to(written);
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
Err(err) => return Err(DispatchError::Io(err)),
|
||||
Poll::Ready(Err(err)) => return Err(DispatchError::Io(err)),
|
||||
}
|
||||
}
|
||||
if written > 0 {
|
||||
@ -350,12 +367,15 @@ where
|
||||
.extend_from_slice(b"HTTP/1.1 100 Continue\r\n\r\n");
|
||||
}
|
||||
|
||||
fn poll_response(&mut self) -> Result<PollResponse, DispatchError> {
|
||||
fn poll_response(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
) -> Result<PollResponse, DispatchError> {
|
||||
loop {
|
||||
let state = match self.state {
|
||||
State::None => match self.messages.pop_front() {
|
||||
Some(DispatcherMessage::Item(req)) => {
|
||||
Some(self.handle_request(req)?)
|
||||
Some(self.handle_request(req, cx)?)
|
||||
}
|
||||
Some(DispatcherMessage::Error(res)) => {
|
||||
Some(self.send_response(res, ResponseBody::Other(Body::Empty))?)
|
||||
@ -365,54 +385,54 @@ where
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
State::ExpectCall(ref mut fut) => match fut.poll() {
|
||||
Ok(Async::Ready(req)) => {
|
||||
State::ExpectCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||
Poll::Ready(Ok(req)) => {
|
||||
self.send_continue();
|
||||
self.state = State::ServiceCall(self.service.call(req));
|
||||
continue;
|
||||
}
|
||||
Ok(Async::NotReady) => None,
|
||||
Err(e) => {
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
Poll::Pending => None,
|
||||
},
|
||||
State::ServiceCall(ref mut fut) => match fut.poll() {
|
||||
Ok(Async::Ready(res)) => {
|
||||
State::ServiceCall(ref mut fut) => match Pin::new(fut).poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
self.state = self.send_response(res, body)?;
|
||||
continue;
|
||||
}
|
||||
Ok(Async::NotReady) => None,
|
||||
Err(e) => {
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
Some(self.send_response(res, body.into_body())?)
|
||||
}
|
||||
Poll::Pending => None,
|
||||
},
|
||||
State::SendPayload(ref mut stream) => {
|
||||
loop {
|
||||
if self.write_buf.len() < HW_BUFFER_SIZE {
|
||||
match stream
|
||||
.poll_next()
|
||||
.map_err(|_| DispatchError::Unknown)?
|
||||
{
|
||||
Async::Ready(Some(item)) => {
|
||||
match stream.poll_next(cx) {
|
||||
Poll::Ready(Some(Ok(item))) => {
|
||||
self.codec.encode(
|
||||
Message::Chunk(Some(item)),
|
||||
&mut self.write_buf,
|
||||
)?;
|
||||
continue;
|
||||
}
|
||||
Async::Ready(None) => {
|
||||
Poll::Ready(None) => {
|
||||
self.codec.encode(
|
||||
Message::Chunk(None),
|
||||
&mut self.write_buf,
|
||||
)?;
|
||||
self.state = State::None;
|
||||
}
|
||||
Async::NotReady => return Ok(PollResponse::DoNothing),
|
||||
Poll::Ready(Some(Err(_))) => {
|
||||
return Err(DispatchError::Unknown)
|
||||
}
|
||||
Poll::Pending => return Ok(PollResponse::DoNothing),
|
||||
}
|
||||
} else {
|
||||
return Ok(PollResponse::DrainWriteBuf);
|
||||
@ -433,7 +453,7 @@ where
|
||||
// if read-backpressure is enabled and we consumed some data.
|
||||
// we may read more data and retry
|
||||
if self.state.is_call() {
|
||||
if self.poll_request()? {
|
||||
if self.poll_request(cx)? {
|
||||
continue;
|
||||
}
|
||||
} else if !self.messages.is_empty() {
|
||||
@ -446,17 +466,21 @@ where
|
||||
Ok(PollResponse::DoNothing)
|
||||
}
|
||||
|
||||
fn handle_request(&mut self, req: Request) -> Result<State<S, B, X>, DispatchError> {
|
||||
fn handle_request(
|
||||
&mut self,
|
||||
req: Request,
|
||||
cx: &mut Context,
|
||||
) -> Result<State<S, B, X>, DispatchError> {
|
||||
// Handle `EXPECT: 100-Continue` header
|
||||
let req = if req.head().expect() {
|
||||
let mut task = self.expect.call(req);
|
||||
match task.poll() {
|
||||
Ok(Async::Ready(req)) => {
|
||||
match Pin::new(&mut task).poll(cx) {
|
||||
Poll::Ready(Ok(req)) => {
|
||||
self.send_continue();
|
||||
req
|
||||
}
|
||||
Ok(Async::NotReady) => return Ok(State::ExpectCall(task)),
|
||||
Err(e) => {
|
||||
Poll::Pending => return Ok(State::ExpectCall(task)),
|
||||
Poll::Ready(Err(e)) => {
|
||||
let e = e.into();
|
||||
let res: Response = e.into();
|
||||
let (res, body) = res.replace_body(());
|
||||
@ -469,13 +493,13 @@ where
|
||||
|
||||
// Call service
|
||||
let mut task = self.service.call(req);
|
||||
match task.poll() {
|
||||
Ok(Async::Ready(res)) => {
|
||||
match Pin::new(&mut task).poll(cx) {
|
||||
Poll::Ready(Ok(res)) => {
|
||||
let (res, body) = res.into().replace_body(());
|
||||
self.send_response(res, body)
|
||||
}
|
||||
Ok(Async::NotReady) => Ok(State::ServiceCall(task)),
|
||||
Err(e) => {
|
||||
Poll::Pending => Ok(State::ServiceCall(task)),
|
||||
Poll::Ready(Err(e)) => {
|
||||
let res: Response = e.into().into();
|
||||
let (res, body) = res.replace_body(());
|
||||
self.send_response(res, body.into_body())
|
||||
@ -484,9 +508,12 @@ where
|
||||
}
|
||||
|
||||
/// Process one incoming requests
|
||||
pub(self) fn poll_request(&mut self) -> Result<bool, DispatchError> {
|
||||
pub(self) fn poll_request(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
) -> Result<bool, DispatchError> {
|
||||
// limit a mount of non processed requests
|
||||
if self.messages.len() >= MAX_PIPELINED_MESSAGES || !self.can_read() {
|
||||
if self.messages.len() >= MAX_PIPELINED_MESSAGES || !self.can_read(cx) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@ -521,7 +548,7 @@ where
|
||||
|
||||
// handle request early
|
||||
if self.state.is_empty() {
|
||||
self.state = self.handle_request(req)?;
|
||||
self.state = self.handle_request(req, cx)?;
|
||||
} else {
|
||||
self.messages.push_back(DispatcherMessage::Item(req));
|
||||
}
|
||||
@ -587,12 +614,12 @@ where
|
||||
}
|
||||
|
||||
/// keep-alive timer
|
||||
fn poll_keepalive(&mut self) -> Result<(), DispatchError> {
|
||||
fn poll_keepalive(&mut self, cx: &mut Context) -> Result<(), DispatchError> {
|
||||
if self.ka_timer.is_none() {
|
||||
// shutdown timeout
|
||||
if self.flags.contains(Flags::SHUTDOWN) {
|
||||
if let Some(interval) = self.codec.config().client_disconnect_timer() {
|
||||
self.ka_timer = Some(Delay::new(interval));
|
||||
self.ka_timer = Some(delay(interval));
|
||||
} else {
|
||||
self.flags.insert(Flags::READ_DISCONNECT);
|
||||
if let Some(mut payload) = self.payload.take() {
|
||||
@ -605,11 +632,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
match self.ka_timer.as_mut().unwrap().poll().map_err(|e| {
|
||||
error!("Timer error {:?}", e);
|
||||
DispatchError::Unknown
|
||||
})? {
|
||||
Async::Ready(_) => {
|
||||
match Pin::new(&mut self.ka_timer.as_mut().unwrap()).poll(cx) {
|
||||
Poll::Ready(()) => {
|
||||
// if we get timeout during shutdown, drop connection
|
||||
if self.flags.contains(Flags::SHUTDOWN) {
|
||||
return Err(DispatchError::DisconnectTimeout);
|
||||
@ -624,9 +648,9 @@ where
|
||||
if let Some(deadline) =
|
||||
self.codec.config().client_disconnect_timer()
|
||||
{
|
||||
if let Some(timer) = self.ka_timer.as_mut() {
|
||||
if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||
timer.reset(deadline);
|
||||
let _ = timer.poll();
|
||||
let _ = Pin::new(&mut timer).poll(cx);
|
||||
}
|
||||
} else {
|
||||
// no shutdown timeout, drop socket
|
||||
@ -650,17 +674,17 @@ where
|
||||
} else if let Some(deadline) =
|
||||
self.codec.config().keep_alive_expire()
|
||||
{
|
||||
if let Some(timer) = self.ka_timer.as_mut() {
|
||||
if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||
timer.reset(deadline);
|
||||
let _ = timer.poll();
|
||||
let _ = Pin::new(&mut timer).poll(cx);
|
||||
}
|
||||
}
|
||||
} else if let Some(timer) = self.ka_timer.as_mut() {
|
||||
} else if let Some(mut timer) = self.ka_timer.as_mut() {
|
||||
timer.reset(self.ka_expire);
|
||||
let _ = timer.poll();
|
||||
let _ = Pin::new(&mut timer).poll(cx);
|
||||
}
|
||||
}
|
||||
Async::NotReady => (),
|
||||
Poll::Pending => (),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -673,33 +697,37 @@ where
|
||||
S: Service<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
{
|
||||
type Item = ();
|
||||
type Error = DispatchError;
|
||||
type Output = Result<(), DispatchError>;
|
||||
|
||||
#[inline]
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
match self.inner {
|
||||
DispatcherState::Normal(ref mut inner) => {
|
||||
inner.poll_keepalive()?;
|
||||
inner.poll_keepalive(cx)?;
|
||||
|
||||
if inner.flags.contains(Flags::SHUTDOWN) {
|
||||
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
// flush buffer
|
||||
inner.poll_flush()?;
|
||||
inner.poll_flush(cx)?;
|
||||
if !inner.write_buf.is_empty() {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
} else {
|
||||
match inner.io.shutdown()? {
|
||||
Async::Ready(_) => Ok(Async::Ready(())),
|
||||
Async::NotReady => Ok(Async::NotReady),
|
||||
match Pin::new(&mut inner.io).poll_shutdown(cx) {
|
||||
Poll::Ready(res) => {
|
||||
Poll::Ready(res.map_err(DispatchError::from))
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -707,12 +735,12 @@ where
|
||||
// read socket into a buf
|
||||
let should_disconnect =
|
||||
if !inner.flags.contains(Flags::READ_DISCONNECT) {
|
||||
read_available(&mut inner.io, &mut inner.read_buf)?
|
||||
read_available(cx, &mut inner.io, &mut inner.read_buf)?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
inner.poll_request()?;
|
||||
inner.poll_request(cx)?;
|
||||
if let Some(true) = should_disconnect {
|
||||
inner.flags.insert(Flags::READ_DISCONNECT);
|
||||
if let Some(mut payload) = inner.payload.take() {
|
||||
@ -724,7 +752,7 @@ where
|
||||
if inner.write_buf.remaining_mut() < LW_BUFFER_SIZE {
|
||||
inner.write_buf.reserve(HW_BUFFER_SIZE);
|
||||
}
|
||||
let result = inner.poll_response()?;
|
||||
let result = inner.poll_response(cx)?;
|
||||
let drain = result == PollResponse::DrainWriteBuf;
|
||||
|
||||
// switch to upgrade handler
|
||||
@ -742,7 +770,7 @@ where
|
||||
self.inner = DispatcherState::Upgrade(
|
||||
inner.upgrade.unwrap().call((req, framed)),
|
||||
);
|
||||
return self.poll();
|
||||
return self.poll(cx);
|
||||
} else {
|
||||
panic!()
|
||||
}
|
||||
@ -751,14 +779,14 @@ where
|
||||
// we didnt get WouldBlock from write operation,
|
||||
// so data get written to kernel completely (OSX)
|
||||
// and we have to write again otherwise response can get stuck
|
||||
if inner.poll_flush()? || !drain {
|
||||
if inner.poll_flush(cx)? || !drain {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// client is gone
|
||||
if inner.flags.contains(Flags::WRITE_DISCONNECT) {
|
||||
return Ok(Async::Ready(()));
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
|
||||
let is_empty = inner.state.is_empty();
|
||||
@ -771,38 +799,44 @@ where
|
||||
// keep-alive and stream errors
|
||||
if is_empty && inner.write_buf.is_empty() {
|
||||
if let Some(err) = inner.error.take() {
|
||||
Err(err)
|
||||
Poll::Ready(Err(err))
|
||||
}
|
||||
// disconnect if keep-alive is not enabled
|
||||
else if inner.flags.contains(Flags::STARTED)
|
||||
&& !inner.flags.intersects(Flags::KEEPALIVE)
|
||||
{
|
||||
inner.flags.insert(Flags::SHUTDOWN);
|
||||
self.poll()
|
||||
self.poll(cx)
|
||||
}
|
||||
// disconnect if shutdown
|
||||
else if inner.flags.contains(Flags::SHUTDOWN) {
|
||||
self.poll()
|
||||
self.poll(cx)
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
DispatcherState::Upgrade(ref mut fut) => fut.poll().map_err(|e| {
|
||||
error!("Upgrade handler error: {}", e);
|
||||
DispatchError::Upgrade
|
||||
}),
|
||||
DispatcherState::Upgrade(ref mut fut) => {
|
||||
Pin::new(fut).poll(cx).map_err(|e| {
|
||||
error!("Upgrade handler error: {}", e);
|
||||
DispatchError::Upgrade
|
||||
})
|
||||
}
|
||||
DispatcherState::None => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_available<T>(io: &mut T, buf: &mut BytesMut) -> Result<Option<bool>, io::Error>
|
||||
fn read_available<T>(
|
||||
cx: &mut Context,
|
||||
io: &mut T,
|
||||
buf: &mut BytesMut,
|
||||
) -> Result<Option<bool>, io::Error>
|
||||
where
|
||||
T: io::Read,
|
||||
T: AsyncRead + Unpin,
|
||||
{
|
||||
let mut read_some = false;
|
||||
loop {
|
||||
@ -810,19 +844,18 @@ where
|
||||
buf.reserve(HW_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
let read = unsafe { io.read(buf.bytes_mut()) };
|
||||
match read {
|
||||
Ok(n) => {
|
||||
match read(cx, io, buf) {
|
||||
Poll::Pending => {
|
||||
return if read_some { Ok(Some(false)) } else { Ok(None) };
|
||||
}
|
||||
Poll::Ready(Ok(n)) => {
|
||||
if n == 0 {
|
||||
return Ok(Some(true));
|
||||
} else {
|
||||
read_some = true;
|
||||
unsafe {
|
||||
buf.advance_mut(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
Poll::Ready(Err(e)) => {
|
||||
return if e.kind() == io::ErrorKind::WouldBlock {
|
||||
if read_some {
|
||||
Ok(Some(false))
|
||||
@ -833,12 +866,23 @@ where
|
||||
Ok(Some(true))
|
||||
} else {
|
||||
Err(e)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read<T>(
|
||||
cx: &mut Context,
|
||||
io: &mut T,
|
||||
buf: &mut BytesMut,
|
||||
) -> Poll<Result<usize, io::Error>>
|
||||
where
|
||||
T: AsyncRead + Unpin,
|
||||
{
|
||||
Pin::new(io).poll_read_buf(cx, buf)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_service::IntoService;
|
||||
|
@ -1,21 +1,24 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{NewService, Service};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{Async, Poll};
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use futures::future::{ok, Ready};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::request::Request;
|
||||
|
||||
pub struct ExpectHandler;
|
||||
|
||||
impl NewService for ExpectHandler {
|
||||
impl ServiceFactory for ExpectHandler {
|
||||
type Config = ServerConfig;
|
||||
type Request = Request;
|
||||
type Response = Request;
|
||||
type Error = Error;
|
||||
type Service = ExpectHandler;
|
||||
type InitError = Error;
|
||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||
|
||||
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
||||
ok(ExpectHandler)
|
||||
@ -26,10 +29,10 @@ impl Service for ExpectHandler {
|
||||
type Request = Request;
|
||||
type Response = Request;
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self::Response, Self::Error>;
|
||||
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Request) -> Self::Future {
|
||||
|
@ -1,12 +1,14 @@
|
||||
//! Payload stream
|
||||
use std::cell::RefCell;
|
||||
use std::collections::VecDeque;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_utils::task::LocalWaker;
|
||||
use bytes::Bytes;
|
||||
use futures::task::current as current_task;
|
||||
use futures::task::Task;
|
||||
use futures::{Async, Poll, Stream};
|
||||
use futures::Stream;
|
||||
|
||||
use crate::error::PayloadError;
|
||||
|
||||
@ -77,15 +79,24 @@ impl Payload {
|
||||
pub fn unread_data(&mut self, data: Bytes) {
|
||||
self.inner.borrow_mut().unread_data(data);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn readany(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
self.inner.borrow_mut().readany(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for Payload {
|
||||
type Item = Bytes;
|
||||
type Error = PayloadError;
|
||||
type Item = Result<Bytes, PayloadError>;
|
||||
|
||||
#[inline]
|
||||
fn poll(&mut self) -> Poll<Option<Bytes>, PayloadError> {
|
||||
self.inner.borrow_mut().readany()
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
self.inner.borrow_mut().readany(cx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,19 +128,14 @@ impl PayloadSender {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn need_read(&self) -> PayloadStatus {
|
||||
pub fn need_read(&self, cx: &mut Context) -> PayloadStatus {
|
||||
// we check need_read only if Payload (other side) is alive,
|
||||
// otherwise always return true (consume payload)
|
||||
if let Some(shared) = self.inner.upgrade() {
|
||||
if shared.borrow().need_read {
|
||||
PayloadStatus::Read
|
||||
} else {
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
if shared.borrow_mut().io_task.is_none() {
|
||||
shared.borrow_mut().io_task = Some(current_task());
|
||||
}
|
||||
}
|
||||
shared.borrow_mut().io_task.register(cx.waker());
|
||||
PayloadStatus::Pause
|
||||
}
|
||||
} else {
|
||||
@ -145,8 +151,8 @@ struct Inner {
|
||||
err: Option<PayloadError>,
|
||||
need_read: bool,
|
||||
items: VecDeque<Bytes>,
|
||||
task: Option<Task>,
|
||||
io_task: Option<Task>,
|
||||
task: LocalWaker,
|
||||
io_task: LocalWaker,
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
@ -157,8 +163,8 @@ impl Inner {
|
||||
err: None,
|
||||
items: VecDeque::new(),
|
||||
need_read: true,
|
||||
task: None,
|
||||
io_task: None,
|
||||
task: LocalWaker::new(),
|
||||
io_task: LocalWaker::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +184,7 @@ impl Inner {
|
||||
self.items.push_back(data);
|
||||
self.need_read = self.len < MAX_BUFFER_SIZE;
|
||||
if let Some(task) = self.task.take() {
|
||||
task.notify()
|
||||
task.wake()
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,34 +193,28 @@ impl Inner {
|
||||
self.len
|
||||
}
|
||||
|
||||
fn readany(&mut self) -> Poll<Option<Bytes>, PayloadError> {
|
||||
fn readany(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
||||
if let Some(data) = self.items.pop_front() {
|
||||
self.len -= data.len();
|
||||
self.need_read = self.len < MAX_BUFFER_SIZE;
|
||||
|
||||
if self.need_read && self.task.is_none() && !self.eof {
|
||||
self.task = Some(current_task());
|
||||
if self.need_read && !self.eof {
|
||||
self.task.register(cx.waker());
|
||||
}
|
||||
if let Some(task) = self.io_task.take() {
|
||||
task.notify()
|
||||
}
|
||||
Ok(Async::Ready(Some(data)))
|
||||
self.io_task.wake();
|
||||
Poll::Ready(Some(Ok(data)))
|
||||
} else if let Some(err) = self.err.take() {
|
||||
Err(err)
|
||||
Poll::Ready(Some(Err(err)))
|
||||
} else if self.eof {
|
||||
Ok(Async::Ready(None))
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
self.need_read = true;
|
||||
#[cfg(not(test))]
|
||||
{
|
||||
if self.task.is_none() {
|
||||
self.task = Some(current_task());
|
||||
}
|
||||
if let Some(task) = self.io_task.take() {
|
||||
task.notify()
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady)
|
||||
self.task.register(cx.waker());
|
||||
self.io_task.wake();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
use std::fmt;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::Framed;
|
||||
use actix_server_config::{Io, IoStream, ServerConfig as SrvConfig};
|
||||
use actix_service::{IntoNewService, NewService, Service};
|
||||
use futures::future::{ok, FutureResult};
|
||||
use futures::{try_ready, Async, Future, IntoFuture, Poll, Stream};
|
||||
use actix_service::{IntoServiceFactory, Service, ServiceFactory};
|
||||
use futures::future::{ok, Ready};
|
||||
use futures::{ready, Stream};
|
||||
|
||||
use crate::body::MessageBody;
|
||||
use crate::cloneable::CloneableService;
|
||||
@ -20,7 +23,7 @@ use super::codec::Codec;
|
||||
use super::dispatcher::Dispatcher;
|
||||
use super::{ExpectHandler, Message, UpgradeHandler};
|
||||
|
||||
/// `NewService` implementation for HTTP1 transport
|
||||
/// `ServiceFactory` implementation for HTTP1 transport
|
||||
pub struct H1Service<T, P, S, B, X = ExpectHandler, U = UpgradeHandler<T>> {
|
||||
srv: S,
|
||||
cfg: ServiceConfig,
|
||||
@ -32,19 +35,23 @@ pub struct H1Service<T, P, S, B, X = ExpectHandler, U = UpgradeHandler<T>> {
|
||||
|
||||
impl<T, P, S, B> H1Service<T, P, S, B>
|
||||
where
|
||||
S: NewService<Config = SrvConfig, Request = Request>,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
P: Unpin,
|
||||
{
|
||||
/// Create new `HttpService` instance with default config.
|
||||
pub fn new<F: IntoNewService<S>>(service: F) -> Self {
|
||||
pub fn new<F: IntoServiceFactory<S>>(service: F) -> Self {
|
||||
let cfg = ServiceConfig::new(KeepAlive::Timeout(5), 5000, 0);
|
||||
|
||||
H1Service {
|
||||
cfg,
|
||||
srv: service.into_new_service(),
|
||||
srv: service.into_factory(),
|
||||
expect: ExpectHandler,
|
||||
upgrade: None,
|
||||
on_connect: None,
|
||||
@ -53,10 +60,13 @@ where
|
||||
}
|
||||
|
||||
/// Create new `HttpService` instance with config.
|
||||
pub fn with_config<F: IntoNewService<S>>(cfg: ServiceConfig, service: F) -> Self {
|
||||
pub fn with_config<F: IntoServiceFactory<S>>(
|
||||
cfg: ServiceConfig,
|
||||
service: F,
|
||||
) -> Self {
|
||||
H1Service {
|
||||
cfg,
|
||||
srv: service.into_new_service(),
|
||||
srv: service.into_factory(),
|
||||
expect: ExpectHandler,
|
||||
upgrade: None,
|
||||
on_connect: None,
|
||||
@ -67,17 +77,24 @@ where
|
||||
|
||||
impl<T, P, S, B, X, U> H1Service<T, P, S, B, X, U>
|
||||
where
|
||||
S: NewService<Config = SrvConfig, Request = Request>,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
P: Unpin,
|
||||
{
|
||||
pub fn expect<X1>(self, expect: X1) -> H1Service<T, P, S, B, X1, U>
|
||||
where
|
||||
X1: NewService<Request = Request, Response = Request>,
|
||||
X1: ServiceFactory<Request = Request, Response = Request>,
|
||||
X1::Error: Into<Error>,
|
||||
X1::InitError: fmt::Debug,
|
||||
X1::Future: Unpin,
|
||||
X1::Service: Unpin,
|
||||
<X1::Service as Service>::Future: Unpin,
|
||||
{
|
||||
H1Service {
|
||||
expect,
|
||||
@ -91,9 +108,12 @@ where
|
||||
|
||||
pub fn upgrade<U1>(self, upgrade: Option<U1>) -> H1Service<T, P, S, B, X, U1>
|
||||
where
|
||||
U1: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U1: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U1::Error: fmt::Display,
|
||||
U1::InitError: fmt::Debug,
|
||||
U1::Future: Unpin,
|
||||
U1::Service: Unpin,
|
||||
<U1::Service as Service>::Future: Unpin,
|
||||
{
|
||||
H1Service {
|
||||
upgrade,
|
||||
@ -115,24 +135,35 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P, S, B, X, U> NewService for H1Service<T, P, S, B, X, U>
|
||||
impl<T, P, S, B, X, U> ServiceFactory for H1Service<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: NewService<Config = SrvConfig, Request = Request>,
|
||||
S: ServiceFactory<Config = SrvConfig, Request = Request>,
|
||||
S::Service: Unpin,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: NewService<Config = SrvConfig, Request = Request, Response = Request>,
|
||||
X: ServiceFactory<Config = SrvConfig, Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
U: NewService<
|
||||
X::Future: Unpin,
|
||||
X::Service: Unpin,
|
||||
<X::Service as Service>::Future: Unpin,
|
||||
U: ServiceFactory<
|
||||
Config = SrvConfig,
|
||||
Request = (Request, Framed<T, Codec>),
|
||||
Response = (),
|
||||
>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Config = SrvConfig;
|
||||
type Request = Io<T, P>;
|
||||
@ -144,7 +175,7 @@ where
|
||||
|
||||
fn new_service(&self, cfg: &SrvConfig) -> Self::Future {
|
||||
H1ServiceResponse {
|
||||
fut: self.srv.new_service(cfg).into_future(),
|
||||
fut: self.srv.new_service(cfg),
|
||||
fut_ex: Some(self.expect.new_service(cfg)),
|
||||
fut_upg: self.upgrade.as_ref().map(|f| f.new_service(cfg)),
|
||||
expect: None,
|
||||
@ -159,15 +190,25 @@ where
|
||||
#[doc(hidden)]
|
||||
pub struct H1ServiceResponse<T, P, S, B, X, U>
|
||||
where
|
||||
S: NewService<Request = Request>,
|
||||
S: ServiceFactory<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::InitError: fmt::Debug,
|
||||
X: NewService<Request = Request, Response = Request>,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
X: ServiceFactory<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
U: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
X::Future: Unpin,
|
||||
X::Service: Unpin,
|
||||
<X::Service as Service>::Future: Unpin,
|
||||
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
fut: S::Future,
|
||||
fut_ex: Option<X::Future>,
|
||||
@ -182,49 +223,63 @@ where
|
||||
impl<T, P, S, B, X, U> Future for H1ServiceResponse<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: NewService<Request = Request>,
|
||||
S: ServiceFactory<Request = Request>,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::InitError: fmt::Debug,
|
||||
S::Future: Unpin,
|
||||
S::Service: Unpin,
|
||||
<S::Service as Service>::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: NewService<Request = Request, Response = Request>,
|
||||
X: ServiceFactory<Request = Request, Response = Request>,
|
||||
X::Error: Into<Error>,
|
||||
X::InitError: fmt::Debug,
|
||||
U: NewService<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
X::Future: Unpin,
|
||||
X::Service: Unpin,
|
||||
<X::Service as Service>::Future: Unpin,
|
||||
U: ServiceFactory<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U::Error: fmt::Display,
|
||||
U::InitError: fmt::Debug,
|
||||
U::Future: Unpin,
|
||||
U::Service: Unpin,
|
||||
<U::Service as Service>::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Item = H1ServiceHandler<T, P, S::Service, B, X::Service, U::Service>;
|
||||
type Error = ();
|
||||
type Output =
|
||||
Result<H1ServiceHandler<T, P, S::Service, B, X::Service, U::Service>, ()>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
if let Some(ref mut fut) = self.fut_ex {
|
||||
let expect = try_ready!(fut
|
||||
.poll()
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||
self.expect = Some(expect);
|
||||
self.fut_ex.take();
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
|
||||
if let Some(ref mut fut) = this.fut_ex {
|
||||
let expect = ready!(Pin::new(fut)
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.expect = Some(expect);
|
||||
this.fut_ex.take();
|
||||
}
|
||||
|
||||
if let Some(ref mut fut) = self.fut_upg {
|
||||
let upgrade = try_ready!(fut
|
||||
.poll()
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||
self.upgrade = Some(upgrade);
|
||||
self.fut_ex.take();
|
||||
if let Some(ref mut fut) = this.fut_upg {
|
||||
let upgrade = ready!(Pin::new(fut)
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)))?;
|
||||
this.upgrade = Some(upgrade);
|
||||
this.fut_ex.take();
|
||||
}
|
||||
|
||||
let service = try_ready!(self
|
||||
.fut
|
||||
.poll()
|
||||
let result = ready!(Pin::new(&mut this.fut)
|
||||
.poll(cx)
|
||||
.map_err(|e| log::error!("Init http service error: {:?}", e)));
|
||||
Ok(Async::Ready(H1ServiceHandler::new(
|
||||
self.cfg.take().unwrap(),
|
||||
service,
|
||||
self.expect.take().unwrap(),
|
||||
self.upgrade.take(),
|
||||
self.on_connect.clone(),
|
||||
)))
|
||||
|
||||
Poll::Ready(result.map(|service| {
|
||||
H1ServiceHandler::new(
|
||||
this.cfg.take().unwrap(),
|
||||
service,
|
||||
this.expect.take().unwrap(),
|
||||
this.upgrade.take(),
|
||||
this.on_connect.clone(),
|
||||
)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,14 +295,18 @@ pub struct H1ServiceHandler<T, P, S, B, X, U> {
|
||||
|
||||
impl<T, P, S, B, X, U> H1ServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
S: Service<Request = Request>,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X::Future: Unpin,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||
U::Future: Unpin,
|
||||
U::Error: fmt::Display,
|
||||
P: Unpin,
|
||||
{
|
||||
fn new(
|
||||
cfg: ServiceConfig,
|
||||
@ -270,24 +329,28 @@ where
|
||||
impl<T, P, S, B, X, U> Service for H1ServiceHandler<T, P, S, B, X, U>
|
||||
where
|
||||
T: IoStream,
|
||||
S: Service<Request = Request>,
|
||||
S: Service<Request = Request> + Unpin,
|
||||
S::Error: Into<Error>,
|
||||
S::Response: Into<Response<B>>,
|
||||
S::Future: Unpin,
|
||||
B: MessageBody,
|
||||
X: Service<Request = Request, Response = Request>,
|
||||
X: Service<Request = Request, Response = Request> + Unpin,
|
||||
X::Error: Into<Error>,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()>,
|
||||
X::Future: Unpin,
|
||||
U: Service<Request = (Request, Framed<T, Codec>), Response = ()> + Unpin,
|
||||
U::Error: fmt::Display,
|
||||
U::Future: Unpin,
|
||||
P: Unpin,
|
||||
{
|
||||
type Request = Io<T, P>;
|
||||
type Response = ();
|
||||
type Error = DispatchError;
|
||||
type Future = Dispatcher<T, S, B, X, U>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
let ready = self
|
||||
.expect
|
||||
.poll_ready()
|
||||
.poll_ready(cx)
|
||||
.map_err(|e| {
|
||||
let e = e.into();
|
||||
log::error!("Http service readiness error: {:?}", e);
|
||||
@ -297,7 +360,7 @@ where
|
||||
|
||||
let ready = self
|
||||
.srv
|
||||
.poll_ready()
|
||||
.poll_ready(cx)
|
||||
.map_err(|e| {
|
||||
let e = e.into();
|
||||
log::error!("Http service readiness error: {:?}", e);
|
||||
@ -307,9 +370,9 @@ where
|
||||
&& ready;
|
||||
|
||||
if ready {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +396,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// `NewService` implementation for `OneRequestService` service
|
||||
/// `ServiceFactory` implementation for `OneRequestService` service
|
||||
#[derive(Default)]
|
||||
pub struct OneRequest<T, P> {
|
||||
config: ServiceConfig,
|
||||
@ -353,7 +416,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P> NewService for OneRequest<T, P>
|
||||
impl<T, P> ServiceFactory for OneRequest<T, P>
|
||||
where
|
||||
T: IoStream,
|
||||
{
|
||||
@ -363,7 +426,7 @@ where
|
||||
type Error = ParseError;
|
||||
type InitError = ();
|
||||
type Service = OneRequestService<T, P>;
|
||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||
|
||||
fn new_service(&self, _: &SrvConfig) -> Self::Future {
|
||||
ok(OneRequestService {
|
||||
@ -389,8 +452,8 @@ where
|
||||
type Error = ParseError;
|
||||
type Future = OneRequestServiceResponse<T>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||
@ -415,19 +478,19 @@ impl<T> Future for OneRequestServiceResponse<T>
|
||||
where
|
||||
T: IoStream,
|
||||
{
|
||||
type Item = (Request, Framed<T, Codec>);
|
||||
type Error = ParseError;
|
||||
type Output = Result<(Request, Framed<T, Codec>), ParseError>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
match self.framed.as_mut().unwrap().poll()? {
|
||||
Async::Ready(Some(req)) => match req {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
match self.framed.as_mut().unwrap().next_item(cx) {
|
||||
Poll::Ready(Some(Ok(req))) => match req {
|
||||
Message::Item(req) => {
|
||||
Ok(Async::Ready((req, self.framed.take().unwrap())))
|
||||
Poll::Ready(Ok((req, self.framed.take().unwrap())))
|
||||
}
|
||||
Message::Chunk(_) => unreachable!("Something is wrong"),
|
||||
},
|
||||
Async::Ready(None) => Err(ParseError::Incomplete),
|
||||
Async::NotReady => Ok(Async::NotReady),
|
||||
Poll::Ready(Some(Err(err))) => Poll::Ready(Err(err)),
|
||||
Poll::Ready(None) => Poll::Ready(Err(ParseError::Incomplete)),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::Framed;
|
||||
use actix_server_config::ServerConfig;
|
||||
use actix_service::{NewService, Service};
|
||||
use futures::future::FutureResult;
|
||||
use futures::{Async, Poll};
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use futures::future::Ready;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::h1::Codec;
|
||||
@ -12,14 +14,14 @@ use crate::request::Request;
|
||||
|
||||
pub struct UpgradeHandler<T>(PhantomData<T>);
|
||||
|
||||
impl<T> NewService for UpgradeHandler<T> {
|
||||
impl<T> ServiceFactory for UpgradeHandler<T> {
|
||||
type Config = ServerConfig;
|
||||
type Request = (Request, Framed<T, Codec>);
|
||||
type Response = ();
|
||||
type Error = Error;
|
||||
type Service = UpgradeHandler<T>;
|
||||
type InitError = Error;
|
||||
type Future = FutureResult<Self::Service, Self::InitError>;
|
||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||
|
||||
fn new_service(&self, _: &ServerConfig) -> Self::Future {
|
||||
unimplemented!()
|
||||
@ -30,10 +32,10 @@ impl<T> Service for UpgradeHandler<T> {
|
||||
type Request = (Request, Framed<T, Codec>);
|
||||
type Response = ();
|
||||
type Error = Error;
|
||||
type Future = FutureResult<Self::Response, Self::Error>;
|
||||
type Future = Ready<Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
Ok(Async::Ready(()))
|
||||
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, _: Self::Request) -> Self::Future {
|
||||
|
@ -1,5 +1,9 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||
use futures::{Async, Future, Poll, Sink};
|
||||
use futures::Sink;
|
||||
|
||||
use crate::body::{BodySize, MessageBody, ResponseBody};
|
||||
use crate::error::Error;
|
||||
@ -30,63 +34,64 @@ where
|
||||
|
||||
impl<T, B> Future for SendResponse<T, B>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite,
|
||||
T: AsyncRead + AsyncWrite + Unpin,
|
||||
B: MessageBody,
|
||||
{
|
||||
type Item = Framed<T, Codec>;
|
||||
type Error = Error;
|
||||
type Output = Result<Framed<T, Codec>, Error>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
let this = self.get_mut();
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
loop {
|
||||
let mut body_ready = self.body.is_some();
|
||||
let framed = self.framed.as_mut().unwrap();
|
||||
let mut body_ready = this.body.is_some();
|
||||
let framed = this.framed.as_mut().unwrap();
|
||||
|
||||
// send body
|
||||
if self.res.is_none() && self.body.is_some() {
|
||||
while body_ready && self.body.is_some() && !framed.is_write_buf_full() {
|
||||
match self.body.as_mut().unwrap().poll_next()? {
|
||||
Async::Ready(item) => {
|
||||
if this.res.is_none() && this.body.is_some() {
|
||||
while body_ready && this.body.is_some() && !framed.is_write_buf_full() {
|
||||
match this.body.as_mut().unwrap().poll_next(cx)? {
|
||||
Poll::Ready(item) => {
|
||||
// body is done
|
||||
if item.is_none() {
|
||||
let _ = self.body.take();
|
||||
let _ = this.body.take();
|
||||
}
|
||||
framed.force_send(Message::Chunk(item))?;
|
||||
}
|
||||
Async::NotReady => body_ready = false,
|
||||
Poll::Pending => body_ready = false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flush write buffer
|
||||
if !framed.is_write_buf_empty() {
|
||||
match framed.poll_complete()? {
|
||||
Async::Ready(_) => {
|
||||
match framed.flush(cx)? {
|
||||
Poll::Ready(_) => {
|
||||
if body_ready {
|
||||
continue;
|
||||
} else {
|
||||
return Ok(Async::NotReady);
|
||||
return Poll::Pending;
|
||||
}
|
||||
}
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
}
|
||||
}
|
||||
|
||||
// send response
|
||||
if let Some(res) = self.res.take() {
|
||||
if let Some(res) = this.res.take() {
|
||||
framed.force_send(res)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
if self.body.is_some() {
|
||||
if this.body.is_some() {
|
||||
if body_ready {
|
||||
continue;
|
||||
} else {
|
||||
return Ok(Async::NotReady);
|
||||
return Poll::Pending;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(Async::Ready(self.framed.take().unwrap()))
|
||||
Poll::Ready(Ok(this.framed.take().unwrap()))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user