li_http_types/
response.rs

1use futures_lite::{io, prelude::*};
2
3use std::convert::{Into, TryInto};
4use std::fmt::Debug;
5use std::mem;
6use std::ops::Index;
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10use crate::convert::DeserializeOwned;
11use crate::headers::{
12    self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values,
13    CONTENT_TYPE,
14};
15use crate::mime::Mime;
16use crate::trailers::{self, Trailers};
17use crate::upgrade;
18use crate::{Body, Extensions, StatusCode, Version};
19
20pin_project_lite::pin_project! {
21    /// An HTTP response.
22    ///
23    /// # Examples
24    ///
25    /// ```
26    /// # fn main() -> Result<(), li_http_types::Error> {
27    /// #
28    /// use li_http_types::{Response, StatusCode};
29    ///
30    /// let mut res = Response::new(StatusCode::Ok);
31    /// res.set_body("Hello, Nori!");
32    /// #
33    /// # Ok(()) }
34    /// ```
35    #[derive(Debug)]
36    pub struct Response {
37        status: StatusCode,
38        headers: Headers,
39        version: Option<Version>,
40        has_trailers: bool,
41        trailers_sender: Option<async_channel::Sender<Trailers>>,
42        trailers_receiver: Option<async_channel::Receiver<Trailers>>,
43        upgrade_sender: Option<async_channel::Sender<upgrade::Connection>>,
44        upgrade_receiver: Option<async_channel::Receiver<upgrade::Connection>>,
45        has_upgrade: bool,
46        #[pin]
47        body: Body,
48        ext: Extensions,
49        local_addr: Option<String>,
50        peer_addr: Option<String>,
51        resolved_url: Option<String>,
52    }
53}
54
55impl Response {
56    /// Create a new response.
57    pub fn new<S>(status: S) -> Self
58    where
59        S: TryInto<StatusCode>,
60        S::Error: Debug,
61    {
62        let status = status
63            .try_into()
64            .expect("Could not convert into a valid `StatusCode`");
65        let (trailers_sender, trailers_receiver) = async_channel::bounded(1);
66        let (upgrade_sender, upgrade_receiver) = async_channel::bounded(1);
67        Self {
68            status,
69            headers: Headers::new(),
70            version: None,
71            body: Body::empty(),
72            trailers_sender: Some(trailers_sender),
73            trailers_receiver: Some(trailers_receiver),
74            has_trailers: false,
75            upgrade_sender: Some(upgrade_sender),
76            upgrade_receiver: Some(upgrade_receiver),
77            has_upgrade: false,
78            ext: Extensions::new(),
79            peer_addr: None,
80            local_addr: None,
81            resolved_url: None,
82        }
83    }
84
85    /// Get the status
86    pub fn status(&self) -> StatusCode {
87        self.status
88    }
89
90    /// Get a mutable reference to a header.
91    pub fn header_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
92        self.headers.get_mut(name.into())
93    }
94
95    /// Get an HTTP header.
96    pub fn header(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
97        self.headers.get(name.into())
98    }
99
100    /// Remove a header.
101    pub fn remove_header(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
102        self.headers.remove(name.into())
103    }
104
105    /// Set an HTTP header.
106    ///
107    /// # Examples
108    ///
109    /// ```
110    /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
111    /// #
112    /// use li_http_types::{Method, Response, StatusCode, Url};
113    ///
114    /// let mut req = Response::new(StatusCode::Ok);
115    /// req.insert_header("Content-Type", "text/plain");
116    /// #
117    /// # Ok(()) }
118    /// ```
119    pub fn insert_header(
120        &mut self,
121        name: impl Into<HeaderName>,
122        values: impl ToHeaderValues,
123    ) -> Option<HeaderValues> {
124        self.headers.insert(name, values)
125    }
126
127    /// Append a header to the headers.
128    ///
129    /// Unlike `insert` this function will not override the contents of a
130    /// header, but insert a header if there aren't any. Or else append to
131    /// the existing list of headers.
132    ///
133    /// # Examples
134    ///
135    /// ```
136    /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
137    /// #
138    /// use li_http_types::{Response, StatusCode};
139    ///
140    /// let mut res = Response::new(StatusCode::Ok);
141    /// res.append_header("Content-Type", "text/plain");
142    /// #
143    /// # Ok(()) }
144    /// ```
145    pub fn append_header(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
146        self.headers.append(name, values)
147    }
148
149    /// Set the body reader.
150    ///
151    /// # Examples
152    ///
153    /// ```
154    /// # fn main() -> Result<(), li_http_types::Error> {
155    /// #
156    /// use li_http_types::{Response, StatusCode};
157    ///
158    /// let mut res = Response::new(StatusCode::Ok);
159    /// res.set_body("Hello, Nori!");
160    /// #
161    /// # Ok(()) }
162    /// ```
163    pub fn set_body(&mut self, body: impl Into<Body>) {
164        self.replace_body(body);
165    }
166
167    /// Replace the response body with a new body, returning the old body.
168    ///
169    /// # Examples
170    ///
171    /// ```
172    /// # use async_std::io::prelude::*;
173    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
174    /// #
175    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
176    ///
177    /// let mut req = Response::new(StatusCode::Ok);
178    /// req.set_body("Hello, Nori!");
179    ///
180    /// let mut body: Body = req.replace_body("Hello, Chashu");
181    ///
182    /// let mut string = String::new();
183    /// body.read_to_string(&mut string).await?;
184    /// assert_eq!(&string, "Hello, Nori!");
185    /// #
186    /// # Ok(()) }) }
187    /// ```
188    pub fn replace_body(&mut self, body: impl Into<Body>) -> Body {
189        let body = mem::replace(&mut self.body, body.into());
190        self.copy_content_type_from_body();
191        body
192    }
193
194    /// Swaps the value of the body with another body, without deinitializing
195    /// either one.
196    ///
197    /// # Examples
198    ///
199    /// ```
200    /// # use async_std::io::prelude::*;
201    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
202    /// #
203    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
204    ///
205    /// let mut req = Response::new(StatusCode::Ok);
206    /// req.set_body("Hello, Nori!");
207    ///
208    /// let mut body = "Hello, Chashu!".into();
209    /// req.swap_body(&mut body);
210    ///
211    /// let mut string = String::new();
212    /// body.read_to_string(&mut string).await?;
213    /// assert_eq!(&string, "Hello, Nori!");
214    /// #
215    /// # Ok(()) }) }
216    /// ```
217    pub fn swap_body(&mut self, body: &mut Body) {
218        mem::swap(&mut self.body, body);
219        self.copy_content_type_from_body();
220    }
221
222    /// Take the response body, replacing it with an empty body.
223    ///
224    /// # Examples
225    ///
226    /// ```
227    /// # use async_std::io::prelude::*;
228    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
229    /// #
230    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
231    ///
232    /// let mut req = Response::new(StatusCode::Ok);
233    /// req.set_body("Hello, Nori!");
234    /// let mut body: Body = req.take_body();
235    ///
236    /// let mut string = String::new();
237    /// body.read_to_string(&mut string).await?;
238    /// assert_eq!(&string, "Hello, Nori!");
239    ///
240    /// # let mut string = String::new();
241    /// # req.read_to_string(&mut string).await?;
242    /// # assert_eq!(&string, "");
243    /// #
244    /// # Ok(()) }) }
245    /// ```
246    pub fn take_body(&mut self) -> Body {
247        self.replace_body(Body::empty())
248    }
249
250    /// Read the body as a string.
251    ///
252    /// This consumes the response. If you want to read the body without
253    /// consuming the response, consider using the `take_body` method and
254    /// then calling `Body::into_string` or using the Response's AsyncRead
255    /// implementation to read the body.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// # use std::io::prelude::*;
261    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
262    /// use async_std::io::Cursor;
263    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
264    ///
265    /// let mut res = Response::new(StatusCode::Ok);
266    /// let cursor = Cursor::new("Hello Nori");
267    /// let body = Body::from_reader(cursor, None);
268    /// res.set_body(body);
269    /// assert_eq!(&res.body_string().await.unwrap(), "Hello Nori");
270    /// # Ok(()) }) }
271    /// ```
272    pub async fn body_string(&mut self) -> crate::Result<String> {
273        let body = self.take_body();
274        body.into_string().await
275    }
276
277    /// Read the body as bytes.
278    ///
279    /// This consumes the `Response`. If you want to read the body without
280    /// consuming the response, consider using the `take_body` method and
281    /// then calling `Body::into_bytes` or using the Response's AsyncRead
282    /// implementation to read the body.
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
288    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
289    ///
290    /// let bytes = vec![1, 2, 3];
291    /// let mut res = Response::new(StatusCode::Ok);
292    /// res.set_body(Body::from_bytes(bytes));
293    ///
294    /// let bytes = res.body_bytes().await?;
295    /// assert_eq!(bytes, vec![1, 2, 3]);
296    /// # Ok(()) }) }
297    /// ```
298    pub async fn body_bytes(&mut self) -> crate::Result<Vec<u8>> {
299        let body = self.take_body();
300        body.into_bytes().await
301    }
302
303    /// Read the body as JSON.
304    ///
305    /// This consumes the response. If you want to read the body without
306    /// consuming the response, consider using the `take_body` method and
307    /// then calling `Body::into_json` or using the Response's AsyncRead
308    /// implementation to read the body.
309    ///
310    /// # Examples
311    ///
312    /// ```
313    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
314    /// use li_http_types::convert::{Deserialize, Serialize};
315    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
316    ///
317    /// #[derive(Debug, Serialize, Deserialize)]
318    /// struct Cat {
319    ///     name: String,
320    /// }
321    ///
322    /// let cat = Cat {
323    ///     name: String::from("chashu"),
324    /// };
325    /// let mut res = Response::new(StatusCode::Ok);
326    /// res.set_body(Body::from_json(&cat)?);
327    ///
328    /// let cat: Cat = res.body_json().await?;
329    /// assert_eq!(&cat.name, "chashu");
330    /// # Ok(()) }) }
331    /// ```
332    pub async fn body_json<T: DeserializeOwned>(&mut self) -> crate::Result<T> {
333        let body = self.take_body();
334        body.into_json().await
335    }
336
337    /// Read the body as `x-www-form-urlencoded`.
338    ///
339    /// This consumes the request. If you want to read the body without
340    /// consuming the request, consider using the `take_body` method and
341    /// then calling `Body::into_json` or using the Response's AsyncRead
342    /// implementation to read the body.
343    ///
344    /// # Examples
345    ///
346    /// ```
347    /// # fn main() -> li_http_types::Result<()> { async_std::task::block_on(async {
348    /// use li_http_types::convert::{Deserialize, Serialize};
349    /// use li_http_types::{Body, Method, Response, StatusCode, Url};
350    ///
351    /// #[derive(Debug, Serialize, Deserialize)]
352    /// struct Cat {
353    ///     name: String,
354    /// }
355    ///
356    /// let cat = Cat {
357    ///     name: String::from("chashu"),
358    /// };
359    /// let mut res = Response::new(StatusCode::Ok);
360    /// res.set_body(Body::from_form(&cat)?);
361    ///
362    /// let cat: Cat = res.body_form().await?;
363    /// assert_eq!(&cat.name, "chashu");
364    /// # Ok(()) }) }
365    /// ```
366    pub async fn body_form<T: DeserializeOwned>(&mut self) -> crate::Result<T> {
367        let body = self.take_body();
368        body.into_form().await
369    }
370
371    /// Set the response MIME.
372    pub fn set_content_type(&mut self, mime: Mime) -> Option<HeaderValues> {
373        let value: HeaderValue = mime.into();
374
375        // A Mime instance is guaranteed to be valid header name.
376        self.insert_header(CONTENT_TYPE, value)
377    }
378
379    /// Copy MIME data from the body.
380    fn copy_content_type_from_body(&mut self) {
381        if self.header(CONTENT_TYPE).is_none() {
382            self.set_content_type(self.body.mime().clone());
383        }
384    }
385
386    /// Get the current content type
387    pub fn content_type(&self) -> Option<Mime> {
388        self.header(CONTENT_TYPE)?.last().as_str().parse().ok()
389    }
390
391    /// Get the length of the body stream, if it has been set.
392    ///
393    /// This value is set when passing a fixed-size object into as the body.
394    /// E.g. a string, or a buffer. Consumers of this API should check this
395    /// value to decide whether to use `Chunked` encoding, or set the
396    /// response length.
397    pub fn len(&self) -> Option<usize> {
398        self.body.len()
399    }
400
401    /// Returns `true` if the set length of the body stream is zero, `false`
402    /// otherwise.
403    pub fn is_empty(&self) -> Option<bool> {
404        self.body.is_empty()
405    }
406
407    /// Get the HTTP version, if one has been set.
408    ///
409    /// # Examples
410    ///
411    /// ```
412    /// # fn main() -> Result<(), li_http_types::Error> {
413    /// #
414    /// use li_http_types::{Response, StatusCode, Version};
415    ///
416    /// let mut res = Response::new(StatusCode::Ok);
417    /// assert_eq!(res.version(), None);
418    ///
419    /// res.set_version(Some(Version::Http2_0));
420    /// assert_eq!(res.version(), Some(Version::Http2_0));
421    /// #
422    /// # Ok(()) }
423    /// ```
424    pub fn version(&self) -> Option<Version> {
425        self.version
426    }
427
428    /// Sets a string representation of the peer address that this
429    /// response was sent to. This might take the form of an ip/fqdn
430    /// and port or a local socket address.
431    pub fn set_peer_addr(&mut self, peer_addr: Option<impl std::string::ToString>) {
432        self.peer_addr = peer_addr.map(|addr| addr.to_string());
433    }
434
435    /// Sets a string representation of the local address that this
436    /// response was sent on. This might take the form of an ip/fqdn and
437    /// port, or a local socket address.
438    pub fn set_local_addr(&mut self, local_addr: Option<impl std::string::ToString>) {
439        self.local_addr = local_addr.map(|addr| addr.to_string());
440    }
441
442    /// Get the peer socket address for the underlying transport, if appropriate
443    pub fn peer_addr(&self) -> Option<&str> {
444        self.peer_addr.as_deref()
445    }
446
447    /// Get the local socket address for the underlying transport, if
448    /// appropriate
449    pub fn local_addr(&self) -> Option<&str> {
450        self.local_addr.as_deref()
451    }
452
453    /// Set the latest URL resolved
454    pub fn set_resolved_url(&mut self, resolved_url: Option<impl std::string::ToString>) {
455        self.resolved_url = resolved_url.map(|addr| addr.to_string());
456    }
457
458    /// Get latest URL resolved
459    pub fn resolved_url(&self) -> Option<&str> {
460        self.resolved_url.as_deref()
461    }
462
463    /// Set the HTTP version.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// # fn main() -> Result<(), li_http_types::Error> {
469    /// #
470    /// use li_http_types::{Response, StatusCode, Version};
471    ///
472    /// let mut res = Response::new(StatusCode::Ok);
473    /// res.set_version(Some(Version::Http2_0));
474    /// #
475    /// # Ok(()) }
476    /// ```
477    pub fn set_version(&mut self, version: Option<Version>) {
478        self.version = version;
479    }
480
481    /// Set the status.
482    pub fn set_status(&mut self, status: StatusCode) {
483        self.status = status;
484    }
485
486    /// Sends trailers to the a receiver.
487    pub fn send_trailers(&mut self) -> trailers::Sender {
488        self.has_trailers = true;
489        let sender = self
490            .trailers_sender
491            .take()
492            .expect("Trailers sender can only be constructed once");
493        trailers::Sender::new(sender)
494    }
495
496    /// Receive trailers from a sender.
497    pub fn recv_trailers(&mut self) -> trailers::Receiver {
498        let receiver = self
499            .trailers_receiver
500            .take()
501            .expect("Trailers receiver can only be constructed once");
502        trailers::Receiver::new(receiver)
503    }
504
505    /// Returns `true` if sending trailers is in progress.
506    pub fn has_trailers(&self) -> bool {
507        self.has_trailers
508    }
509
510    /// Sends an upgrade connection to the a receiver.
511    #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
512    pub fn send_upgrade(&mut self) -> upgrade::Sender {
513        self.has_upgrade = true;
514        let sender = self
515            .upgrade_sender
516            .take()
517            .expect("Upgrade sender can only be constructed once");
518        upgrade::Sender::new(sender)
519    }
520
521    /// Receive an upgraded connection from a sender.
522    #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
523    pub async fn recv_upgrade(&mut self) -> upgrade::Receiver {
524        self.has_upgrade = true;
525        let receiver = self
526            .upgrade_receiver
527            .take()
528            .expect("Upgrade receiver can only be constructed once");
529        upgrade::Receiver::new(receiver)
530    }
531
532    /// Returns `true` if a protocol upgrade is in progress.
533    #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
534    pub fn has_upgrade(&self) -> bool {
535        self.has_upgrade
536    }
537
538    /// An iterator visiting all header pairs in arbitrary order.
539    pub fn iter(&self) -> headers::Iter<'_> {
540        self.headers.iter()
541    }
542
543    /// An iterator visiting all header pairs in arbitrary order, with mutable
544    /// references to the values.
545    pub fn iter_mut(&mut self) -> headers::IterMut<'_> {
546        self.headers.iter_mut()
547    }
548
549    /// An iterator visiting all header names in arbitrary order.
550    pub fn header_names(&self) -> Names<'_> {
551        self.headers.names()
552    }
553
554    /// An iterator visiting all header values in arbitrary order.
555    pub fn header_values(&self) -> Values<'_> {
556        self.headers.values()
557    }
558
559    /// Returns a reference to the existing local.
560    pub fn ext(&self) -> &Extensions {
561        &self.ext
562    }
563
564    /// Returns a mutuable reference to the existing local state.
565    ///
566    ///
567    /// # Examples
568    ///
569    /// ```
570    /// # fn main() -> Result<(), li_http_types::Error> {
571    /// #
572    /// use li_http_types::{Response, StatusCode, Version};
573    ///
574    /// let mut res = Response::new(StatusCode::Ok);
575    /// res.ext_mut().insert("hello from the extension");
576    /// assert_eq!(res.ext().get(), Some(&"hello from the extension"));
577    /// #
578    /// # Ok(()) }
579    /// ```
580    pub fn ext_mut(&mut self) -> &mut Extensions {
581        &mut self.ext
582    }
583}
584
585impl Clone for Response {
586    /// Clone the response, resolving the body to `Body::empty()` and removing
587    /// extensions.
588    fn clone(&self) -> Self {
589        Self {
590            status: self.status,
591            headers: self.headers.clone(),
592            version: self.version,
593            trailers_sender: self.trailers_sender.clone(),
594            trailers_receiver: self.trailers_receiver.clone(),
595            has_trailers: false,
596            upgrade_sender: self.upgrade_sender.clone(),
597            upgrade_receiver: self.upgrade_receiver.clone(),
598            has_upgrade: false,
599            body: Body::empty(),
600            ext: Extensions::new(),
601            peer_addr: self.peer_addr.clone(),
602            local_addr: self.local_addr.clone(),
603            resolved_url: self.resolved_url.clone(),
604        }
605    }
606}
607
608impl AsyncRead for Response {
609    #[allow(missing_doc_code_examples)]
610    fn poll_read(
611        mut self: Pin<&mut Self>,
612        cx: &mut Context<'_>,
613        buf: &mut [u8],
614    ) -> Poll<io::Result<usize>> {
615        Pin::new(&mut self.body).poll_read(cx, buf)
616    }
617}
618
619impl AsyncBufRead for Response {
620    #[allow(missing_doc_code_examples)]
621    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&'_ [u8]>> {
622        let this = self.project();
623        this.body.poll_fill_buf(cx)
624    }
625
626    fn consume(mut self: Pin<&mut Self>, amt: usize) {
627        Pin::new(&mut self.body).consume(amt)
628    }
629}
630
631impl AsRef<Headers> for Response {
632    fn as_ref(&self) -> &Headers {
633        &self.headers
634    }
635}
636
637impl AsMut<Headers> for Response {
638    fn as_mut(&mut self) -> &mut Headers {
639        &mut self.headers
640    }
641}
642
643impl From<()> for Response {
644    fn from(_: ()) -> Self {
645        Response::new(StatusCode::NoContent)
646    }
647}
648impl Index<HeaderName> for Response {
649    type Output = HeaderValues;
650
651    /// Returns a reference to the value corresponding to the supplied name.
652    ///
653    /// # Panics
654    ///
655    /// Panics if the name is not present in `Response`.
656    #[inline]
657    fn index(&self, name: HeaderName) -> &HeaderValues {
658        self.headers.index(name)
659    }
660}
661
662impl Index<&str> for Response {
663    type Output = HeaderValues;
664
665    /// Returns a reference to the value corresponding to the supplied name.
666    ///
667    /// # Panics
668    ///
669    /// Panics if the name is not present in `Response`.
670    #[inline]
671    fn index(&self, name: &str) -> &HeaderValues {
672        self.headers.index(name)
673    }
674}
675
676impl From<StatusCode> for Response {
677    fn from(s: StatusCode) -> Self {
678        Response::new(s)
679    }
680}
681
682impl<T> From<T> for Response
683where
684    T: Into<Body>,
685{
686    fn from(value: T) -> Self {
687        let body: Body = value.into();
688        let mut res = Response::new(StatusCode::Ok);
689        res.set_body(body);
690        res
691    }
692}
693
694impl IntoIterator for Response {
695    type Item = (HeaderName, HeaderValues);
696    type IntoIter = headers::IntoIter;
697
698    /// Returns a iterator of references over the remaining items.
699    #[inline]
700    fn into_iter(self) -> Self::IntoIter {
701        self.headers.into_iter()
702    }
703}
704
705impl<'a> IntoIterator for &'a Response {
706    type Item = (&'a HeaderName, &'a HeaderValues);
707    type IntoIter = headers::Iter<'a>;
708
709    #[inline]
710    fn into_iter(self) -> Self::IntoIter {
711        self.headers.iter()
712    }
713}
714
715impl<'a> IntoIterator for &'a mut Response {
716    type Item = (&'a HeaderName, &'a mut HeaderValues);
717    type IntoIter = headers::IterMut<'a>;
718
719    #[inline]
720    fn into_iter(self) -> Self::IntoIter {
721        self.headers.iter_mut()
722    }
723}
724
725#[cfg(test)]
726mod test {
727    use super::Response;
728
729    #[test]
730    fn construct_shorthand_with_valid_status_code() {
731        let _res = Response::new(200);
732    }
733
734    #[test]
735    #[should_panic(expected = "Could not convert into a valid `StatusCode`")]
736    fn construct_shorthand_with_invalid_status_code() {
737        let _res = Response::new(600);
738    }
739}