|
1 | | -//! Streaming bodies for Requests and Responses |
2 | | -//! |
3 | | -//! For both [Clients](::client) and [Servers](::server), requests and |
4 | | -//! responses use streaming bodies, instead of complete buffering. This |
5 | | -//! allows applications to not use memory they don't need, and allows exerting |
6 | | -//! back-pressure on connections by only reading when asked. |
7 | | -//! |
8 | | -//! There are two pieces to this in hyper: |
9 | | -//! |
10 | | -//! - The [`Payload`](Payload) trait the describes all possible bodies. hyper |
11 | | -//! allows any body type that implements `Payload`, allowing applications to |
12 | | -//! have fine-grained control over their streaming. |
13 | | -//! - The [`Body`](Body) concrete type, which is an implementation of `Payload`, |
14 | | -//! and returned by hyper as a "receive stream" (so, for server requests and |
15 | | -//! client responses). It is also a decent default implementation if you don't |
16 | | -//! have very custom needs of your send streams. |
17 | 1 | use std::borrow::Cow; |
18 | 2 | use std::fmt; |
19 | 3 |
|
20 | | -use bytes::{Buf, Bytes}; |
| 4 | +use bytes::Bytes; |
21 | 5 | use futures::{Async, Future, Poll, Stream}; |
22 | 6 | use futures::sync::{mpsc, oneshot}; |
23 | 7 | use h2; |
24 | 8 | use http::HeaderMap; |
25 | 9 |
|
26 | 10 | use common::Never; |
27 | | -pub use chunk::Chunk; |
| 11 | +use super::{Chunk, Payload}; |
| 12 | +use super::internal::{FullDataArg, FullDataRet}; |
28 | 13 |
|
29 | | -use self::internal::{FullDataArg, FullDataRet}; |
30 | 14 |
|
31 | 15 | type BodySender = mpsc::Sender<Result<Chunk, ::Error>>; |
32 | 16 |
|
33 | | - |
34 | | -/// This trait represents a streaming body of a `Request` or `Response`. |
35 | | -/// |
36 | | -/// The built-in implementation of this trait is [`Body`](Body), in case you |
37 | | -/// don't need to customize a send stream for your own application. |
38 | | -pub trait Payload: Send + 'static { |
39 | | - /// A buffer of bytes representing a single chunk of a body. |
40 | | - type Data: Buf + Send; |
41 | | - |
42 | | - /// The error type of this stream. |
43 | | - type Error: Into<Box<::std::error::Error + Send + Sync>>; |
44 | | - |
45 | | - /// Poll for a `Data` buffer. |
46 | | - /// |
47 | | - /// Similar to `Stream::poll_next`, this yields `Some(Data)` until |
48 | | - /// the body ends, when it yields `None`. |
49 | | - fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error>; |
50 | | - |
51 | | - /// Poll for an optional **single** `HeaderMap` of trailers. |
52 | | - /// |
53 | | - /// This should **only** be called after `poll_data` has ended. |
54 | | - /// |
55 | | - /// Note: Trailers aren't currently used for HTTP/1, only for HTTP/2. |
56 | | - fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { |
57 | | - Ok(Async::Ready(None)) |
58 | | - } |
59 | | - |
60 | | - /// A hint that the `Body` is complete, and doesn't need to be polled more. |
61 | | - /// |
62 | | - /// This can be useful to determine if the there is any body or trailers |
63 | | - /// without having to poll. An empty `Body` could return `true` and hyper |
64 | | - /// would be able to know that only the headers need to be sent. Or, it can |
65 | | - /// also be checked after each `poll_data` call, to allow hyper to try to |
66 | | - /// end the underlying stream with the last chunk, instead of needing to |
67 | | - /// send an extra `DATA` frame just to mark the stream as finished. |
68 | | - /// |
69 | | - /// As a hint, it is used to try to optimize, and thus is OK for a default |
70 | | - /// implementation to return `false`. |
71 | | - fn is_end_stream(&self) -> bool { |
72 | | - false |
73 | | - } |
74 | | - |
75 | | - /// Return a length of the total bytes that will be streamed, if known. |
76 | | - /// |
77 | | - /// If an exact size of bytes is known, this would allow hyper to send a |
78 | | - /// `Content-Length` header automatically, not needing to fall back to |
79 | | - /// `Transfer-Encoding: chunked`. |
80 | | - /// |
81 | | - /// This does not need to be kept updated after polls, it will only be |
82 | | - /// called once to create the headers. |
83 | | - fn content_length(&self) -> Option<u64> { |
84 | | - None |
85 | | - } |
86 | | - |
87 | | - // This API is unstable, and is impossible to use outside of hyper. Some |
88 | | - // form of it may become stable in a later version. |
89 | | - // |
90 | | - // The only thing a user *could* do is reference the method, but DON'T |
91 | | - // DO THAT! :) |
92 | | - #[doc(hidden)] |
93 | | - fn __hyper_full_data(&mut self, FullDataArg) -> FullDataRet<Self::Data> { |
94 | | - FullDataRet(None) |
95 | | - } |
96 | | -} |
97 | | - |
98 | | -impl<E: Payload> Payload for Box<E> { |
99 | | - type Data = E::Data; |
100 | | - type Error = E::Error; |
101 | | - |
102 | | - fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> { |
103 | | - (**self).poll_data() |
104 | | - } |
105 | | - |
106 | | - fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> { |
107 | | - (**self).poll_trailers() |
108 | | - } |
109 | | - |
110 | | - fn is_end_stream(&self) -> bool { |
111 | | - (**self).is_end_stream() |
112 | | - } |
113 | | - |
114 | | - fn content_length(&self) -> Option<u64> { |
115 | | - (**self).content_length() |
116 | | - } |
117 | | - |
118 | | - #[doc(hidden)] |
119 | | - fn __hyper_full_data(&mut self, arg: FullDataArg) -> FullDataRet<Self::Data> { |
120 | | - (**self).__hyper_full_data(arg) |
121 | | - } |
122 | | -} |
123 | | - |
124 | | - |
125 | 17 | /// A stream of `Chunk`s, used when receiving bodies. |
126 | 18 | /// |
127 | 19 | /// A good default `Payload` to use in many applications. |
@@ -496,35 +388,8 @@ impl From<Cow<'static, str>> for Body { |
496 | 388 | } |
497 | 389 | } |
498 | 390 |
|
499 | | -// The full_data API is not stable, so these types are to try to prevent |
500 | | -// users from being able to: |
501 | | -// |
502 | | -// - Implment `__hyper_full_data` on their own Payloads. |
503 | | -// - Call `__hyper_full_data` on any Payload. |
504 | | -// |
505 | | -// That's because to implement it, they need to name these types, and |
506 | | -// they can't because they aren't exported. And to call it, they would |
507 | | -// need to create one of these values, which they also can't. |
508 | | -pub(crate) mod internal { |
509 | | - #[allow(missing_debug_implementations)] |
510 | | - pub struct FullDataArg(pub(crate) ()); |
511 | | - #[allow(missing_debug_implementations)] |
512 | | - pub struct FullDataRet<B>(pub(crate) Option<B>); |
513 | | -} |
514 | | - |
515 | | -fn _assert_send_sync() { |
516 | | - fn _assert_send<T: Send>() {} |
517 | | - fn _assert_sync<T: Sync>() {} |
518 | | - |
519 | | - _assert_send::<Body>(); |
520 | | - _assert_send::<Chunk>(); |
521 | | - _assert_sync::<Chunk>(); |
522 | | -} |
523 | | - |
524 | 391 | #[test] |
525 | 392 | fn test_body_stream_concat() { |
526 | | - use futures::{Stream, Future}; |
527 | | - |
528 | 393 | let body = Body::from("hello world"); |
529 | 394 |
|
530 | 395 | let total = body |
|
0 commit comments