Skip to main content

timvw_rust_runtime/
response.rs

1use std::fmt;
2
3use bytes::Bytes;
4use futures_core::Stream;
5use futures_util::TryStreamExt;
6use http_body_util::BodyDataStream;
7use serde::de::DeserializeOwned;
8
9use crate::{Body, Error, HeaderMap, StatusCode};
10
11/// A response, with the methods of reqwest's `Response` that generated clients use.
12pub struct Response {
13    inner: http::Response<Body>,
14}
15
16impl Response {
17    /// The status code.
18    pub fn status(&self) -> StatusCode {
19        self.inner.status()
20    }
21
22    /// The headers.
23    pub fn headers(&self) -> &HeaderMap {
24        self.inner.headers()
25    }
26
27    /// The headers, to change.
28    pub fn headers_mut(&mut self) -> &mut HeaderMap {
29        self.inner.headers_mut()
30    }
31
32    /// Reads the body into memory.
33    pub async fn bytes(self) -> Result<Bytes, Error> {
34        self.inner
35            .into_body()
36            .collect_bytes()
37            .await
38            .map_err(Error::body)
39    }
40
41    /// Reads the body as text; bytes that are not UTF-8 become U+FFFD.
42    pub async fn text(self) -> Result<String, Error> {
43        let bytes = self.bytes().await?;
44        Ok(match String::from_utf8(bytes.to_vec()) {
45            Ok(text) => text,
46            Err(error) => String::from_utf8_lossy(error.as_bytes()).into_owned(),
47        })
48    }
49
50    /// Reads the body as JSON.
51    pub async fn json<T: DeserializeOwned>(self) -> Result<T, Error> {
52        let bytes = self.bytes().await?;
53        serde_json::from_slice(&bytes).map_err(Error::decode)
54    }
55
56    /// The body as a stream of chunks, as they arrive.
57    pub fn bytes_stream(self) -> impl Stream<Item = Result<Bytes, Error>> + Send + 'static {
58        BodyDataStream::new(self.inner.into_body()).map_err(Error::body)
59    }
60
61    /// The body as server-sent events (`text/event-stream`), as they arrive. [`Events::json`](crate::sse::Events::json)
62    /// decodes their `data:` as JSON. The status and the content type are not checked.
63    pub fn events(self) -> crate::sse::Events {
64        crate::sse::Events::from_response(self)
65    }
66
67    /// The underlying `http::Response`.
68    pub fn into_http(self) -> http::Response<Body> {
69        self.inner
70    }
71}
72
73impl From<http::Response<Body>> for Response {
74    fn from(inner: http::Response<Body>) -> Self {
75        Self { inner }
76    }
77}
78
79impl fmt::Debug for Response {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        f.debug_struct("Response")
82            .field("status", &self.inner.status())
83            .field("headers", self.inner.headers())
84            .finish_non_exhaustive()
85    }
86}