use std::fmt; #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll};
use bytes::Bytes; #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] use futures_channel::{mpsc, oneshot}; #[cfg(all(
any(feature = "http1", feature = "http2"),
any(feature = "client", feature = "server")
))] use futures_core::ready; #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] use futures_core::{stream::FusedStream, Stream}; // for mpsc::Receiver #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] use http::HeaderMap; use http_body::{Body, Frame, SizeHint};
/// A stream of `Bytes`, used when receiving bodies from the network. /// /// Note that Users should not instantiate this struct directly. When working with the hyper client, /// `Incoming` is returned to you in responses. Similarly, when operating with the hyper server, /// it is provided within requests. /// /// # Examples /// /// ```rust,ignore /// async fn echo( /// req: Request<hyper::body::Incoming>, /// ) -> Result<Response<BoxBody<Bytes, hyper::Error>>, hyper::Error> { /// //Here, you can process `Incoming` /// } /// ``` #[must_use = "streams do nothing unless polled"] pubstruct Incoming {
kind: Kind,
}
/// A sender half created through [`Body::channel()`]. /// /// Useful when wanting to stream chunks from another thread. /// /// ## Body Closing /// /// Note that the request body will always be closed normally when the sender is dropped (meaning /// that the empty terminating chunk will be sent to the remote). If you desire to close the /// connection with an incomplete response (e.g. in the case of an error during asynchronous /// processing), call the [`Sender::abort()`] method to abort the body in an abnormal fashion. /// /// [`Body::channel()`]: struct.Body.html#method.channel /// [`Sender::abort()`]: struct.Sender.html#method.abort #[must_use = "Sender does nothing unless sent on"] #[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] pub(crate) struct Sender {
want_rx: watch::Receiver,
data_tx: BodySender,
trailers_tx: Option<TrailersSender>,
}
// If wanter is true, `Sender::poll_ready()` won't becoming ready // until the `Body` has been polled for data once. let want = if wanter { WANT_PENDING } else { WANT_READY };
let (want_tx, want_rx) = watch::channel(want);
let tx = Sender {
want_rx,
data_tx,
trailers_tx: Some(trailers_tx),
}; let rx = Incoming::new(Kind::Chan {
content_length,
want_tx,
data_rx,
trailers_rx,
});
if !data_rx.is_terminated() { iflet Some(chunk) = ready!(Pin::new(data_rx).poll_next(cx)?) {
len.sub_if(chunk.len() as u64); return Poll::Ready(Some(Ok(Frame::data(chunk))));
}
}
// check trailers after data is terminated match ready!(Pin::new(trailers_rx).poll(cx)) {
Ok(t) => Poll::Ready(Some(Ok(Frame::trailers(t)))),
Err(_) => Poll::Ready(None),
}
} #[cfg(all(feature = "http2", any(feature = "client", feature = "server")))]
Kind::H2 { refmut data_done, ref ping,
recv: refmut h2,
content_length: refmut len,
} => { if !*data_done { match ready!(h2.poll_data(cx)) {
Some(Ok(bytes)) => { let _ = h2.flow_control().release_capacity(bytes.len());
len.sub_if(bytes.len() as u64);
ping.record_data(bytes.len()); return Poll::Ready(Some(Ok(Frame::data(bytes))));
}
Some(Err(e)) => { returnmatch e.reason() { // These reasons should cause the body reading to stop, but not fail it. // The same logic as for `Read for H2Upgraded` is applied here.
Some(h2::Reason::NO_ERROR) | Some(h2::Reason::CANCEL) => {
Poll::Ready(None)
}
_ => Poll::Ready(Some(Err(crate::Error::new_body(e)))),
};
}
None => {
*data_done = true; // fall through to trailers
}
}
}
// after data, check trailers match ready!(h2.poll_trailers(cx)) {
Ok(t) => {
ping.record_non_data();
Poll::Ready(Ok(t.map(Frame::trailers)).transpose())
}
Err(e) => Poll::Ready(Some(Err(crate::Error::new_h2(e)))),
}
}
#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] impl Sender { /// Check to see if this `Sender` can send more data. pub(crate) fn poll_ready(&mutself, cx: &mut Context<'_>) -> Poll<crate::Result<()>> { // Check if the receiver end has tried polling for the body yet
ready!(self.poll_want(cx)?); self.data_tx
.poll_ready(cx)
.map_err(|_| crate::Error::new_closed())
}
/// Send data on data channel when it is ready. #[cfg(test)] #[allow(unused)] pub(crate) asyncfn send_data(&mutself, chunk: Bytes) -> crate::Result<()> { self.ready().await?; self.data_tx
.try_send(Ok(chunk))
.map_err(|_| crate::Error::new_closed())
}
/// Try to send data on this channel. /// /// # Errors /// /// Returns `Err(Bytes)` if the channel could not (currently) accept /// another `Bytes`. /// /// # Note /// /// This is mostly useful for when trying to send from some other thread /// that doesn't have an async context. If in an async context, prefer /// `send_data()` instead. #[cfg(feature = "http1")] pub(crate) fn try_send_data(&mutself, chunk: Bytes) -> Result<(), Bytes> { self.data_tx
.try_send(Ok(chunk))
.map_err(|err| err.into_inner().expect("just sent Ok"))
}
pub(crate) fn send_error(&mutself, err: crate::Error) { let _ = self
.data_tx // clone so the send works even if buffer is full
.clone()
.try_send(Err(err));
}
}
#[cfg(all(feature = "http1", any(feature = "client", feature = "server")))] #[test] fn test_size_of() { // These are mostly to help catch *accidentally* increasing // the size by too much.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.