| @@ -1,498 +0,0 @@ | ||||
| //! Streaming bodies for Requests and Responses | ||||
| use std::borrow::Cow; | ||||
| use std::fmt; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| use http::HeaderMap; | ||||
|  | ||||
| use common::Never; | ||||
| use super::Chunk; | ||||
|  | ||||
| type BodySender = mpsc::Sender<Result<Chunk, ::Error>>; | ||||
|  | ||||
| /// This trait represents a streaming body of a `Request` or `Response`. | ||||
| pub trait Entity { | ||||
|     /// A buffer of bytes representing a single chunk of a body. | ||||
|     type Data: AsRef<[u8]>; | ||||
|  | ||||
|     /// The error type of this stream. | ||||
|     type Error: Into<Box<::std::error::Error + Send + Sync>>; | ||||
|  | ||||
|     /// Poll for a `Data` buffer. | ||||
|     /// | ||||
|     /// Similar to `Stream::poll_next`, this yields `Some(Data)` until | ||||
|     /// the body ends, when it yields `None`. | ||||
|     fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>; | ||||
|  | ||||
|     /// Poll for an optional **single** `HeaderMap` of trailers. | ||||
|     /// | ||||
|     /// This should **only** be called after `poll_data` has ended. | ||||
|     /// | ||||
|     /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2. | ||||
|     fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { | ||||
|         Ok(Async::Ready(None)) | ||||
|     } | ||||
|  | ||||
|     /// A hint that the `Body` is complete, and doesn't need to be polled more. | ||||
|     /// | ||||
|     /// This can be useful to determine if the there is any body or trailers | ||||
|     /// without having to poll. An empty `Body` could return `true` and hyper | ||||
|     /// would be able to know that only the headers need to be sent. Or, it can | ||||
|     /// also be checked after each `poll_data` call, to allow hyper to try to | ||||
|     /// end the underlying stream with the last chunk, instead of needing to | ||||
|     /// send an extra `DATA` frame just to mark the stream as finished. | ||||
|     /// | ||||
|     /// As a hint, it is used to try to optimize, and thus is OK for a default | ||||
|     /// implementation to return `false`. | ||||
|     fn is_end_stream(&self) -> bool { | ||||
|         false | ||||
|     } | ||||
|  | ||||
|     /// Return a length of the total bytes that will be streamed, if known. | ||||
|     /// | ||||
|     /// If an exact size of bytes is known, this would allow hyper to send a | ||||
|     /// `Content-Length` header automatically, not needing to fall back to | ||||
|     /// `Transfer-Encoding: chunked`. | ||||
|     /// | ||||
|     /// This does not need to be kept updated after polls, it will only be | ||||
|     /// called once to create the headers. | ||||
|     fn content_length(&self) -> Option<u64> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<E: Entity> Entity for Box<E> { | ||||
|     type Data = E::Data; | ||||
|     type Error = E::Error; | ||||
|  | ||||
|     fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> { | ||||
|         (**self).poll_data() | ||||
|     } | ||||
|  | ||||
|     fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { | ||||
|         (**self).poll_trailers() | ||||
|     } | ||||
|  | ||||
|     fn is_end_stream(&self) -> bool { | ||||
|         (**self).is_end_stream() | ||||
|     } | ||||
|  | ||||
|     fn content_length(&self) -> Option<u64> { | ||||
|         (**self).content_length() | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// A wrapper to consume an `Entity` as a futures `Stream`. | ||||
| #[must_use = "streams do nothing unless polled"] | ||||
| #[derive(Debug)] | ||||
| pub struct EntityStream<E> { | ||||
|     is_data_eof: bool, | ||||
|     entity: E, | ||||
| } | ||||
|  | ||||
| impl<E: Entity> Stream for EntityStream<E> { | ||||
|     type Item = E::Data; | ||||
|     type Error = E::Error; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { | ||||
|         loop { | ||||
|             if self.is_data_eof { | ||||
|                 return self.entity.poll_trailers() | ||||
|                     .map(|async| { | ||||
|                         async.map(|_opt| { | ||||
|                             // drop the trailers and return that Stream is done | ||||
|                             None | ||||
|                         }) | ||||
|                     }); | ||||
|             } | ||||
|  | ||||
|             let opt = try_ready!(self.entity.poll_data()); | ||||
|             if let Some(data) = opt { | ||||
|                 return Ok(Async::Ready(Some(data))); | ||||
|             } else { | ||||
|                 self.is_data_eof = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// An `Entity` of `Chunk`s, used when receiving bodies. | ||||
| /// | ||||
| /// Also a good default `Entity` to use in many applications. | ||||
| #[must_use = "streams do nothing unless polled"] | ||||
| pub struct Body { | ||||
|     kind: Kind, | ||||
|     /// Allow the client to pass a future to delay the `Body` from returning | ||||
|     /// EOF. This allows the `Client` to try to put the idle connection | ||||
|     /// back into the pool before the body is "finished". | ||||
|     /// | ||||
|     /// The reason for this is so that creating a new request after finishing | ||||
|     /// streaming the body of a response could sometimes result in creating | ||||
|     /// a brand new connection, since the pool didn't know about the idle | ||||
|     /// connection yet. | ||||
|     delayed_eof: Option<DelayEof>, | ||||
| } | ||||
|  | ||||
| enum Kind { | ||||
|     Chan { | ||||
|         _close_tx: oneshot::Sender<()>, | ||||
|         rx: mpsc::Receiver<Result<Chunk, ::Error>>, | ||||
|     }, | ||||
|     Wrapped(Box<Stream<Item=Chunk, Error=Box<::std::error::Error + Send + Sync>> + Send>), | ||||
|     Once(Option<Chunk>), | ||||
|     Empty, | ||||
| } | ||||
|  | ||||
| type DelayEofUntil = oneshot::Receiver<Never>; | ||||
|  | ||||
| enum DelayEof { | ||||
|     /// Initial state, stream hasn't seen EOF yet. | ||||
|     NotEof(DelayEofUntil), | ||||
|     /// Transitions to this state once we've seen `poll` try to | ||||
|     /// return EOF (`None`). This future is then polled, and | ||||
|     /// when it completes, the Body finally returns EOF (`None`). | ||||
|     Eof(DelayEofUntil), | ||||
| } | ||||
|  | ||||
| /// A sender half used with `Body::channel()`. | ||||
| #[derive(Debug)] | ||||
| pub struct Sender { | ||||
|     close_rx: oneshot::Receiver<()>, | ||||
|     tx: BodySender, | ||||
| } | ||||
|  | ||||
| impl Body { | ||||
|     /// Create an empty `Body` stream. | ||||
|     /// | ||||
|     /// # Example | ||||
|     /// | ||||
|     /// ``` | ||||
|     /// use hyper::{Body, Request}; | ||||
|     /// | ||||
|     /// // create a `GET /` request | ||||
|     /// let get = Request::new(Body::empty()); | ||||
|     /// ``` | ||||
|     #[inline] | ||||
|     pub fn empty() -> Body { | ||||
|         Body::new(Kind::Empty) | ||||
|     } | ||||
|  | ||||
|     /// Create a `Body` stream with an associated sender half. | ||||
|     #[inline] | ||||
|     pub fn channel() -> (Sender, Body) { | ||||
|         let (tx, rx) = mpsc::channel(0); | ||||
|         let (close_tx, close_rx) = oneshot::channel(); | ||||
|  | ||||
|         let tx = Sender { | ||||
|             close_rx: close_rx, | ||||
|             tx: tx, | ||||
|         }; | ||||
|         let rx = Body::new(Kind::Chan { | ||||
|             _close_tx: close_tx, | ||||
|             rx: rx, | ||||
|         }); | ||||
|  | ||||
|         (tx, rx) | ||||
|     } | ||||
|  | ||||
|     /// Wrap a futures `Stream` in a box inside `Body`. | ||||
|     /// | ||||
|     /// # Example | ||||
|     /// | ||||
|     /// ``` | ||||
|     /// # extern crate futures; | ||||
|     /// # extern crate hyper; | ||||
|     /// # use hyper::Body; | ||||
|     /// # fn main() { | ||||
|     /// let chunks = vec![ | ||||
|     ///     "hello", | ||||
|     ///     " ", | ||||
|     ///     "world", | ||||
|     /// ]; | ||||
|     /// | ||||
|     /// let stream = futures::stream::iter_ok::<_, ::std::io::Error>(chunks); | ||||
|     /// | ||||
|     /// let body = Body::wrap_stream(stream); | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     pub fn wrap_stream<S>(stream: S) -> Body | ||||
|     where | ||||
|         S: Stream + Send + 'static, | ||||
|         S::Error: Into<Box<::std::error::Error + Send + Sync>>, | ||||
|         Chunk: From<S::Item>, | ||||
|     { | ||||
|         let mapped = stream | ||||
|             .map(Chunk::from) | ||||
|             .map_err(Into::into); | ||||
|         Body::new(Kind::Wrapped(Box::new(mapped))) | ||||
|     } | ||||
|  | ||||
|     /// Convert this `Body` into a `Stream<Item=Chunk, Error=hyper::Error>`. | ||||
|     /// | ||||
|     /// # Example | ||||
|     /// | ||||
|     /// ``` | ||||
|     /// # extern crate futures; | ||||
|     /// # extern crate hyper; | ||||
|     /// # use futures::{Future, Stream}; | ||||
|     /// # use hyper::{Body, Request}; | ||||
|     /// # fn request_concat(some_req: Request<Body>) { | ||||
|     /// let req: Request<Body> = some_req; | ||||
|     /// let body = req.into_body(); | ||||
|     /// | ||||
|     /// let stream = body.into_stream(); | ||||
|     /// stream.concat2() | ||||
|     ///     .map(|buf| { | ||||
|     ///         println!("body length: {}", buf.len()); | ||||
|     ///     }); | ||||
|     /// # } | ||||
|     /// # fn main() {} | ||||
|     /// ``` | ||||
|     #[inline] | ||||
|     pub fn into_stream(self) -> EntityStream<Body> { | ||||
|         EntityStream { | ||||
|             is_data_eof: false, | ||||
|             entity: self, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns if this body was constructed via `Body::empty()`. | ||||
|     /// | ||||
|     /// # Note | ||||
|     /// | ||||
|     /// This does **not** detect if the body stream may be at the end, or | ||||
|     /// if the stream will not yield any chunks, in all cases. For instance, | ||||
|     /// a streaming body using `chunked` encoding is not able to tell if | ||||
|     /// there are more chunks immediately. | ||||
|     #[inline] | ||||
|     pub fn is_empty(&self) -> bool { | ||||
|         match self.kind { | ||||
|             Kind::Empty => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn new(kind: Kind) -> Body { | ||||
|         Body { | ||||
|             kind: kind, | ||||
|             delayed_eof: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn delayed_eof(&mut self, fut: DelayEofUntil) { | ||||
|         self.delayed_eof = Some(DelayEof::NotEof(fut)); | ||||
|     } | ||||
|  | ||||
|     fn poll_eof(&mut self) -> Poll<Option<Chunk>, ::Error> { | ||||
|         match self.delayed_eof.take() { | ||||
|             Some(DelayEof::NotEof(mut delay)) => { | ||||
|                 match self.poll_inner() { | ||||
|                     ok @ Ok(Async::Ready(Some(..))) | | ||||
|                     ok @ Ok(Async::NotReady) => { | ||||
|                         self.delayed_eof = Some(DelayEof::NotEof(delay)); | ||||
|                         ok | ||||
|                     }, | ||||
|                     Ok(Async::Ready(None)) => match delay.poll() { | ||||
|                         Ok(Async::Ready(never)) => match never {}, | ||||
|                         Ok(Async::NotReady) => { | ||||
|                             self.delayed_eof = Some(DelayEof::Eof(delay)); | ||||
|                             Ok(Async::NotReady) | ||||
|                         }, | ||||
|                         Err(_done) => { | ||||
|                             Ok(Async::Ready(None)) | ||||
|                         }, | ||||
|                     }, | ||||
|                     Err(e) => Err(e), | ||||
|                 } | ||||
|             }, | ||||
|             Some(DelayEof::Eof(mut delay)) => { | ||||
|                 match delay.poll() { | ||||
|                     Ok(Async::Ready(never)) => match never {}, | ||||
|                     Ok(Async::NotReady) => { | ||||
|                         self.delayed_eof = Some(DelayEof::Eof(delay)); | ||||
|                         Ok(Async::NotReady) | ||||
|                     }, | ||||
|                     Err(_done) => { | ||||
|                         Ok(Async::Ready(None)) | ||||
|                     }, | ||||
|                 } | ||||
|             }, | ||||
|             None => self.poll_inner(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn poll_inner(&mut self) -> Poll<Option<Chunk>, ::Error> { | ||||
|         match self.kind { | ||||
|             Kind::Chan { ref mut rx, .. } => match rx.poll().expect("mpsc cannot error") { | ||||
|                 Async::Ready(Some(Ok(chunk))) => Ok(Async::Ready(Some(chunk))), | ||||
|                 Async::Ready(Some(Err(err))) => Err(err), | ||||
|                 Async::Ready(None) => Ok(Async::Ready(None)), | ||||
|                 Async::NotReady => Ok(Async::NotReady), | ||||
|             }, | ||||
|             Kind::Wrapped(ref mut s) => s.poll().map_err(::Error::new_body), | ||||
|             Kind::Once(ref mut val) => Ok(Async::Ready(val.take())), | ||||
|             Kind::Empty => Ok(Async::Ready(None)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Default for Body { | ||||
|     #[inline] | ||||
|     fn default() -> Body { | ||||
|         Body::empty() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Entity for Body { | ||||
|     type Data = Chunk; | ||||
|     type Error = ::Error; | ||||
|  | ||||
|     fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> { | ||||
|         self.poll_eof() | ||||
|     } | ||||
|  | ||||
|     fn is_end_stream(&self) -> bool { | ||||
|         match self.kind { | ||||
|             Kind::Chan { .. } => false, | ||||
|             Kind::Wrapped(..) => false, | ||||
|             Kind::Once(ref val) => val.is_none(), | ||||
|             Kind::Empty => true | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn content_length(&self) -> Option<u64> { | ||||
|         match self.kind { | ||||
|             Kind::Chan { .. } => None, | ||||
|             Kind::Wrapped(..) => None, | ||||
|             Kind::Once(Some(ref val)) => Some(val.len() as u64), | ||||
|             Kind::Once(None) => None, | ||||
|             Kind::Empty => Some(0) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Debug for Body { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         f.debug_struct("Body") | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Sender { | ||||
|     /// Check to see if this `Sender` can send more data. | ||||
|     pub fn poll_ready(&mut self) -> Poll<(), ()> { | ||||
|         match self.close_rx.poll() { | ||||
|             Ok(Async::Ready(())) | Err(_) => return Err(()), | ||||
|             Ok(Async::NotReady) => (), | ||||
|         } | ||||
|  | ||||
|         self.tx.poll_ready().map_err(|_| ()) | ||||
|     } | ||||
|  | ||||
|     /// Sends data on this channel. | ||||
|     /// | ||||
|     /// This should be called after `poll_ready` indicated the channel | ||||
|     /// could accept another `Chunk`. | ||||
|     /// | ||||
|     /// Returns `Err(Chunk)` if the channel could not (currently) accept | ||||
|     /// another `Chunk`. | ||||
|     pub fn send_data(&mut self, chunk: Chunk) -> Result<(), Chunk> { | ||||
|         self.tx.try_send(Ok(chunk)) | ||||
|             .map_err(|err| err.into_inner().expect("just sent Ok")) | ||||
|     } | ||||
|  | ||||
|     pub(crate) fn send_error(&mut self, err: ::Error) { | ||||
|         let _ = self.tx.try_send(Err(err)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Chunk> for Body { | ||||
|     #[inline] | ||||
|     fn from(chunk: Chunk) -> Body { | ||||
|         if chunk.is_empty() { | ||||
|             Body::empty() | ||||
|         } else { | ||||
|             Body::new(Kind::Once(Some(chunk))) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Bytes> for Body { | ||||
|     #[inline] | ||||
|     fn from (bytes: Bytes) -> Body { | ||||
|         Body::from(Chunk::from(bytes)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Vec<u8>> for Body { | ||||
|     #[inline] | ||||
|     fn from (vec: Vec<u8>) -> Body { | ||||
|         Body::from(Chunk::from(vec)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static [u8]> for Body { | ||||
|     #[inline] | ||||
|     fn from (slice: &'static [u8]) -> Body { | ||||
|         Body::from(Chunk::from(slice)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Cow<'static, [u8]>> for Body { | ||||
|     #[inline] | ||||
|     fn from (cow: Cow<'static, [u8]>) -> Body { | ||||
|         match cow { | ||||
|             Cow::Borrowed(b) => Body::from(b), | ||||
|             Cow::Owned(o) => Body::from(o) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for Body { | ||||
|     #[inline] | ||||
|     fn from (s: String) -> Body { | ||||
|         Body::from(Chunk::from(s.into_bytes())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static str> for Body { | ||||
|     #[inline] | ||||
|     fn from(slice: &'static str) -> Body { | ||||
|         Body::from(Chunk::from(slice.as_bytes())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Cow<'static, str>> for Body { | ||||
|     #[inline] | ||||
|     fn from(cow: Cow<'static, str>) -> Body { | ||||
|         match cow { | ||||
|             Cow::Borrowed(b) => Body::from(b), | ||||
|             Cow::Owned(o) => Body::from(o) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn _assert_send_sync() { | ||||
|     fn _assert_send<T: Send>() {} | ||||
|     fn _assert_sync<T: Sync>() {} | ||||
|  | ||||
|     _assert_send::<Body>(); | ||||
|     _assert_send::<Chunk>(); | ||||
|     _assert_sync::<Chunk>(); | ||||
| } | ||||
|  | ||||
| #[test] | ||||
| fn test_body_stream_concat() { | ||||
|     use futures::{Stream, Future}; | ||||
|  | ||||
|     let body = Body::from("hello world"); | ||||
|  | ||||
|     let total = body.into_stream() | ||||
|         .concat2() | ||||
|         .wait() | ||||
|         .unwrap(); | ||||
|     assert_eq!(total.as_ref(), b"hello world"); | ||||
|  | ||||
| } | ||||
| @@ -1,107 +0,0 @@ | ||||
| use std::fmt; | ||||
|  | ||||
| use bytes::Bytes; | ||||
|  | ||||
| /// A piece of a message body. | ||||
| pub struct Chunk(Inner); | ||||
|  | ||||
| enum Inner { | ||||
|     Shared(Bytes), | ||||
| } | ||||
|  | ||||
| impl From<Vec<u8>> for Chunk { | ||||
|     #[inline] | ||||
|     fn from(v: Vec<u8>) -> Chunk { | ||||
|         Chunk::from(Bytes::from(v)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static [u8]> for Chunk { | ||||
|     #[inline] | ||||
|     fn from(slice: &'static [u8]) -> Chunk { | ||||
|         Chunk::from(Bytes::from_static(slice)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<String> for Chunk { | ||||
|     #[inline] | ||||
|     fn from(s: String) -> Chunk { | ||||
|         s.into_bytes().into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<&'static str> for Chunk { | ||||
|     #[inline] | ||||
|     fn from(slice: &'static str) -> Chunk { | ||||
|         slice.as_bytes().into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Bytes> for Chunk { | ||||
|     #[inline] | ||||
|     fn from(mem: Bytes) -> Chunk { | ||||
|         Chunk(Inner::Shared(mem)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Chunk> for Bytes { | ||||
|     #[inline] | ||||
|     fn from(chunk: Chunk) -> Bytes { | ||||
|         match chunk.0 { | ||||
|             Inner::Shared(bytes) => bytes, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl ::std::ops::Deref for Chunk { | ||||
|     type Target = [u8]; | ||||
|  | ||||
|     #[inline] | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|         self.as_ref() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl AsRef<[u8]> for Chunk { | ||||
|     #[inline] | ||||
|     fn as_ref(&self) -> &[u8] { | ||||
|         match self.0 { | ||||
|             Inner::Shared(ref slice) => slice, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl fmt::Debug for Chunk { | ||||
|     #[inline] | ||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||
|         fmt::Debug::fmt(self.as_ref(), f) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Default for Chunk { | ||||
|     #[inline] | ||||
|     fn default() -> Chunk { | ||||
|         Chunk(Inner::Shared(Bytes::new())) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl IntoIterator for Chunk { | ||||
|     type Item = u8; | ||||
|     type IntoIter = <Bytes as IntoIterator>::IntoIter; | ||||
|  | ||||
|     #[inline] | ||||
|     fn into_iter(self) -> Self::IntoIter { | ||||
|         match self.0 { | ||||
|             Inner::Shared(bytes) => bytes.into_iter(), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Extend<u8> for Chunk { | ||||
|     #[inline] | ||||
|     fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item=u8> { | ||||
|         match self.0 { | ||||
|             Inner::Shared(ref mut bytes) => bytes.extend(iter) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -8,7 +8,8 @@ use futures::task::Task; | ||||
| use http::{Method, Version}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use proto::{BodyLength, Chunk, Decode, Http1Transaction, MessageHead}; | ||||
| use ::Chunk; | ||||
| use proto::{BodyLength, Decode, Http1Transaction, MessageHead}; | ||||
| use super::io::{Cursor, Buffered}; | ||||
| use super::{EncodedBuf, Encoder, Decoder}; | ||||
|  | ||||
|   | ||||
| @@ -4,13 +4,13 @@ use http::{Request, Response, StatusCode}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
| use tokio_service::Service; | ||||
|  | ||||
| use proto::body::Entity; | ||||
| use proto::{Body, BodyLength, Conn, Http1Transaction, MessageHead, RequestHead, RequestLine, ResponseHead}; | ||||
| use body::{Body, Payload}; | ||||
| use proto::{BodyLength, Conn, Http1Transaction, MessageHead, RequestHead, RequestLine, ResponseHead}; | ||||
|  | ||||
| pub(crate) struct Dispatcher<D, Bs, I, B, T> { | ||||
|     conn: Conn<I, B, T>, | ||||
|     dispatch: D, | ||||
|     body_tx: Option<::proto::body::Sender>, | ||||
|     body_tx: Option<::body::Sender>, | ||||
|     body_rx: Option<Bs>, | ||||
|     is_closing: bool, | ||||
| } | ||||
| @@ -45,7 +45,7 @@ where | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     B: AsRef<[u8]>, | ||||
|     T: Http1Transaction, | ||||
|     Bs: Entity<Data=B>, | ||||
|     Bs: Payload<Data=B>, | ||||
| { | ||||
|     pub fn new(dispatch: D, conn: Conn<I, B, T>) -> Self { | ||||
|         Dispatcher { | ||||
| @@ -292,7 +292,7 @@ where | ||||
|     I: AsyncRead + AsyncWrite, | ||||
|     B: AsRef<[u8]>, | ||||
|     T: Http1Transaction, | ||||
|     Bs: Entity<Data=B>, | ||||
|     Bs: Payload<Data=B>, | ||||
| { | ||||
|     type Item = (); | ||||
|     type Error = ::Error; | ||||
| @@ -318,7 +318,7 @@ impl<S, Bs> Dispatch for Server<S> | ||||
| where | ||||
|     S: Service<Request=Request<Body>, Response=Response<Bs>>, | ||||
|     S::Error: Into<Box<::std::error::Error + Send + Sync>>, | ||||
|     Bs: Entity, | ||||
|     Bs: Payload, | ||||
| { | ||||
|     type PollItem = MessageHead<StatusCode>; | ||||
|     type PollBody = Bs; | ||||
| @@ -388,7 +388,7 @@ impl<B> Client<B> { | ||||
|  | ||||
| impl<B> Dispatch for Client<B> | ||||
| where | ||||
|     B: Entity, | ||||
|     B: Payload, | ||||
| { | ||||
|     type PollItem = RequestHead; | ||||
|     type PollBody = B; | ||||
|   | ||||
| @@ -428,7 +428,7 @@ impl Client<()> { | ||||
|  | ||||
| fn set_length(headers: &mut HeaderMap, body: BodyLength, can_chunked: bool) -> Encoder { | ||||
|     // If the user already set specific headers, we should respect them, regardless | ||||
|     // of what the Entity knows about itself. They set them for a reason. | ||||
|     // of what the Payload knows about itself. They set them for a reason. | ||||
|  | ||||
|     // Because of the borrow checker, we can't check the for an existing | ||||
|     // Content-Length header while holding an `Entry` for the Transfer-Encoding | ||||
|   | ||||
| @@ -4,12 +4,8 @@ use http::{HeaderMap, Method, StatusCode, Uri, Version}; | ||||
|  | ||||
| use headers; | ||||
|  | ||||
| pub use self::body::Body; | ||||
| pub use self::chunk::Chunk; | ||||
| pub(crate) use self::h1::{dispatch, Conn}; | ||||
|  | ||||
| pub mod body; | ||||
| mod chunk; | ||||
| mod h1; | ||||
| //mod h2; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user