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