[go: up one dir, main page]

ureq/body/
build.rs

1use std::io::{self, Cursor};
2use std::sync::Arc;
3
4use ureq_proto::BodyMode;
5
6use super::{Body, BodyDataSource, ContentEncoding, ResponseInfo};
7
8/// Builder for creating a response body.
9///
10/// This is useful for testing, or for [`Middleware`][crate::middleware::Middleware] that
11/// returns another body than the requested one.
12///
13/// # Example
14///
15/// ```
16/// use ureq::Body;
17/// use ureq::http::Response;
18///
19/// let body = Body::builder()
20///     .mime_type("text/plain")
21///     .charset("utf-8")
22///     .data("Hello world!");
23///
24/// let mut response = Response::builder()
25///     .status(200)
26///     .header("content-type", "text/plain; charset=utf-8")
27///     .body(body)?;
28///
29/// let text = response
30///     .body_mut()
31///     .read_to_string()?;
32///
33/// assert_eq!(text, "Hello world!");
34/// # Ok::<_, ureq::Error>(())
35/// ```
36pub struct BodyBuilder {
37    info: ResponseInfo,
38    limit: Option<u64>,
39}
40
41impl BodyBuilder {
42    pub(crate) fn new() -> Self {
43        BodyBuilder {
44            info: ResponseInfo {
45                content_encoding: ContentEncoding::None,
46                mime_type: None,
47                charset: None,
48                body_mode: BodyMode::NoBody,
49            },
50            limit: None,
51        }
52    }
53
54    /// Set the mime type of the body.
55    ///
56    /// **This does not set any HTTP headers. Affects Body decoding.**
57    ///
58    /// ```
59    /// use ureq::Body;
60    ///
61    /// let body = Body::builder()
62    ///     .mime_type("text/plain")
63    ///     .data("Hello world!");
64    /// ```
65    pub fn mime_type(mut self, mime_type: impl Into<String>) -> Self {
66        self.info.mime_type = Some(mime_type.into());
67        self
68    }
69
70    /// Set the mime type of the body
71    ///
72    /// **This does not set any HTTP headers. Affects Body decoding.**
73    ///
74    /// ```
75    /// use ureq::Body;
76    ///
77    /// let body = Body::builder()
78    ///     .mime_type("text/plain")
79    ///     .charset("utf-8")
80    ///     .data("Hello world!");
81    /// ```
82    pub fn charset(mut self, charset: impl Into<String>) -> Self {
83        self.info.charset = Some(charset.into());
84        self
85    }
86
87    /// Limit how much data is to be released from the body.
88    ///
89    /// **This does not set any HTTP headers. Affects Body decoding.**
90    ///
91    /// ```
92    /// use ureq::Body;
93    ///
94    /// let body = Body::builder()
95    ///     .mime_type("text/plain")
96    ///     .charset("utf-8")
97    ///     .limit(5)
98    ///     // This will be limited to "Hello"
99    ///     .data("Hello world!");
100    /// ```
101    pub fn limit(mut self, l: u64) -> Self {
102        self.limit = Some(l);
103        self
104    }
105
106    /// Creates the body data turned into bytes.
107    ///
108    /// Will automatically limit the body reader to the lenth of the data.
109    pub fn data(mut self, data: impl Into<Vec<u8>>) -> Body {
110        let data: Vec<u8> = data.into();
111
112        let len = self.limit.unwrap_or(data.len() as u64);
113        self.info.body_mode = BodyMode::LengthDelimited(len);
114
115        self.reader(Cursor::new(data))
116    }
117
118    /// Creates a body from a streaming reader.
119    ///
120    /// The reader can be limited by using `.limit()` or that the reader
121    /// reaches the end.
122    pub fn reader(self, data: impl io::Read + Send + Sync + 'static) -> Body {
123        Body {
124            source: BodyDataSource::Reader(Box::new(data)),
125            info: Arc::new(self.info),
126        }
127    }
128}