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}